1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
use crate::{
builder::Builder, errors::ErrorKind, slice_helpers::SliceWithStartOffset, Cursor, Offset,
Result, UnionOffset,
};
use core::mem::MaybeUninit;
#[doc(hidden)]
pub trait Primitive {
const ALIGNMENT: usize;
const ALIGNMENT_MASK: usize = Self::ALIGNMENT - 1;
const SIZE: usize;
}
/// Interface for getting a view into serialized data.
///
/// To get an owned variant use [`TryInto`] on the `Ref` type. Note that for
/// nested types with lots of sharing the owned variants can be much larger than
/// the serialized representation.
///
/// # Examples
///
/// ```no_run
/// use std::error::Error;
/// use planus::ReadAsRoot;
/// use planus_example::monster_generated::my_game::sample::{Monster, MonsterRef};
///
/// fn main() -> Result<(), Box<dyn Error>> {
/// let buf = std::fs::read("monster.bin")?;
/// let monster: MonsterRef<'_> = MonsterRef::read_as_root(&buf)?;
/// let monster_health = monster.hp()?;
/// let owned_monster: Monster = monster.try_into().expect("invalid monster");
/// Ok(())
/// }
pub trait ReadAsRoot<'a>: Sized {
/// Takes a slice assumed to be of this type and returns a view into it.
///
/// If the data is not valid for this type the field accessors will give
/// errors or invalid values, but will still be memory safe.
fn read_as_root(slice: &'a [u8]) -> Result<Self>;
}
/// Trait used by generated code to serialize primitive types.
pub trait WriteAs<P: Primitive> {
#[doc(hidden)]
type Prepared: WriteAsPrimitive<P>;
#[doc(hidden)]
fn prepare(&self, builder: &mut Builder) -> Self::Prepared;
}
/// Trait used by generated code to serialize primitive types with default values.
pub trait WriteAsDefault<P: Primitive, D: ?Sized> {
#[doc(hidden)]
type Prepared: WriteAsPrimitive<P>;
#[doc(hidden)]
fn prepare(&self, builder: &mut Builder, default: &D) -> Option<Self::Prepared>;
}
/// Trait used by generated code to serialize optional primitive types.
pub trait WriteAsOptional<P: Primitive> {
#[doc(hidden)]
type Prepared: WriteAsPrimitive<P>;
#[doc(hidden)]
fn prepare(&self, builder: &mut Builder) -> Option<Self::Prepared>;
}
/// Trait used by generated code to serialize offsets to already serialized data.
pub trait WriteAsOffset<T: ?Sized> {
#[doc(hidden)]
fn prepare(&self, builder: &mut Builder) -> Offset<T>;
}
/// Trait used by generated code to serialize offsets to unions.
pub trait WriteAsUnion<T: ?Sized> {
#[doc(hidden)]
fn prepare(&self, builder: &mut Builder) -> UnionOffset<T>;
}
/// Trait used by generated code to serialize offsets to optional unions.
pub trait WriteAsOptionalUnion<T: ?Sized> {
#[doc(hidden)]
fn prepare(&self, builder: &mut Builder) -> Option<UnionOffset<T>>;
}
#[doc(hidden)]
pub trait WriteAsPrimitive<P> {
fn write<const N: usize>(&self, cursor: Cursor<'_, N>, buffer_position: u32);
}
#[doc(hidden)]
pub trait TableRead<'buf>: Sized {
fn from_buffer(
buffer: SliceWithStartOffset<'buf>,
offset: usize,
) -> core::result::Result<Self, ErrorKind>;
}
#[doc(hidden)]
pub trait TableReadUnion<'buf>: Sized {
fn from_buffer(
buffer: SliceWithStartOffset<'buf>,
offset: usize,
tag: u8,
) -> core::result::Result<Self, ErrorKind>;
}
/// Trait used by generated code to read elements from vectors.
pub trait VectorRead<'buf> {
#[doc(hidden)]
const STRIDE: usize;
#[doc(hidden)]
unsafe fn from_buffer(buffer: SliceWithStartOffset<'buf>, offset: usize) -> Self;
}
/// This trait is a hack to get around the coherence restriction.
/// Ideally we would want to be able to do an `impl VectorRead<'buf> for planus::Result<MyType>`
/// in our generated code, however instead we do something like this:
/// impl<T: VectorReadInner<'buf>, E> VectorRead<'buf> for Result<T, E>
#[doc(hidden)]
pub trait VectorReadInner<'buf>: Sized {
#[doc(hidden)]
type Error: Sized;
#[doc(hidden)]
const STRIDE: usize;
#[doc(hidden)]
unsafe fn from_buffer(
buffer: SliceWithStartOffset<'buf>,
offset: usize,
) -> core::result::Result<Self, Self::Error>;
}
/// Trait used by generated code to write elements to vectors.
pub trait VectorWrite<P> {
#[doc(hidden)]
const STRIDE: usize;
#[doc(hidden)]
type Value: WriteAsPrimitive<P> + Sized;
#[doc(hidden)]
fn prepare(&self, builder: &mut Builder) -> Self::Value;
#[doc(hidden)]
unsafe fn write_values(
values: &[Self::Value],
bytes: *mut MaybeUninit<u8>,
buffer_position: u32,
);
}