@@ -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" . 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) ) ?,
@@ -1467,7 +1476,8 @@ fn bit_array<'a>(
1467
1476
if segment. type_ == crate :: type_:: int ( ) {
1468
1477
match ( details. size_value , segment. value . as_ref ( ) ) {
1469
1478
( Some ( size_value) , Constant :: Int { int_value, .. } )
1470
- if size_value <= SAFE_INT_SEGMENT_MAX_SIZE . into ( ) =>
1479
+ if size_value <= SAFE_INT_SEGMENT_MAX_SIZE . into ( )
1480
+ && ( & size_value % BigInt :: from ( 8 ) == BigInt :: ZERO ) =>
1471
1481
{
1472
1482
let bytes = bit_array_segment_int_value_to_bytes (
1473
1483
int_value. clone ( ) ,
@@ -1521,8 +1531,23 @@ fn bit_array<'a>(
1521
1531
Ok ( docvec ! [ "codepointBits(" , value, ")" ] )
1522
1532
}
1523
1533
1524
- // Bit strings
1525
- [ Opt :: Bits { .. } ] => Ok ( docvec ! [ value, ".buffer" ] ) ,
1534
+ // Bit arrays
1535
+ [ Opt :: Bits { .. } ] => Ok ( value) ,
1536
+
1537
+ // Bit arrays with explicit size. The explicit size slices the bit array to the
1538
+ // specified size. A runtime exception is thrown if the size exceeds the number
1539
+ // of bits in the bit array.
1540
+ [ Opt :: Bits { .. } , Opt :: Size { value : size, .. } ]
1541
+ | [ Opt :: Size { value : size, .. } , Opt :: Bits { .. } ] => match & * * size {
1542
+ Constant :: Int { value : size, .. } => {
1543
+ Ok ( docvec ! [ value, ".slice(0, " , size, ")" ] )
1544
+ }
1545
+
1546
+ _ => Err ( Error :: Unsupported {
1547
+ feature : "This bit array segment option" . into ( ) ,
1548
+ location : segment. location ,
1549
+ } ) ,
1550
+ } ,
1526
1551
1527
1552
// Anything else
1528
1553
_ => Err ( Error :: Unsupported {
@@ -1585,15 +1610,6 @@ fn sized_bit_array_segment_details<'a>(
1585
1610
_ => None ,
1586
1611
} ;
1587
1612
1588
- if let Some ( size_value) = size_value. as_ref ( ) {
1589
- if * size_value > BigInt :: ZERO && size_value % 8 != BigInt :: ZERO {
1590
- return Err ( Error :: Unsupported {
1591
- feature : "Non byte aligned array" . into ( ) ,
1592
- location : segment. location ,
1593
- } ) ;
1594
- }
1595
- }
1596
-
1597
1613
( size_value, constant_expr_fun ( tracker, size) ?)
1598
1614
}
1599
1615
_ => {
0 commit comments