ab_contracts_io_type/
lib.rs

1#![feature(maybe_uninit_slice, non_null_from_ref)]
2#![no_std]
3
4pub mod maybe_data;
5pub mod metadata;
6pub mod trivial_type;
7pub mod variable_bytes;
8pub mod variable_elements;
9
10use crate::trivial_type::TrivialType;
11use core::ops::{Deref, DerefMut};
12use core::ptr::NonNull;
13
14/// The maximum alignment supported by [`IoType`] types (16 bytes, corresponds to alignment of
15/// `u128`)
16pub const MAX_ALIGNMENT: u8 = 16;
17
18const _: () = {
19    assert!(
20        size_of::<usize>() >= size_of::<u32>(),
21        "At least 32-bit platform required"
22    );
23
24    // Only support little-endian environments, in big-endian byte order will be different, and
25    // it'll not be possible to simply send bytes of data structures that implement `TrivialType`
26    // from host to guest environment
27    assert!(
28        u16::from_ne_bytes(1u16.to_le_bytes()) == 1u16,
29        "Only little-endian platform supported"
30    );
31
32    // Max alignment is expected to match that of `u128`
33    assert!(
34        align_of::<u128>() == MAX_ALIGNMENT as usize,
35        "Max alignment mismatch"
36    );
37
38    // Only support targets with expected alignment and refuse to compile on other targets
39    assert!(align_of::<()>() == 1, "Unsupported alignment of `()`");
40    assert!(align_of::<u8>() == 1, "Unsupported alignment of `u8`");
41    assert!(align_of::<u16>() == 2, "Unsupported alignment of `u16`");
42    assert!(align_of::<u32>() == 4, "Unsupported alignment of `u32`");
43    assert!(align_of::<u64>() == 8, "Unsupported alignment of `u64`");
44    assert!(align_of::<u128>() == 16, "Unsupported alignment of `u128`");
45    assert!(align_of::<i8>() == 1, "Unsupported alignment of `i8`");
46    assert!(align_of::<i16>() == 2, "Unsupported alignment of `i16`");
47    assert!(align_of::<i32>() == 4, "Unsupported alignment of `i32`");
48    assert!(align_of::<i64>() == 8, "Unsupported alignment of `i64`");
49    assert!(align_of::<i128>() == 16, "Unsupported alignment of `i128`");
50};
51
52struct DerefWrapper<T>(T);
53
54impl<T> Deref for DerefWrapper<T> {
55    type Target = T;
56
57    #[inline(always)]
58    fn deref(&self) -> &Self::Target {
59        &self.0
60    }
61}
62
63impl<T> DerefMut for DerefWrapper<T> {
64    #[inline(always)]
65    fn deref_mut(&mut self) -> &mut Self::Target {
66        &mut self.0
67    }
68}
69
70// TODO: A way to point output types to input types in order to avoid unnecessary memory copy
71//  (setting a pointer)
72/// Trait that is used for types that are crossing host/guest boundary in contracts.
73///
74/// Crucially, it is implemented for any type that implements [`TrivialType`] and for
75/// [`VariableBytes`](crate::variable_bytes::VariableBytes).
76///
77/// # Safety
78/// This trait is used for types with memory transmutation capabilities, it must not be relied on
79/// with untrusted data. Serializing and deserializing of types that implement this trait is simply
80/// casting of underlying memory. As a result, all the types implementing this trait must not use
81/// implicit padding, unions or anything similar that might make it unsound to access any bits of
82/// the type.
83///
84/// Helper functions are provided to make casting to/from bytes a bit safer than it would otherwise,
85/// but extra care is still needed.
86///
87/// **Do not implement this trait explicitly!** Use `#[derive(TrivialType)]` instead, which will
88/// ensure safety requirements are upheld, or use `VariableBytes` if more flexibility is needed.
89///
90/// In case of variable state size is needed, create a wrapper struct around `VariableBytes` and
91/// implement traits on it by forwarding everything to inner implementation.
92pub unsafe trait IoType {
93    /// Data structure metadata in binary form, describing shape and types of the contents, see
94    /// [`IoTypeMetadataKind`] for encoding details
95    ///
96    /// [`IoTypeMetadataKind`]: crate::metadata::IoTypeMetadataKind
97    const METADATA: &[u8];
98
99    /// Pointer with trivial type that this `IoType` represents
100    type PointerType: TrivialType;
101
102    /// Number of bytes that are currently used to store data
103    fn size(&self) -> u32;
104
105    /// Pointer to the number of bytes that are currently used to store data.
106    ///
107    /// # Safety
108    /// While calling this function is technically safe, it and allows to ignore many of its
109    /// invariants, so requires extra care. In particular, no modifications must be done to the
110    /// value while this returned pointer might be used and no changes must be done through the
111    /// returned pointer. Also, lifetimes are only superficial here and can be easily (and
112    /// incorrectly) ignored by using `Copy`.
113    unsafe fn size_ptr(&self) -> impl Deref<Target = NonNull<u32>>;
114
115    /// An exclusive pointer to the number of bytes that are currently used to store data.
116    ///
117    /// NOTE: Pointer might be `null` for [`TrivialType`]s that don't store size internally, in
118    /// which case type's capacity should be used as size.
119    ///
120    /// # Safety
121    /// While calling this function is technically safe, it and allows to ignore many of its
122    /// invariants, so requires extra care. In particular, the value's contents must not be read or
123    /// written to while returned point might be used. Also, lifetimes are only superficial here and
124    /// can be easily (and incorrectly) ignored by using `Copy`.
125    unsafe fn size_mut_ptr(&mut self) -> impl DerefMut<Target = *mut u32>;
126
127    /// Number of bytes are allocated right now
128    fn capacity(&self) -> u32;
129
130    /// Number of bytes are allocated right now
131    ///
132    /// # Safety
133    /// While calling this function is technically safe, it and allows to ignore many of its
134    /// invariants, so requires extra care. In particular, no modifications must be done to the
135    /// value while this returned pointer might be used and no changes must be done through the
136    /// returned pointer. Also, lifetimes are only superficial here and can be easily (and
137    /// incorrectly) ignored by using `Copy`.
138    unsafe fn capacity_ptr(&self) -> impl Deref<Target = NonNull<u32>>;
139
140    /// Set the number of used bytes
141    ///
142    /// # Safety
143    /// `size` must be set to number of properly initialized bytes
144    unsafe fn set_size(&mut self, size: u32);
145
146    /// Create a reference to a type, which is represented by provided memory.
147    ///
148    /// Memory must be correctly aligned and sufficient in size, but padding beyond the size of the
149    /// type is allowed. Memory behind a pointer must not be written to in the meantime either.
150    ///
151    /// Only `size` are guaranteed to be allocated for types that can store variable amount of
152    /// data due to read-only nature of read-only access here.
153    ///
154    /// # Panics
155    /// Panics if `size` is a `null` pointer in case of non-[`TrivialType`]
156    ///
157    /// # Safety
158    /// Input bytes must be previously produced by taking underlying bytes of the same type.
159    // `impl Deref` is used to tie lifetime of returned value to inputs, but still treat it as a
160    // shared reference for most practical purposes. While lifetime here is somewhat superficial due
161    // to `Copy` nature of the value, it must be respected. Size must point to properly initialized
162    // memory.
163    #[track_caller]
164    unsafe fn from_ptr<'a>(
165        ptr: &'a NonNull<Self::PointerType>,
166        size: &'a u32,
167        capacity: u32,
168    ) -> impl Deref<Target = Self> + 'a;
169
170    /// Create a mutable reference to a type, which is represented by provided memory.
171    ///
172    /// Memory must be correctly aligned and sufficient in size or else `None` will be returned, but
173    /// padding beyond the size of the type is allowed. Memory behind a pointer must not be read or
174    /// written to in the meantime either.
175    ///
176    /// `size` indicates how many bytes are used within larger allocation for types that can
177    /// store variable amount of data.
178    ///
179    /// # Panics
180    /// Panics if `size` is a `null` pointer in case of non-[`TrivialType`]
181    ///
182    /// # Safety
183    /// Input bytes must be previously produced by taking underlying bytes of the same type.
184    // `impl DerefMut` is used to tie lifetime of returned value to inputs, but still treat it as an
185    // exclusive reference for most practical purposes. While lifetime here is somewhat superficial
186    // due to `Copy` nature of the value, it must be respected. Size must point to properly
187    // initialized memory for non-[`TrivialType`].
188    #[track_caller]
189    unsafe fn from_mut_ptr<'a>(
190        ptr: &'a mut NonNull<Self::PointerType>,
191        size: &'a mut *mut u32,
192        capacity: u32,
193    ) -> impl DerefMut<Target = Self> + 'a;
194
195    /// Get a raw pointer to the underlying data with no checks.
196    ///
197    /// # Safety
198    /// While calling this function is technically safe, it and allows to ignore many of its
199    /// invariants, so requires extra care. In particular, no modifications must be done to the
200    /// value while this returned pointer might be used and no changes must be done through the
201    /// returned pointer. Also, lifetimes are only superficial here and can be easily (and
202    /// incorrectly) ignored by using `Copy`.
203    unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>>;
204
205    /// Get an exclusive raw pointer to the underlying data with no checks.
206    ///
207    /// # Safety
208    /// While calling this function is technically safe, it and allows to ignore many of its
209    /// invariants, so requires extra care. In particular, the value's contents must not be read or
210    /// written to while returned point might be used. Also, lifetimes are only superficial here and
211    /// can be easily (and incorrectly) ignored by using `Copy`.
212    unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>>;
213}
214
215/// Marker trait, companion to [`IoType`] that indicates the ability to store optional contents
216pub trait IoTypeOptional: IoType {}