@@ -60,7 +60,7 @@ public Struct(params object[] args) {
6060 }
6161
6262 [ Documentation ( "creates a new uninitialized struct object - all arguments are ignored" ) ]
63- public Struct ( [ ParamDictionary ] IDictionary < object , object > kwArgs , params object [ ] args ) {
63+ public Struct ( [ ParamDictionary ] IDictionary < object , object > kwArgs , params object [ ] args ) {
6464 }
6565
6666 [ Documentation ( "initializes or re-initializes the compiled struct object with a new format" ) ]
@@ -191,9 +191,22 @@ public void __init__(CodeContext/*!*/ context, object fmt) {
191191 break ;
192192 case FormatType . Float :
193193 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
194- WriteFloat ( res , _isLittleEndian , ( float ) GetDoubleValue ( context , curObj ++ , values ) ) ;
194+ var d = GetDoubleValue ( context , curObj ++ , values ) ;
195+ var val = ( float ) d ;
196+ if ( float . IsInfinity ( val ) && ! double . IsInfinity ( d ) ) throw PythonOps . OverflowError ( "float too large to pack with f format" ) ;
197+ WriteFloat ( res , _isLittleEndian , val ) ;
195198 }
196199 break ;
200+ #if NET6_0_OR_GREATER
201+ case FormatType . Half:
202+ for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
203+ var d = GetDoubleValue ( context , curObj ++ , values ) ;
204+ var val = ( Half ) d ;
205+ if ( Half . IsInfinity ( val ) && ! double . IsInfinity ( d ) ) throw PythonOps . OverflowError ( "float too large to pack with e format" ) ;
206+ WriteHalf ( res , _isLittleEndian , val ) ;
207+ }
208+ break ;
209+ #endif
197210 case FormatType . CString :
198211 WriteString ( res , curFormat . Count , GetStringValue ( context , curObj ++ , values ) ) ;
199212 break ;
@@ -274,7 +287,7 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] ByteArray/*!*/ buffer,
274287 break ;
275288 case FormatType . SignedChar :
276289 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
277- res [ res_idx ++ ] = ( int ) ( sbyte ) CreateCharValue ( context , ref curIndex , data ) ;
290+ res [ res_idx ++ ] = ( int ) unchecked ( ( sbyte ) CreateCharValue ( context , ref curIndex , data ) ) ;
278291 }
279292 break ;
280293 case FormatType . UnsignedChar :
@@ -337,7 +350,7 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] ByteArray/*!*/ buffer,
337350 break ;
338351 case FormatType . SizeT :
339352 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
340- res [ res_idx ++ ] = CreateUIntValue ( context , ref curIndex , _isLittleEndian , data ) ;
353+ res [ res_idx ++ ] = BigIntegerOps . __int__ ( CreateUIntValue ( context , ref curIndex , _isLittleEndian , data ) ) ;
341354 }
342355 break ;
343356 case FormatType . LongLong :
@@ -350,9 +363,16 @@ public void pack_into(CodeContext/*!*/ context, [NotNone] ByteArray/*!*/ buffer,
350363 res [ res_idx ++ ] = BigIntegerOps . __int__ ( CreateULongValue ( context , ref curIndex , _isLittleEndian , data ) ) ;
351364 }
352365 break ;
366+ #if NET6_0_OR_GREATER
367+ case FormatType . Half:
368+ for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
369+ res [ res_idx ++ ] = ( double ) CreateHalfValue ( context , ref curIndex , _isLittleEndian , data ) ;
370+ }
371+ break ;
372+ #endif
353373 case FormatType . Float :
354374 for ( int j = 0 ; j < curFormat . Count ; j ++ ) {
355- res [ res_idx ++ ] = CreateFloatValue ( context , ref curIndex , _isLittleEndian , data ) ;
375+ res [ res_idx ++ ] = ( double ) CreateFloatValue ( context , ref curIndex , _isLittleEndian , data ) ;
356376 }
357377 break ;
358378 case FormatType . Double :
@@ -487,6 +507,12 @@ private static Struct CompileAndCache(CodeContext/*!*/ context, string/*!*/ fmt)
487507 res . Add ( new Format ( FormatType . UnsignedLongLong , count ) ) ;
488508 count = 1 ;
489509 break ;
510+ #if NET6_0_OR_GREATER
511+ case 'e' : // half
512+ res . Add ( new Format ( FormatType . Half , count ) ) ;
513+ count = 1 ;
514+ break ;
515+ #endif
490516 case 'f' : // float
491517 res . Add ( new Format ( FormatType . Float , count ) ) ;
492518 count = 1 ;
@@ -725,6 +751,9 @@ private enum FormatType {
725751
726752 Short ,
727753 UnsignedShort ,
754+ #if NET6_0_OR_GREATER
755+ Half ,
756+ #endif
728757
729758 Int,
730759 UnsignedInt ,
@@ -758,6 +787,9 @@ private static int GetNativeSize(FormatType c) {
758787 return 1 ;
759788 case FormatType . Short :
760789 case FormatType . UnsignedShort :
790+ #if NET6_0_OR_GREATER
791+ case FormatType . Half:
792+ #endif
761793 return 2 ;
762794 case FormatType . Int :
763795 case FormatType . UnsignedInt :
@@ -953,6 +985,18 @@ private static void WriteSignedNetPointer(this MemoryStream res, bool fLittleEnd
953985 res . WritePointer ( fLittleEndian , unchecked ( ( ulong ) val . ToInt64 ( ) ) ) ;
954986 }
955987
988+ #if NET6_0_OR_GREATER
989+ private static void WriteHalf ( this MemoryStream res , bool fLittleEndian , Half val ) {
990+ byte [ ] bytes = BitConverter . GetBytes ( val ) ;
991+ if ( BitConverter . IsLittleEndian == fLittleEndian ) {
992+ res . Write ( bytes , 0 , bytes . Length ) ;
993+ } else {
994+ res . WriteByte ( bytes [ 1 ] ) ;
995+ res . WriteByte ( bytes [ 0 ] ) ;
996+ }
997+ }
998+ #endif
999+
9561000 private static void WriteFloat ( this MemoryStream res , bool fLittleEndian , float val ) {
9571001 byte [ ] bytes = BitConverter . GetBytes ( val ) ;
9581002 if ( BitConverter . IsLittleEndian == fLittleEndian ) {
@@ -1176,7 +1220,7 @@ internal static ulong GetULongLongValue(CodeContext/*!*/ context, int index, obj
11761220 internal static double GetDoubleValue ( CodeContext /*!*/ context , int index , object [ ] args ) {
11771221 object val = GetValue ( context , index , args ) ;
11781222 if ( Converter . TryConvertToDouble ( val , out double res ) ) return res ;
1179- throw Error ( context , "expected double value " ) ;
1223+ throw Error ( context , "required argument is not a float " ) ;
11801224 }
11811225
11821226 internal static IList < byte > GetStringValue ( CodeContext /*!*/ context , int index , object [ ] args ) {
@@ -1236,6 +1280,28 @@ internal static ushort CreateUShortValue(CodeContext/*!*/ context, ref int index
12361280 }
12371281 }
12381282
1283+ #if NET6_0_OR_GREATER
1284+ internal static Half CreateHalfValue ( CodeContext /*!*/ context , ref int index , bool fLittleEndian , IList < byte > data ) {
1285+ byte [ ] bytes = new byte [ 2 ] ;
1286+ if ( fLittleEndian ) {
1287+ bytes [ 0 ] = ( byte ) ReadData ( context , ref index , data ) ;
1288+ bytes [ 1 ] = ( byte ) ReadData ( context , ref index , data ) ;
1289+ } else {
1290+ bytes [ 1 ] = ( byte ) ReadData ( context , ref index , data ) ;
1291+ bytes [ 0 ] = ( byte ) ReadData ( context , ref index , data ) ;
1292+ }
1293+ Half res = BitConverter . ToHalf ( bytes , 0 ) ;
1294+
1295+ if ( context . LanguageContext . FloatFormat == FloatFormat . Unknown ) {
1296+ if ( Half . IsNaN ( res ) || Half . IsInfinity ( res ) ) {
1297+ throw PythonOps . ValueError ( "can't unpack IEEE 754 special value on non-IEEE platform" ) ;
1298+ }
1299+ }
1300+
1301+ return res ;
1302+ }
1303+ #endif
1304+
12391305 internal static float CreateFloatValue ( CodeContext /*!*/ context , ref int index , bool fLittleEndian , IList < byte > data ) {
12401306 byte [ ] bytes = new byte [ 4 ] ;
12411307 if ( fLittleEndian ) {
0 commit comments