Skip to content

Commit 715fa2a

Browse files
authored
Defaults (#297)
1 parent cb1bb0d commit 715fa2a

57 files changed

Lines changed: 883 additions & 392 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ bundle exec smithy build --debug
2020

2121
local build using smithy-ruby executable:
2222
```
23-
export SMITHY_PLUGIN_DIR=build/smithy/source/smithy-ruby
24-
bundle exec smithy-ruby smith client --gem-name weather --gem-version 1.0.0 --destination-root projections/weather <<< $(smithy ast model/weather.smithy)
23+
SMITHY_PLUGIN_DIR=build/smithy/source/smithy-ruby bundle exec smithy-ruby smith client --gem-name weather --gem-version 1.0.0 --destination-root projections/weather <<< $(smithy ast model/weather.smithy)
2524
```
2625

2726
### IRB

gems/smithy-cbor/lib/smithy-cbor/deserializer.rb

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def list(ref, values, target = nil)
3838
values.each do |value|
3939
next if value.nil? && !sparse?(ref.shape)
4040

41-
target << (value.nil? ? nil : shape(ref.shape.member, value))
41+
target << shape(ref.shape.member, value)
4242
end
4343
target
4444
end
@@ -48,37 +48,31 @@ def map(ref, values, target = nil)
4848
values.each do |key, value|
4949
next if value.nil? && !sparse?(ref.shape)
5050

51-
target[key] = value.nil? ? nil : shape(ref.shape.value, value)
51+
target[key] = shape(ref.shape.value, value)
5252
end
5353
target
5454
end
5555

5656
def structure(ref, values, target = nil)
57-
return Schema::EmptyStructure.new if ref.shape == Prelude::Unit
58-
5957
target = ref.shape.type.new if target.nil?
6058
ref.shape.members.each do |member_name, member_ref|
61-
key = member_ref.member_name
62-
next unless values.key?(key)
63-
64-
target[member_name] = shape(member_ref, values[key])
59+
value = values[member_ref.member_name]
60+
target[member_name] = shape(member_ref, value) unless value.nil?
6561
end
6662
target
6763
end
6864

6965
def union(ref, values, target = nil) # rubocop:disable Metrics/AbcSize
70-
raise ArgumentError, "union value includes more than one key, received: #{values.keys}" if values.size > 1
71-
72-
key, value = values.first
73-
return nil if key.nil?
74-
7566
ref.shape.members.each do |member_name, member_ref|
76-
name = member_ref.member_name
77-
next unless values.key?(name)
67+
value = values[member_ref.member_name]
68+
next if value.nil?
7869

7970
target = ref.shape.member_type(member_name) if target.nil?
80-
return target.new(shape(member_ref, values[name]))
71+
return target.new(shape(member_ref, value))
8172
end
73+
74+
values.delete('__type')
75+
key, value = values.first
8276
ref.shape.member_type(:unknown).new(key, value)
8377
end
8478

gems/smithy-cbor/lib/smithy-cbor/serializer.rb

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def initialize(options = {})
1414

1515
def serialize(shape, data)
1616
ref = shape.is_a?(ShapeRef) ? shape : ShapeRef.new(shape: shape)
17-
return nil if ref.shape == Prelude::Unit
17+
return if ref.shape == Prelude::Unit
1818

1919
CBOR.encode(shape(ref, data))
2020
end
@@ -33,38 +33,40 @@ def shape(ref, value)
3333
end
3434

3535
def blob(value)
36-
value.is_a?(String) ? value : value.read
36+
value.respond_to?(:read) ? value.read : value
3737
end
3838

3939
def list(ref, values)
40+
shape = ref.shape
4041
values.collect do |value|
41-
next if value.nil? && !sparse?(ref.shape)
42+
next if value.nil? && !sparse?(shape.traits)
4243

43-
value.nil? ? nil : shape(ref.shape.member, value)
44+
value.nil? ? nil : shape(shape.member, value)
4445
end
4546
end
4647

4748
def map(ref, values)
49+
shape = ref.shape
4850
values.each.with_object({}) do |(key, value), data|
49-
next if value.nil? && !sparse?(ref.shape)
51+
next if value.nil? && !sparse?(shape.traits)
5052

51-
data[key] = value.nil? ? nil : shape(ref.shape.value, value)
53+
data[key] = value.nil? ? nil : shape(shape.value, value)
5254
end
5355
end
5456

5557
def structure(ref, values)
56-
values.each_pair.with_object({}) do |(key, value), data|
57-
if ref.shape.member?(key) && !value.nil?
58-
member_ref = ref.shape.member(key)
59-
data[member_ref.member_name] = shape(member_ref, value)
60-
end
58+
ref.shape.members.each_with_object({}) do |(member_name, member_ref), data|
59+
value = values[member_name]
60+
next if value.nil?
61+
62+
data[member_ref.member_name] = shape(member_ref, value)
6163
end
6264
end
6365

6466
def union(ref, values) # rubocop:disable Metrics/AbcSize
6567
data = {}
6668
if values.is_a?(Schema::Union)
67-
member_ref = ref.shape.member_by_type(values.class)
69+
_name, member_ref = ref.shape.member_by_type(values.class)
6870
data[member_ref.member_name] = shape(member_ref, values).value
6971
else
7072
key, value = values.first
@@ -76,8 +78,8 @@ def union(ref, values) # rubocop:disable Metrics/AbcSize
7678
data
7779
end
7880

79-
def sparse?(shape)
80-
shape.traits.include?('smithy.api#sparse')
81+
def sparse?(traits)
82+
traits.include?('smithy.api#sparse')
8183
end
8284
end
8385
end

gems/smithy-cbor/spec/smithy-cbor/codec_spec.rb

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
module Smithy
66
module CBOR
7+
# TODO: test all codec cases
78
describe Codec do
89
let(:shape) { SchemaHelper.sample_schema.const_get(:Structure) }
910

@@ -83,31 +84,13 @@ module CBOR
8384
expect(subject.deserialize(shape, bytes).union).to eq(nil)
8485
end
8586

86-
it 'serializes an empty union' do
87-
data = { union: {} }
88-
bytes = subject.serialize(shape, data)
89-
expect(subject.deserialize(shape, bytes).union).to eq(nil)
90-
end
91-
92-
it 'serializes nil union values' do
93-
data = { union: { string: nil } }
94-
bytes = subject.serialize(shape, data)
95-
expect(subject.deserialize(shape, bytes).to_h).to eq(data)
96-
end
97-
9887
it 'deserializes unknown union members' do
9988
unknown_union_type = shape.member(:union).shape.member_type(:unknown)
10089
data = { union: { 'someThing' => 'someValue' } }
10190
deserialized = subject.deserialize(shape, CBOR.encode(data))
10291
expect(deserialized.union).to be_a(unknown_union_type)
10392
expect(deserialized.union.to_h).to eq(unknown: { name: 'someThing', value: 'someValue' })
10493
end
105-
106-
it 'raises when deserializing unions with more than one member' do
107-
data = { union: { string: 'string', integer: 1 } }
108-
expect { subject.deserialize(shape, CBOR.encode(data)) }
109-
.to raise_error(ArgumentError, /union value includes more than one key/)
110-
end
11194
end
11295

11396
context 'lists' do

gems/smithy-client/lib/smithy-client.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require 'base64'
4+
require 'bigdecimal'
35
require 'jmespath'
46

57
require 'smithy-cbor'

gems/smithy-client/lib/smithy-client/handler_context.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class HandlerContext
77
# @option options [Symbol] :operation_name (nil)
88
# @option options [OperationShape] :operation (nil)
99
# @option options [Base] :client (nil)
10-
# @option options [Hash] :params ({})
10+
# @option options [Hash, Struct] :params ({})
1111
# @option options [Configuration] :config (nil)
1212
# @option options [Request] :request (HTTP::Request.new)
1313
# @option options [Response] :response (HTTP::Response.new)
@@ -33,7 +33,7 @@ def initialize(options = {})
3333
# @return [Base]
3434
attr_accessor :client
3535

36-
# @return [Hash] The hash of request parameters.
36+
# @return [Hash, Struct] The request parameters as a Hash or a Struct.
3737
attr_accessor :params
3838

3939
# @return [Struct] The client configuration.

gems/smithy-client/lib/smithy-client/param_converter.rb

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ class ParamConverter
1515
@mutex = Mutex.new
1616
@converters = Hash.new { |h, k| h[k] = {} }
1717

18-
def initialize(schema)
18+
def initialize(schema, convert_structures: true)
1919
@schema = schema
20+
@convert_structures = convert_structures
2021
@opened_files = []
2122
end
2223

@@ -39,67 +40,67 @@ def c(ref, value)
3940
self.class.c(ref.shape.class, value, self)
4041
end
4142

43+
def shape(ref, value)
44+
case ref.shape
45+
when ListShape then list(ref, value)
46+
when MapShape then map(ref, value)
47+
when StructureShape then structure(ref, value)
48+
when UnionShape then union(ref, value)
49+
else c(ref, value)
50+
end
51+
end
52+
4253
def list(ref, values)
4354
values = c(ref, values)
44-
if values.is_a?(Array)
45-
values.map { |v| member(ref.shape.member, v) }
46-
else
47-
values
48-
end
55+
return values unless values.is_a?(Array)
56+
57+
values.collect { |v| shape(ref.shape.member, v) }
4958
end
5059

5160
def map(ref, values)
5261
values = c(ref, values)
53-
if values.is_a?(Hash)
54-
values.each.with_object({}) do |(key, value), hash|
55-
hash[member(ref.shape.key, key)] = member(ref.shape.value, value)
56-
end
57-
else
58-
values
59-
end
60-
end
62+
return values unless values.is_a?(Hash)
6163

62-
def member(ref, value)
63-
case ref.shape
64-
when StructureShape then structure(ref, value)
65-
when UnionShape then union(ref, value)
66-
when ListShape then list(ref, value)
67-
when MapShape then map(ref, value)
68-
else c(ref, value)
64+
values.each.with_object({}) do |(key, value), hash|
65+
hash[shape(ref.shape.key, key)] = shape(ref.shape.value, value)
6966
end
7067
end
7168

7269
def structure(ref, values)
7370
values = c(ref, values)
74-
if values.respond_to?(:each_pair)
75-
values.each_pair do |k, v|
76-
next if v.nil?
71+
return if values.nil?
7772

78-
next unless ref.shape.member?(k)
73+
type = @convert_structures ? ref.shape.type.new : values
74+
return type unless values.respond_to?(:each_pair)
7975

80-
values[k] = member(ref.shape.member(k), v)
81-
end
76+
values.each_pair do |k, v|
77+
next if v.nil?
78+
next unless ref.shape.member?(k)
79+
80+
type[k] = shape(ref.shape.member(k), v)
8281
end
83-
values
82+
type
8483
end
8584

86-
def union(ref, values)
85+
def union(ref, values) # rubocop:disable Metrics/AbcSize
8786
values = c(ref, values)
87+
return if values.nil?
88+
8889
if values.is_a?(Schema::Union)
89-
member_ref = ref.shape.member_by_type(values.class)
90-
member(member_ref, values)
90+
name, member_ref = ref.shape.member_by_type(values.class)
91+
member_type = ref.shape.member_type(name)
92+
member_type.new(shape(member_ref, values.value))
9193
else
9294
key, value = values.first
93-
values[key] = member(ref.shape.member(key), value)
95+
return { key => shape(ref.shape.member(key), value) } unless @convert_structures
96+
return unless ref.shape.member?(key)
97+
98+
member_type = ref.shape.member_type(key)
99+
member_type.new(shape(ref.shape.member(key), value))
94100
end
95-
values
96101
end
97102

98103
class << self
99-
def convert(shape, params)
100-
new(shape).convert(params)
101-
end
102-
103104
# Registers a new value converter. Converters run in the context
104105
# of a shape and value class.
105106
#
@@ -245,7 +246,6 @@ def each_base_class(shape_class, &)
245246
end
246247

247248
add(UnionShape, Hash) { |h, _| h.dup }
248-
add(UnionShape, Schema::Union)
249249
end
250250
end
251251
end

gems/smithy-client/lib/smithy-client/param_validator.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def union(ref, values, errors, context)
148148
return unless valid_union?(ref, values, errors, context)
149149

150150
if values.is_a?(Schema::Union)
151-
member_ref = ref.shape.member_by_type(values.class)
151+
_name, member_ref = ref.shape.member_by_type(values.class)
152152
shape(member_ref, values.value, errors, context)
153153
else
154154
values.each_pair do |name, value|
@@ -176,7 +176,8 @@ def valid_union?(ref, values, errors, context)
176176

177177
def validate_required_members(ref, values, errors, context)
178178
ref.shape.members.each do |name, member_ref|
179-
next unless member_ref.traits.include?('smithy.api#required')
179+
traits = member_ref.traits
180+
next unless traits.include?('smithy.api#required') && !traits.include?('smithy.api#clientOptional')
180181

181182
if values[name].nil?
182183
param = "#{context}[#{name.inspect}]"

gems/smithy-client/lib/smithy-client/rpc_v2_cbor/protocol.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ def stub_data(service, operation, data)
2929
ResponseStubber.new(@options).stub_data(service, operation, data)
3030
end
3131

32-
def stub_error(error_code)
33-
ResponseStubber.new(@options).stub_error(error_code)
32+
def stub_error(service, error_code)
33+
ResponseStubber.new(@options).stub_error(service, error_code)
3434
end
3535
end
3636
end

gems/smithy-client/lib/smithy-client/rpc_v2_cbor/response_stubber.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def stub_data(_service, operation, data)
1818
resp
1919
end
2020

21-
def stub_error(error_code)
21+
def stub_error(_service, error_code)
2222
resp = HTTP::Response.new
2323
resp.status_code = 400
2424
resp.headers['Smithy-Protocol'] = 'rpc-v2-cbor'

0 commit comments

Comments
 (0)