Skip to content

Commit 39c9bb8

Browse files
Add Cbor request and structure marshallers generators
1 parent e94867f commit 39c9bb8

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
@@ -1355,7 +1355,7 @@ internal static bool WriteFile(string baseOutputDir,
13551355
/// Sets the marshaller of the generator based on the service type
13561356
/// </summary>
13571357
/// <param name="marshaller">The marshaller to be set</param>
1358-
/// <param name="normalizeMarshallers">If the service type is a type of json then normalizeMarshallers is set to true, false otherwise</param>
1358+
/// <param name="normalizeMarshallers">If the service type is using structure marshallers then normalizeMarshallers is set to true, false otherwise</param>
13591359
void GetRequestMarshaller(out BaseRequestMarshaller marshaller, out bool normalizeMarshallers)
13601360
{
13611361
normalizeMarshallers = false;
@@ -1366,6 +1366,10 @@ void GetRequestMarshaller(out BaseRequestMarshaller marshaller, out bool normali
13661366
marshaller = new JsonRPCRequestMarshaller();
13671367
normalizeMarshallers = true;
13681368
break;
1369+
case ServiceType.Cbor:
1370+
marshaller = new CborRequestMarshaller();
1371+
normalizeMarshallers = true;
1372+
break;
13691373
case ServiceType.Query:
13701374
marshaller = new AWSQueryRequestMarshaller();
13711375
break;
@@ -1388,6 +1392,8 @@ BaseRequestMarshaller GetStructureMarshaller()
13881392
case ServiceType.Rest_Json:
13891393
case ServiceType.Json:
13901394
return new JsonRPCStructureMarshaller();
1395+
case ServiceType.Cbor:
1396+
return new CborStructureMarshaller();
13911397
default:
13921398
throw new Exception("No structure marshaller for service type: " + this.Configuration.ServiceModel.Type);
13931399
}
@@ -1409,6 +1415,8 @@ BaseResponseUnmarshaller GetResponseUnmarshaller()
14091415
return new AWSQueryResponseUnmarshaller();
14101416
case ServiceType.Rest_Xml:
14111417
return new RestXmlResponseUnmarshaller();
1418+
case ServiceType.Cbor:
1419+
return new CborResponseUnmarshaller();
14121420
default:
14131421
throw new Exception("No response unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14141422
}
@@ -1429,6 +1437,8 @@ BaseResponseUnmarshaller GetStructureUnmarshaller()
14291437
return new AWSQueryStructureUnmarshaller();
14301438
case ServiceType.Rest_Xml:
14311439
return new RestXmlStructureUnmarshaller();
1440+
case ServiceType.Cbor:
1441+
return new CborStructureUnmarshaller();
14321442
default:
14331443
throw new Exception("No structure unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14341444
}
@@ -1448,6 +1458,8 @@ BaseResponseUnmarshaller GetExceptionUnmarshaller()
14481458
return new AWSQueryExceptionUnmarshaller();
14491459
case ServiceType.Rest_Xml:
14501460
return new RestXmlExceptionUnmarshaller();
1461+
case ServiceType.Cbor:
1462+
return new CborExceptionUnmarshaller();
14511463
default:
14521464
throw new Exception("No structure unmarshaller for service type: " + this.Configuration.ServiceModel.Type);
14531465
}

0 commit comments

Comments
 (0)