yeptris 0.6.3.3 → 0.6.4.1
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 +11 -0
- data/lib/yeptris/json/descriptor.rb +50 -4
- data/lib/yeptris/yaml/descriptor.rb +54 -0
- data/lib/yeptris/yaml.rb +2 -0
- data/lib/yeptris.rb +1 -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: d45b2a3218406977adea5d7ae6d9184042864fce7bd2aeb9e69f3d87f0d11351
|
|
4
|
+
data.tar.gz: f2c61980fb7ca80b0d5686820718594c9cf8a0290975b555b2ce777d136bbfad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ef6d04e084a9bf84458396a560176ccd56eacd375bbc8bbf215e6ba810f2e07d149cd95727842fd5864f7eafc90306a09395becc154f16e68e4ec43fcc183322
|
|
7
|
+
data.tar.gz: da3bc2434c554b1d656e4f2749a1ee98acaaef71d37f5fad4372da679e22ff1c15b5be55545f18cb4e62e3984fc409f8763f563bd1b21d682c765b5f4af8b59b
|
data/lib/yeptris/ffi.rb
CHANGED
|
@@ -91,6 +91,17 @@ module Yeptris
|
|
|
91
91
|
attach_function :yeptris_plan_result_str_lens, %i[pointer size_t], :pointer
|
|
92
92
|
attach_function :yeptris_plan_result_nulls, %i[pointer size_t], :pointer
|
|
93
93
|
|
|
94
|
+
# the DOM (YAML) leg of the plan walk (#293 slice three): same
|
|
95
|
+
# compiled plan over a parsed document; str columns expose
|
|
96
|
+
# (ptr,len) views into the document's regions
|
|
97
|
+
attach_function :yeptris_document_plan_walk, %i[yeptris_document pointer pointer], :pointer
|
|
98
|
+
attach_function :yeptris_plan_result_strs, %i[pointer size_t], :pointer
|
|
99
|
+
|
|
100
|
+
# yeptris_plan_str (plan.h): one string view
|
|
101
|
+
class PlanStr < ::FFI::Struct
|
|
102
|
+
layout :p, :pointer, :len, :size_t
|
|
103
|
+
end
|
|
104
|
+
|
|
94
105
|
attach_function :yeptris_document_free, [:yeptris_document], :void
|
|
95
106
|
attach_function :yeptris_document_count, [:yeptris_document], :size_t
|
|
96
107
|
attach_function :yeptris_document_root, [:yeptris_document, :size_t], :yeptris_node
|
|
@@ -50,9 +50,18 @@ class Yeptris::JSON::Descriptor
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
# +kind+: :seq (rows are the root array) or :map (rows live under
|
|
53
|
-
# +path:+'s value). +
|
|
54
|
-
#
|
|
53
|
+
# +path:+'s value). +path+: a String, or an Array of Strings for a
|
|
54
|
+
# segmented (nested) path. +children+: the leaf columns; each row
|
|
55
|
+
# is a mapping, every child names one typed column.
|
|
55
56
|
def self.build(kind:, path: nil, children:)
|
|
57
|
+
handle, names = compile_handle(kind, path, children)
|
|
58
|
+
new(handle, names)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# The compile half of .build (shared with the YAML subclass's
|
|
62
|
+
# build — ONE owner of the spec grammar). Returns the owned handle
|
|
63
|
+
# and the leaf names.
|
|
64
|
+
def self.compile_handle(kind, path, children)
|
|
56
65
|
unless ROOT_KINDS.include?(kind)
|
|
57
66
|
raise ArgumentError, "kind must be one of #{ROOT_KINDS.inspect}, got #{kind.inspect}"
|
|
58
67
|
end
|
|
@@ -74,8 +83,20 @@ class Yeptris::JSON::Descriptor
|
|
|
74
83
|
{ "name" => name, "kind" => LEAF_SPEC_NAMES[code] }
|
|
75
84
|
end
|
|
76
85
|
|
|
86
|
+
case path
|
|
87
|
+
when nil then nil
|
|
88
|
+
when ::String then spec_path = path
|
|
89
|
+
when ::Array
|
|
90
|
+
unless path.all? { |seg| seg.is_a?(::String) && !seg.empty? }
|
|
91
|
+
raise ArgumentError, "path segments must be non-empty Strings"
|
|
92
|
+
end
|
|
93
|
+
spec_path = path
|
|
94
|
+
else
|
|
95
|
+
raise ArgumentError, "path must be a String or an Array of Strings"
|
|
96
|
+
end
|
|
97
|
+
|
|
77
98
|
spec = { "kind" => kind == :map ? "map" : "seq", "children" => leaves }
|
|
78
|
-
spec["path"] =
|
|
99
|
+
spec["path"] = spec_path unless spec_path.nil?
|
|
79
100
|
|
|
80
101
|
# the spec is strict JSON (the C compiler parses it through the
|
|
81
102
|
# strict JSON DOM); compile once, the engine owns the copy
|
|
@@ -86,8 +107,9 @@ class Yeptris::JSON::Descriptor
|
|
|
86
107
|
raise Error, "plan compile failed (status=#{st.read_int}): #{spec_json}"
|
|
87
108
|
end
|
|
88
109
|
|
|
89
|
-
|
|
110
|
+
[Handle.new(raw), leaves.map { |leaf| leaf["name"] }]
|
|
90
111
|
end
|
|
112
|
+
private_class_method :compile_handle
|
|
91
113
|
|
|
92
114
|
attr_reader :names # the planned leaf names, in spec order
|
|
93
115
|
|
|
@@ -173,6 +195,30 @@ class Yeptris::JSON::Descriptor
|
|
|
173
195
|
end
|
|
174
196
|
private_class_method :read_column
|
|
175
197
|
|
|
198
|
+
# @api private — the DOM leg's read: typed lanes as above; str
|
|
199
|
+
# columns materialize from the (ptr,len) views into the document
|
|
200
|
+
def self.read_dom(raw, names)
|
|
201
|
+
rows = ::Yeptris::FFI.yeptris_plan_result_rows(raw)
|
|
202
|
+
columns = {}
|
|
203
|
+
names.each_with_index do |name, c|
|
|
204
|
+
kind = ::Yeptris::FFI.yeptris_plan_result_kind(raw, c)
|
|
205
|
+
if kind == 2
|
|
206
|
+
nulls = ::Yeptris::FFI.yeptris_plan_result_nulls(raw, c).read_bytes(rows).unpack("C*")
|
|
207
|
+
base = ::FFI::Pointer.new(::Yeptris::FFI.yeptris_plan_result_strs(raw, c))
|
|
208
|
+
stride = ::Yeptris::FFI::PlanStr.size
|
|
209
|
+
columns[name] = Array.new(rows) do |i|
|
|
210
|
+
next nil if nulls[i] == 1
|
|
211
|
+
|
|
212
|
+
v = ::Yeptris::FFI::PlanStr.new(base + i * stride)
|
|
213
|
+
v[:p].read_bytes(v[:len]).force_encoding(Encoding::UTF_8)
|
|
214
|
+
end
|
|
215
|
+
else
|
|
216
|
+
columns[name] = read_column(raw, c, kind, rows, nil)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
new(rows, names, columns)
|
|
220
|
+
end
|
|
221
|
+
|
|
176
222
|
def initialize(rows, names, columns)
|
|
177
223
|
@rows = rows
|
|
178
224
|
@names = names
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The YAML leg of the Descriptor plan walk (yeptris#293 slice three,
|
|
4
|
+
# over the C DOM plan walk of libyeptris v0.6.4): the same compiled
|
|
5
|
+
# row shape as Yeptris::JSON::Descriptor, applied to a parsed YAML
|
|
6
|
+
# document — block YAML hydrates to typed columns with no
|
|
7
|
+
# intermediate Ruby tree.
|
|
8
|
+
#
|
|
9
|
+
# descriptor = Yeptris::YAML::Descriptor.build(
|
|
10
|
+
# kind: :map, path: ["data", "items"], # segmented paths work
|
|
11
|
+
# children: [{ name: "id", kind: :int }, { name: "name", kind: :str }])
|
|
12
|
+
# descriptor.walk(yaml).column("id") # => [1, 2, ...]
|
|
13
|
+
#
|
|
14
|
+
# Typed extraction rides the parse-time tag ids (schema: selects the
|
|
15
|
+
# resolver — :compat_11 keeps the Psych/libyaml implicit typing
|
|
16
|
+
# YAML.load uses); string columns are materialized from the
|
|
17
|
+
# document's regions before the result returns (nothing borrowed).
|
|
18
|
+
class Yeptris::YAML::Descriptor < ::Yeptris::JSON::Descriptor
|
|
19
|
+
# schema: :core_12 (YAML 1.2) or :compat_11 (the Psych-compatible
|
|
20
|
+
# implicit typing Yeptris::YAML.load uses).
|
|
21
|
+
def initialize(handle, names, schema)
|
|
22
|
+
super(handle, names)
|
|
23
|
+
@schema = schema
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @api private — the compile rides the JSON Descriptor's grammar
|
|
27
|
+
# (inherited private class method); schema selects the resolver
|
|
28
|
+
def self.build(kind:, path: nil, children:, schema: :compat_11)
|
|
29
|
+
handle, names = compile_handle(kind, path, children)
|
|
30
|
+
new(handle, names, schema)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def walk(yaml)
|
|
34
|
+
src = ::Yeptris.read_input(yaml).to_s
|
|
35
|
+
doc = ::Yeptris::Document.parse(src, schema: @schema)
|
|
36
|
+
begin
|
|
37
|
+
st = ::FFI::MemoryPointer.new(:int)
|
|
38
|
+
raw = ::Yeptris::FFI.yeptris_document_plan_walk(doc.c_ptr, @handle, st)
|
|
39
|
+
if raw.null?
|
|
40
|
+
raise ::Yeptris::JSON::Descriptor::Error,
|
|
41
|
+
"plan walk failed (status=#{st.read_int}) — the document shape " \
|
|
42
|
+
"disagrees with the plan"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
::Yeptris::JSON::Descriptor::PlanResult.read_dom(raw, @names)
|
|
47
|
+
ensure
|
|
48
|
+
::Yeptris::FFI.yeptris_plan_result_free(raw)
|
|
49
|
+
end
|
|
50
|
+
ensure
|
|
51
|
+
doc.free
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/yeptris/yaml.rb
CHANGED
|
@@ -9,6 +9,8 @@ module Yeptris
|
|
|
9
9
|
# the recorder-driven Visitors in phase B; this is the yeptris-native
|
|
10
10
|
# face users target first).
|
|
11
11
|
module YAML
|
|
12
|
+
autoload :Descriptor, "yeptris/yaml/descriptor"
|
|
13
|
+
|
|
12
14
|
module_function
|
|
13
15
|
|
|
14
16
|
# Loads the FIRST document of a YAML stream as native Ruby objects.
|
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.6.
|
|
6
|
+
VERSION = "0.6.4.1".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
|
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.6.
|
|
4
|
+
version: 0.6.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -55,6 +55,7 @@ files:
|
|
|
55
55
|
- lib/yeptris/schema.rb
|
|
56
56
|
- lib/yeptris/valueml.rb
|
|
57
57
|
- lib/yeptris/yaml.rb
|
|
58
|
+
- lib/yeptris/yaml/descriptor.rb
|
|
58
59
|
homepage: https://github.com/leptris/yeptris
|
|
59
60
|
licenses:
|
|
60
61
|
- MIT
|