Skip to main content

IoType

Trait IoType 

Source
pub unsafe trait IoType {
    type PointerType: TrivialType;

    const METADATA: &[u8];

    // Required methods
    fn size(&self) -> u32;
    fn capacity(&self) -> u32;
    unsafe fn set_size(&mut self, size: u32);
    unsafe fn from_ptr<'a>(
        ptr: &'a NonNull<Self::PointerType>,
        size: &'a u32,
        capacity: u32,
    ) -> impl Deref<Target = Self> + 'a;
    unsafe fn from_mut_ptr<'a>(
        ptr: &'a mut NonNull<Self::PointerType>,
        size: &'a mut u32,
        capacity: u32,
    ) -> impl DerefMut<Target = Self> + 'a;
    unsafe fn try_from_ptr<'a>(
        ptr: &'a NonNull<Self::PointerType>,
        size: &'a u32,
        capacity: u32,
    ) -> Option<impl Deref<Target = Self> + 'a>;
    unsafe fn try_from_mut_ptr<'a>(
        ptr: &'a mut NonNull<Self::PointerType>,
        size: &'a mut u32,
        capacity: u32,
    ) -> Option<impl DerefMut<Target = Self> + 'a>;
    fn as_ptr(&self) -> NonNull<Self::PointerType>;
    fn as_mut_ptr(&mut self) -> NonNull<Self::PointerType>;
}
Expand description

Trait that is used for types that are crossing the host/guest boundary in contracts.

Crucially, it is implemented for any type that implements TrivialType and for VariableBytes.

§Safety

This trait is used for types with memory transmutation capabilities. Memory with untrusted contents is parsed with IoType::try_from_ptr() and IoType::try_from_mut_ptr(). Serializing and deserializing of types that implement this trait is simply casting of underlying memory. As a result, all the types implementing this trait must not use implicit padding, unions, or anything similar that might make it unsound to access any bits of the type. IoType::try_from_ptr() and IoType::try_from_mut_ptr() return Some only if IoType::from_ptr() and IoType::from_mut_ptr() with the same arguments would be sound.

Helper functions are provided to make casting to/from bytes a bit safer than it would otherwise, but extra care is still needed.

Do not implement this trait explicitly! Use #[derive(TrivialType)] instead, which will ensure safety requirements are upheld, or use VariableBytes or other provided wrapper types if more flexibility is needed.

In case of variable state size is needed, create a wrapper struct around VariableBytes and implement traits on it by forwarding everything to the inner implementation, including IoType::try_from_ptr() and IoType::try_from_mut_ptr().

Required Associated Constants§

Source

const METADATA: &[u8]

Data structure metadata in binary form, describing shape and types of the contents, see IoTypeMetadataKind for encoding details

Required Associated Types§

Source

type PointerType: TrivialType

Pointer with a trivial type that this IoType represents

Required Methods§

Source

fn size(&self) -> u32

Number of bytes that are currently used to store data

Source

fn capacity(&self) -> u32

Number of bytes are allocated right now

Source

unsafe fn set_size(&mut self, size: u32)

Set the number of used bytes.

§Safety

size must be valid for the type (see Self::try_from_ptr()) and not exceed the capacity, and that many bytes must be initialized. They don’t need to be a valid value of the type, but then the contents must not be accessed through this value until they are parsed, for example with Self::try_from_mut_ptr().

Source

unsafe fn from_ptr<'a>( ptr: &'a NonNull<Self::PointerType>, size: &'a u32, capacity: u32, ) -> impl Deref<Target = Self> + 'a

Create a reference to a type, which is represented by provided memory.

Memory must be correctly aligned and sufficient in size, but padding beyond the size of the type is allowed. Memory behind a pointer must not be written to in the meantime either.

Only size bytes are guaranteed to be allocated for types that can store a variable amount of data due to the read-only nature of read-only access here.

§Safety

The memory holds a valid value of the type with a valid size, for example one that Self::try_from_ptr() accepts.

Source

unsafe fn from_mut_ptr<'a>( ptr: &'a mut NonNull<Self::PointerType>, size: &'a mut u32, capacity: u32, ) -> impl DerefMut<Target = Self> + 'a

Create a mutable reference to a type, which is represented by provided memory.

Memory must be correctly aligned and sufficient in size, but padding beyond the size of the type is allowed. Memory behind a pointer must not be read or written to in the meantime either.

size indicates how many bytes are used within a larger allocation for types that can store a variable amount of data.

§Safety

The memory holds a valid value of the type with a valid size, for example one that Self::try_from_mut_ptr() accepts.

Source

unsafe fn try_from_ptr<'a>( ptr: &'a NonNull<Self::PointerType>, size: &'a u32, capacity: u32, ) -> Option<impl Deref<Target = Self> + 'a>

Create a reference to a type, which is represented by provided memory, if the memory holds a valid value.

In contrast to Self::from_ptr(), the contents are checked, None is returned if the first size bytes are not a valid value. Alignment, size and capacity are trusted like in Self::from_ptr() and only checked with debug assertions.

§Safety

ptr is aligned for Self::PointerType, size doesn’t exceed capacity, and both are valid for the type: size is the size of a TrivialType, 0 or the size of the data for MaybeData and a multiple of the element size for VariableElements, and the capacity of MaybeData is 0 or at least the size of the data. ptr is valid for reads of size bytes, which are initialized and not written to during the call and while the returned value exists.

Source

unsafe fn try_from_mut_ptr<'a>( ptr: &'a mut NonNull<Self::PointerType>, size: &'a mut u32, capacity: u32, ) -> Option<impl DerefMut<Target = Self> + 'a>

Like Self::try_from_ptr(), but returns an exclusive reference.

§Safety

ptr, size and capacity are valid as required by Self::try_from_ptr(), except that the capacity of MaybeData is at least the size of the data, since data can be written into it even if it is empty. ptr is valid for writes of capacity bytes and for reads of the first size, which are initialized, while the bytes after them may be uninitialized. The memory is not accessed otherwise during the call and while the returned value exists.

Source

fn as_ptr(&self) -> NonNull<Self::PointerType>

Get a raw pointer to the underlying data.

The pointer can be used for reading Self::size() bytes as long as the value is not modified, it must not be used for writing.

Source

fn as_mut_ptr(&mut self) -> NonNull<Self::PointerType>

Get an exclusive raw pointer to the underlying data.

The pointer can be used for reading Self::size() bytes and writing up to Self::capacity() bytes as long as the value is not accessed otherwise in the meantime. Self::set_size() needs to be called afterward if the number of initialized bytes changes.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl<Data> IoType for MaybeData<Data>
where Data: TrivialType, [(); _]:,

Source§

impl<Element, const RECOMMENDED_ALLOCATION: u32> IoType for VariableElements<Element, RECOMMENDED_ALLOCATION>
where Element: TrivialType, [(); _]:,

Source§

const METADATA: &[u8]

Source§

type PointerType = Element

Source§

impl<T> IoType for T
where T: TrivialType,

Source§

const METADATA: &[u8] = T::METADATA

Source§

type PointerType = T