yeptris 0.2.1.1-aarch64-linux → 0.2.1.2-aarch64-linux

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a6bb083838e4a5c101af3dda7b8872f7ddc9c17b5926e7f53d8dc89267563b2
4
- data.tar.gz: e3b3ed68162b71af5b6f5549f03d6fbfd527f57f907a8fc8232f9fdeffcd0209
3
+ metadata.gz: f876e15dade67cc5cbec6eba74a48c6936d636200ed3111f79d4da6b2402813d
4
+ data.tar.gz: ba9dc5f7735cd6d770d97e6f091ccf4c0931652628d8530a6563e9d463580a24
5
5
  SHA512:
6
- metadata.gz: 2de1413ca27b42df0e9cde8bcc3df01298152f9984c8d3085503d914b0566b39d1da66d3acf66beba4427c8cd4980875a4d7b94144250f8232765064f90211d2
7
- data.tar.gz: 74ec82d60158db3e4428ea083b11cb9a25ac8efe31f72c9760ea713afb4e763833669d7941b88015d389eea75c9fda8c4a3e00aaea1a43afad1d71e8436155c4
6
+ metadata.gz: 3999f2ac1fedd953c8dfe3461a903b683c9b2260f601ad09430c39677662b22477c0537bc4d5b026abb05c6239a704820c05ee9e39e44f3caa11966221d91bb0
7
+ data.tar.gz: e32834ea781ca94e0bd2f4d3335b0114edc44eddb68e3c26d5eea3b1cb881753cc3e03fb36504dbcb6f7e0f75aa67597b32faf74315c1868724f75a6753f09e6
data/lib/yeptris/ffi.rb CHANGED
@@ -240,6 +240,23 @@ module Yeptris
240
240
  TAG_NULL = 4
241
241
  TAG_TIMESTAMP = 5
242
242
 
243
+ # the schema-descriptor API (issue #238; TODO.restructure/83)
244
+ DESC_ABI = 1
245
+ SCHEMA_ERROR = 9
246
+
247
+ class DescNode < ::FFI::Struct
248
+ layout :wire_name, :pointer, :kind, :uint8, :type_tag, :uint8,
249
+ :flags, :uint16, :child_index, :uint32, :child_count, :uint32,
250
+ :reserved, :uint32
251
+ end
252
+
253
+ class SchemaColumn < ::FFI::Struct
254
+ layout :data, :pointer, :capacity, :uint32, :count, :uint32
255
+ end
256
+
257
+ attach_function :yeptris_schema_load,
258
+ %i[pointer size_t int pointer uint32 uint32 pointer], :int
259
+
243
260
  SCHEMA_12_CORE = 0
244
261
  SCHEMA_11_COMPAT = 1
245
262
 
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yeptris
4
+ # The schema-descriptor materialization (issue #238; the C ABI lives
5
+ # in yeptris/schema.h and docs/schema-abi.md). One native pass fills
6
+ # typed columns against a caller-compiled descriptor; the
7
+ # intermediate generic document never exists.
8
+ module Schema
9
+ module_function
10
+
11
+ KIND = { scalar: 0, sequence: 1, mapping: 2, callback: 3 }.freeze
12
+ TYPE = { str: 0, int: 1, float: 2, bool: 3, null: 4 }.freeze
13
+ REQUIRED = 1 << 0
14
+
15
+ class Error < Yeptris::Error; end
16
+ class RequiredMissing < Error; end
17
+
18
+ ELEMENT_SIZE = { 0 => 16, 1 => 8, 2 => 8, 3 => 1, 4 => 1 }.freeze # by TYPE value
19
+
20
+ # A materialized span: zero-copy off/len into the source plus the
21
+ # node's byte offset (the CALLBACK escape hatch).
22
+ Span = Struct.new(:offset, :length, :node_offset) do
23
+ def bytes_from(source)
24
+ source.byteslice(offset, length)
25
+ end
26
+ end
27
+
28
+ # desc: a flat array of node hashes, the C ABI 1:1 —
29
+ # { wire_name:, kind:, type:, required:, child_index:, child_count: }
30
+ # (kind/type symbolic; wire_name nil = the root). Returns one typed
31
+ # Ruby array per node: Integer/Float/true/false/nil/String for
32
+ # scalars and sequence elements (document order), Span for
33
+ # callbacks.
34
+ def load(source, schema: :core_12, desc:, capacity: 64)
35
+ source = Yeptris.read_input(source).to_s
36
+ schema_id = schema == :compat_11 ? FFI::SCHEMA_11_COMPAT : FFI::SCHEMA_12_CORE
37
+ plans = compile(desc)
38
+ loop do
39
+ result = run(source, schema_id, plans, capacity)
40
+ return result unless result == :grow
41
+ capacity *= 2
42
+ end
43
+ end
44
+
45
+ def compile(desc)
46
+ desc.map do |n|
47
+ { kind: KIND.fetch(n.fetch(:kind)),
48
+ type: TYPE.fetch(n[:type] || :str),
49
+ wire: n[:wire_name],
50
+ flags: n[:required] ? REQUIRED : 0,
51
+ child_index: n[:child_index] || 0,
52
+ child_count: n[:child_count] || 0 }
53
+ end
54
+ end
55
+ private_class_method :compile
56
+
57
+ def run(source, schema_id, plans, capacity) # rubocop:disable Metrics/MethodLength
58
+ n = plans.length
59
+ desc_buf = ::FFI::MemoryPointer.new(FFI::DescNode, n, true)
60
+ wires = []
61
+ plans.each_with_index do |p, i|
62
+ node = FFI::DescNode.new(desc_buf + i * FFI::DescNode.size)
63
+ if p[:wire]
64
+ wires << (wire = ::FFI::MemoryPointer.from_string(p[:wire]))
65
+ node[:wire_name] = wire
66
+ end
67
+ node[:kind] = p[:kind]
68
+ node[:type_tag] = p[:type]
69
+ node[:flags] = p[:flags]
70
+ node[:child_index] = p[:child_index]
71
+ node[:child_count] = p[:child_count]
72
+ node[:reserved] = 0
73
+ end
74
+ cols_buf = ::FFI::MemoryPointer.new(FFI::SchemaColumn, n, true)
75
+ data_ptrs = []
76
+ plans.each_with_index do |p, i|
77
+ col = FFI::SchemaColumn.new(cols_buf + i * FFI::SchemaColumn.size)
78
+ elem = ELEMENT_SIZE.fetch(p[:type], 16)
79
+ data = ::FFI::MemoryPointer.new(elem, capacity, true)
80
+ data_ptrs << data
81
+ col[:data] = data
82
+ col[:capacity] = capacity
83
+ col[:count] = 0
84
+ end
85
+
86
+ src = ::FFI::MemoryPointer.from_string(source) # NUL-safe copy for the C side
87
+ st = FFI.yeptris_schema_load(src, source.bytesize, schema_id, desc_buf, n,
88
+ FFI::DESC_ABI, cols_buf)
89
+ case st
90
+ when FFI::OK
91
+ plans.each_with_index.map { |p, i| drain(cols_buf, i, p, source) }
92
+ when FFI::ERROR_MEMORY
93
+ :grow
94
+ when FFI::SCHEMA_ERROR
95
+ msg = FFI.last_error_message
96
+ raise RequiredMissing, msg
97
+ else
98
+ raise Yeptris::ParseError, FFI.last_error_message
99
+ end
100
+ end
101
+ private_class_method :run
102
+
103
+ def drain(cols_buf, i, plan, source)
104
+ col = FFI::SchemaColumn.new(cols_buf + i * FFI::SchemaColumn.size)
105
+ count = col[:count]
106
+ data = col[:data]
107
+ case plan[:kind]
108
+ when KIND[:callback]
109
+ Array.new(count) do |k|
110
+ off = data.get_uint32(k * 16)
111
+ len = data.get_uint32(k * 16 + 4)
112
+ node_off = data.get_uint32(k * 16 + 8)
113
+ Span.new(off, len, node_off)
114
+ end
115
+ else
116
+ type = plan[:type]
117
+ Array.new(count) do |k|
118
+ case type
119
+ when TYPE[:int] then data.get_int64(k * 8)
120
+ when TYPE[:float] then data.get_double(k * 8)
121
+ when TYPE[:bool] then data.get_uchar(k) == 1
122
+ when TYPE[:null] then nil
123
+ else
124
+ off = data.get_uint32(k * 16)
125
+ len = data.get_uint32(k * 16 + 4)
126
+ source.byteslice(off, len)
127
+ end
128
+ end
129
+ end
130
+ end
131
+ private_class_method :drain
132
+ end
133
+ end
data/lib/yeptris.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Yeptris
4
4
  # The gem's version lives in the parent namespace's file — the last
5
5
  # internal require (yeptris/version) retired with it.
6
- VERSION = "0.2.1.1".freeze
6
+ VERSION = "0.2.1.2".freeze
7
7
  # The error hierarchy lives in THIS file (the parent namespace's
8
8
  # own file): nested constants do not trigger a parent-constant
9
9
  # autoload, and the law forbids internal requires — defining the
@@ -43,6 +43,13 @@ module Yeptris
43
43
  autoload :Materializer, "yeptris/materializer"
44
44
  autoload :ValueML, "yeptris/valueml"
45
45
  autoload :Psych, "yeptris/psych"
46
+ autoload :Schema, "yeptris/schema"
47
+
48
+ # The safe_load error names, aliased at the top level so consumers
49
+ # writing rescues need no nesting knowledge (issue #73's naming
50
+ # note): Yeptris::DisallowedClass is Yeptris::Psych::DisallowedClass.
51
+ DisallowedClass = Psych::DisallowedClass
52
+ AliasesError = Psych::AliasesError
46
53
  end
47
54
 
48
55
  # Eager native-library resolution (leptris-ruby lesson): fail at
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yeptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1.1
4
+ version: 0.2.1.2
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Ribose Inc.
@@ -51,6 +51,7 @@ files:
51
51
  - lib/yeptris/psych/handler.rb
52
52
  - lib/yeptris/psych/parser.rb
53
53
  - lib/yeptris/psych/visitors.rb
54
+ - lib/yeptris/schema.rb
54
55
  - lib/yeptris/valueml.rb
55
56
  - lib/yeptris/yaml.rb
56
57
  - libyeptris.so