borsh 0.1.0
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 +7 -0
- data/AUTHORS +1 -0
- data/CHANGES.md +10 -0
- data/README.md +122 -0
- data/UNLICENSE +24 -0
- data/VERSION +1 -0
- data/lib/borsh/buffer.rb +77 -0
- data/lib/borsh/readable.rb +171 -0
- data/lib/borsh/writable.rb +172 -0
- data/lib/borsh.rb +7 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f889d5e7f96680cfdb852425c23b8053c0c2b9b6c783e8cc2ba5929821091712
|
4
|
+
data.tar.gz: 9fb32d11e1f054a12aa752bf33ee94ff109ca5dae8c0555e28c41bd7c6217201
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e5321fc35e88b65794c7c22670667713f036b0b5a5a6217d72af8142179bc91fa15ef1ba079b22bc07098f81cb9f2c3eea040239723b2a63e10a2ba5dd7eb180
|
7
|
+
data.tar.gz: bb3dcf4db0c101e30450eaee3333745e5ba35829c35f17ee1c778fbde9a79b70673a977a61b7abf630195a1c893c90ed064dd239891d361b958e1ade0cf5557c
|
data/AUTHORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Arto Bendiken <arto@bendiken.net>
|
data/CHANGES.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## 0.1.0 - 2025-01-11
|
9
|
+
|
10
|
+
## 0.0.0 - 2025-01-09
|
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# Borsh for Ruby
|
2
|
+
|
3
|
+
[](https://unlicense.org)
|
4
|
+
[](https://rubygems.org/gems/borsh)
|
5
|
+
[](https://rubygems.org/gems/borsh)
|
6
|
+
|
7
|
+
A Ruby library for the [Borsh] binary serialization format.
|
8
|
+
|
9
|
+
[Borsh]: https://borsh.io
|
10
|
+
|
11
|
+
## 🛠️ Prerequisites
|
12
|
+
|
13
|
+
- [Ruby](https://ruby-lang.org) 2.6+
|
14
|
+
|
15
|
+
## ⬇️ Installation
|
16
|
+
|
17
|
+
### Installation via RubyGems
|
18
|
+
|
19
|
+
```bash
|
20
|
+
gem install borsh
|
21
|
+
```
|
22
|
+
|
23
|
+
## 👉 Examples
|
24
|
+
|
25
|
+
### Importing the library
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'borsh'
|
29
|
+
```
|
30
|
+
|
31
|
+
### Writing to an output stream
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
$stdout.extend(Borsh::Writable)
|
35
|
+
$stdout.write_string("Hello, world!")
|
36
|
+
```
|
37
|
+
|
38
|
+
### Reading from an input stream
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
$stdin.extend(Borsh::Readable)
|
42
|
+
p $stdin.read_string
|
43
|
+
```
|
44
|
+
|
45
|
+
### Writing to an in-memory buffer
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
serialized_data = Borsh::Buffer.open do |buf|
|
49
|
+
# Primitive types:
|
50
|
+
buf.write_bool(true)
|
51
|
+
buf.write_u8(255)
|
52
|
+
buf.write_i32(-12345)
|
53
|
+
buf.write_f64(3.14159)
|
54
|
+
buf.write_string("Hello, Borsh!")
|
55
|
+
|
56
|
+
# Fixed-size array:
|
57
|
+
buf.write_array([1, 2, 3])
|
58
|
+
|
59
|
+
# Dynamic-sized array (array with a length prefix):
|
60
|
+
buf.write_vector(['a', 'b', 'c'])
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
### Reading from an in-memory buffer
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
Borsh::Buffer.new(serialized_data) do |buf|
|
68
|
+
# Primitive types:
|
69
|
+
bool_val = buf.read_bool # => true
|
70
|
+
u8_val = buf.read_u8 # => 255
|
71
|
+
i32_val = buf.read_i32 # => -12345
|
72
|
+
f64_val = buf.read_f64 # => 3.14159
|
73
|
+
string_val = buf.read_string # => "Hello, Borsh!"
|
74
|
+
|
75
|
+
# Fixed-size array:
|
76
|
+
array = buf.read_array(:i32, 3) # => [1, 2, 3]
|
77
|
+
|
78
|
+
# Dynamic-sized array (array with a length prefix):
|
79
|
+
vector = buf.read_vector(:string) # => ['a', 'b', 'c']
|
80
|
+
end
|
81
|
+
```
|
82
|
+
|
83
|
+
## 📚 Reference
|
84
|
+
|
85
|
+
| Informal Type | `Borsh::Writable` | `Borsh::Readable` |
|
86
|
+
| :------------ | :---------------- | :---------------- |
|
87
|
+
| nil/unit | `write_unit()` | `read_unit()` |
|
88
|
+
| boolean | `write_bool(x)` | `read_bool()` |
|
89
|
+
| u8 integer | `write_u8(n)` | `read_u8()` |
|
90
|
+
| u16 integer | `write_u16(n)` | `read_u16()` |
|
91
|
+
| u32 integer | `write_u32(n)` | `read_u32()` |
|
92
|
+
| u64 integer | `write_u64(n)` | `read_u64()` |
|
93
|
+
| u128 integer | `write_u128(n)` | `read_u128()` |
|
94
|
+
| i8 integer | `write_i8(n)` | `read_i8()` |
|
95
|
+
| i16 integer | `write_i16(n)` | `read_i16()` |
|
96
|
+
| i32 integer | `write_i32(n)` | `read_i32()` |
|
97
|
+
| i64 integer | `write_i64(n)` | `read_i64()` |
|
98
|
+
| i128 integer | `write_i128(n)` | `read_i128()` |
|
99
|
+
| f32 float | `write_f32(f)` | `read_f32()` |
|
100
|
+
| f64 float | `write_f64(f)` | `read_f64()` |
|
101
|
+
| string | `write_string(x)` | `read_string()` |
|
102
|
+
| array | `write_array(x)` | `read_array(element_type, count)` |
|
103
|
+
| vector | `write_vector(x)` | `read_vector(element_type)` |
|
104
|
+
| struct | `write_struct(x)` | `read_struct(struct_class)` |
|
105
|
+
| enum | `write_enum(x)` | `read_enum(variants)` |
|
106
|
+
| map/hash | `write_map(x)` | `read_map(key_type, value_type)` |
|
107
|
+
| set | `write_set(x)` | `read_set(element_type)` |
|
108
|
+
| option | `write_option(x)` | `read_option(element_type)` |
|
109
|
+
| result | `write_result(x)` | `read_result(ok_type, err_type)` |
|
110
|
+
|
111
|
+
## 👨💻 Development
|
112
|
+
|
113
|
+
```bash
|
114
|
+
git clone https://github.com/dryruby/borsh.rb.git
|
115
|
+
```
|
116
|
+
|
117
|
+
- - -
|
118
|
+
|
119
|
+
[](https://twitter.com/share?url=https://github.com/dryruby/borsh.rb&text=Borsh+for+Ruby)
|
120
|
+
[](https://reddit.com/submit?url=https://github.com/dryruby/borsh.rb&title=Borsh+for+Ruby)
|
121
|
+
[](https://news.ycombinator.com/submitlink?u=https://github.com/dryruby/borsh.rb&t=Borsh+for+Ruby)
|
122
|
+
[](https://www.facebook.com/sharer/sharer.php?u=https://github.com/dryruby/borsh.rb)
|
data/UNLICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
4
|
+
distribute this software, either in source code form or as a compiled
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
6
|
+
means.
|
7
|
+
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
9
|
+
of this software dedicate any and all copyright interest in the
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
11
|
+
of the public at large and to the detriment of our heirs and
|
12
|
+
successors. We intend this dedication to be an overt act of
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
14
|
+
software under copyright law.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
For more information, please refer to <https://unlicense.org/>
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/borsh/buffer.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require_relative 'readable'
|
5
|
+
require_relative 'writable'
|
6
|
+
|
7
|
+
##
|
8
|
+
# A buffer for reading and writing Borsh data.
|
9
|
+
class Borsh::Buffer
|
10
|
+
include Borsh::Readable
|
11
|
+
include Borsh::Writable
|
12
|
+
|
13
|
+
##
|
14
|
+
# @param [String, nil] data
|
15
|
+
# @yield [buffer]
|
16
|
+
# @yieldreturn [Object]
|
17
|
+
# @return [String]
|
18
|
+
def self.open(data = nil, &block)
|
19
|
+
buffer = self.new(data || '', &block)
|
20
|
+
buffer.close
|
21
|
+
buffer.data
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# @param [String] data
|
26
|
+
# @yield [buffer]
|
27
|
+
# @yieldreturn [void]
|
28
|
+
# @return [void]
|
29
|
+
def initialize(data = '', &block)
|
30
|
+
@buffer = StringIO.new(data)
|
31
|
+
@buffer.binmode
|
32
|
+
block.call(self) if block_given?
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Returns the buffer data.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
def data
|
40
|
+
@buffer.string
|
41
|
+
end
|
42
|
+
alias_method :string, :data
|
43
|
+
|
44
|
+
##
|
45
|
+
# Returns `true` if the buffer is closed.
|
46
|
+
#
|
47
|
+
# @return [Boolean]
|
48
|
+
def closed?
|
49
|
+
@buffer.closed?
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Closes the buffer.
|
54
|
+
#
|
55
|
+
# @return [void]
|
56
|
+
def close;
|
57
|
+
@buffer.close
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Reads the specified number of bytes from the buffer.
|
62
|
+
#
|
63
|
+
# @param [Integer, #to_i] length
|
64
|
+
# @return [String]
|
65
|
+
def read(length)
|
66
|
+
@buffer.read(length.to_i)
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Writes data to the buffer.
|
71
|
+
#
|
72
|
+
# @param [String, #to_s] data
|
73
|
+
# @return [Integer]
|
74
|
+
def write(data)
|
75
|
+
@buffer.write(data.to_s)
|
76
|
+
end
|
77
|
+
end # Borsh::Buffer
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Borsh::Readable
|
6
|
+
def read_object(type)
|
7
|
+
case type
|
8
|
+
when :nil then self.read_unit
|
9
|
+
when :bool then self.read_bool
|
10
|
+
when :u8 then self.read_u8
|
11
|
+
when :u16 then self.read_u16
|
12
|
+
when :u32 then self.read_u32
|
13
|
+
when :u64 then self.read_u64
|
14
|
+
when :u128 then self.read_u128
|
15
|
+
when :i8 then self.read_i8
|
16
|
+
when :i16 then self.read_i16
|
17
|
+
when :i32 then self.read_i32
|
18
|
+
when :i64 then self.read_i64
|
19
|
+
when :i128 then self.read_i128
|
20
|
+
when :f32 then self.read_f32
|
21
|
+
when :f64 then self.read_f64
|
22
|
+
when :string then self.read_string
|
23
|
+
when Array
|
24
|
+
case type.first
|
25
|
+
when :array then self.read_array(type[1], type[2])
|
26
|
+
when :vector then self.read_vector(type[1])
|
27
|
+
when :map then self.read_map(type[1], type[2])
|
28
|
+
when :set then self.read_set(type[1])
|
29
|
+
when :option then self.read_option(type[1])
|
30
|
+
when :result then self.read_result(type[1], type[2])
|
31
|
+
else raise "unsupported array type specifier: #{type.inspect}"
|
32
|
+
end
|
33
|
+
when Class
|
34
|
+
raise "unsupported class type: #{type}" unless type < Struct
|
35
|
+
self.read_struct(type)
|
36
|
+
else raise "unsupported type specifier: #{type.inspect}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def read_unit
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
alias_method :read_nil, :read_unit
|
44
|
+
|
45
|
+
def read_bool
|
46
|
+
self.read_u8 == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
def read_u8
|
50
|
+
self.read(1).unpack('C').first
|
51
|
+
end
|
52
|
+
|
53
|
+
def read_u16
|
54
|
+
self.read(2).unpack('v').first
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_u32
|
58
|
+
self.read(4).unpack('V').first
|
59
|
+
end
|
60
|
+
|
61
|
+
def read_u64
|
62
|
+
self.read(8).unpack('Q<').first
|
63
|
+
end
|
64
|
+
|
65
|
+
def read_u128
|
66
|
+
# Read two 64-bit integers (little-endian):
|
67
|
+
lower = self.read_u64
|
68
|
+
upper = self.read_u64
|
69
|
+
# Combine into a 128-bit number:
|
70
|
+
(upper << 64) | lower
|
71
|
+
end
|
72
|
+
|
73
|
+
def read_i8
|
74
|
+
self.read(1).unpack('c').first
|
75
|
+
end
|
76
|
+
|
77
|
+
def read_i16
|
78
|
+
self.read(2).unpack('s').first
|
79
|
+
end
|
80
|
+
|
81
|
+
def read_i32
|
82
|
+
self.read(4).unpack('l<').first
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_i64
|
86
|
+
self.read(8).unpack('q<').first
|
87
|
+
end
|
88
|
+
|
89
|
+
def read_i128
|
90
|
+
n = self.read_u128
|
91
|
+
# Handle two's complement for negative numbers:
|
92
|
+
if n >= (1 << 127)
|
93
|
+
n - (1 << 128)
|
94
|
+
else
|
95
|
+
n
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def read_f32
|
100
|
+
self.read(4).unpack('e').first
|
101
|
+
end
|
102
|
+
|
103
|
+
def read_f64
|
104
|
+
self.read(8).unpack('E').first
|
105
|
+
end
|
106
|
+
|
107
|
+
def read_string
|
108
|
+
self.read(self.read_u32)
|
109
|
+
end
|
110
|
+
|
111
|
+
def read_array(element_type, count)
|
112
|
+
Array.new(count) { self.read_object(element_type) }
|
113
|
+
end
|
114
|
+
|
115
|
+
def read_vector(element_type)
|
116
|
+
count = self.read_u32
|
117
|
+
self.read_array(element_type, count)
|
118
|
+
end
|
119
|
+
alias_method :read_vec, :read_vector
|
120
|
+
|
121
|
+
def read_struct(struct_class)
|
122
|
+
values = struct_class.members.map { |member|
|
123
|
+
type = struct_class::MEMBER_TYPES.fetch(member)
|
124
|
+
self.read_object(type)
|
125
|
+
}
|
126
|
+
struct_class.new(*values)
|
127
|
+
end
|
128
|
+
|
129
|
+
def read_enum(variants)
|
130
|
+
ordinal = self.read_u8
|
131
|
+
type = variants.fetch(ordinal)
|
132
|
+
value = self.read_object(type)
|
133
|
+
[ordinal, value]
|
134
|
+
end
|
135
|
+
|
136
|
+
def read_map(key_type, value_type)
|
137
|
+
count = self.read_u32
|
138
|
+
result = {}
|
139
|
+
count.times do
|
140
|
+
key = self.read_object(key_type)
|
141
|
+
value = self.read_object(value_type)
|
142
|
+
result[key] = value
|
143
|
+
end
|
144
|
+
result
|
145
|
+
end
|
146
|
+
alias_method :read_hash, :read_map
|
147
|
+
|
148
|
+
def read_set(element_type)
|
149
|
+
count = self.read_u32
|
150
|
+
result = Set.new
|
151
|
+
count.times do
|
152
|
+
result << self.read_object(element_type)
|
153
|
+
end
|
154
|
+
result
|
155
|
+
end
|
156
|
+
|
157
|
+
def read_option(element_type)
|
158
|
+
if self.read_bool
|
159
|
+
self.read_object(element_type)
|
160
|
+
else
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def read_result(ok_type, err_type)
|
166
|
+
ok = self.read_bool
|
167
|
+
type = ok ? ok_type : err_type
|
168
|
+
value = self.read_object(type)
|
169
|
+
[ok, value]
|
170
|
+
end
|
171
|
+
end # Borsh::Readable
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Borsh::Writable
|
6
|
+
def write_object(x)
|
7
|
+
x = x.to_borsh if x.respond_to?(:to_borsh)
|
8
|
+
case x
|
9
|
+
when NilClass then self.write_unit()
|
10
|
+
when FalseClass then self.write_bool(x)
|
11
|
+
when TrueClass then self.write_bool(x)
|
12
|
+
when Integer then self.write_i64(x)
|
13
|
+
when Float then self.write_f64(x)
|
14
|
+
when String then self.write_string(x)
|
15
|
+
when Array then self.write_vector(x)
|
16
|
+
when Hash then self.write_map(x)
|
17
|
+
when Set then self.write_set(x)
|
18
|
+
else raise "unsupported type: #{x.class}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def write_unit()
|
23
|
+
# nothing to write
|
24
|
+
end
|
25
|
+
alias_method :write_nil, :write_unit
|
26
|
+
|
27
|
+
def write_bool(x)
|
28
|
+
self.write_u8(x ? 1 : 0)
|
29
|
+
end
|
30
|
+
|
31
|
+
def write_u8(n)
|
32
|
+
self.write([n].pack('C'))
|
33
|
+
end
|
34
|
+
|
35
|
+
def write_u16(n)
|
36
|
+
self.write([n].pack('v'))
|
37
|
+
end
|
38
|
+
|
39
|
+
def write_u32(n)
|
40
|
+
self.write([n].pack('V'))
|
41
|
+
end
|
42
|
+
|
43
|
+
def write_u64(n)
|
44
|
+
self.write([n].pack('Q<'))
|
45
|
+
end
|
46
|
+
|
47
|
+
def write_u128(n)
|
48
|
+
# Split 128-bit number into two 64-bit parts:
|
49
|
+
lower = n & ((1 << 64) - 1)
|
50
|
+
upper = (n >> 64) & ((1 << 64) - 1)
|
51
|
+
# Write the lower 64 bits first (little-endian):
|
52
|
+
self.write_u64(lower)
|
53
|
+
# Then write the upper 64 bits:
|
54
|
+
self.write_u64(upper)
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_i8(n)
|
58
|
+
self.write([n].pack('c'))
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_i16(n)
|
62
|
+
self.write([n].pack('s'))
|
63
|
+
end
|
64
|
+
|
65
|
+
def write_i32(n)
|
66
|
+
self.write([n].pack('l<'))
|
67
|
+
end
|
68
|
+
|
69
|
+
def write_i64(n)
|
70
|
+
self.write([n].pack('q<'))
|
71
|
+
end
|
72
|
+
|
73
|
+
def write_i128(n)
|
74
|
+
# Convert negative numbers to two's complement:
|
75
|
+
n = (1 << 128) + n if n < 0
|
76
|
+
# Use `#write_u128` to write the bits:
|
77
|
+
self.write_u128(n)
|
78
|
+
end
|
79
|
+
|
80
|
+
def write_f32(f)
|
81
|
+
self.write([f].pack('e'))
|
82
|
+
end
|
83
|
+
|
84
|
+
def write_f64(f)
|
85
|
+
self.write([f].pack('E'))
|
86
|
+
end
|
87
|
+
|
88
|
+
def write_string(x)
|
89
|
+
self.write_u32(x.bytesize)
|
90
|
+
self.write(x)
|
91
|
+
end
|
92
|
+
|
93
|
+
def write_array(x)
|
94
|
+
x.each { |e| self.write_object(e) }
|
95
|
+
end
|
96
|
+
|
97
|
+
def write_vector(x)
|
98
|
+
self.write_u32(x.size)
|
99
|
+
x.each { |e| self.write_object(e) }
|
100
|
+
end
|
101
|
+
alias_method :write_vec, :write_vector
|
102
|
+
|
103
|
+
def write_struct(x)
|
104
|
+
raise "value must be a Struct" unless x.is_a?(Struct)
|
105
|
+
|
106
|
+
x.members.each do |k|
|
107
|
+
self.write_object(x[k])
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def write_enum(x)
|
112
|
+
# An enum should be represented as `[ordinal, value]`:
|
113
|
+
unless x.is_a?(Array) && x.size == 2 && x[0].is_a?(Integer)
|
114
|
+
raise "enum must be [ordinal, value]"
|
115
|
+
end
|
116
|
+
|
117
|
+
ordinal, value = x
|
118
|
+
self.write_u8(ordinal)
|
119
|
+
self.write_object(value)
|
120
|
+
end
|
121
|
+
|
122
|
+
def write_map(x)
|
123
|
+
self.write_u32(x.size)
|
124
|
+
case x
|
125
|
+
when Array
|
126
|
+
x.sort.each do |(k, v)|
|
127
|
+
self.write_object(k)
|
128
|
+
self.write_object(v)
|
129
|
+
end
|
130
|
+
when Hash
|
131
|
+
x.keys.sort.each do |k|
|
132
|
+
self.write_object(k)
|
133
|
+
self.write_object(x[k])
|
134
|
+
end
|
135
|
+
else raise "unsupported type: #{x.class}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
alias_method :write_hash, :write_map
|
139
|
+
|
140
|
+
def write_set(x)
|
141
|
+
self.write_u32(x.size)
|
142
|
+
keys = case x
|
143
|
+
when Array then x
|
144
|
+
when Hash then x.keys
|
145
|
+
when Set then x.to_a
|
146
|
+
else raise "unsupported type: #{x.class}"
|
147
|
+
end
|
148
|
+
keys.sort.each do |k|
|
149
|
+
self.write_object(k)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def write_option(x)
|
154
|
+
if !x.nil?
|
155
|
+
self.write_u8(1)
|
156
|
+
self.write_object(x)
|
157
|
+
else
|
158
|
+
self.write_u8(0)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def write_result(x)
|
163
|
+
# A result should be represented as `[ok, value]`:
|
164
|
+
unless x.is_a?(Array) && x.size == 2
|
165
|
+
raise "result must be [ok, value]"
|
166
|
+
end
|
167
|
+
|
168
|
+
ok, value = x
|
169
|
+
self.write_u8(ok ? 1 : 0)
|
170
|
+
self.write_object(value)
|
171
|
+
end
|
172
|
+
end # Borsh::Writable
|
data/lib/borsh.rb
ADDED
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: borsh
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Arto Bendiken
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2025-01-11 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: rspec
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '3.12'
|
19
|
+
type: :development
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '3.12'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: yard
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.9'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.9'
|
40
|
+
description: A Ruby library for the Borsh binary serialization format.
|
41
|
+
email: arto@bendiken.net
|
42
|
+
executables: []
|
43
|
+
extensions: []
|
44
|
+
extra_rdoc_files: []
|
45
|
+
files:
|
46
|
+
- AUTHORS
|
47
|
+
- CHANGES.md
|
48
|
+
- README.md
|
49
|
+
- UNLICENSE
|
50
|
+
- VERSION
|
51
|
+
- lib/borsh.rb
|
52
|
+
- lib/borsh/buffer.rb
|
53
|
+
- lib/borsh/readable.rb
|
54
|
+
- lib/borsh/writable.rb
|
55
|
+
homepage: https://github.com/dryruby/borsh.rb
|
56
|
+
licenses:
|
57
|
+
- Unlicense
|
58
|
+
metadata:
|
59
|
+
bug_tracker_uri: https://github.com/dryruby/borsh.rb/issues
|
60
|
+
changelog_uri: https://github.com/dryruby/borsh.rb/blob/master/CHANGES.md
|
61
|
+
documentation_uri: https://github.com/dryruby/borsh.rb/blob/master/README.md
|
62
|
+
homepage_uri: https://github.com/dryruby/borsh.rb
|
63
|
+
source_code_uri: https://github.com/dryruby/borsh.rb
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '2.6'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubygems_version: 3.6.2
|
79
|
+
specification_version: 4
|
80
|
+
summary: Borsh for Ruby
|
81
|
+
test_files: []
|