@@ -2243,6 +2243,7 @@ mod _sqlite {
22432243 let inner = self . inner ( vm) ?;
22442244
22452245 if let Some ( index) = needle. try_index_opt ( vm) {
2246+ // Handle single item assignment: blob[i] = b
22462247 let Some ( value) = value. downcast_ref :: < PyInt > ( ) else {
22472248 return Err ( vm. new_type_error ( format ! (
22482249 "'{}' object cannot be interpreted as an integer" ,
@@ -2255,11 +2256,63 @@ mod _sqlite {
22552256 Self :: expect_write ( blob_len, 1 , index, vm) ?;
22562257 let ret = inner. blob . write_single ( value, index) ;
22572258 self . check ( ret, vm)
2258- } else if let Some ( _slice) = needle. downcast_ref :: < PySlice > ( ) {
2259- Err ( vm. new_not_implemented_error ( "Blob slice assignment is not implemented" ) )
2260- // let blob_len = inner.blob.bytes();
2261- // let slice = slice.to_saturated(vm)?;
2262- // let (range, step, length) = slice.adjust_indices(blob_len as usize);
2259+ } else if let Some ( slice) = needle. downcast_ref :: < PySlice > ( ) {
2260+ // Handle slice assignment: blob[a:b:c] = b"..."
2261+ let value_buf = PyBuffer :: try_from_borrowed_object ( vm, & value) ?;
2262+
2263+ let buf = value_buf. as_contiguous ( ) . ok_or_else ( || {
2264+ vm. new_buffer_error ( "a contiguous buffer object is required" . to_owned ( ) )
2265+ } ) ?;
2266+
2267+ let blob_len = inner. blob . bytes ( ) ;
2268+ let slice = slice. to_saturated ( vm) ?;
2269+ let ( range, step, slice_len) = slice. adjust_indices ( blob_len as usize ) ;
2270+
2271+ if step == 0 {
2272+ return Err ( vm. new_value_error ( "step cannot be zero" . to_owned ( ) ) ) ;
2273+ }
2274+
2275+ if buf. len ( ) != slice_len {
2276+ return Err ( vm. new_index_error ( "wrong size" . to_owned ( ) ) ) ;
2277+ }
2278+
2279+ if slice_len == 0 {
2280+ return Ok ( ( ) ) ;
2281+ }
2282+
2283+ if step == 1 {
2284+ // Fast path for simple slices (step=1).
2285+ let ret = inner. blob . write (
2286+ buf. as_ptr ( ) . cast ( ) ,
2287+ buf. len ( ) as c_int ,
2288+ range. start as c_int ,
2289+ ) ;
2290+ self . check ( ret, vm)
2291+ } else {
2292+ // "Read-modify-write" strategy for extended slices (step != 1).
2293+ let span_len = ( range. end - range. start ) as usize ;
2294+ let mut temp_buf = vec ! [ 0u8 ; span_len] ;
2295+
2296+ let ret = inner. blob . read (
2297+ temp_buf. as_mut_ptr ( ) . cast ( ) ,
2298+ span_len as c_int ,
2299+ range. start as c_int ,
2300+ ) ;
2301+ self . check ( ret, vm) ?;
2302+
2303+ let mut i_in_temp: usize = 0 ;
2304+ for i_in_src in 0 ..slice_len {
2305+ temp_buf[ i_in_temp] = buf[ i_in_src] ;
2306+ i_in_temp += step as usize ;
2307+ }
2308+
2309+ let ret = inner. blob . write (
2310+ temp_buf. as_ptr ( ) . cast ( ) ,
2311+ span_len as c_int ,
2312+ range. start as c_int ,
2313+ ) ;
2314+ self . check ( ret, vm)
2315+ }
22632316 } else {
22642317 Err ( vm. new_type_error ( "Blob indices must be integers" ) )
22652318 }
0 commit comments