@@ -240,7 +240,8 @@ impl<'module> Generator<'module> {
240
240
if segment. type_ == crate :: type_:: int ( ) {
241
241
match ( details. size_value , segment. value . as_ref ( ) ) {
242
242
( Some ( size_value) , TypedExpr :: Int { int_value, .. } )
243
- if size_value <= SAFE_INT_SEGMENT_MAX_SIZE . into ( ) =>
243
+ if size_value <= SAFE_INT_SEGMENT_MAX_SIZE . into ( )
244
+ && ( & size_value % BigInt :: from ( 8 ) == BigInt :: ZERO ) =>
244
245
{
245
246
let bytes = bit_array_segment_int_value_to_bytes (
246
247
int_value. clone ( ) ,
@@ -295,7 +296,24 @@ impl<'module> Generator<'module> {
295
296
}
296
297
297
298
// Bit arrays
298
- [ Opt :: Bytes { .. } | Opt :: Bits { .. } ] => Ok ( docvec ! [ value, ".buffer" ] ) ,
299
+ [ Opt :: Bits { .. } ] => Ok ( value) ,
300
+
301
+ // Bit arrays with explicit size. The explicit size slices the bit array to the
302
+ // specified size. A runtime exception is thrown if the size exceeds the number
303
+ // of bits in the bit array.
304
+ [ Opt :: Bits { .. } , Opt :: Size { value : size, .. } ]
305
+ | [ Opt :: Size { value : size, .. } , Opt :: Bits { .. } ] => match & * * size {
306
+ TypedExpr :: Int { value : size, .. } => {
307
+ Ok ( docvec ! [ value, ".slice(0, " , size, ")" ] )
308
+ }
309
+
310
+ TypedExpr :: Var { name, .. } => Ok ( docvec ! [ value, ".slice(0, " , name, ")" ] ) ,
311
+
312
+ _ => Err ( Error :: Unsupported {
313
+ feature : "This bit array segment option UNREACHABLE" . into ( ) ,
314
+ location : segment. location ,
315
+ } ) ,
316
+ } ,
299
317
300
318
// Anything else
301
319
_ => Err ( Error :: Unsupported {
@@ -348,15 +366,6 @@ impl<'module> Generator<'module> {
348
366
_ => None ,
349
367
} ;
350
368
351
- if let Some ( size_value) = size_value. as_ref ( ) {
352
- if * size_value > BigInt :: ZERO && size_value % 8 != BigInt :: ZERO {
353
- return Err ( Error :: Unsupported {
354
- feature : "Non byte aligned array" . into ( ) ,
355
- location : segment. location ,
356
- } ) ;
357
- }
358
- }
359
-
360
369
(
361
370
size_value,
362
371
self . not_in_tail_position ( |gen| gen. wrap_expression ( size) ) ?,
@@ -1460,7 +1469,8 @@ fn bit_array<'a>(
1460
1469
if segment. type_ == crate :: type_:: int ( ) {
1461
1470
match ( details. size_value , segment. value . as_ref ( ) ) {
1462
1471
( Some ( size_value) , Constant :: Int { int_value, .. } )
1463
- if size_value <= SAFE_INT_SEGMENT_MAX_SIZE . into ( ) =>
1472
+ if size_value <= SAFE_INT_SEGMENT_MAX_SIZE . into ( )
1473
+ && ( & size_value % BigInt :: from ( 8 ) == BigInt :: ZERO ) =>
1464
1474
{
1465
1475
let bytes = bit_array_segment_int_value_to_bytes (
1466
1476
int_value. clone ( ) ,
@@ -1514,9 +1524,24 @@ fn bit_array<'a>(
1514
1524
Ok ( docvec ! [ "codepointBits(" , value, ")" ] )
1515
1525
}
1516
1526
1517
- // Bit strings
1527
+ // Bit arrays
1518
1528
[ Opt :: Bits { .. } ] => Ok ( docvec ! [ value, ".buffer" ] ) ,
1519
1529
1530
+ // Bit arrays with explicit size. The explicit size slices the bit array to the
1531
+ // specified size. A runtime exception is thrown if the size exceeds the number
1532
+ // of bits in the bit array.
1533
+ [ Opt :: Bits { .. } , Opt :: Size { value : size, .. } ]
1534
+ | [ Opt :: Size { value : size, .. } , Opt :: Bits { .. } ] => match & * * size {
1535
+ Constant :: Int { value : size, .. } => {
1536
+ Ok ( docvec ! [ value, ".slice(0, " , size, ")" ] )
1537
+ }
1538
+
1539
+ _ => Err ( Error :: Unsupported {
1540
+ feature : "This bit array segment option" . into ( ) ,
1541
+ location : segment. location ,
1542
+ } ) ,
1543
+ } ,
1544
+
1520
1545
// Anything else
1521
1546
_ => Err ( Error :: Unsupported {
1522
1547
feature : "This bit array segment option" . into ( ) ,
@@ -1578,15 +1603,6 @@ fn sized_bit_array_segment_details<'a>(
1578
1603
_ => None ,
1579
1604
} ;
1580
1605
1581
- if let Some ( size_value) = size_value. as_ref ( ) {
1582
- if * size_value > BigInt :: ZERO && size_value % 8 != BigInt :: ZERO {
1583
- return Err ( Error :: Unsupported {
1584
- feature : "Non byte aligned array" . into ( ) ,
1585
- location : segment. location ,
1586
- } ) ;
1587
- }
1588
- }
1589
-
1590
1606
( size_value, constant_expr_fun ( tracker, size) ?)
1591
1607
}
1592
1608
_ => {
0 commit comments