unibuf 0.1.1 → 0.1.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +170 -200
  3. data/CODE_OF_CONDUCT.md +132 -0
  4. data/README.adoc +306 -114
  5. data/docs/CAPNPROTO.adoc +436 -0
  6. data/docs/FLATBUFFERS.adoc +430 -0
  7. data/docs/PROTOBUF.adoc +515 -0
  8. data/docs/TXTPROTO.adoc +369 -0
  9. data/lib/unibuf/commands/convert.rb +60 -2
  10. data/lib/unibuf/commands/schema.rb +68 -11
  11. data/lib/unibuf/errors.rb +23 -26
  12. data/lib/unibuf/models/capnproto/enum_definition.rb +72 -0
  13. data/lib/unibuf/models/capnproto/field_definition.rb +81 -0
  14. data/lib/unibuf/models/capnproto/interface_definition.rb +70 -0
  15. data/lib/unibuf/models/capnproto/method_definition.rb +81 -0
  16. data/lib/unibuf/models/capnproto/schema.rb +84 -0
  17. data/lib/unibuf/models/capnproto/struct_definition.rb +96 -0
  18. data/lib/unibuf/models/capnproto/union_definition.rb +62 -0
  19. data/lib/unibuf/models/flatbuffers/enum_definition.rb +69 -0
  20. data/lib/unibuf/models/flatbuffers/field_definition.rb +88 -0
  21. data/lib/unibuf/models/flatbuffers/schema.rb +102 -0
  22. data/lib/unibuf/models/flatbuffers/struct_definition.rb +70 -0
  23. data/lib/unibuf/models/flatbuffers/table_definition.rb +73 -0
  24. data/lib/unibuf/models/flatbuffers/union_definition.rb +60 -0
  25. data/lib/unibuf/models/message.rb +10 -0
  26. data/lib/unibuf/parsers/capnproto/binary_parser.rb +267 -0
  27. data/lib/unibuf/parsers/capnproto/grammar.rb +272 -0
  28. data/lib/unibuf/parsers/capnproto/list_reader.rb +208 -0
  29. data/lib/unibuf/parsers/capnproto/pointer_decoder.rb +163 -0
  30. data/lib/unibuf/parsers/capnproto/processor.rb +348 -0
  31. data/lib/unibuf/parsers/capnproto/segment_reader.rb +131 -0
  32. data/lib/unibuf/parsers/capnproto/struct_reader.rb +199 -0
  33. data/lib/unibuf/parsers/flatbuffers/binary_parser.rb +325 -0
  34. data/lib/unibuf/parsers/flatbuffers/grammar.rb +235 -0
  35. data/lib/unibuf/parsers/flatbuffers/processor.rb +299 -0
  36. data/lib/unibuf/serializers/binary_serializer.rb +218 -0
  37. data/lib/unibuf/serializers/capnproto/binary_serializer.rb +402 -0
  38. data/lib/unibuf/serializers/capnproto/list_writer.rb +199 -0
  39. data/lib/unibuf/serializers/capnproto/pointer_encoder.rb +118 -0
  40. data/lib/unibuf/serializers/capnproto/segment_builder.rb +124 -0
  41. data/lib/unibuf/serializers/capnproto/struct_writer.rb +139 -0
  42. data/lib/unibuf/serializers/flatbuffers/binary_serializer.rb +167 -0
  43. data/lib/unibuf/version.rb +1 -1
  44. data/lib/unibuf.rb +27 -0
  45. metadata +36 -1
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unibuf
4
+ module Serializers
5
+ module Capnproto
6
+ # Encoder for Cap'n Proto pointer words
7
+ # Encodes pointer information into 64-bit words
8
+ class PointerEncoder
9
+ # Pointer type constants (bits 0-1)
10
+ POINTER_TYPE_STRUCT = 0
11
+ POINTER_TYPE_LIST = 1
12
+ POINTER_TYPE_FAR = 2
13
+ POINTER_TYPE_OTHER = 3
14
+
15
+ # List element size constants
16
+ ELEMENT_SIZE_VOID = 0
17
+ ELEMENT_SIZE_BIT = 1
18
+ ELEMENT_SIZE_BYTE = 2
19
+ ELEMENT_SIZE_TWO_BYTES = 3
20
+ ELEMENT_SIZE_FOUR_BYTES = 4
21
+ ELEMENT_SIZE_EIGHT_BYTES = 5
22
+ ELEMENT_SIZE_POINTER = 6
23
+ ELEMENT_SIZE_INLINE_COMPOSITE = 7
24
+
25
+ class << self
26
+ # Encode a null pointer
27
+ # @return [Integer] 64-bit word
28
+ def encode_null
29
+ 0
30
+ end
31
+
32
+ # Encode a struct pointer
33
+ # @param offset [Integer] Signed word offset (relative to pointer position)
34
+ # @param data_words [Integer] Number of data words
35
+ # @param pointer_words [Integer] Number of pointer words
36
+ # @return [Integer] 64-bit pointer word
37
+ def encode_struct(offset, data_words, pointer_words)
38
+ # Bits: [pointer_words:16][data_words:16][offset:30][type:2]
39
+
40
+ # Convert signed offset to 30-bit representation
41
+ offset_bits = offset & 0x3FFFFFFF
42
+
43
+ word = POINTER_TYPE_STRUCT |
44
+ (offset_bits << 2) |
45
+ (data_words << 32) |
46
+ (pointer_words << 48)
47
+
48
+ word & 0xFFFFFFFFFFFFFFFF
49
+ end
50
+
51
+ # Encode a list pointer
52
+ # @param offset [Integer] Signed word offset
53
+ # @param element_size [Integer] Element size code (0-7)
54
+ # @param element_count [Integer] Number of elements
55
+ # @return [Integer] 64-bit pointer word
56
+ def encode_list(offset, element_size, element_count)
57
+ # Bits: [element_count:29][element_size:3][offset:30][type:2]
58
+
59
+ # Convert signed offset to 30-bit representation
60
+ offset_bits = offset & 0x3FFFFFFF
61
+
62
+ word = POINTER_TYPE_LIST |
63
+ (offset_bits << 2) |
64
+ (element_size << 32) |
65
+ (element_count << 35)
66
+
67
+ word & 0xFFFFFFFFFFFFFFFF
68
+ end
69
+
70
+ # Encode a far pointer
71
+ # @param segment_id [Integer] Target segment ID
72
+ # @param offset [Integer] Word offset within target segment
73
+ # @param double_far [Boolean] Landing pad flag
74
+ # @return [Integer] 64-bit pointer word
75
+ def encode_far(segment_id, offset, double_far: false)
76
+ # Bits: [segment_id:32][offset:29][double_far:1][type:2]
77
+
78
+ double_far_bit = double_far ? 1 : 0
79
+
80
+ word = POINTER_TYPE_FAR |
81
+ (double_far_bit << 2) |
82
+ (offset << 3) |
83
+ (segment_id << 32)
84
+
85
+ word & 0xFFFFFFFFFFFFFFFF
86
+ end
87
+
88
+ # Encode a capability pointer
89
+ # @param index [Integer] Capability index
90
+ # @return [Integer] 64-bit pointer word
91
+ def encode_capability(index)
92
+ # Bits: [index:32][reserved:30][type:2]
93
+
94
+ word = POINTER_TYPE_OTHER |
95
+ (index << 32)
96
+
97
+ word & 0xFFFFFFFFFFFFFFFF
98
+ end
99
+
100
+ # Get element size code for a type
101
+ # @param type_name [String, Symbol] Type name
102
+ # @return [Integer] Element size code
103
+ def element_size_for_type(type_name)
104
+ case type_name.to_s
105
+ when "Void" then ELEMENT_SIZE_VOID
106
+ when "Bool" then ELEMENT_SIZE_BIT
107
+ when "Int8", "UInt8" then ELEMENT_SIZE_BYTE
108
+ when "Int16", "UInt16" then ELEMENT_SIZE_TWO_BYTES
109
+ when "Int32", "UInt32", "Float32" then ELEMENT_SIZE_FOUR_BYTES
110
+ when "Int64", "UInt64", "Float64" then ELEMENT_SIZE_EIGHT_BYTES
111
+ else ELEMENT_SIZE_POINTER # For user types and Text/Data
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unibuf
4
+ module Serializers
5
+ module Capnproto
6
+ # Builder for Cap'n Proto binary segments
7
+ # Manages segment allocation and word-aligned writes
8
+ class SegmentBuilder
9
+ WORD_SIZE = 8 # Cap'n Proto uses 8-byte words
10
+
11
+ attr_reader :segments
12
+
13
+ def initialize
14
+ @segments = []
15
+ @current_segment = []
16
+ @current_segment_id = 0
17
+ end
18
+
19
+ # Get all segments including current
20
+ def segments
21
+ if @current_segment.empty?
22
+ @segments
23
+ else
24
+ @segments + [@current_segment]
25
+ end
26
+ end
27
+
28
+ # Allocate words in current segment
29
+ # @param word_count [Integer] Number of words to allocate
30
+ # @return [Array<Integer>] [segment_id, word_offset]
31
+ def allocate(word_count)
32
+ segment_id = @current_segment_id
33
+ word_offset = @current_segment.length
34
+
35
+ # Add placeholder words
36
+ word_count.times { @current_segment << 0 }
37
+
38
+ [segment_id, word_offset]
39
+ end
40
+
41
+ # Write a word at specific location
42
+ # @param segment_id [Integer] Segment index
43
+ # @param word_offset [Integer] Word offset within segment
44
+ # @param value [Integer] 64-bit word value
45
+ def write_word(segment_id, word_offset, value)
46
+ if segment_id == @current_segment_id
47
+ # Writing to current segment
48
+ @current_segment[word_offset] = value & 0xFFFFFFFFFFFFFFFF
49
+ elsif segment_id < @segments.length
50
+ # Writing to finalized segment
51
+ @segments[segment_id][word_offset] = value & 0xFFFFFFFFFFFFFFFF
52
+ else
53
+ raise "Invalid segment ID: #{segment_id}"
54
+ end
55
+ end
56
+
57
+ # Write multiple words
58
+ # @param segment_id [Integer] Segment index
59
+ # @param word_offset [Integer] Starting word offset
60
+ # @param values [Array<Integer>] Word values
61
+ def write_words(segment_id, word_offset, values)
62
+ values.each_with_index do |value, i|
63
+ write_word(segment_id, word_offset + i, value)
64
+ end
65
+ end
66
+
67
+ # Finalize current segment and start a new one
68
+ def finalize_segment
69
+ @segments << @current_segment unless @current_segment.empty?
70
+ @current_segment = []
71
+ @current_segment_id = @segments.length
72
+ end
73
+
74
+ # Build final binary output
75
+ # @return [String] Binary data
76
+ def build
77
+ # Finalize current segment if not empty
78
+ finalize_segment unless @current_segment.empty?
79
+
80
+ return "" if @segments.empty?
81
+
82
+ # Build segment table
83
+ segment_count = @segments.length
84
+ segment_sizes = @segments.map(&:length)
85
+
86
+ # Segment table header
87
+ output = [segment_count - 1].pack("L<") # segment count - 1
88
+
89
+ # Segment sizes
90
+ segment_sizes.each do |size|
91
+ output += [size].pack("L<")
92
+ end
93
+
94
+ # Add padding if needed (when segment count is even)
95
+ output += [0].pack("L<") unless segment_count.odd?
96
+
97
+ # Write segment data
98
+ @segments.each do |segment|
99
+ segment.each do |word|
100
+ output += [word].pack("Q<")
101
+ end
102
+ end
103
+
104
+ output
105
+ end
106
+
107
+ # Get current position for relative offset calculation
108
+ # @return [Array<Integer>] [segment_id, word_offset]
109
+ def current_position
110
+ [@current_segment_id, @current_segment.length]
111
+ end
112
+
113
+ private
114
+
115
+ def ensure_segment(segment_id)
116
+ return if segment_id == @current_segment_id
117
+ return if segment_id < @segments.length
118
+
119
+ raise "Invalid segment ID: #{segment_id}"
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "segment_builder"
4
+ require_relative "pointer_encoder"
5
+
6
+ module Unibuf
7
+ module Serializers
8
+ module Capnproto
9
+ # Writer for Cap'n Proto struct data
10
+ # Writes data section (primitives) and pointer section (references)
11
+ class StructWriter
12
+ attr_reader :segment_builder, :segment_id, :word_offset, :data_words,
13
+ :pointer_words
14
+
15
+ # Initialize struct writer
16
+ # @param segment_builder [SegmentBuilder] Segment builder
17
+ # @param segment_id [Integer] Segment ID
18
+ # @param word_offset [Integer] Word offset in segment
19
+ # @param data_words [Integer] Number of data words
20
+ # @param pointer_words [Integer] Number of pointer words
21
+ def initialize(segment_builder, segment_id, word_offset, data_words,
22
+ pointer_words)
23
+ @segment_builder = segment_builder
24
+ @segment_id = segment_id
25
+ @word_offset = word_offset
26
+ @data_words = data_words
27
+ @pointer_words = pointer_words
28
+ end
29
+
30
+ # Write a primitive value to data section
31
+ # @param word_index [Integer] Word index in data section
32
+ # @param bit_offset [Integer] Bit offset within word (0-63)
33
+ # @param bit_width [Integer] Width in bits
34
+ # @param value [Integer] Value to write
35
+ def write_data_field(word_index, bit_offset, bit_width, value)
36
+ return if word_index >= @data_words
37
+
38
+ # Read current word
39
+ all_segments = @segment_builder.segments
40
+ current = if @segment_id < all_segments.length
41
+ all_segments[@segment_id][@word_offset + word_index] || 0
42
+ else
43
+ 0
44
+ end
45
+
46
+ # Create mask and insert value
47
+ mask = ((1 << bit_width) - 1) << bit_offset
48
+ cleared = current & ~mask
49
+ new_value = cleared | ((value << bit_offset) & mask)
50
+
51
+ @segment_builder.write_word(@segment_id, @word_offset + word_index,
52
+ new_value)
53
+ end
54
+
55
+ # Write unsigned 8-bit integer
56
+ def write_uint8(word_index, byte_offset, value)
57
+ write_data_field(word_index, byte_offset * 8, 8, value & 0xFF)
58
+ end
59
+
60
+ # Write signed 8-bit integer
61
+ def write_int8(word_index, byte_offset, value)
62
+ unsigned = value.negative? ? value + 256 : value
63
+ write_uint8(word_index, byte_offset, unsigned)
64
+ end
65
+
66
+ # Write unsigned 16-bit integer
67
+ def write_uint16(word_index, half_word_offset, value)
68
+ write_data_field(word_index, half_word_offset * 16, 16,
69
+ value & 0xFFFF)
70
+ end
71
+
72
+ # Write signed 16-bit integer
73
+ def write_int16(word_index, half_word_offset, value)
74
+ unsigned = value.negative? ? value + 65536 : value
75
+ write_uint16(word_index, half_word_offset, unsigned)
76
+ end
77
+
78
+ # Write unsigned 32-bit integer
79
+ def write_uint32(word_index, dword_offset, value)
80
+ write_data_field(word_index, dword_offset * 32, 32,
81
+ value & 0xFFFFFFFF)
82
+ end
83
+
84
+ # Write signed 32-bit integer
85
+ def write_int32(word_index, dword_offset, value)
86
+ unsigned = value.negative? ? value + 4294967296 : value
87
+ write_uint32(word_index, dword_offset, unsigned)
88
+ end
89
+
90
+ # Write unsigned 64-bit integer
91
+ def write_uint64(word_index, value)
92
+ @segment_builder.write_word(@segment_id, @word_offset + word_index,
93
+ value & 0xFFFFFFFFFFFFFFFF)
94
+ end
95
+
96
+ # Write signed 64-bit integer
97
+ def write_int64(word_index, value)
98
+ unsigned = value.negative? ? value + 18446744073709551616 : value
99
+ write_uint64(word_index, unsigned)
100
+ end
101
+
102
+ # Write 32-bit float
103
+ def write_float32(word_index, dword_offset, value)
104
+ bits = [value].pack("f").unpack1("L")
105
+ write_uint32(word_index, dword_offset, bits)
106
+ end
107
+
108
+ # Write 64-bit float
109
+ def write_float64(word_index, value)
110
+ bits = [value].pack("d").unpack1("Q")
111
+ write_uint64(word_index, bits)
112
+ end
113
+
114
+ # Write boolean
115
+ def write_bool(word_index, bit_offset, value)
116
+ write_data_field(word_index, bit_offset, 1, value ? 1 : 0)
117
+ end
118
+
119
+ # Write a pointer to pointer section
120
+ # @param pointer_index [Integer] Pointer index in pointer section
121
+ # @param pointer_word [Integer] Encoded pointer word
122
+ def write_pointer(pointer_index, pointer_word)
123
+ return if pointer_index >= @pointer_words
124
+
125
+ pointer_word_offset = @word_offset + @data_words + pointer_index
126
+ @segment_builder.write_word(@segment_id, pointer_word_offset,
127
+ pointer_word)
128
+ end
129
+
130
+ # Get pointer position for offset calculations
131
+ # @param pointer_index [Integer] Pointer index
132
+ # @return [Integer] Absolute word offset of pointer
133
+ def pointer_position(pointer_index)
134
+ @word_offset + @data_words + pointer_index
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unibuf
4
+ module Serializers
5
+ module Flatbuffers
6
+ # FlatBuffers binary format serializer - Pure Ruby
7
+ class BinarySerializer
8
+ attr_reader :schema
9
+
10
+ def initialize(schema)
11
+ @schema = schema
12
+ end
13
+
14
+ def serialize(data)
15
+ raise ArgumentError, "Data cannot be nil" if data.nil?
16
+
17
+ root_table_def = schema.find_table(schema.root_type)
18
+ unless root_table_def
19
+ raise Unibuf::SerializationError,
20
+ "Root type '#{schema.root_type}' not found in schema"
21
+ end
22
+
23
+ # Manual buffer construction
24
+ []
25
+
26
+ # Serialize table and collect parts
27
+ table_parts = serialize_table(data, root_table_def)
28
+
29
+ # Calculate positions
30
+ root_offset = 4 # After root offset itself
31
+
32
+ # Build final buffer
33
+ buffer = [root_offset].pack("L<") # Root offset
34
+ buffer += table_parts.pack("C*")
35
+
36
+ buffer
37
+ end
38
+
39
+ def serialize_to_file(data, path)
40
+ File.binwrite(path, serialize(data))
41
+ end
42
+
43
+ private
44
+
45
+ def serialize_table(data, table_def)
46
+ # PHASE 1: Write strings (out-of-line data)
47
+ string_data = {}
48
+ string_bytes_total = []
49
+
50
+ table_def.fields.each do |field_def|
51
+ value = data[field_def.name]
52
+ next unless value && field_def.type == "string"
53
+
54
+ # Serialize string
55
+ str_bytes = []
56
+ str_bytes.concat([value.bytesize].pack("L<").bytes) # length
57
+ str_bytes.concat(value.bytes) # content
58
+ str_bytes << 0 # null terminator
59
+
60
+ # Align to 4
61
+ while (str_bytes.size % 4) != 0
62
+ str_bytes << 0
63
+ end
64
+
65
+ string_data[field_def.name] = {
66
+ bytes: str_bytes,
67
+ start_in_string_section: string_bytes_total.size,
68
+ }
69
+ string_bytes_total.concat(str_bytes)
70
+ end
71
+
72
+ # PHASE 2: Build table
73
+ table_bytes = []
74
+
75
+ # Reserve vtable offset
76
+ table_bytes.push(0, 0, 0, 0)
77
+
78
+ # Calculate vtable size
79
+ vtable_size = 4 + (table_def.fields.size * 2)
80
+
81
+ # Write fields
82
+ field_offsets = []
83
+ current_pos = 4 # Start after vtable offset
84
+
85
+ table_def.fields.each do |field_def|
86
+ value = data[field_def.name]
87
+
88
+ if value.nil?
89
+ field_offsets << 0
90
+ elsif field_def.scalar?
91
+ field_offsets << current_pos
92
+ # Write scalar value
93
+ case field_def.type
94
+ when "byte"
95
+ table_bytes.concat([value].pack("c").bytes)
96
+ current_pos += 1
97
+ when "ubyte", "bool"
98
+ val = if value.is_a?(TrueClass)
99
+ 1
100
+ else
101
+ (value.is_a?(FalseClass) ? 0 : value)
102
+ end
103
+ table_bytes << (val & 0xFF)
104
+ current_pos += 1
105
+ when "short"
106
+ table_bytes.concat([value].pack("s<").bytes)
107
+ current_pos += 2
108
+ when "ushort"
109
+ table_bytes.concat([value].pack("S<").bytes)
110
+ current_pos += 2
111
+ when "int"
112
+ table_bytes.concat([value].pack("l<").bytes)
113
+ current_pos += 4
114
+ when "uint"
115
+ table_bytes.concat([value].pack("L<").bytes)
116
+ current_pos += 4
117
+ when "long"
118
+ table_bytes.concat([value].pack("q<").bytes)
119
+ current_pos += 8
120
+ when "ulong"
121
+ table_bytes.concat([value].pack("Q<").bytes)
122
+ current_pos += 8
123
+ when "float"
124
+ table_bytes.concat([value].pack("e").bytes)
125
+ current_pos += 4
126
+ when "double"
127
+ table_bytes.concat([value].pack("E").bytes)
128
+ current_pos += 8
129
+ end
130
+ elsif field_def.type == "string" && string_data[field_def.name]
131
+ field_offsets << current_pos
132
+ # Calculate uoffset from current field position to string
133
+ # String will be at: 4 (root) + table_size + vtable_size + string_start
134
+ str_info = string_data[field_def.name]
135
+ table_size = table_bytes.size + 4 # +4 for remaining field
136
+ string_abs_pos = 4 + table_size + vtable_size + str_info[:start_in_string_section]
137
+ # uoffset from field position in final buffer
138
+ field_abs_pos = 4 + current_pos
139
+ uoffset = string_abs_pos - field_abs_pos
140
+ table_bytes.concat([uoffset].pack("L<").bytes)
141
+ current_pos += 4
142
+ else
143
+ field_offsets << 0
144
+ end
145
+ end
146
+
147
+ # PHASE 3: Build vtable
148
+ vtable_bytes = []
149
+ object_size = table_bytes.size
150
+
151
+ vtable_bytes.concat([vtable_size].pack("S<").bytes)
152
+ vtable_bytes.concat([object_size].pack("S<").bytes)
153
+ field_offsets.each do |off|
154
+ vtable_bytes.concat([off].pack("S<").bytes)
155
+ end
156
+
157
+ # Patch vtable offset
158
+ vtable_offset = -object_size
159
+ table_bytes[0..3] = [vtable_offset].pack("l<").bytes
160
+
161
+ # Return table + vtable + strings
162
+ table_bytes + vtable_bytes + string_bytes_total
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Unibuf
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/unibuf.rb CHANGED
@@ -21,6 +21,10 @@ module Unibuf
21
21
  # FlatBuffers schema parser
22
22
  module Flatbuffers
23
23
  end
24
+
25
+ # Cap'n Proto schema parser
26
+ module Capnproto
27
+ end
24
28
  end
25
29
 
26
30
  # Module for all models
@@ -31,6 +35,10 @@ module Unibuf
31
35
  module Validators
32
36
  end
33
37
 
38
+ # Module for serializers
39
+ module Serializers
40
+ end
41
+
34
42
  class << self
35
43
  # ===== TEXT FORMAT PARSING (no schema required) =====
36
44
 
@@ -123,6 +131,22 @@ module Unibuf
123
131
  Parsers::Flatbuffers::BinaryParser.new(schema).parse(content)
124
132
  end
125
133
 
134
+ # ===== CAP'N PROTO =====
135
+
136
+ # Parse Cap'n Proto schema file
137
+ # @param path [String] Path to .capnp file
138
+ # @return [Models::Capnproto::Schema] Cap'n Proto schema
139
+ def parse_capnproto_schema(path)
140
+ require_relative "unibuf/parsers/capnproto/grammar"
141
+ require_relative "unibuf/parsers/capnproto/processor"
142
+
143
+ grammar = Parsers::Capnproto::Grammar.new
144
+ content = File.read(path)
145
+ ast = grammar.parse(content)
146
+ Parsers::Capnproto::Processor.process(ast)
147
+ end
148
+ alias parse_capnp parse_capnproto_schema
149
+
126
150
  # ===== AUTO-DETECTION (convenience methods) =====
127
151
 
128
152
  # Auto-detect format and parse
@@ -158,6 +182,9 @@ module Unibuf
158
182
  when ".fbs"
159
183
  raise ArgumentError,
160
184
  ".fbs files are schemas, use parse_flatbuffers_schema()"
185
+ when ".capnp"
186
+ raise ArgumentError,
187
+ ".capnp files are schemas, use parse_capnproto_schema()"
161
188
  when ".pb"
162
189
  # Ambiguous extension - try to detect
163
190
  detect_and_parse_pb(path, schema)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unibuf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ronald Tse
@@ -78,8 +78,13 @@ files:
78
78
  - ".rspec"
79
79
  - ".rubocop.yml"
80
80
  - ".rubocop_todo.yml"
81
+ - CODE_OF_CONDUCT.md
81
82
  - README.adoc
82
83
  - Rakefile
84
+ - docs/CAPNPROTO.adoc
85
+ - docs/FLATBUFFERS.adoc
86
+ - docs/PROTOBUF.adoc
87
+ - docs/TXTPROTO.adoc
83
88
  - exe/unibuf
84
89
  - lib/unibuf.rb
85
90
  - lib/unibuf/cli.rb
@@ -88,9 +93,22 @@ files:
88
93
  - lib/unibuf/commands/schema.rb
89
94
  - lib/unibuf/commands/validate.rb
90
95
  - lib/unibuf/errors.rb
96
+ - lib/unibuf/models/capnproto/enum_definition.rb
97
+ - lib/unibuf/models/capnproto/field_definition.rb
98
+ - lib/unibuf/models/capnproto/interface_definition.rb
99
+ - lib/unibuf/models/capnproto/method_definition.rb
100
+ - lib/unibuf/models/capnproto/schema.rb
101
+ - lib/unibuf/models/capnproto/struct_definition.rb
102
+ - lib/unibuf/models/capnproto/union_definition.rb
91
103
  - lib/unibuf/models/enum_definition.rb
92
104
  - lib/unibuf/models/field.rb
93
105
  - lib/unibuf/models/field_definition.rb
106
+ - lib/unibuf/models/flatbuffers/enum_definition.rb
107
+ - lib/unibuf/models/flatbuffers/field_definition.rb
108
+ - lib/unibuf/models/flatbuffers/schema.rb
109
+ - lib/unibuf/models/flatbuffers/struct_definition.rb
110
+ - lib/unibuf/models/flatbuffers/table_definition.rb
111
+ - lib/unibuf/models/flatbuffers/union_definition.rb
94
112
  - lib/unibuf/models/message.rb
95
113
  - lib/unibuf/models/message_definition.rb
96
114
  - lib/unibuf/models/schema.rb
@@ -100,11 +118,28 @@ files:
100
118
  - lib/unibuf/models/values/message_value.rb
101
119
  - lib/unibuf/models/values/scalar_value.rb
102
120
  - lib/unibuf/parsers/binary/wire_format_parser.rb
121
+ - lib/unibuf/parsers/capnproto/binary_parser.rb
122
+ - lib/unibuf/parsers/capnproto/grammar.rb
123
+ - lib/unibuf/parsers/capnproto/list_reader.rb
124
+ - lib/unibuf/parsers/capnproto/pointer_decoder.rb
125
+ - lib/unibuf/parsers/capnproto/processor.rb
126
+ - lib/unibuf/parsers/capnproto/segment_reader.rb
127
+ - lib/unibuf/parsers/capnproto/struct_reader.rb
128
+ - lib/unibuf/parsers/flatbuffers/binary_parser.rb
129
+ - lib/unibuf/parsers/flatbuffers/grammar.rb
130
+ - lib/unibuf/parsers/flatbuffers/processor.rb
103
131
  - lib/unibuf/parsers/proto3/grammar.rb
104
132
  - lib/unibuf/parsers/proto3/processor.rb
105
133
  - lib/unibuf/parsers/textproto/grammar.rb
106
134
  - lib/unibuf/parsers/textproto/parser.rb
107
135
  - lib/unibuf/parsers/textproto/processor.rb
136
+ - lib/unibuf/serializers/binary_serializer.rb
137
+ - lib/unibuf/serializers/capnproto/binary_serializer.rb
138
+ - lib/unibuf/serializers/capnproto/list_writer.rb
139
+ - lib/unibuf/serializers/capnproto/pointer_encoder.rb
140
+ - lib/unibuf/serializers/capnproto/segment_builder.rb
141
+ - lib/unibuf/serializers/capnproto/struct_writer.rb
142
+ - lib/unibuf/serializers/flatbuffers/binary_serializer.rb
108
143
  - lib/unibuf/validators/schema_validator.rb
109
144
  - lib/unibuf/validators/type_validator.rb
110
145
  - lib/unibuf/version.rb