@ -19,14 +19,16 @@ use std::cell::UnsafeCell;
use std ::ffi ::c_int ;
use std ::ffi ::c_int ;
use std ::fmt ;
use std ::fmt ;
use std ::marker ::PhantomData ;
use std ::marker ::PhantomData ;
use std ::mem ::{ size_of , ManuallyDrop , MaybeUninit } ;
use std ::mem ::{ align_of , size_of , ManuallyDrop , MaybeUninit } ;
use std ::ops ::Deref ;
use std ::ops ::Deref ;
use std ::ptr ::{ self , NonNull } ;
use std ::ptr ::{ self , NonNull } ;
use std ::slice ;
use std ::slice ;
use std ::sync ::{ Once , OnceLock } ;
use std ::sync ::OnceLock ;
/// See `upb/port/def.inc`.
/// See `upb/port/def.inc`.
const UPB_MALLOC_ALIGN : usize = 8 ;
const UPB_MALLOC_ALIGN : usize = 8 ;
const _CHECK_UPB_MALLOC_ALIGN_AT_LEAST_POINTER_ALIGNED : ( ) =
assert! ( UPB_MALLOC_ALIGN > = align_of ::< * const ( ) > ( ) ) ;
/// A wrapper over a `upb_Arena`.
/// A wrapper over a `upb_Arena`.
///
///
@ -148,37 +150,23 @@ impl Drop for Arena {
}
}
}
}
static mut INTERNAL_PTR : Option < RawMessage > = None ;
/// The scratch size of 64 KiB matches the maximum supported size that a
static INIT : Once = Once ::new ( ) ;
/// upb_Message can possibly be.
// The scratch size of 64 KiB matches the maximum supported size that a
// upb_Message can possibly be.
// TODO: Allow dynamic sized ScratchSpace.
const UPB_SCRATCH_SPACE_BYTES : usize = 65_536 ;
const UPB_SCRATCH_SPACE_BYTES : usize = 65_536 ;
const ALIGN : usize = 32 ;
/// Holds a zero-initialized block of memory for use by upb.
/// Holds a zero-initialized block of memory for use by upb.
///
/// By default, if a message is not set in cpp, a default message is created.
/// By default, if a message is not set in cpp, a default message is created.
/// upb departs from this and returns a null ptr. However, since contiguous
/// upb departs from this and returns a null ptr. However, since contiguous
/// chunks of memory filled with zeroes are legit messages from upb's point of
/// chunks of memory filled with zeroes are legit messages from upb's point of
/// view, we can allocate a large block and refer to that when dealing
/// view, we can allocate a large block and refer to that when dealing
/// with readonly access.
/// with readonly access.
pub struct ScratchSpace ;
#[ repr(C, align(8)) ] // align to UPB_MALLOC_ALIGN = 8
pub struct ScratchSpace ( [ u8 ; UPB_SCRATCH_SPACE_BYTES ] ) ;
impl ScratchSpace {
impl ScratchSpace {
pub fn zeroed_block ( _private : Private ) -> RawMessage {
pub fn zeroed_block ( _private : Private ) -> RawMessage {
unsafe {
static ZEROED_BLOCK : ScratchSpace = ScratchSpace ( [ 0 ; UPB_SCRATCH_SPACE_BYTES ] ) ;
INIT . call_once ( | | {
NonNull ::from ( & ZEROED_BLOCK ) . cast ( )
let layout =
std ::alloc ::Layout ::from_size_align ( UPB_SCRATCH_SPACE_BYTES , ALIGN ) . unwrap ( ) ;
let Some ( ptr ) =
crate ::__internal ::RawMessage ::new ( std ::alloc ::alloc_zeroed ( layout ) . cast ( ) )
else {
std ::alloc ::handle_alloc_error ( layout )
} ;
INTERNAL_PTR = Some ( ptr )
} ) ;
INTERNAL_PTR . unwrap ( )
}
}
}
}
}