@@ -14,10 +14,11 @@ pub(crate) mod _struct {
14
14
use crate :: {
15
15
builtins:: { float, PyBaseExceptionRef , PyBytesRef , PyStr , PyStrRef , PyTupleRef , PyTypeRef } ,
16
16
common:: str:: wchar_t,
17
- function:: { ArgBytesLike , ArgIntoBool , ArgMemoryBuffer , IntoPyObject , PosArgs } ,
17
+ function:: {
18
+ ArgAsciiBuffer , ArgBytesLike , ArgIntoBool , ArgMemoryBuffer , IntoPyObject , PosArgs ,
19
+ } ,
18
20
protocol:: PyIterReturn ,
19
21
slots:: { IteratorIterable , SlotConstructor , SlotIterator } ,
20
- utils:: Either ,
21
22
PyObjectRef , PyRef , PyResult , PyValue , TryFromObject , VirtualMachine ,
22
23
} ;
23
24
use crossbeam_utils:: atomic:: AtomicCell ;
@@ -211,24 +212,8 @@ pub(crate) mod _struct {
211
212
}
212
213
213
214
impl FormatSpec {
214
- fn decode_and_parse (
215
- vm : & VirtualMachine ,
216
- fmt : & Either < PyStrRef , PyBytesRef > ,
217
- ) -> PyResult < FormatSpec > {
218
- let decoded_fmt = match fmt {
219
- Either :: A ( string) => string. as_str ( ) ,
220
- Either :: B ( bytes) if bytes. is_ascii ( ) => std:: str:: from_utf8 ( bytes) . unwrap ( ) ,
221
- _ => {
222
- return Err ( vm. new_unicode_decode_error (
223
- "Struct format must be a ascii string" . to_owned ( ) ,
224
- ) )
225
- }
226
- } ;
227
- FormatSpec :: parse ( decoded_fmt, vm)
228
- }
229
-
230
- pub fn parse ( fmt : & str , vm : & VirtualMachine ) -> PyResult < FormatSpec > {
231
- let mut chars = fmt. bytes ( ) . peekable ( ) ;
215
+ pub fn parse ( fmt : & [ u8 ] , vm : & VirtualMachine ) -> PyResult < FormatSpec > {
216
+ let mut chars = fmt. iter ( ) . copied ( ) . peekable ( ) ;
232
217
233
218
// First determine "@", "<", ">","!" or "="
234
219
let endianness = parse_endianness ( & mut chars) ;
@@ -399,10 +384,10 @@ pub(crate) mod _struct {
399
384
let mut repeat = 0isize ;
400
385
while let Some ( b'0' ..=b'9' ) = chars. peek ( ) {
401
386
if let Some ( c) = chars. next ( ) {
402
- let current_digit = ( c as char ) . to_digit ( 10 ) . unwrap ( ) as isize ;
387
+ let current_digit = c - b'0' ;
403
388
repeat = repeat
404
389
. checked_mul ( 10 )
405
- . and_then ( |r| r. checked_add ( current_digit) )
390
+ . and_then ( |r| r. checked_add ( current_digit as _ ) )
406
391
. ok_or_else ( || OVERFLOW_MSG . to_owned ( ) ) ?;
407
392
}
408
393
}
@@ -486,20 +471,26 @@ pub(crate) mod _struct {
486
471
}
487
472
buffer_len - ( -offset as usize )
488
473
} else {
489
- if offset as usize >= buffer_len {
474
+ let offset = offset as usize ;
475
+ let ( op, op_action) = if is_pack {
476
+ ( "pack_into" , "packing" )
477
+ } else {
478
+ ( "unpack_from" , "unpacking" )
479
+ } ;
480
+ if offset >= buffer_len {
490
481
let msg = format ! (
491
482
"{op} requires a buffer of at least {required} bytes for {op_action} {needed} \
492
483
bytes at offset {offset} (actual buffer size is {buffer_len})",
493
- op = if is_pack { "pack_into" } else { "unpack_from" } ,
494
- op_action = if is_pack { "packing" } else { "unpacking" } ,
484
+ op = op ,
485
+ op_action = op_action ,
495
486
required = needed + offset as usize ,
496
487
needed = needed,
497
488
offset = offset,
498
489
buffer_len = buffer_len
499
490
) ;
500
491
return Err ( new_struct_error ( vm, msg) ) ;
501
492
}
502
- offset as usize
493
+ offset
503
494
} ;
504
495
505
496
if ( buffer_len - offset_from_start) < needed {
@@ -717,24 +708,20 @@ pub(crate) mod _struct {
717
708
}
718
709
719
710
#[ pyfunction]
720
- fn pack (
721
- fmt : Either < PyStrRef , PyBytesRef > ,
722
- args : PosArgs ,
723
- vm : & VirtualMachine ,
724
- ) -> PyResult < Vec < u8 > > {
725
- let format_spec = FormatSpec :: decode_and_parse ( vm, & fmt) ?;
711
+ fn pack ( fmt : ArgAsciiBuffer , args : PosArgs , vm : & VirtualMachine ) -> PyResult < Vec < u8 > > {
712
+ let format_spec = fmt. with_ref ( |bytes| FormatSpec :: parse ( bytes, vm) ) ?;
726
713
format_spec. pack ( args. into_vec ( ) , vm)
727
714
}
728
715
729
716
#[ pyfunction]
730
717
fn pack_into (
731
- fmt : Either < PyStrRef , PyBytesRef > ,
718
+ fmt : ArgAsciiBuffer ,
732
719
buffer : ArgMemoryBuffer ,
733
720
offset : isize ,
734
721
args : PosArgs ,
735
722
vm : & VirtualMachine ,
736
723
) -> PyResult < ( ) > {
737
- let format_spec = FormatSpec :: decode_and_parse ( vm , & fmt ) ?;
724
+ let format_spec = fmt . with_ref ( |bytes| FormatSpec :: parse ( bytes , vm ) ) ?;
738
725
let offset = get_buffer_offset ( buffer. len ( ) , offset, format_spec. size , true , vm) ?;
739
726
buffer. with_ref ( |data| format_spec. pack_into ( & mut data[ offset..] , args. into_vec ( ) , vm) )
740
727
}
@@ -757,11 +744,11 @@ pub(crate) mod _struct {
757
744
758
745
#[ pyfunction]
759
746
fn unpack (
760
- fmt : Either < PyStrRef , PyBytesRef > ,
747
+ fmt : ArgAsciiBuffer ,
761
748
buffer : ArgBytesLike ,
762
749
vm : & VirtualMachine ,
763
750
) -> PyResult < PyTupleRef > {
764
- let format_spec = FormatSpec :: decode_and_parse ( vm , & fmt ) ?;
751
+ let format_spec = fmt . with_ref ( |bytes| FormatSpec :: parse ( bytes , vm ) ) ?;
765
752
buffer. with_ref ( |buf| format_spec. unpack ( buf, vm) )
766
753
}
767
754
@@ -774,11 +761,11 @@ pub(crate) mod _struct {
774
761
775
762
#[ pyfunction]
776
763
fn unpack_from (
777
- fmt : Either < PyStrRef , PyBytesRef > ,
764
+ fmt : ArgAsciiBuffer ,
778
765
args : UpdateFromArgs ,
779
766
vm : & VirtualMachine ,
780
767
) -> PyResult < PyTupleRef > {
781
- let format_spec = FormatSpec :: decode_and_parse ( vm , & fmt ) ?;
768
+ let format_spec = fmt . with_ref ( |bytes| FormatSpec :: parse ( bytes , vm ) ) ?;
782
769
let offset =
783
770
get_buffer_offset ( args. buffer . len ( ) , args. offset , format_spec. size , false , vm) ?;
784
771
args. buffer
@@ -849,17 +836,17 @@ pub(crate) mod _struct {
849
836
850
837
#[ pyfunction]
851
838
fn iter_unpack (
852
- fmt : Either < PyStrRef , PyBytesRef > ,
839
+ fmt : ArgAsciiBuffer ,
853
840
buffer : ArgBytesLike ,
854
841
vm : & VirtualMachine ,
855
842
) -> PyResult < UnpackIterator > {
856
- let format_spec = FormatSpec :: decode_and_parse ( vm , & fmt ) ?;
843
+ let format_spec = fmt . with_ref ( |bytes| FormatSpec :: parse ( bytes , vm ) ) ?;
857
844
UnpackIterator :: new ( vm, format_spec, buffer)
858
845
}
859
846
860
847
#[ pyfunction]
861
- fn calcsize ( fmt : Either < PyStrRef , PyBytesRef > , vm : & VirtualMachine ) -> PyResult < usize > {
862
- let format_spec = FormatSpec :: decode_and_parse ( vm , & fmt ) ?;
848
+ fn calcsize ( fmt : ArgAsciiBuffer , vm : & VirtualMachine ) -> PyResult < usize > {
849
+ let format_spec = fmt . with_ref ( |bytes| FormatSpec :: parse ( bytes , vm ) ) ?;
863
850
Ok ( format_spec. size )
864
851
}
865
852
@@ -872,14 +859,15 @@ pub(crate) mod _struct {
872
859
}
873
860
874
861
impl SlotConstructor for PyStruct {
875
- type Args = Either < PyStrRef , PyBytesRef > ;
862
+ type Args = ArgAsciiBuffer ;
876
863
877
864
fn py_new ( cls : PyTypeRef , fmt : Self :: Args , vm : & VirtualMachine ) -> PyResult {
878
- let spec = FormatSpec :: decode_and_parse ( vm , & fmt ) ?;
865
+ let spec = fmt . with_ref ( |bytes| FormatSpec :: parse ( bytes , vm ) ) ?;
879
866
let fmt_str = match fmt {
880
- Either :: A ( s) => s,
881
- Either :: B ( b) => PyStr :: from ( std:: str:: from_utf8 ( b. as_bytes ( ) ) . unwrap ( ) )
882
- . into_ref_with_type ( vm, vm. ctx . types . str_type . clone ( ) ) ?,
867
+ ArgAsciiBuffer :: String ( s) => s,
868
+ buffer => buffer
869
+ . with_ref ( |bytes| PyStr :: from ( std:: str:: from_utf8 ( bytes) . unwrap ( ) ) )
870
+ . into_ref ( vm) ,
883
871
} ;
884
872
PyStruct { spec, fmt_str } . into_pyresult_with_type ( vm, cls)
885
873
}
0 commit comments