Skip to content

Commit d6a1c84

Browse files
Add Cbor request and structure marshallers generators
1 parent c9f4c56 commit d6a1c84

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
@@ -1379,7 +1379,7 @@ internal static bool WriteFile(string baseOutputDir,
13791379
/// Sets the marshaller of the generator based on the service type
13801380
/// </summary>
13811381
/// <param name="marshaller">The marshaller to be set</param>
1382-
/// <param name="normalizeMarshallers">If the service type is a type of json then normalizeMarshallers is set to true, false otherwise</param>
1382+
/// <param name="normalizeMarshallers">If the service type is using structure marshallers then normalizeMarshallers is set to true, false otherwise</param>
13831383
void GetRequestMarshaller(out BaseRequestMarshaller marshaller, out bool normalizeMarshallers)
13841384
{
13851385
normalizeMarshallers = false;
@@ -1390,6 +1390,10 @@ void GetRequestMarshaller(out BaseRequestMarshaller marshaller, out bool normali
13901390
marshaller = new JsonRPCRequestMarshaller();
13911391
normalizeMarshallers = true;
13921392
break;
1393+
case ServiceType.Cbor:
1394+
marshaller = new CborRequestMarshaller();
1395+
normalizeMarshallers = true;
1396+
break;
13931397
case ServiceType.Query:
13941398
marshaller = new AWSQueryRequestMarshaller();
13951399
break;
@@ -1412,6 +1416,8 @@ BaseRequestMarshaller GetStructureMarshaller()
14121416
case ServiceType.Rest_Json:
14131417
case ServiceType.Json:
14141418
return new JsonRPCStructureMarshaller();
1419+
case ServiceType.Cbor:
1420+
return new CborStructureMarshaller();
14151421
default:
14161422
throw new Exception("No structure marshaller for service type: " + this.Configuration.ServiceModel.Type);
14171423
}
@@ -1433,6 +1439,8 @@ BaseResponseUnmarshaller GetResponseUnmarshaller()
14331439
return new AWSQueryResponseUnmarshaller();
14341440
case ServiceType.Rest_Xml:
14351441
return new RestXmlResponseUnmarshaller();
1442+
case ServiceType.Cbor:
1443+
return new CborResponseUnmarshaller();
14361444
default:
14371445
throw new Exception("No response unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14381446
}
@@ -1453,6 +1461,8 @@ BaseResponseUnmarshaller GetStructureUnmarshaller()
14531461
return new AWSQueryStructureUnmarshaller();
14541462
case ServiceType.Rest_Xml:
14551463
return new RestXmlStructureUnmarshaller();
1464+
case ServiceType.Cbor:
1465+
return new CborStructureUnmarshaller();
14561466
default:
14571467
throw new Exception("No structure unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14581468
}
@@ -1472,6 +1482,8 @@ BaseResponseUnmarshaller GetExceptionUnmarshaller()
14721482
return new AWSQueryExceptionUnmarshaller();
14731483
case ServiceType.Rest_Xml:
14741484
return new RestXmlExceptionUnmarshaller();
1485+
case ServiceType.Cbor:
1486+
return new CborExceptionUnmarshaller();
14751487
default:
14761488
throw new Exception("No structure unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14771489
}

0 commit comments

Comments
 (0)