-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathparser.rb
More file actions
84 lines (67 loc) · 2.2 KB
/
parser.rb
File metadata and controls
84 lines (67 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# frozen_string_literal: true
require 'base64'
module Smithy
module Cbor
# @api private
class Parser
include Schema::Shapes
def initialize(options = {})
@options = options
end
def parse(shape, bytes, target = nil)
return {} if bytes.empty?
ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape)
shape(ref, Cbor.decode(bytes), target)
end
private
def shape(ref, value, target = nil)
return nil if value.nil?
case ref.shape
when ListShape then list(ref, value, target)
when MapShape then map(ref, value, target)
when StructureShape then structure(ref, value, target)
when UnionShape then union(ref, value, target)
else value
end
end
def list(ref, values, target = nil)
target = [] if target.nil?
values.each do |value|
next if value.nil? && !sparse?(ref.shape)
target << shape(ref.shape.member, value)
end
target
end
def map(ref, values, target = nil)
target = {} if target.nil?
values.each do |key, value|
next if value.nil? && !sparse?(ref.shape)
target[key] = shape(ref.shape.value, value)
end
target
end
def structure(ref, values, target = nil)
target = ref.shape.type.new if target.nil?
ref.shape.members.each do |member_name, member_ref|
value = values[member_ref.location_name]
target[member_name] = shape(member_ref, value) unless value.nil?
end
target
end
def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize
ref.shape.members.each do |member_name, member_ref|
value = values[member_ref.location_name]
next if value.nil?
target = ref.shape.member_type(member_name) if target.nil?
return target.new(member_name => shape(member_ref, value))
end
values.delete('__type')
key, value = values.first
ref.shape.member_type(:unknown).new(unknown: { key => value })
end
def sparse?(shape)
shape.traits.key?('smithy.api#sparse')
end
end
end
end