@@ -595,6 +595,91 @@ def test_vector_cython_deserializer(self):
595595 self .assertIn ('serialized size' , str (cm .exception ))
596596
597597
598+ def test_vector_cython_deserializer_variable_size_subtype (self ):
599+ """
600+ Test that DesVectorType falls back gracefully for variable-size subtypes.
601+ Variable-size types (e.g. UTF8Type) are not supported by the Cython fast path
602+ and should raise ValueError from DesVectorType._deserialize_generic.
603+ The pure Python VectorType.deserialize handles these correctly.
604+
605+ @since 3.x
606+ @expected_result Cython deserializer raises ValueError for variable-size subtypes;
607+ pure Python path correctly deserializes them
608+
609+ @test_category data_types:vector
610+ """
611+ try :
612+ from cassandra .deserializers import find_deserializer
613+ except ImportError :
614+ self .skipTest ('Cython deserializers not available' )
615+
616+ vt_text = VectorType .apply_parameters (['UTF8Type' , 3 ], {})
617+ des_text = find_deserializer (vt_text )
618+ self .assertEqual (des_text .__class__ .__name__ , 'DesVectorType' )
619+
620+ # Cython path should raise for variable-size subtypes
621+ data = vt_text .serialize (['abc' , 'def' , 'ghi' ], 5 )
622+ with self .assertRaises (ValueError ) as cm :
623+ des_text .deserialize_bytes (data , 5 )
624+ self .assertIn ('variable-size subtype' , str (cm .exception ))
625+
626+ # Pure Python path should work correctly
627+ result = vt_text .deserialize (data , 5 )
628+ self .assertEqual (result , ['abc' , 'def' , 'ghi' ])
629+
630+ def test_vector_numpy_large_deserialization (self ):
631+ """
632+ Test that large vectors (>= 32 elements) use the numpy deserialization path
633+ and return correct results for all supported numeric types.
634+
635+ @since 3.x
636+ @expected_result Large vectors are correctly deserialized (via numpy when available)
637+
638+ @test_category data_types:vector
639+ """
640+ import struct
641+ from cassandra .cqltypes import DoubleType
642+
643+ vector_size = 64 # >= 32 threshold for numpy path
644+
645+ # Float vector
646+ float_data = list (range (vector_size ))
647+ float_values = [float (x ) for x in float_data ]
648+ vt_float = VectorType .apply_parameters (['FloatType' , vector_size ], {})
649+ packed = struct .pack ('>%df' % vector_size , * float_values )
650+ result = vt_float .deserialize (packed , 5 )
651+ self .assertEqual (len (result ), vector_size )
652+ for i in range (vector_size ):
653+ self .assertAlmostEqual (result [i ], float_values [i ], places = 5 )
654+
655+ # Double vector
656+ double_values = [float (x ) * 1.1 for x in range (vector_size )]
657+ vt_double = VectorType .apply_parameters (['DoubleType' , vector_size ], {})
658+ packed = struct .pack ('>%dd' % vector_size , * double_values )
659+ result = vt_double .deserialize (packed , 5 )
660+ self .assertEqual (len (result ), vector_size )
661+ for i in range (vector_size ):
662+ self .assertAlmostEqual (result [i ], double_values [i ], places = 10 )
663+
664+ # Int32 vector
665+ int32_values = list (range (vector_size ))
666+ vt_int32 = VectorType .apply_parameters (['Int32Type' , vector_size ], {})
667+ packed = struct .pack ('>%di' % vector_size , * int32_values )
668+ result = vt_int32 .deserialize (packed , 5 )
669+ self .assertEqual (result , int32_values )
670+
671+ # Int64/Long vector
672+ int64_values = list (range (vector_size ))
673+ vt_int64 = VectorType .apply_parameters (['LongType' , vector_size ], {})
674+ packed = struct .pack ('>%dq' % vector_size , * int64_values )
675+ result = vt_int64 .deserialize (packed , 5 )
676+ self .assertEqual (result , int64_values )
677+
678+ # ShortType skipped: serial_size() returns None (pre-existing bug),
679+ # so VectorType.deserialize takes the variable-size path which fails.
680+ # ShortType struct.unpack works for small vectors via _vector_struct.
681+
682+
598683ZERO = datetime .timedelta (0 )
599684
600685
0 commit comments