Skip to content

Commit 019c154

Browse files
author
Amit Kulkarni
committed
Add support for Smithy bigInteger and bigDecimal types as string wrappers in aws-smithy-types, allowing users to parse with their preferred big number library.
1 parent 3b94437 commit 019c154

File tree

24 files changed

+766
-8
lines changed

24 files changed

+766
-8
lines changed

.changelog/1763738215.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
applies_to:
3+
- client
4+
- aws-sdk-rust
5+
authors:
6+
- AmitKulkarni23
7+
references:
8+
- smithy-rs#312
9+
breaking: false
10+
new_feature: true
11+
bug_fix: false
12+
---
13+
Add support for Smithy bigInteger and bigDecimal types as string wrappers in aws-smithy-types, allowing users to parse with their preferred big number library.

codegen-client-test/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ data class ClientTest(
6262

6363
val allCodegenTests = listOf(
6464
ClientTest("com.amazonaws.simple#SimpleService", "simple", dependsOn = listOf("simple.smithy")),
65+
ClientTest("com.amazonaws.bignumbers#BigNumberService", "big_numbers", dependsOn = listOf("big-numbers.smithy")),
6566
ClientTest("com.amazonaws.dynamodb#DynamoDB_20120810", "dynamo"),
6667
ClientTest("com.amazonaws.ebs#Ebs", "ebs", dependsOn = listOf("ebs.json")),
6768
ClientTest("aws.protocoltests.json10#JsonRpc10", "json_rpc10"),

codegen-client-test/model/rest-xml-extras.smithy

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ service RestXmlExtras {
2121
StringHeader,
2222
CreateFoo,
2323
RequiredMember,
24+
BigNumberXml,
2425
]
2526
}
2627

@@ -254,3 +255,48 @@ structure RequiredMemberInputOutput {
254255
@required
255256
requiredString: String
256257
}
258+
259+
@http(uri: "/big-numbers", method: "POST")
260+
@httpRequestTests([
261+
{
262+
id: "RestXmlBigNumbersInput",
263+
protocol: restXml,
264+
method: "POST",
265+
uri: "/big-numbers",
266+
body: "<BigNumberXmlInput><bigInt>123456789</bigInt><bigDec>123.456</bigDec></BigNumberXmlInput>",
267+
bodyMediaType: "application/xml",
268+
headers: {"Content-Type": "application/xml"},
269+
params: {
270+
bigInt: 123456789,
271+
bigDec: 123.456
272+
}
273+
}
274+
])
275+
@httpResponseTests([
276+
{
277+
id: "RestXmlBigNumbersOutput",
278+
protocol: restXml,
279+
code: 200,
280+
body: "<BigNumberXmlOutput><bigInt>987654321</bigInt><bigDec>456.789</bigDec></BigNumberXmlOutput>",
281+
bodyMediaType: "application/xml",
282+
headers: {"Content-Type": "application/xml"},
283+
params: {
284+
bigInt: 987654321,
285+
bigDec: 456.789
286+
}
287+
}
288+
])
289+
operation BigNumberXml {
290+
input: BigNumberXmlInput,
291+
output: BigNumberXmlOutput
292+
}
293+
294+
structure BigNumberXmlInput {
295+
bigInt: BigInteger,
296+
bigDec: BigDecimal
297+
}
298+
299+
structure BigNumberXmlOutput {
300+
bigInt: BigInteger,
301+
bigDec: BigDecimal
302+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
$version: "2.0"
2+
3+
namespace com.amazonaws.bignumbers
4+
5+
use aws.protocols#restJson1
6+
use smithy.test#httpRequestTests
7+
use smithy.test#httpResponseTests
8+
9+
@restJson1
10+
service BigNumberService {
11+
version: "2023-01-01"
12+
operations: [ProcessBigNumbers]
13+
}
14+
15+
@http(uri: "/process", method: "POST")
16+
@httpRequestTests([
17+
{
18+
id: "BigNumbersInJsonRequest",
19+
protocol: restJson1,
20+
method: "POST",
21+
uri: "/process",
22+
body: "{\"bigInt\":123456789,\"bigDec\":123.456789}",
23+
bodyMediaType: "application/json",
24+
headers: {"Content-Type": "application/json"},
25+
params: {
26+
bigInt: 123456789,
27+
bigDec: 123.456789
28+
}
29+
},
30+
{
31+
id: "NegativeBigNumbersInJsonRequest",
32+
protocol: restJson1,
33+
method: "POST",
34+
uri: "/process",
35+
body: "{\"bigInt\":-987654321,\"bigDec\":-0.000000001}",
36+
bodyMediaType: "application/json",
37+
headers: {"Content-Type": "application/json"},
38+
params: {
39+
bigInt: -987654321,
40+
bigDec: -0.000000001
41+
}
42+
},
43+
{
44+
id: "ZeroBigNumbersInJsonRequest",
45+
protocol: restJson1,
46+
method: "POST",
47+
uri: "/process",
48+
body: "{\"bigInt\":0,\"bigDec\":0.0}",
49+
bodyMediaType: "application/json",
50+
headers: {"Content-Type": "application/json"},
51+
params: {
52+
bigInt: 0,
53+
bigDec: 0.0
54+
}
55+
},
56+
{
57+
id: "VeryLargeBigNumbersInJsonRequest",
58+
protocol: restJson1,
59+
method: "POST",
60+
uri: "/process",
61+
body: "{\"bigInt\":9007199254740991,\"bigDec\":123456.789}",
62+
bodyMediaType: "application/json",
63+
headers: {"Content-Type": "application/json"},
64+
params: {
65+
bigInt: 9007199254740991,
66+
bigDec: 123456.789
67+
}
68+
}
69+
])
70+
@httpResponseTests([
71+
{
72+
id: "BigNumbersInJsonResponse",
73+
protocol: restJson1,
74+
code: 200,
75+
body: "{\"result\":999999999,\"ratio\":0.123456789}",
76+
bodyMediaType: "application/json",
77+
headers: {"Content-Type": "application/json"},
78+
params: {
79+
result: 999999999,
80+
ratio: 0.123456789
81+
}
82+
},
83+
{
84+
id: "NegativeBigNumbersInJsonResponse",
85+
protocol: restJson1,
86+
code: 200,
87+
body: "{\"result\":-123456789,\"ratio\":-999.999}",
88+
bodyMediaType: "application/json",
89+
headers: {"Content-Type": "application/json"},
90+
params: {
91+
result: -123456789,
92+
ratio: -999.999
93+
}
94+
},
95+
{
96+
id: "VeryLargeBigNumbersInJsonResponse",
97+
protocol: restJson1,
98+
code: 200,
99+
body: "{\"result\":9007199254740991,\"ratio\":123456.789}",
100+
bodyMediaType: "application/json",
101+
headers: {"Content-Type": "application/json"},
102+
params: {
103+
result: 9007199254740991,
104+
ratio: 123456.789
105+
}
106+
},
107+
{
108+
id: "ZeroBigNumbersInJsonResponse",
109+
protocol: restJson1,
110+
code: 200,
111+
body: "{\"result\":0,\"ratio\":0.0}",
112+
bodyMediaType: "application/json",
113+
headers: {"Content-Type": "application/json"},
114+
params: {
115+
result: 0,
116+
ratio: 0.0
117+
}
118+
},
119+
{
120+
id: "NullBigNumbersInJsonResponse",
121+
protocol: restJson1,
122+
code: 200,
123+
body: "{\"result\":null,\"ratio\":null}",
124+
bodyMediaType: "application/json",
125+
headers: {"Content-Type": "application/json"},
126+
params: {}
127+
}
128+
])
129+
130+
operation ProcessBigNumbers {
131+
input: BigNumberInput
132+
output: BigNumberOutput
133+
}
134+
135+
structure BigNumberInput {
136+
bigInt: BigInteger
137+
bigDec: BigDecimal
138+
}
139+
140+
structure BigNumberOutput {
141+
result: BigInteger
142+
ratio: BigDecimal
143+
}

codegen-core/common-test-models/misc.smithy

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,11 @@ structure InnermostShape {
9595
@required
9696
aDouble: Double,
9797

98-
// TODO(https://github.com/smithy-lang/smithy-rs/issues/312)
99-
// @required
100-
// aBigInteger: BigInteger,
98+
@required
99+
aBigInteger: BigInteger,
101100

102-
// @required
103-
// aBigDecimal: BigDecimal,
101+
@required
102+
aBigDecimal: BigDecimal,
104103

105104
@required
106105
aTimestamp: Timestamp,

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/RuntimeType.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,10 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null)
425425

426426
fun dateTime(runtimeConfig: RuntimeConfig) = smithyTypes(runtimeConfig).resolve("DateTime")
427427

428+
fun bigInteger(runtimeConfig: RuntimeConfig) = smithyTypes(runtimeConfig).resolve("BigInteger")
429+
430+
fun bigDecimal(runtimeConfig: RuntimeConfig) = smithyTypes(runtimeConfig).resolve("BigDecimal")
431+
428432
fun document(runtimeConfig: RuntimeConfig): RuntimeType = smithyTypes(runtimeConfig).resolve("Document")
429433

430434
fun format(runtimeConfig: RuntimeConfig) = smithyTypes(runtimeConfig).resolve("date_time::Format")

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/SymbolVisitor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,11 @@ open class SymbolVisitor(
245245
}
246246

247247
override fun bigIntegerShape(shape: BigIntegerShape?): Symbol {
248-
TODO("Not yet implemented: https://github.com/smithy-lang/smithy-rs/issues/312")
248+
return RuntimeType.bigInteger(config.runtimeConfig).toSymbol()
249249
}
250250

251251
override fun bigDecimalShape(shape: BigDecimalShape?): Symbol {
252-
TODO("Not yet implemented: https://github.com/smithy-lang/smithy-rs/issues/312")
252+
return RuntimeType.bigDecimal(config.runtimeConfig).toSymbol()
253253
}
254254

255255
override fun operationShape(shape: OperationShape): Symbol {

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/Instantiator.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import software.amazon.smithy.model.node.NullNode
1414
import software.amazon.smithy.model.node.NumberNode
1515
import software.amazon.smithy.model.node.ObjectNode
1616
import software.amazon.smithy.model.node.StringNode
17+
import software.amazon.smithy.model.shapes.BigDecimalShape
18+
import software.amazon.smithy.model.shapes.BigIntegerShape
1719
import software.amazon.smithy.model.shapes.BlobShape
1820
import software.amazon.smithy.model.shapes.BooleanShape
1921
import software.amazon.smithy.model.shapes.CollectionShape
@@ -544,6 +546,20 @@ class PrimitiveInstantiator(
544546
}
545547

546548
is StringShape -> renderString(shape, data as StringNode)(this)
549+
is BigIntegerShape -> {
550+
val value = (data as NumberNode).value.toString()
551+
rustTemplate(
552+
"<#{BigInteger} as ::std::str::FromStr>::from_str(${value.dq()}).unwrap()",
553+
"BigInteger" to RuntimeType.bigInteger(runtimeConfig),
554+
)
555+
}
556+
is BigDecimalShape -> {
557+
val value = (data as NumberNode).value.toString()
558+
rustTemplate(
559+
"<#{BigDecimal} as ::std::str::FromStr>::from_str(${value.dq()}).unwrap()",
560+
"BigDecimal" to RuntimeType.bigDecimal(runtimeConfig),
561+
)
562+
}
547563
is NumberShape ->
548564
when (data) {
549565
is StringNode -> {

codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/CborParserGenerator.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
package software.amazon.smithy.rust.codegen.core.smithy.protocols.parse
77

88
import software.amazon.smithy.codegen.core.Symbol
9+
import software.amazon.smithy.model.shapes.BigDecimalShape
10+
import software.amazon.smithy.model.shapes.BigIntegerShape
911
import software.amazon.smithy.model.shapes.BlobShape
1012
import software.amazon.smithy.model.shapes.BooleanShape
1113
import software.amazon.smithy.model.shapes.ByteShape
@@ -579,6 +581,19 @@ class CborParserGenerator(
579581

580582
is TimestampShape -> rust("decoder.timestamp()")
581583

584+
is BigIntegerShape ->
585+
rustTemplate(
586+
"<#{BigInteger} as ::std::str::FromStr>::from_str(decoder.str()?.as_ref()).map_err(|_| #{Error}::custom(\"infallible\", decoder.position()))",
587+
"BigInteger" to RuntimeType.bigInteger(codegenContext.runtimeConfig),
588+
"Error" to RuntimeType.smithyCbor(codegenContext.runtimeConfig).resolve("decode::DeserializeError"),
589+
)
590+
is BigDecimalShape ->
591+
rustTemplate(
592+
"<#{BigDecimal} as ::std::str::FromStr>::from_str(decoder.str()?.as_ref()).map_err(|_| #{Error}::custom(\"infallible\", decoder.position()))",
593+
"BigDecimal" to RuntimeType.bigDecimal(codegenContext.runtimeConfig),
594+
"Error" to RuntimeType.smithyCbor(codegenContext.runtimeConfig).resolve("decode::DeserializeError"),
595+
)
596+
582597
// Aggregate shapes: https://smithy.io/2.0/spec/aggregate-types.html
583598
is StructureShape -> deserializeStruct(target)
584599
is CollectionShape -> deserializeCollection(target)

0 commit comments

Comments
 (0)