@@ -16,6 +16,7 @@ use rustler::{Encoder, Env, NewBinary, Term};
1616use serde:: de:: { self , DeserializeSeed , MapAccess , SeqAccess , Visitor } ;
1717use serde:: Deserialize ;
1818use std:: fmt;
19+ use std:: mem:: MaybeUninit ;
1920
2021use crate :: atoms;
2122use crate :: nif_util:: make_tuple2;
@@ -40,6 +41,14 @@ fn make_binary_term(env: Env, s: &str) -> ERL_NIF_TERM {
4041 term. as_c_arg ( )
4142}
4243
44+ /// View the initialized `count`-element prefix of a MaybeUninit stack array.
45+ ///
46+ /// SAFETY: callers must have written `arr[..count]` before calling.
47+ #[ inline]
48+ unsafe fn stack_slice ( arr : & [ MaybeUninit < ERL_NIF_TERM > ] , count : usize ) -> & [ ERL_NIF_TERM ] {
49+ std:: slice:: from_raw_parts ( arr. as_ptr ( ) as * const ERL_NIF_TERM , count)
50+ }
51+
4352/// Try to create a sub-binary; fall back to copy if the str is not in the input buffer.
4453#[ inline]
4554fn make_str_term ( env : Env , input : InputRef , s : & str ) -> ERL_NIF_TERM {
@@ -189,7 +198,8 @@ impl<'de, 'a> Visitor<'de> for TermVisitor<'a> {
189198 let input = self . input ;
190199
191200 if hint <= STACK_SIZE {
192- let mut stack: [ ERL_NIF_TERM ; STACK_SIZE ] = [ 0 ; STACK_SIZE ] ;
201+ let mut stack: [ MaybeUninit < ERL_NIF_TERM > ; STACK_SIZE ] =
202+ [ MaybeUninit :: uninit ( ) ; STACK_SIZE ] ;
193203 let mut count = 0 ;
194204
195205 while count < STACK_SIZE {
@@ -199,19 +209,23 @@ impl<'de, 'a> Visitor<'de> for TermVisitor<'a> {
199209 depth : child_depth,
200210 } ) ? {
201211 Some ( term) => {
202- stack[ count] = term;
212+ stack[ count] . write ( term) ;
203213 count += 1 ;
204214 }
205215 None => {
206216 return Ok ( unsafe {
207- enif_make_list_from_array ( env. as_c_arg ( ) , stack. as_ptr ( ) , count as u32 )
217+ enif_make_list_from_array (
218+ env. as_c_arg ( ) ,
219+ stack. as_ptr ( ) as * const ERL_NIF_TERM ,
220+ count as u32 ,
221+ )
208222 } ) ;
209223 }
210224 }
211225 }
212226
213227 let mut heap = Vec :: with_capacity ( STACK_SIZE * 2 ) ;
214- heap. extend_from_slice ( & stack[ ..count ] ) ;
228+ heap. extend ( stack. iter ( ) . map ( |s| unsafe { s . assume_init ( ) } ) ) ;
215229 while let Some ( term) = seq. next_element_seed ( TermSeed {
216230 env,
217231 input,
@@ -247,8 +261,10 @@ impl<'de, 'a> Visitor<'de> for TermVisitor<'a> {
247261 let input = self . input ;
248262
249263 if hint <= STACK_SIZE {
250- let mut key_stack: [ ERL_NIF_TERM ; STACK_SIZE ] = [ 0 ; STACK_SIZE ] ;
251- let mut val_stack: [ ERL_NIF_TERM ; STACK_SIZE ] = [ 0 ; STACK_SIZE ] ;
264+ let mut key_stack: [ MaybeUninit < ERL_NIF_TERM > ; STACK_SIZE ] =
265+ [ MaybeUninit :: uninit ( ) ; STACK_SIZE ] ;
266+ let mut val_stack: [ MaybeUninit < ERL_NIF_TERM > ; STACK_SIZE ] =
267+ [ MaybeUninit :: uninit ( ) ; STACK_SIZE ] ;
252268 let mut count = 0 ;
253269
254270 while count < STACK_SIZE {
@@ -259,20 +275,22 @@ impl<'de, 'a> Visitor<'de> for TermVisitor<'a> {
259275 input,
260276 depth : child_depth,
261277 } ) ?;
262- key_stack[ count] = key;
263- val_stack[ count] = val;
278+ key_stack[ count] . write ( key) ;
279+ val_stack[ count] . write ( val) ;
264280 count += 1 ;
265281 }
266282 None => {
267- return build_map ( env, & key_stack[ ..count] , & val_stack[ ..count] , count) ;
283+ let keys = unsafe { stack_slice ( & key_stack, count) } ;
284+ let vals = unsafe { stack_slice ( & val_stack, count) } ;
285+ return build_map ( env, keys, vals, count) ;
268286 }
269287 }
270288 }
271289
272290 let mut keys = Vec :: with_capacity ( STACK_SIZE * 2 ) ;
273291 let mut vals = Vec :: with_capacity ( STACK_SIZE * 2 ) ;
274- keys. extend_from_slice ( & key_stack[ ..count ] ) ;
275- vals. extend_from_slice ( & val_stack[ ..count ] ) ;
292+ keys. extend ( key_stack. iter ( ) . map ( |s| unsafe { s . assume_init ( ) } ) ) ;
293+ vals. extend ( val_stack. iter ( ) . map ( |s| unsafe { s . assume_init ( ) } ) ) ;
276294 while let Some ( key) = map. next_key_seed ( KeySeed { env, input } ) ? {
277295 let val = map. next_value_seed ( TermSeed {
278296 env,
0 commit comments