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 +4 -4
- data/lib/yeptris/ffi.rb +17 -0
- data/lib/yeptris/schema.rb +133 -0
- data/lib/yeptris.rb +8 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f876e15dade67cc5cbec6eba74a48c6936d636200ed3111f79d4da6b2402813d
|
|
4
|
+
data.tar.gz: ba9dc5f7735cd6d770d97e6f091ccf4c0931652628d8530a6563e9d463580a24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
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.
|
|
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
|