rdf-borsh 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +4 -0
- data/README.md +47 -4
- data/VERSION +1 -1
- data/lib/rdf/borsh/format.rb +1 -1
- data/lib/rdf/borsh/reader.rb +15 -12
- data/lib/rdf/borsh/writer.rb +66 -15
- data/lib/rdf/borsh.rb +4 -2
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12224960d664fe3f0b70581cb3c1a0bce77e7425cd0cc9a83b4e6df9fe8d71f7
|
4
|
+
data.tar.gz: d83f64ba1f5e33243dd091b0a04e6c7c39a401bb057703ae03b1373278196204
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cea629b36b4aaea1e18c292210f9942e6ac2ee26659164daffa0540ddbe82fbb8bd54f57c55a726268ce4a985f611ee870fcb6feb31c3fb8b9f92dd914927ed4
|
7
|
+
data.tar.gz: 960ba17587d985344357d9c8c1b12e63827e070cb66ea1f0479727df8578519269d8bbfc24ad6a6925c261037db958b1cd897c64e403813b82f74a7e6350b9d5
|
data/CHANGES.md
CHANGED
@@ -5,4 +5,8 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## 1.0.2 - 2025-01-11
|
9
|
+
|
10
|
+
## 1.0.1 - 2025-01-07
|
11
|
+
|
8
12
|
## 1.0.0 - 2025-01-07
|
data/README.md
CHANGED
@@ -3,15 +3,25 @@
|
|
3
3
|
[](https://unlicense.org)
|
4
4
|
[](https://rubygems.org/gems/rdf-borsh)
|
5
5
|
[](https://rubygems.org/gems/rdf-borsh)
|
6
|
+
[](https://rubydoc.info/gems/rdf-borsh)
|
6
7
|
|
7
|
-
|
8
|
-
binary serialization
|
8
|
+
**RDF/Borsh** is a [Ruby] library and [RDF.rb] extension for encoding
|
9
|
+
and decoding [RDF] knowledge graphs in the [Borsh] binary serialization
|
10
|
+
format. (See the [specification].)
|
9
11
|
|
10
|
-
|
12
|
+
## ✨ Features
|
13
|
+
|
14
|
+
- Serializes RDF datasets into compact and efficient binary files.
|
15
|
+
- Implements the `application/x-rdf+borsh` MIME type with a `.rdfb` extension.
|
16
|
+
- Employes LZ4 compression for both the term dictionary and quad data.
|
17
|
+
- Designed for blockchain and distributed ledger applications.
|
18
|
+
- Supports reading from and writing to files or I/O streams.
|
19
|
+
- Plays nice with others: entirely contained in the `RDF::Borsh` module.
|
20
|
+
- 100% free and unencumbered public domain software.
|
11
21
|
|
12
22
|
## 🛠️ Prerequisites
|
13
23
|
|
14
|
-
- [Ruby]
|
24
|
+
- [Ruby] 3.0+
|
15
25
|
|
16
26
|
## ⬇️ Installation
|
17
27
|
|
@@ -27,8 +37,35 @@ gem install rdf-borsh
|
|
27
37
|
|
28
38
|
```ruby
|
29
39
|
require 'rdf/borsh'
|
40
|
+
|
41
|
+
include RDF
|
42
|
+
```
|
43
|
+
|
44
|
+
### Serializing an RDF graph into an RDF/Borsh file
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
RDF::Borsh::Writer.open("mygraph.rdfb") do |writer|
|
48
|
+
writer << [RDF::URI("https://rubygems.org/gems/rdf-borsh"), RDFS.label, "RDF/Borsh for Ruby"]
|
49
|
+
end
|
30
50
|
```
|
31
51
|
|
52
|
+
### Parsing an RDF graph from an RDF/Borsh file
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
graph = RDF::Graph.load("mygraph.rdfb")
|
56
|
+
graph.to_a
|
57
|
+
```
|
58
|
+
|
59
|
+
### Parsing an RDF/Borsh dataset from standard input
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
RDF::Borsh::Reader.new($stdin).to_a
|
63
|
+
```
|
64
|
+
|
65
|
+
## 📚 Reference
|
66
|
+
|
67
|
+
https://rubydoc.info/gems/rdf-borsh
|
68
|
+
|
32
69
|
## 👨💻 Development
|
33
70
|
|
34
71
|
```bash
|
@@ -41,3 +78,9 @@ git clone https://github.com/ruby-rdf/rdf-borsh.git
|
|
41
78
|
[](https://reddit.com/submit?url=https://github.com/ruby-rdf/rdf-borsh&title=RDF%2FBorsh+for+Ruby)
|
42
79
|
[](https://news.ycombinator.com/submitlink?u=https://github.com/ruby-rdf/rdf-borsh&t=RDF%2FBorsh+for+Ruby)
|
43
80
|
[](https://www.facebook.com/sharer/sharer.php?u=https://github.com/ruby-rdf/rdf-borsh)
|
81
|
+
|
82
|
+
[Borsh]: https://borsh.io
|
83
|
+
[RDF]: https://www.w3.org/TR/rdf12-concepts/
|
84
|
+
[RDF.rb]: https://github.com/ruby-rdf/rdf
|
85
|
+
[Ruby]: https://ruby-lang.org
|
86
|
+
[specification]: https://github.com/ruby-rdf/rdf-borsh/blob/master/doc/spec.md
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
data/lib/rdf/borsh/format.rb
CHANGED
data/lib/rdf/borsh/reader.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# This is free and unencumbered software released into the public domain.
|
2
2
|
|
3
|
+
require 'borsh'
|
3
4
|
require 'extlz4'
|
4
5
|
require 'rdf'
|
5
6
|
require 'stringio'
|
@@ -15,15 +16,17 @@ module RDF::Borsh
|
|
15
16
|
def initialize(input = $stdin, **options, &block)
|
16
17
|
super(input, **options) do
|
17
18
|
input = @input
|
19
|
+
|
20
|
+
@input.extend(Borsh::Readable)
|
18
21
|
@version, @flags, @quad_count = self.read_header
|
19
22
|
|
20
|
-
input_size = input.
|
21
|
-
@input =
|
23
|
+
input_size = input.read_u32
|
24
|
+
@input = Borsh::Buffer.new(self.decompress(input.read(input_size)))
|
22
25
|
@terms = [nil] + self.read_terms
|
23
26
|
|
24
|
-
input_size = input.
|
25
|
-
@input =
|
26
|
-
_ = @input.
|
27
|
+
input_size = input.read_u32
|
28
|
+
@input = Borsh::Buffer.new(self.decompress(input.read(input_size)))
|
29
|
+
_ = @input.read_u32
|
27
30
|
|
28
31
|
if block_given?
|
29
32
|
case block.arity
|
@@ -46,9 +49,9 @@ module RDF::Borsh
|
|
46
49
|
##
|
47
50
|
# Reads the compressed terms dictionary.
|
48
51
|
def read_terms
|
49
|
-
term_count = @input.
|
52
|
+
term_count = @input.read_u32
|
50
53
|
term_count.times.map do
|
51
|
-
term_kind, term_string_size = @input.
|
54
|
+
term_kind, term_string_size = @input.read_u8, @input.read_u32
|
52
55
|
term_string = @input.read(term_string_size)
|
53
56
|
|
54
57
|
case term_kind
|
@@ -56,10 +59,10 @@ module RDF::Borsh
|
|
56
59
|
when 2 then RDF::Node(term_string)
|
57
60
|
when 3 then RDF::Literal(term_string)
|
58
61
|
when 4
|
59
|
-
term_datatype_size = @input.
|
62
|
+
term_datatype_size = @input.read_u32
|
60
63
|
RDF::Literal(term_string, datatype: @input.read(term_datatype_size))
|
61
64
|
when 5
|
62
|
-
term_language_size = @input.
|
65
|
+
term_language_size = @input.read_u32
|
63
66
|
RDF::Literal(term_string, language: @input.read(term_language_size))
|
64
67
|
else
|
65
68
|
raise RDF::ReaderError, "unknown RDF/Borsh term type: #{term_kind}"
|
@@ -73,13 +76,13 @@ module RDF::Borsh
|
|
73
76
|
magic = @input.read(4).unpack('a4').first
|
74
77
|
raise RDF::ReaderError, "invalid RDF/Borsh header: #{magic.inspect}" if magic != MAGIC
|
75
78
|
|
76
|
-
version = @input.
|
79
|
+
version = @input.read_u8
|
77
80
|
raise RDF::ReaderError, "invalid RDF/Borsh version: #{version}" if version != VERSION
|
78
81
|
|
79
|
-
flags = @input.
|
82
|
+
flags = @input.read_u8
|
80
83
|
raise RDF::ReaderError, "invalid RDF/Borsh flags: #{flags}" if flags != FLAGS
|
81
84
|
|
82
|
-
quad_count = @input.
|
85
|
+
quad_count = @input.read_u32
|
83
86
|
[version, flags, quad_count]
|
84
87
|
end
|
85
88
|
|
data/lib/rdf/borsh/writer.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# This is free and unencumbered software released into the public domain.
|
2
2
|
|
3
|
+
require 'borsh'
|
3
4
|
require 'extlz4'
|
4
5
|
require 'rdf'
|
5
6
|
require 'sorted_set'
|
6
|
-
require 'stringio'
|
7
7
|
|
8
8
|
module RDF::Borsh
|
9
9
|
class Writer < RDF::Writer
|
@@ -14,7 +14,19 @@ module RDF::Borsh
|
|
14
14
|
FLAGS = RDF::Borsh::Format::FLAGS
|
15
15
|
LZ4HC_CLEVEL_MAX = 12
|
16
16
|
|
17
|
+
##
|
18
|
+
# Initializes the RDF/Borsh writer.
|
19
|
+
#
|
20
|
+
# @param [IO, StringIO] output
|
21
|
+
# @param [Hash{Symbol => Object}] options
|
22
|
+
# @yield [writer]
|
23
|
+
# @yieldparam [RDF::Borsh::Writer] writer
|
24
|
+
# @yieldreturn [void]
|
25
|
+
# @return [void]
|
17
26
|
def initialize(output = $stdout, **options, &block)
|
27
|
+
output.extend(Borsh::Writable)
|
28
|
+
output.binmode if output.respond_to?(:binmode)
|
29
|
+
|
18
30
|
@terms_dict, @terms_map = [], {}
|
19
31
|
@quads_set = SortedSet.new
|
20
32
|
|
@@ -24,14 +36,30 @@ module RDF::Borsh
|
|
24
36
|
when 0 then self.instance_eval(&block)
|
25
37
|
else block.call(self)
|
26
38
|
end
|
39
|
+
self.finish
|
27
40
|
end
|
28
41
|
end
|
29
42
|
end
|
30
43
|
|
44
|
+
##
|
45
|
+
# Writes an RDF triple.
|
46
|
+
#
|
47
|
+
# @param [RDF::Resource] subject
|
48
|
+
# @param [RDF::URI] predicate
|
49
|
+
# @param [RDF::Term] object
|
50
|
+
# @return [void]
|
31
51
|
def write_triple(subject, predicate, object)
|
32
52
|
self.write_quad(subject, predicate, object, nil)
|
33
53
|
end
|
34
54
|
|
55
|
+
##
|
56
|
+
# Writes an RDF quad.
|
57
|
+
#
|
58
|
+
# @param [RDF::Resource] subject
|
59
|
+
# @param [RDF::URI] predicate
|
60
|
+
# @param [RDF::Term] object
|
61
|
+
# @param [RDF::Resource] context
|
62
|
+
# @return [void]
|
35
63
|
def write_quad(subject, predicate, object, context)
|
36
64
|
s = self.intern_term(subject)
|
37
65
|
p = self.intern_term(predicate)
|
@@ -40,28 +68,42 @@ module RDF::Borsh
|
|
40
68
|
@quads_set << [g, s, p, o]
|
41
69
|
end
|
42
70
|
|
71
|
+
##
|
72
|
+
# Flushes the output.
|
73
|
+
#
|
74
|
+
# @return [void]
|
43
75
|
def flush
|
44
76
|
self.finish
|
45
77
|
super
|
46
78
|
end
|
47
79
|
|
80
|
+
##
|
81
|
+
# Finishes writing the output.
|
82
|
+
#
|
83
|
+
# @return [void]
|
48
84
|
def finish
|
49
85
|
self.write_header
|
50
86
|
self.write_terms
|
51
87
|
self.write_quads
|
52
88
|
end
|
53
89
|
|
90
|
+
##
|
54
91
|
# Writes the uncompressed header.
|
92
|
+
#
|
93
|
+
# @return [void]
|
55
94
|
def write_header
|
95
|
+
@output.binmode
|
56
96
|
@output.write([MAGIC, VERSION, FLAGS].pack('a4CC'))
|
57
|
-
@output.
|
97
|
+
@output.write_u32(@quads_set.size)
|
58
98
|
end
|
59
99
|
|
100
|
+
##
|
60
101
|
# Writes the compressed terms dictionary.
|
102
|
+
#
|
103
|
+
# @return [void]
|
61
104
|
def write_terms
|
62
|
-
buffer =
|
63
|
-
output.
|
64
|
-
output.write([@terms_dict.size].pack('V'))
|
105
|
+
buffer = self.compress do |output|
|
106
|
+
output.write_u32(@terms_dict.size)
|
65
107
|
@terms_dict.each do |term|
|
66
108
|
output.write(case
|
67
109
|
when term.iri?
|
@@ -85,25 +127,30 @@ module RDF::Borsh
|
|
85
127
|
raise RDF::WriterError, "unsupported RDF/Borsh term type: #{term.inspect}"
|
86
128
|
end)
|
87
129
|
end
|
88
|
-
self.compress(output.string)
|
89
130
|
end
|
90
|
-
@output.
|
131
|
+
@output.write_u32(buffer.size)
|
91
132
|
@output.write(buffer)
|
92
133
|
end
|
93
134
|
|
135
|
+
##
|
136
|
+
# Writes the compressed quads set.
|
137
|
+
#
|
138
|
+
# @return [void]
|
94
139
|
def write_quads
|
95
|
-
buffer =
|
96
|
-
output.
|
97
|
-
output.write([@quads_set.size].pack('V'))
|
140
|
+
buffer = self.compress do |output|
|
141
|
+
output.write_u32(@quads_set.size)
|
98
142
|
@quads_set.each do |quad|
|
99
|
-
output.
|
143
|
+
quad.each { |tid| output.write_u16(tid) }
|
100
144
|
end
|
101
|
-
self.compress(output.string)
|
102
145
|
end
|
103
|
-
@output.
|
146
|
+
@output.write_u32(buffer.size)
|
104
147
|
@output.write(buffer)
|
105
148
|
end
|
106
149
|
|
150
|
+
##
|
151
|
+
# Interns the given RDF term.
|
152
|
+
#
|
153
|
+
# @param [RDF::Term] term
|
107
154
|
# @return [Integer]
|
108
155
|
def intern_term(term)
|
109
156
|
return 0 if term.nil? # for the default graph
|
@@ -116,8 +163,12 @@ module RDF::Borsh
|
|
116
163
|
term_id
|
117
164
|
end
|
118
165
|
|
119
|
-
|
120
|
-
|
166
|
+
##
|
167
|
+
# @yield [Borsh::Buffer]
|
168
|
+
# @return [String]
|
169
|
+
def compress(&block)
|
170
|
+
uncompressed = Borsh::Buffer.open(&block)
|
171
|
+
LZ4::BlockEncoder.new(LZ4HC_CLEVEL_MAX).encode(uncompressed)
|
121
172
|
end
|
122
173
|
end # Writer
|
123
174
|
end # RDF::Borsh
|
data/lib/rdf/borsh.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# This is free and unencumbered software released into the public domain.
|
2
2
|
|
3
|
+
require 'rdf'
|
4
|
+
|
3
5
|
module RDF
|
4
6
|
##
|
5
|
-
# RDF/Borsh.
|
7
|
+
# RDF/Borsh extension for RDF.rb.
|
6
8
|
module Borsh
|
7
9
|
autoload :Format, 'rdf/borsh/format'
|
8
10
|
autoload :Reader, 'rdf/borsh/reader'
|
@@ -10,4 +12,4 @@ module RDF
|
|
10
12
|
end
|
11
13
|
end
|
12
14
|
|
13
|
-
|
15
|
+
require_relative 'borsh/version'
|
metadata
CHANGED
@@ -1,14 +1,28 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdf-borsh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arto Bendiken
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-01-
|
10
|
+
date: 2025-01-11 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: borsh
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0.1'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '0.1'
|
12
26
|
- !ruby/object:Gem::Dependency
|
13
27
|
name: extlz4
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -93,8 +107,8 @@ dependencies:
|
|
93
107
|
- - "~>"
|
94
108
|
- !ruby/object:Gem::Version
|
95
109
|
version: '0.9'
|
96
|
-
description:
|
97
|
-
serialization format.
|
110
|
+
description: An RDF.rb extension for encoding and decoding RDF knowledge graphs in
|
111
|
+
the Borsh binary serialization format.
|
98
112
|
email: public-rdf-ruby@w3.org
|
99
113
|
executables: []
|
100
114
|
extensions: []
|
@@ -116,7 +130,7 @@ licenses:
|
|
116
130
|
metadata:
|
117
131
|
bug_tracker_uri: https://github.com/ruby-rdf/rdf-borsh/issues
|
118
132
|
changelog_uri: https://github.com/ruby-rdf/rdf-borsh/blob/master/CHANGES.md
|
119
|
-
documentation_uri: https://
|
133
|
+
documentation_uri: https://rubydoc.info/gems/rdf-borsh
|
120
134
|
homepage_uri: https://github.com/ruby-rdf/rdf-borsh
|
121
135
|
source_code_uri: https://github.com/ruby-rdf/rdf-borsh
|
122
136
|
rdoc_options: []
|