Skip to content

Commit dad3441

Browse files
Add Cbor request and structure marshallers generators
1 parent fbe0d46 commit dad3441

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
@@ -1380,7 +1380,7 @@ internal static bool WriteFile(string baseOutputDir,
13801380
/// Sets the marshaller of the generator based on the service type
13811381
/// </summary>
13821382
/// <param name="marshaller">The marshaller to be set</param>
1383-
/// <param name="normalizeMarshallers">If the service type is a type of json then normalizeMarshallers is set to true, false otherwise</param>
1383+
/// <param name="normalizeMarshallers">If the service type is using structure marshallers then normalizeMarshallers is set to true, false otherwise</param>
13841384
void GetRequestMarshaller(out BaseRequestMarshaller marshaller, out bool normalizeMarshallers)
13851385
{
13861386
normalizeMarshallers = false;
@@ -1391,6 +1391,10 @@ void GetRequestMarshaller(out BaseRequestMarshaller marshaller, out bool normali
13911391
marshaller = new JsonRPCRequestMarshaller();
13921392
normalizeMarshallers = true;
13931393
break;
1394+
case ServiceType.Cbor:
1395+
marshaller = new CborRequestMarshaller();
1396+
normalizeMarshallers = true;
1397+
break;
13941398
case ServiceType.Query:
13951399
marshaller = new AWSQueryRequestMarshaller();
13961400
break;
@@ -1413,6 +1417,8 @@ BaseRequestMarshaller GetStructureMarshaller()
14131417
case ServiceType.Rest_Json:
14141418
case ServiceType.Json:
14151419
return new JsonRPCStructureMarshaller();
1420+
case ServiceType.Cbor:
1421+
return new CborStructureMarshaller();
14161422
default:
14171423
throw new Exception("No structure marshaller for service type: " + this.Configuration.ServiceModel.Type);
14181424
}
@@ -1434,6 +1440,8 @@ BaseResponseUnmarshaller GetResponseUnmarshaller()
14341440
return new AWSQueryResponseUnmarshaller();
14351441
case ServiceType.Rest_Xml:
14361442
return new RestXmlResponseUnmarshaller();
1443+
case ServiceType.Cbor:
1444+
return new CborResponseUnmarshaller();
14371445
default:
14381446
throw new Exception("No response unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14391447
}
@@ -1454,6 +1462,8 @@ BaseResponseUnmarshaller GetStructureUnmarshaller()
14541462
return new AWSQueryStructureUnmarshaller();
14551463
case ServiceType.Rest_Xml:
14561464
return new RestXmlStructureUnmarshaller();
1465+
case ServiceType.Cbor:
1466+
return new CborStructureUnmarshaller();
14571467
default:
14581468
throw new Exception("No structure unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14591469
}
@@ -1473,6 +1483,8 @@ BaseResponseUnmarshaller GetExceptionUnmarshaller()
14731483
return new AWSQueryExceptionUnmarshaller();
14741484
case ServiceType.Rest_Xml:
14751485
return new RestXmlExceptionUnmarshaller();
1486+
case ServiceType.Cbor:
1487+
return new CborExceptionUnmarshaller();
14761488
default:
14771489
throw new Exception("No structure unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14781490
}

0 commit comments

Comments
 (0)