flatbuffers_util/
ownedfb.rs

1use flatbuffers::{Follow, InvalidFlatbuffer, Verifiable, root, root_unchecked};
2
3/// Stores the owned bytes of the flatbuffer type
4/// and can access the actual type.
5pub struct OwnedFB<T> {
6    buf: Box<[u8]>,
7    _phantom: std::marker::PhantomData<T>,
8}
9
10impl<T> OwnedFB<T> {
11    pub fn new<'a>(buf: &'a [u8]) -> OwnedFB<T>
12    where
13        T: Verifiable + Follow<'a> + 'a,
14    {
15        let _verified = root::<'a, T>(buf).expect("Invalid Flatbuffer");
16        unsafe { Self::new_boxed_unchecked(buf.to_owned().into_boxed_slice()) }
17    }
18
19    /// # Safety
20    /// Caller is responsible for verifying the buffer.
21    pub unsafe fn new_boxed_unchecked(buf: Box<[u8]>) -> Self {
22        Self {
23            buf,
24            _phantom: std::marker::PhantomData,
25        }
26    }
27
28    pub fn new_boxed(buf: Box<[u8]>) -> Result<OwnedFB<T>, InvalidFlatbuffer>
29    where
30        T: Verifiable + Follow<'static> + 'static,
31    {
32        check_flatbuffer::<T>(&buf)?;
33
34        Ok(unsafe { Self::new_boxed_unchecked(buf) })
35    }
36
37    pub fn get_ref<'a>(&'a self) -> <T as Follow<'a>>::Inner
38    where
39        T: Follow<'a>,
40    {
41        // Safety: We have already verified the buffer in `new_owned_fb`.
42        unsafe { root_unchecked::<'a, T>(&self.buf) }
43    }
44
45    pub fn get_slice(&self) -> &[u8] {
46        &self.buf
47    }
48}
49
50/// Generic check.
51pub fn check_flatbuffer<'a, T>(buf: &[u8]) -> Result<(), InvalidFlatbuffer>
52where
53    T: Verifiable + Follow<'a> + 'a,
54{
55    // Verify buffer using unsafe code to handle lifetime issues
56    // Safety: We drop the unsafe slice immediately.
57    unsafe {
58        // Transmute the slice to have a 'static lifetime for verification purposes
59        let static_slice: &'static [u8] = std::mem::transmute(buf);
60        let _verified = flatbuffers::root::<T>(static_slice)?;
61    }
62    Ok(())
63}
64
65/// # Safety
66/// Caller is responsible for verifying the buffer.
67pub unsafe fn get_ref_flatbuffer_unchecked<'a, T>(buf: &'a [u8]) -> T::Inner
68where
69    T: Verifiable + Follow<'a> + 'a,
70{
71    // Safety: We have already verified the buffer in `check_flatbuffer`.
72    unsafe { root_unchecked::<'a, T>(buf) }
73}