Skip to content

Commit ba2e6a5

Browse files
Add Cbor request and structure marshallers generators
1 parent 8404a80 commit ba2e6a5

File tree

7 files changed

+2380
-17
lines changed

7 files changed

+2380
-17
lines changed

extensions/src/AWSSDK.Extensions.CborProtocol/CborWriterExtensions.cs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,10 @@
1212
* express or implied. See the License for the specific language governing
1313
* permissions and limitations under the License.
1414
*/
15-
using Amazon.Runtime;
16-
using Amazon.Runtime.Internal;
17-
using Amazon.Runtime.Internal.Transform;
18-
using Amazon.Runtime.Internal.Util;
19-
using Amazon.Util;
15+
2016
using System;
21-
using System.Collections.Generic;
2217
using System.Formats.Cbor;
23-
using System.IO;
24-
using System.Text.RegularExpressions;
18+
using Amazon.Util;
2519

2620
namespace AWSSDK.Extensions.CborProtocol
2721
{
@@ -47,57 +41,82 @@ public static void WriteOptimizedNumber(this CborWriter writer, double value)
4741
{
4842
if (double.IsNaN(value) || double.IsInfinity(value))
4943
{
50-
writer.WriteDouble(value);
44+
writer.WriteDouble(value); // Write NaN or Infinity as a double.
5145
return;
5246
}
5347

48+
// If the value is an integer (without fractional part), write it as Int64 or UInt64.
5449
if (value % 1 == 0)
5550
{
5651
if (value >= long.MinValue && value <= long.MaxValue)
5752
{
53+
// If the value fits within the signed 64-bit integer (long) range,
54+
// WriteInt64 serializes it into the smallest CBOR type representation
55+
// that can contain its value without loss of precision.
5856
writer.WriteInt64((long)value);
5957
return;
6058
}
6159

6260
if (value >= 0 && value <= ulong.MaxValue)
6361
{
62+
// If the value is non-negative and fits within the unsigned 64-bit range,
63+
// WriteUInt64 serializes it into the smallest possible CBOR type representation.
6464
writer.WriteUInt64((ulong)value);
6565
return;
6666
}
6767
}
6868

69+
// Check if value can safely be represented as float32
70+
float floatCandidate = (float)value;
71+
if ((double)floatCandidate == value)
72+
{
73+
WriteOptimizedNumber(writer, floatCandidate);
74+
return;
75+
}
76+
77+
// If none of the above conditions are satisfied, write the value as a double.
6978
writer.WriteDouble(value);
7079
}
7180

7281
/// <summary>
7382
/// Writes a float using the smallest CBOR representation that preserves value and precision.
83+
/// This method uses manual encoding to avoid writing as a half-precision float.
7484
/// </summary>
7585
/// <param name="writer">The CBOR writer to use.</param>
7686
/// <param name="value">The float value to write.</param>
7787
public static void WriteOptimizedNumber(this CborWriter writer, float value)
7888
{
79-
if (float.IsNaN(value) || float.IsInfinity(value))
80-
{
81-
writer.WriteSingle(value);
82-
return;
83-
}
84-
89+
// If the value is an integer (without fractional part), write it as Int64 or UInt64.
8590
if (value % 1 == 0)
8691
{
8792
if (value >= long.MinValue && value <= long.MaxValue)
8893
{
94+
// If the value fits within the signed 64-bit integer (long) range,
95+
// WriteInt64 serializes it into the smallest CBOR type representation
96+
// that can contain its value without loss of precision.
8997
writer.WriteInt64((long)value);
9098
return;
9199
}
92100

93101
if (value >= 0 && value <= ulong.MaxValue)
94102
{
103+
// If the value is non-negative and fits within the unsigned 64-bit range,
104+
// WriteUInt64 serializes it into the smallest possible CBOR type representation.
95105
writer.WriteUInt64((ulong)value);
96106
return;
97107
}
98108
}
99109

100-
writer.WriteSingle(value);
110+
// Manual encoding to avoid half-precision floats
111+
var bytes = new byte[5];
112+
bytes[0] = 0xFA; // CBOR float32 marker
113+
BitConverter.GetBytes(value).CopyTo(bytes, 1);
114+
115+
// Ensure the bytes are in the correct endian order for CBOR.
116+
if (BitConverter.IsLittleEndian)
117+
Array.Reverse(bytes, 1, 4);
118+
119+
writer.WriteEncodedValue(bytes);
101120
}
102121
}
103122
}

generator/ServiceClientGeneratorLib/GeneratorDriver.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,7 @@ internal static bool WriteFile(string baseOutputDir,
14021402
/// Sets the marshaller of the generator based on the service type
14031403
/// </summary>
14041404
/// <param name="marshaller">The marshaller to be set</param>
1405-
/// <param name="normalizeMarshallers">If the service type is a type of json then normalizeMarshallers is set to true, false otherwise</param>
1405+
/// <param name="normalizeMarshallers">If the service type is using structure marshallers then normalizeMarshallers is set to true, false otherwise</param>
14061406
void GetRequestMarshaller(out BaseRequestMarshaller marshaller, out bool normalizeMarshallers)
14071407
{
14081408
normalizeMarshallers = false;
@@ -1413,6 +1413,10 @@ void GetRequestMarshaller(out BaseRequestMarshaller marshaller, out bool normali
14131413
marshaller = new JsonRPCRequestMarshaller();
14141414
normalizeMarshallers = true;
14151415
break;
1416+
case ServiceType.Cbor:
1417+
marshaller = new CborRequestMarshaller();
1418+
normalizeMarshallers = true;
1419+
break;
14161420
case ServiceType.Query:
14171421
marshaller = new AWSQueryRequestMarshaller();
14181422
break;
@@ -1435,6 +1439,8 @@ BaseRequestMarshaller GetStructureMarshaller()
14351439
case ServiceType.Rest_Json:
14361440
case ServiceType.Json:
14371441
return new JsonRPCStructureMarshaller();
1442+
case ServiceType.Cbor:
1443+
return new CborStructureMarshaller();
14381444
default:
14391445
throw new Exception("No structure marshaller for service type: " + this.Configuration.ServiceModel.Type);
14401446
}
@@ -1456,6 +1462,8 @@ BaseResponseUnmarshaller GetResponseUnmarshaller()
14561462
return new AWSQueryResponseUnmarshaller();
14571463
case ServiceType.Rest_Xml:
14581464
return new RestXmlResponseUnmarshaller();
1465+
case ServiceType.Cbor:
1466+
return new CborResponseUnmarshaller();
14591467
default:
14601468
throw new Exception("No response unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14611469
}
@@ -1476,6 +1484,8 @@ BaseResponseUnmarshaller GetStructureUnmarshaller()
14761484
return new AWSQueryStructureUnmarshaller();
14771485
case ServiceType.Rest_Xml:
14781486
return new RestXmlStructureUnmarshaller();
1487+
case ServiceType.Cbor:
1488+
return new CborStructureUnmarshaller();
14791489
default:
14801490
throw new Exception("No structure unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14811491
}
@@ -1495,6 +1505,8 @@ BaseResponseUnmarshaller GetExceptionUnmarshaller()
14951505
return new AWSQueryExceptionUnmarshaller();
14961506
case ServiceType.Rest_Xml:
14971507
return new RestXmlExceptionUnmarshaller();
1508+
case ServiceType.Cbor:
1509+
return new CborExceptionUnmarshaller();
14981510
default:
14991511
throw new Exception("No structure unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
15001512
}

0 commit comments

Comments
 (0)