@@ -173,6 +173,21 @@ impl<const MAX_PAGES: usize> IsolatedMemory<MAX_PAGES> {
173173 store_f64_inner ( self . flat_mut ( ) , active, offset, value)
174174 }
175175
176+ /// Initialize a region of memory from a byte slice (Wasm data segment).
177+ ///
178+ /// Copies `data` into linear memory starting at `offset`. Equivalent to
179+ /// calling `store_u8` for each byte, but avoids emitting N separate
180+ /// function calls in generated code.
181+ ///
182+ /// # Errors
183+ /// Returns `Err(WasmTrap::OutOfBounds)` if `offset + data.len()` exceeds
184+ /// `active_pages * PAGE_SIZE`.
185+ #[ inline( always) ]
186+ pub fn init_data ( & mut self , offset : usize , data : & [ u8 ] ) -> WasmResult < ( ) > {
187+ let active = self . active_size ( ) ;
188+ init_data_inner ( self . flat_mut ( ) , active, offset, data)
189+ }
190+
176191 // ── Unchecked (verified) load/store ───────────────────────────────
177192 //
178193 // These skip bounds checking entirely. The caller MUST guarantee that
@@ -387,6 +402,18 @@ fn store_f64_inner(
387402 Ok ( ( ) )
388403}
389404
405+ #[ inline( never) ]
406+ fn init_data_inner (
407+ memory : & mut [ u8 ] ,
408+ active_bytes : usize ,
409+ offset : usize ,
410+ data : & [ u8 ] ,
411+ ) -> WasmResult < ( ) > {
412+ let dst = checked_slice_mut ( memory, active_bytes, offset, data. len ( ) ) ?;
413+ dst. copy_from_slice ( data) ;
414+ Ok ( ( ) )
415+ }
416+
390417// ── Unchecked inner functions ─────────────────────────────────────────
391418//
392419// SAFETY: the caller (verified backend) guarantees the offset is in-bounds,
@@ -623,6 +650,50 @@ mod tests {
623650 assert_eq ! ( mem. load_i32( PAGE_SIZE ) , Ok ( 99 ) ) ;
624651 }
625652
653+ // ── init_data ──
654+
655+ #[ test]
656+ fn init_data_writes_bytes ( ) {
657+ let mut mem = Mem :: try_new ( 1 ) . unwrap ( ) ;
658+ mem. init_data ( 10 , & [ 1u8 , 2 , 3 , 4 ] ) . unwrap ( ) ;
659+ assert_eq ! ( mem. load_u8( 10 ) . unwrap( ) , 1 ) ;
660+ assert_eq ! ( mem. load_u8( 11 ) . unwrap( ) , 2 ) ;
661+ assert_eq ! ( mem. load_u8( 12 ) . unwrap( ) , 3 ) ;
662+ assert_eq ! ( mem. load_u8( 13 ) . unwrap( ) , 4 ) ;
663+ }
664+
665+ #[ test]
666+ fn init_data_empty_slice_is_noop ( ) {
667+ let mut mem = Mem :: try_new ( 1 ) . unwrap ( ) ;
668+ assert ! ( mem. init_data( 0 , & [ ] ) . is_ok( ) ) ;
669+ }
670+
671+ #[ test]
672+ fn init_data_out_of_bounds ( ) {
673+ let mut mem = Mem :: try_new ( 1 ) . unwrap ( ) ;
674+ let data = [ 0u8 ; 10 ] ;
675+ assert_eq ! (
676+ mem. init_data( PAGE_SIZE - 5 , & data) ,
677+ Err ( WasmTrap :: OutOfBounds )
678+ ) ;
679+ }
680+
681+ #[ test]
682+ fn init_data_at_boundary ( ) {
683+ let mut mem = Mem :: try_new ( 1 ) . unwrap ( ) ;
684+ let data = [ 42u8 ; 4 ] ;
685+ assert ! ( mem. init_data( PAGE_SIZE - 4 , & data) . is_ok( ) ) ;
686+ assert_eq ! ( mem. load_u8( PAGE_SIZE - 1 ) . unwrap( ) , 42 ) ;
687+ }
688+
689+ #[ test]
690+ fn init_data_overwrites_existing ( ) {
691+ let mut mem = Mem :: try_new ( 1 ) . unwrap ( ) ;
692+ mem. store_u8 ( 5 , 0xFF ) . unwrap ( ) ;
693+ mem. init_data ( 5 , & [ 0xABu8 ] ) . unwrap ( ) ;
694+ assert_eq ! ( mem. load_u8( 5 ) . unwrap( ) , 0xAB ) ;
695+ }
696+
626697 // ── little-endian encoding ──
627698
628699 #[ test]
0 commit comments