Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions gems/smithy-cbor/lib/smithy-cbor/deserializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,70 +15,71 @@ def initialize(options = {})
def deserialize(shape, bytes, target)
return {} if bytes.empty?

shape(shape, CBOR.decode(bytes), target)
ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape)
shape(ref, CBOR.decode(bytes), target)
end

private

def shape(shape, value, target = nil)
def shape(ref, value, target = nil)
return nil if value.nil?

case shape
when ListShape then list(shape, value, target)
when MapShape then map(shape, value, target)
when StructureShape then structure(shape, value, target)
when UnionShape then union(shape, value, target)
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(shape, values, target = nil)
def list(ref, values, target = nil)
target = [] if target.nil?
values.each do |value|
next if value.nil? && !sparse?(shape)
next if value.nil? && !sparse?(ref.shape)

target << (value.nil? ? nil : shape(shape.member.shape, value))
target << (value.nil? ? nil : shape(ref.shape.member, value))
end
target
end

def map(shape, values, target = nil)
def map(ref, values, target = nil)
target = {} if target.nil?
values.each do |key, value|
next if value.nil? && !sparse?(shape)
next if value.nil? && !sparse?(ref.shape)

target[key] = value.nil? ? nil : shape(shape.value.shape, value)
target[key] = value.nil? ? nil : shape(ref.shape.value, value)
end
target
end

def structure(shape, values, target = nil)
return Schema::EmptyStructure.new if shape == Prelude::Unit
def structure(ref, values, target = nil)
return Schema::EmptyStructure.new if ref.shape == Prelude::Unit

target = shape.type.new if target.nil?
shape.members.each do |member_name, member_shape|
key = member_shape.name
target = ref.shape.type.new if target.nil?
ref.shape.members.each do |member_name, member_ref|
key = member_ref.location_name
next unless values.key?(key)

target[member_name] = shape(member_shape.shape, values[key])
target[member_name] = shape(member_ref, values[key])
end
target
end

def union(shape, values, target = nil) # rubocop:disable Metrics/AbcSize
def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize
raise ArgumentError, "union value includes more than one key, received: #{values.keys}" if values.size > 1

key, value = values.first
return nil if key.nil?

shape.members.each do |member_name, member_shape|
name = member_shape.name
ref.shape.members.each do |member_name, member_ref|
name = member_ref.location_name
next unless values.key?(name)

target = shape.member_type(member_name) if target.nil?
return target.new(shape(member_shape.shape, values[name]))
target = ref.shape.member_type(member_name) if target.nil?
return target.new(shape(member_ref, values[name]))
end
shape.member_type(:unknown).new(key, value)
ref.shape.member_type(:unknown).new(key, value)
end

def sparse?(shape)
Expand Down
49 changes: 25 additions & 24 deletions gems/smithy-cbor/lib/smithy-cbor/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,21 @@ def initialize(options = {})
end

def serialize(shape, data)
return nil if shape == Prelude::Unit
ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape)
return nil if ref.shape == Prelude::Unit
Comment thread
jterapin marked this conversation as resolved.

CBOR.encode(shape(shape, data))
CBOR.encode(shape(ref, data))
end

private

def shape(shape, value)
case shape
def shape(ref, value)
case ref.shape
when BlobShape then blob(value)
when ListShape then list(shape, value)
when MapShape then map(shape, value)
when StructureShape then structure(shape, value)
when UnionShape then union(shape, value)
when ListShape then list(ref, value)
when MapShape then map(ref, value)
when StructureShape then structure(ref, value)
when UnionShape then union(ref, value)
else value
end
end
Expand All @@ -35,41 +36,41 @@ def blob(value)
value.is_a?(String) ? value : value.read
end

def list(shape, values)
def list(ref, values)
values.collect do |value|
next if value.nil? && !sparse?(shape)
next if value.nil? && !sparse?(ref.shape)

value.nil? ? nil : shape(shape.member.shape, value)
value.nil? ? nil : shape(ref.shape.member, value)
end
end

def map(shape, values)
def map(ref, values)
values.each.with_object({}) do |(key, value), data|
next if value.nil? && !sparse?(shape)
next if value.nil? && !sparse?(ref.shape)

data[key] = value.nil? ? nil : shape(shape.value.shape, value)
data[key] = value.nil? ? nil : shape(ref.shape.value, value)
end
end

def structure(shape, values)
def structure(ref, values)
values.each_pair.with_object({}) do |(key, value), data|
if shape.member?(key) && !value.nil?
member_shape = shape.member(key)
data[member_shape.name] = shape(member_shape.shape, value)
if ref.shape.member?(key) && !value.nil?
member_ref = ref.shape.member(key)
data[member_ref.location_name] = shape(member_ref, value)
end
end
end

def union(shape, values)
def union(ref, values) # rubocop:disable Metrics/AbcSize
data = {}
if values.is_a?(Schema::Union)
member_shape = shape.member_by_type(values.class)
data[member_shape.name] = shape(member_shape.shape, values).value
member_ref = ref.shape.member_by_type(values.class)
data[member_ref.location_name] = shape(member_ref, values).value
else
key, value = values.first
if shape.member?(key)
member_shape = shape.member(key)
data[member_shape.name] = shape(member_shape.shape, value)
if ref.shape.member?(key)
member_ref = ref.shape.member(key)
data[member_ref.location_name] = shape(member_ref, value)
end
end
data
Expand Down
79 changes: 39 additions & 40 deletions gems/smithy-client/lib/smithy-client/param_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,65 +35,64 @@ def close_opened_files

private

def structure(shape, values)
values = c(shape, values)
if values.respond_to?(:each_pair)
values.each_pair do |k, v|
next if v.nil?

next unless shape.member?(k)

values[k] = member(shape.member(k), v)
end
end
values
end

def union(shape, values)
values = c(shape, values)
if values.is_a?(Schema::Union)
member_shape = shape.member_by_type(values.class)
member(member_shape, values)
else
key, value = values.first
values[key] = member(shape.member(key), value)
end
values
def c(ref, value)
self.class.c(ref.shape.class, value, self)
end

def list(shape, values)
values = c(shape, values)
def list(ref, values)
values = c(ref, values)
if values.is_a?(Array)
values.map { |v| member(shape.member, v) }
values.map { |v| member(ref.shape.member, v) }
else
values
end
end

def map(shape, values)
values = c(shape, values)
def map(ref, values)
values = c(ref, values)
if values.is_a?(Hash)
values.each.with_object({}) do |(key, value), hash|
hash[member(shape.key, key)] = member(shape.value, value)
hash[member(ref.shape.key, key)] = member(ref.shape.value, value)
end
else
values
end
end

def member(member_shape, value)
shape = member_shape.shape
case shape
when StructureShape then structure(shape, value)
when UnionShape then union(shape, value)
when ListShape then list(shape, value)
when MapShape then map(shape, value)
else c(shape, value)
def member(ref, value)
case ref.shape
when StructureShape then structure(ref, value)
when UnionShape then union(ref, value)
when ListShape then list(ref, value)
when MapShape then map(ref, value)
else c(ref, value)
end
end

def c(ref, value)
self.class.c(ref.class, value, self)
def structure(ref, values)
values = c(ref, values)
if values.respond_to?(:each_pair)
values.each_pair do |k, v|
next if v.nil?

next unless ref.shape.member?(k)

values[k] = member(ref.shape.member(k), v)
end
end
values
end

def union(ref, values)
values = c(ref, values)
if values.is_a?(Schema::Union)
member_ref = ref.shape.member_by_type(values.class)
member(member_ref, values)
else
key, value = values.first
values[key] = member(ref.shape.member(key), value)
end
values
end

class << self
Expand Down
Loading