@@ -1237,10 +1237,7 @@ private void AppendPropertyTypes(string name, XElement interfaceXml, bool genera
12371237 string nullableInterfaceName = $ "INullable{ propertiesClassName } ";
12381238 string changedInterfaceName = $ "IChanged{ propertiesClassName } ";
12391239
1240- if ( readableProperties . Length > 64 )
1241- {
1242- throw new NotSupportedException ( $ "Interface '{ name } ' has { readableProperties . Length } readable properties, but the maximum supported is 64.") ;
1243- }
1240+ bool useByteArray = readableProperties . Length > 64 ;
12441241
12451242 AppendLine ( $ "interface { nullableInterfaceName } ") ;
12461243 StartBlock ( ) ;
@@ -1263,26 +1260,45 @@ private void AppendPropertyTypes(string name, XElement interfaceXml, bool genera
12631260 AppendLine ( $ "sealed class { propertiesClassName } : { changedInterfaceName } , I{ name } Properties") ;
12641261 StartBlock ( ) ;
12651262
1266- string flagType = readableProperties . Length <= 32 ? "uint" : "ulong" ;
1267- string one = readableProperties . Length <= 32 ? "1U" : "1UL" ;
1268-
1269- string allSetValue ;
1270- if ( readableProperties . Length <= 32 )
1263+ if ( useByteArray )
12711264 {
1272- uint value = readableProperties . Length == 32 ? uint . MaxValue : ( 1U << readableProperties . Length ) - 1 ;
1273- allSetValue = $ "0x{ value : X} U";
1265+ int byteCount = ( readableProperties . Length + 7 ) / 8 ;
1266+ var allSetBytes = new byte [ byteCount ] ;
1267+ for ( int i = 0 ; i < byteCount - 1 ; i ++ )
1268+ allSetBytes [ i ] = 0xFF ;
1269+ int remainder = readableProperties . Length % 8 ;
1270+ allSetBytes [ byteCount - 1 ] = remainder == 0 ? ( byte ) 0xFF : ( byte ) ( ( 1 << remainder ) - 1 ) ;
1271+ string allSetLiteral = string . Join ( ", " , allSetBytes . Select ( b => $ "0x{ b : X2} ") ) ;
1272+
1273+ AppendLine ( $ "private byte[] __set = new byte[{ byteCount } ];") ;
1274+ AppendLine ( $ "private byte[] __invalidated = new byte[{ byteCount } ];") ;
1275+ AppendLine ( $ "private static ReadOnlySpan<byte> PropertiesAllSet => new byte[] {{ { allSetLiteral } }}; // { readableProperties . Length } properties") ;
1276+ AppendLine ( $ "private static int FlagIndex({ propertyEnumName } property) => ((int)property - 1) / 8;") ;
1277+ AppendLine ( $ "private static byte FlagMask({ propertyEnumName } property) => (byte)(1 << (((int)property - 1) % 8));") ;
12741278 }
12751279 else
12761280 {
1277- ulong value = readableProperties . Length == 64 ? ulong . MaxValue : ( 1UL << readableProperties . Length ) - 1 ;
1278- allSetValue = $ "0x{ value : X} UL";
1279- }
1281+ string flagType = readableProperties . Length <= 32 ? "uint" : "ulong" ;
1282+ string one = readableProperties . Length <= 32 ? "1U" : "1UL" ;
1283+
1284+ string allSetValue ;
1285+ if ( readableProperties . Length <= 32 )
1286+ {
1287+ uint value = readableProperties . Length == 32 ? uint . MaxValue : ( 1U << readableProperties . Length ) - 1 ;
1288+ allSetValue = $ "0x{ value : X} U";
1289+ }
1290+ else
1291+ {
1292+ ulong value = readableProperties . Length == 64 ? ulong . MaxValue : ( 1UL << readableProperties . Length ) - 1 ;
1293+ allSetValue = $ "0x{ value : X} UL";
1294+ }
12801295
1281- AppendLine ( $ "private { flagType } __set;") ;
1282- AppendLine ( $ "private { flagType } __invalidated;") ;
1283- AppendLine ( $ "private const { flagType } PropertiesAllSet = { allSetValue } ; // { readableProperties . Length } properties") ;
1296+ AppendLine ( $ "private { flagType } __set;") ;
1297+ AppendLine ( $ "private { flagType } __invalidated;") ;
1298+ AppendLine ( $ "private const { flagType } PropertiesAllSet = { allSetValue } ; // { readableProperties . Length } properties") ;
12841299
1285- AppendLine ( $ "private static { flagType } Flag({ propertyEnumName } property) => property == 0 ? 0 : { one } << ((int)property - 1);") ;
1300+ AppendLine ( $ "private static { flagType } Flag({ propertyEnumName } property) => property == 0 ? 0 : { one } << ((int)property - 1);") ;
1301+ }
12861302
12871303 AppendLine ( $ "public { propertiesClassName } () {{ }}") ;
12881304 AppendLine ( "#nullable disable" ) ;
@@ -1304,7 +1320,14 @@ private void AppendPropertyTypes(string name, XElement interfaceXml, bool genera
13041320 AppendLine ( $ "public required { property . DotnetReadType } { property . NameUpper } ") ;
13051321 StartBlock ( ) ;
13061322 AppendLine ( $ "get {{ EnsureSet({ propertyEnumName } .{ property . NameUpper } ); return { property . UnderscoreNameLower } ; }}") ;
1307- AppendLine ( $ "set {{ { property . UnderscoreNameLower } = value; __set |= Flag({ propertyEnumName } .{ property . NameUpper } ); }}") ;
1323+ if ( useByteArray )
1324+ {
1325+ AppendLine ( $ "set {{ { property . UnderscoreNameLower } = value; __set[FlagIndex({ propertyEnumName } .{ property . NameUpper } )] |= FlagMask({ propertyEnumName } .{ property . NameUpper } ); }}") ;
1326+ }
1327+ else
1328+ {
1329+ AppendLine ( $ "set {{ { property . UnderscoreNameLower } = value; __set |= Flag({ propertyEnumName } .{ property . NameUpper } ); }}") ;
1330+ }
13081331 EndBlock ( ) ;
13091332 }
13101333
@@ -1333,10 +1356,21 @@ private void AppendPropertyTypes(string name, XElement interfaceXml, bool genera
13331356
13341357 AppendLine ( $ "public static { propertiesClassName } CreateUninitialized() => new { propertiesClassName } (false);") ;
13351358
1336- AppendLine ( $ "private bool HasFlag({ flagType } flags, { propertyEnumName } property)") ;
1337- _indentation ++ ;
1338- AppendLine ( $ "=> property != 0 && (flags & Flag(property)) != 0;") ;
1339- _indentation -- ;
1359+ if ( useByteArray )
1360+ {
1361+ AppendLine ( $ "private bool HasFlag(byte[] flags, { propertyEnumName } property)") ;
1362+ _indentation ++ ;
1363+ AppendLine ( $ "=> property != 0 && (flags[FlagIndex(property)] & FlagMask(property)) != 0;") ;
1364+ _indentation -- ;
1365+ }
1366+ else
1367+ {
1368+ string flagType = readableProperties . Length <= 32 ? "uint" : "ulong" ;
1369+ AppendLine ( $ "private bool HasFlag({ flagType } flags, { propertyEnumName } property)") ;
1370+ _indentation ++ ;
1371+ AppendLine ( $ "=> property != 0 && (flags & Flag(property)) != 0;") ;
1372+ _indentation -- ;
1373+ }
13401374
13411375 AppendLine ( $ "public bool IsSet({ propertyEnumName } property) => HasFlag(__set, property);") ;
13421376 AppendLine ( $ "public bool IsInvalidated({ propertyEnumName } property) => HasFlag(__invalidated, property);") ;
@@ -1345,17 +1379,38 @@ private void AppendPropertyTypes(string name, XElement interfaceXml, bool genera
13451379 StartBlock ( ) ;
13461380 AppendLine ( "if (property != 0)" ) ;
13471381 StartBlock ( ) ;
1348- AppendLine ( "__invalidated |= Flag(property);" ) ;
1382+ if ( useByteArray )
1383+ {
1384+ AppendLine ( "__invalidated[FlagIndex(property)] |= FlagMask(property);" ) ;
1385+ }
1386+ else
1387+ {
1388+ AppendLine ( "__invalidated |= Flag(property);" ) ;
1389+ }
13491390 EndBlock ( ) ;
13501391 EndBlock ( ) ;
13511392
1352- AppendLine ( $ "public bool AreAllPropertiesSet() => __set == PropertiesAllSet;") ;
1393+ if ( useByteArray )
1394+ {
1395+ AppendLine ( $ "public bool AreAllPropertiesSet() => __set.AsSpan().SequenceEqual(PropertiesAllSet);") ;
1396+ }
1397+ else
1398+ {
1399+ AppendLine ( $ "public bool AreAllPropertiesSet() => __set == PropertiesAllSet;") ;
1400+ }
13531401
13541402 AppendLine ( "public void EnsureAllPropertiesSet()" ) ;
13551403 StartBlock ( ) ;
13561404 AppendLine ( "if (!AreAllPropertiesSet())" ) ;
13571405 StartBlock ( ) ;
1358- AppendLine ( "throw new DBusUnexpectedValueException($\" Not all properties have been set (0x{__set:x}).\" );" ) ;
1406+ if ( useByteArray )
1407+ {
1408+ AppendLine ( "throw new DBusUnexpectedValueException($\" Not all properties have been set ({BitConverter.ToString(__set)}).\" );" ) ;
1409+ }
1410+ else
1411+ {
1412+ AppendLine ( "throw new DBusUnexpectedValueException($\" Not all properties have been set (0x{__set:x}).\" );" ) ;
1413+ }
13591414 EndBlock ( ) ;
13601415 EndBlock ( ) ;
13611416
@@ -1395,15 +1450,32 @@ private void AppendPropertyTypes(string name, XElement interfaceXml, bool genera
13951450 AppendLine ( "while (reader.HasNext(invalidatedEnd))" ) ;
13961451 StartBlock ( ) ;
13971452 AppendLine ( "var propertyName = reader.ReadString();" ) ;
1398- AppendLine ( "props.__invalidated |= propertyName switch" ) ;
1399- StartBlock ( ) ;
1400- foreach ( var property in readableProperties )
1453+ if ( useByteArray )
14011454 {
1402- AppendLine ( $ "\" { property . Name } \" => Flag({ propertyEnumName } .{ property . NameUpper } ),") ;
1455+ AppendLine ( "switch (propertyName)" ) ;
1456+ StartBlock ( ) ;
1457+ foreach ( var property in readableProperties )
1458+ {
1459+ AppendLine ( $ "case \" { property . Name } \" :") ;
1460+ _indentation ++ ;
1461+ AppendLine ( $ "props.__invalidated[FlagIndex({ propertyEnumName } .{ property . NameUpper } )] |= FlagMask({ propertyEnumName } .{ property . NameUpper } );") ;
1462+ AppendLine ( "break;" ) ;
1463+ _indentation -- ;
1464+ }
1465+ EndBlock ( ) ;
1466+ }
1467+ else
1468+ {
1469+ AppendLine ( "props.__invalidated |= propertyName switch" ) ;
1470+ StartBlock ( ) ;
1471+ foreach ( var property in readableProperties )
1472+ {
1473+ AppendLine ( $ "\" { property . Name } \" => Flag({ propertyEnumName } .{ property . NameUpper } ),") ;
1474+ }
1475+ AppendLine ( "_ => 0" ) ;
1476+ _indentation -- ;
1477+ AppendLine ( "};" ) ;
14031478 }
1404- AppendLine ( "_ => 0" ) ;
1405- _indentation -- ;
1406- AppendLine ( "};" ) ;
14071479 EndBlock ( ) ; // while
14081480 EndBlock ( ) ; // if
14091481
0 commit comments