Skip to content

Commit aa62fc3

Browse files
feat(codegen): assert sets have no duplicates (#2764)
* feat(codegen): assert sets have no duplicates * chore(codegen): update generated code
1 parent 1159680 commit aa62fc3

File tree

7 files changed

+103
-18
lines changed

7 files changed

+103
-18
lines changed

Diff for: clients/client-app-mesh/protocols/Aws_restJson1.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -8488,13 +8488,20 @@ const deserializeAws_restJson1PortMapping = (output: any, context: __SerdeContex
84888488
};
84898489

84908490
const deserializeAws_restJson1PortSet = (output: any, context: __SerdeContext): number[] => {
8491+
const uniqueValues = new Set<any>();
84918492
return (output || [])
84928493
.filter((e: any) => e != null)
84938494
.map((entry: any) => {
84948495
if (entry === null) {
84958496
return null as any;
84968497
}
8497-
return __expectInt32(entry) as any;
8498+
const parsedEntry = __expectInt32(entry) as any;
8499+
if (uniqueValues.has(parsedEntry)) {
8500+
throw new TypeError('All elements of the set "com.amazonaws.appmesh#PortSet" must be unique.');
8501+
} else {
8502+
uniqueValues.add(parsedEntry);
8503+
return parsedEntry;
8504+
}
84988505
});
84998506
};
85008507

Diff for: clients/client-codeguruprofiler/protocols/Aws_restJson1.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -3132,24 +3132,38 @@ const deserializeAws_restJson1Channel = (output: any, context: __SerdeContext):
31323132
};
31333133

31343134
const deserializeAws_restJson1Channels = (output: any, context: __SerdeContext): Channel[] => {
3135+
const uniqueValues = new Set<any>();
31353136
return (output || [])
31363137
.filter((e: any) => e != null)
31373138
.map((entry: any) => {
31383139
if (entry === null) {
31393140
return null as any;
31403141
}
3141-
return deserializeAws_restJson1Channel(entry, context);
3142+
const parsedEntry = deserializeAws_restJson1Channel(entry, context);
3143+
if (uniqueValues.has(parsedEntry)) {
3144+
throw new TypeError('All elements of the set "com.amazonaws.codeguruprofiler#Channels" must be unique.');
3145+
} else {
3146+
uniqueValues.add(parsedEntry);
3147+
return parsedEntry;
3148+
}
31423149
});
31433150
};
31443151

31453152
const deserializeAws_restJson1EventPublishers = (output: any, context: __SerdeContext): (EventPublisher | string)[] => {
3153+
const uniqueValues = new Set<any>();
31463154
return (output || [])
31473155
.filter((e: any) => e != null)
31483156
.map((entry: any) => {
31493157
if (entry === null) {
31503158
return null as any;
31513159
}
3152-
return __expectString(entry) as any;
3160+
const parsedEntry = __expectString(entry) as any;
3161+
if (uniqueValues.has(parsedEntry)) {
3162+
throw new TypeError('All elements of the set "com.amazonaws.codeguruprofiler#EventPublishers" must be unique.');
3163+
} else {
3164+
uniqueValues.add(parsedEntry);
3165+
return parsedEntry;
3166+
}
31533167
});
31543168
};
31553169

Diff for: clients/client-ssm-incidents/protocols/Aws_restJson1.ts

+38-4
Original file line numberDiff line numberDiff line change
@@ -3993,24 +3993,42 @@ const deserializeAws_restJson1AutomationExecutionSet = (
39933993
output: any,
39943994
context: __SerdeContext
39953995
): AutomationExecution[] => {
3996+
const uniqueValues = new Set<any>();
39963997
return (output || [])
39973998
.filter((e: any) => e != null)
39983999
.map((entry: any) => {
39994000
if (entry === null) {
40004001
return null as any;
40014002
}
4002-
return deserializeAws_restJson1AutomationExecution(entry, context);
4003+
const parsedEntry = deserializeAws_restJson1AutomationExecution(entry, context);
4004+
if (uniqueValues.has(parsedEntry)) {
4005+
throw new TypeError(
4006+
'All elements of the set "com.amazonaws.ssmincidents#AutomationExecutionSet" must be unique.'
4007+
);
4008+
} else {
4009+
uniqueValues.add(parsedEntry);
4010+
return parsedEntry;
4011+
}
40034012
});
40044013
};
40054014

40064015
const deserializeAws_restJson1ChatbotSnsConfigurationSet = (output: any, context: __SerdeContext): string[] => {
4016+
const uniqueValues = new Set<any>();
40074017
return (output || [])
40084018
.filter((e: any) => e != null)
40094019
.map((entry: any) => {
40104020
if (entry === null) {
40114021
return null as any;
40124022
}
4013-
return __expectString(entry) as any;
4023+
const parsedEntry = __expectString(entry) as any;
4024+
if (uniqueValues.has(parsedEntry)) {
4025+
throw new TypeError(
4026+
'All elements of the set "com.amazonaws.ssmincidents#ChatbotSnsConfigurationSet" must be unique.'
4027+
);
4028+
} else {
4029+
uniqueValues.add(parsedEntry);
4030+
return parsedEntry;
4031+
}
40144032
});
40154033
};
40164034

@@ -4033,13 +4051,20 @@ const deserializeAws_restJson1EmptyChatChannel = (output: any, context: __SerdeC
40334051
};
40344052

40354053
const deserializeAws_restJson1EngagementSet = (output: any, context: __SerdeContext): string[] => {
4054+
const uniqueValues = new Set<any>();
40364055
return (output || [])
40374056
.filter((e: any) => e != null)
40384057
.map((entry: any) => {
40394058
if (entry === null) {
40404059
return null as any;
40414060
}
4042-
return __expectString(entry) as any;
4061+
const parsedEntry = __expectString(entry) as any;
4062+
if (uniqueValues.has(parsedEntry)) {
4063+
throw new TypeError('All elements of the set "com.amazonaws.ssmincidents#EngagementSet" must be unique.');
4064+
} else {
4065+
uniqueValues.add(parsedEntry);
4066+
return parsedEntry;
4067+
}
40434068
});
40444069
};
40454070

@@ -4204,13 +4229,22 @@ const deserializeAws_restJson1NotificationTargetSet = (
42044229
output: any,
42054230
context: __SerdeContext
42064231
): NotificationTargetItem[] => {
4232+
const uniqueValues = new Set<any>();
42074233
return (output || [])
42084234
.filter((e: any) => e != null)
42094235
.map((entry: any) => {
42104236
if (entry === null) {
42114237
return null as any;
42124238
}
4213-
return deserializeAws_restJson1NotificationTargetItem(entry, context);
4239+
const parsedEntry = deserializeAws_restJson1NotificationTargetItem(entry, context);
4240+
if (uniqueValues.has(parsedEntry)) {
4241+
throw new TypeError(
4242+
'All elements of the set "com.amazonaws.ssmincidents#NotificationTargetSet" must be unique.'
4243+
);
4244+
} else {
4245+
uniqueValues.add(parsedEntry);
4246+
return parsedEntry;
4247+
}
42144248
});
42154249
};
42164250

Diff for: codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsProtocolUtils.java

-4
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,6 @@ private static boolean filterMalformedRequestTests(
330330
if (testCase.getId().startsWith("RestJsonMalformedUnion")) {
331331
return true;
332332
}
333-
//TODO: we don't do any set validation
334-
if (testCase.getId().startsWith("RestJsonMalformedSet")) {
335-
return true;
336-
}
337333
//TODO: we don't do any list validation
338334
if (testCase.getId().startsWith("RestJsonBodyMalformedList")) {
339335
return true;

Diff for: codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/JsonShapeDeserVisitor.java

+17-4
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,27 @@ protected void deserializeCollection(GenerationContext context, CollectionShape
6969
potentialFilter = ".filter((e: any) => e != null)";
7070
}
7171

72+
if (shape.isSetShape()) {
73+
writer.write("const uniqueValues = new Set<any>();");
74+
}
75+
7276
writer.openBlock("return (output || [])$L.map((entry: any) => {", "});", potentialFilter, () -> {
7377
// Short circuit null values from serialization.
7478
writer.write("if (entry === null) { return null as any; }");
7579

76-
// Dispatch to the output value provider for any additional handling.
77-
writer.write("return $L$L;",
78-
target.accept(getMemberVisitor(shape.getMember(), "entry")),
79-
usesExpect(target) ? " as any" : "");
80+
if (shape.isSetShape()) {
81+
writer.write("const parsedEntry = $L$L;",
82+
target.accept(getMemberVisitor(shape.getMember(), "entry")),
83+
usesExpect(target) ? " as any" : "");
84+
writer.write("if (uniqueValues.has(parsedEntry)) { throw new "
85+
+ "TypeError('All elements of the set $S must be unique.'); } else { "
86+
+ "uniqueValues.add(parsedEntry)\nreturn parsedEntry; }",
87+
shape.getId());
88+
} else {
89+
// Dispatch to the output value provider for any additional handling.
90+
writer.write("return $L$L;", target.accept(getMemberVisitor(shape.getMember(), "entry")),
91+
usesExpect(target) ? " as any" : "");
92+
}
8093
});
8194
}
8295

Diff for: protocol_tests/aws-json/protocols/Aws_json1_1.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1653,13 +1653,20 @@ const deserializeAws_json1_1FooEnumMap = (
16531653
};
16541654

16551655
const deserializeAws_json1_1FooEnumSet = (output: any, context: __SerdeContext): (FooEnum | string)[] => {
1656+
const uniqueValues = new Set<any>();
16561657
return (output || [])
16571658
.filter((e: any) => e != null)
16581659
.map((entry: any) => {
16591660
if (entry === null) {
16601661
return null as any;
16611662
}
1662-
return __expectString(entry) as any;
1663+
const parsedEntry = __expectString(entry) as any;
1664+
if (uniqueValues.has(parsedEntry)) {
1665+
throw new TypeError('All elements of the set "aws.protocoltests.shared#FooEnumSet" must be unique.');
1666+
} else {
1667+
uniqueValues.add(parsedEntry);
1668+
return parsedEntry;
1669+
}
16631670
});
16641671
};
16651672

Diff for: protocol_tests/aws-restjson/protocols/Aws_restJson1.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -4704,13 +4704,20 @@ const deserializeAws_restJson1FooEnumMap = (
47044704
};
47054705

47064706
const deserializeAws_restJson1FooEnumSet = (output: any, context: __SerdeContext): (FooEnum | string)[] => {
4707+
const uniqueValues = new Set<any>();
47074708
return (output || [])
47084709
.filter((e: any) => e != null)
47094710
.map((entry: any) => {
47104711
if (entry === null) {
47114712
return null as any;
47124713
}
4713-
return __expectString(entry) as any;
4714+
const parsedEntry = __expectString(entry) as any;
4715+
if (uniqueValues.has(parsedEntry)) {
4716+
throw new TypeError('All elements of the set "aws.protocoltests.shared#FooEnumSet" must be unique.');
4717+
} else {
4718+
uniqueValues.add(parsedEntry);
4719+
return parsedEntry;
4720+
}
47144721
});
47154722
};
47164723

@@ -4787,13 +4794,20 @@ const deserializeAws_restJson1StringMap = (output: any, context: __SerdeContext)
47874794
};
47884795

47894796
const deserializeAws_restJson1StringSet = (output: any, context: __SerdeContext): string[] => {
4797+
const uniqueValues = new Set<any>();
47904798
return (output || [])
47914799
.filter((e: any) => e != null)
47924800
.map((entry: any) => {
47934801
if (entry === null) {
47944802
return null as any;
47954803
}
4796-
return __expectString(entry) as any;
4804+
const parsedEntry = __expectString(entry) as any;
4805+
if (uniqueValues.has(parsedEntry)) {
4806+
throw new TypeError('All elements of the set "aws.protocoltests.shared#StringSet" must be unique.');
4807+
} else {
4808+
uniqueValues.add(parsedEntry);
4809+
return parsedEntry;
4810+
}
47974811
});
47984812
};
47994813

0 commit comments

Comments
 (0)