@@ -10,8 +10,8 @@ use crate::{
1010 } ,
1111 class:: StaticType ,
1212 function:: { ArgBytesLike , FuncArgs , PySetterValue } ,
13- protocol:: { BufferDescriptor , PyBuffer , PyMappingMethods , PyNumberMethods , PySequenceMethods } ,
14- types:: { AsBuffer , AsMapping , AsNumber , AsSequence , Constructor , Initializer } ,
13+ protocol:: { BufferDescriptor , PyBuffer , PyMappingMethods , PySequenceMethods } ,
14+ types:: { AsBuffer , AsMapping , AsSequence , Constructor , Initializer } ,
1515} ;
1616use alloc:: borrow:: Cow ;
1717use num_traits:: { Signed , ToPrimitive } ;
@@ -44,6 +44,27 @@ fn get_size_from_format(fmt: &str) -> usize {
4444 code. map_or ( 1 , |c| simple_type_size ( & c) . unwrap_or ( 1 ) )
4545}
4646
47+ pub ( super ) static CTYPE_SEQUENCE_METHODS : PySequenceMethods = PySequenceMethods {
48+ repeat : Some ( |seq, length, vm| repeat_type ( seq. obj , length, vm) ) ,
49+ ..PySequenceMethods :: NOT_IMPLEMENTED
50+ } ;
51+
52+ pub ( super ) fn repeat_type ( ctype : & PyObject , length : isize , vm : & VirtualMachine ) -> PyResult {
53+ if length < 0 {
54+ return Err ( vm. new_value_error ( format ! ( "Array length must be >= 0, not {length}" ) ) ) ;
55+ }
56+ let cls = ctype
57+ . downcast_ref :: < PyType > ( )
58+ . ok_or_else ( || vm. new_type_error ( "expected type" ) ) ?;
59+ if let Some ( info) = cls. stg_info_opt ( )
60+ && info. size != 0
61+ && length as usize > isize:: MAX as usize / info. size
62+ {
63+ return Err ( vm. new_overflow_error ( "array too large" ) ) ;
64+ }
65+ array_type_from_ctype ( ctype. to_owned ( ) , length as usize , vm)
66+ }
67+
4768/// Creates array type for (element_type, length)
4869/// Uses _array_type_cache to ensure identical calls return the same type object
4970pub ( super ) fn array_type_from_ctype (
@@ -305,7 +326,7 @@ impl Initializer for PyCArrayType {
305326 }
306327}
307328
308- #[ pyclass( flags( IMMUTABLETYPE ) , with( Initializer , AsNumber ) ) ]
329+ #[ pyclass( flags( IMMUTABLETYPE ) , with( Initializer , AsSequence ) ) ]
309330impl PyCArrayType {
310331 #[ pygetset( name = "__pointer_type__" ) ]
311332 fn pointer_type ( zelf : PyTypeRef , vm : & VirtualMachine ) -> PyResult {
@@ -350,41 +371,9 @@ impl PyCArrayType {
350371 }
351372}
352373
353- impl AsNumber for PyCArrayType {
354- fn as_number ( ) -> & ' static PyNumberMethods {
355- static AS_NUMBER : PyNumberMethods = PyNumberMethods {
356- multiply : Some ( |a, b, vm| {
357- // a is a type object whose metaclass is PyCArrayType (e.g., Array_5)
358- let n = b
359- . try_index ( vm) ?
360- . as_bigint ( )
361- . to_isize ( )
362- . ok_or_else ( || vm. new_overflow_error ( "array size too large" ) ) ?;
363-
364- if n < 0 {
365- return Err ( vm. new_value_error ( format ! ( "Array length must be >= 0, not {n}" ) ) ) ;
366- }
367-
368- // Check for overflow before creating the new array type
369- let zelf_type = a
370- . downcast_ref :: < PyType > ( )
371- . ok_or_else ( || vm. new_type_error ( "Expected type" ) ) ?;
372-
373- if let Some ( stg_info) = zelf_type. stg_info_opt ( ) {
374- let current_size = stg_info. size ;
375- // Check if current_size * n would overflow
376- if current_size != 0 && ( n as usize ) > isize:: MAX as usize / current_size {
377- return Err ( vm. new_overflow_error ( "array too large" ) ) ;
378- }
379- }
380-
381- // Use cached array type creation
382- // The element type of the new array is the current array type itself
383- array_type_from_ctype ( a. to_owned ( ) , n as usize , vm)
384- } ) ,
385- ..PyNumberMethods :: NOT_IMPLEMENTED
386- } ;
387- & AS_NUMBER
374+ impl AsSequence for PyCArrayType {
375+ fn as_sequence ( ) -> & ' static PySequenceMethods {
376+ & super :: array:: CTYPE_SEQUENCE_METHODS
388377 }
389378}
390379
0 commit comments