From 374f8fb5fbd698c2e5719076c82224fe06542d18 Mon Sep 17 00:00:00 2001 From: Raphael Taylor-Davies <1781103+tustvold@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:58:49 +0100 Subject: [PATCH] Rust soundness fixes (#7518) * Rust soundness fixes * Second pass * Make init_from_table unsafe * Remove SafeSliceAccess * Clippy * Remove create_vector_of_strings * More clippy * Remove deprecated root type accessors * More soundness fixes * Fix EndianScalar for bool * Add TriviallyTransmutable * Add debug assertions * Review comments * Review feedback --- rust/flatbuffers/Cargo.toml | 1 - rust/flatbuffers/src/array.rs | 59 +-- rust/flatbuffers/src/builder.rs | 146 +++---- rust/flatbuffers/src/endian_scalar.rs | 182 +++++---- rust/flatbuffers/src/follow.rs | 16 +- rust/flatbuffers/src/get_root.rs | 4 + rust/flatbuffers/src/lib.rs | 8 +- rust/flatbuffers/src/primitives.rs | 53 ++- rust/flatbuffers/src/push.rs | 30 +- rust/flatbuffers/src/table.rs | 38 +- rust/flatbuffers/src/vector.rs | 134 +++--- rust/flatbuffers/src/verifier.rs | 40 +- rust/flatbuffers/src/vtable.rs | 28 +- rust/flatbuffers/src/vtable_writer.rs | 18 +- .../my_game/sample/color_generated.rs | 20 +- .../my_game/sample/equipment_generated.rs | 20 +- .../my_game/sample/monster_generated.rs | 81 ++-- .../my_game/sample/vec_3_generated.rs | 76 ++-- .../my_game/sample/weapon_generated.rs | 16 +- samples/sample_binary.rs | 5 +- src/idl_gen_rust.cpp | 215 +++++----- .../my_game/example/array_struct_generated.rs | 104 +++-- .../my_game/example/array_table_generated.rs | 23 +- .../example/nested_struct_generated.rs | 68 +-- .../my_game/example/test_enum_generated.rs | 20 +- .../from_include_generated.rs | 20 +- .../other_name_space/table_b_generated.rs | 11 +- .../other_name_space/unused_generated.rs | 40 +- tests/include_test1/table_a_generated.rs | 11 +- .../from_include_generated.rs | 20 +- .../other_name_space/table_b_generated.rs | 11 +- .../other_name_space/unused_generated.rs | 40 +- tests/include_test2/table_a_generated.rs | 11 +- .../keyword_test/abc_generated.rs | 20 +- .../keywords_in_table_generated.rs | 26 +- .../keywords_in_union_generated.rs | 20 +- .../keyword_test/public_generated.rs | 20 +- .../my_game/example/ability_generated.rs | 58 ++- .../any_ambiguous_aliases_generated.rs | 20 +- .../my_game/example/any_generated.rs | 20 +- .../example/any_unique_aliases_generated.rs | 20 +- .../my_game/example/color_generated.rs | 30 +- .../my_game/example/long_enum_generated.rs | 30 +- .../my_game/example/monster_generated.rs | 386 +++++++++++++----- .../my_game/example/race_generated.rs | 20 +- .../my_game/example/referrable_generated.rs | 11 +- .../my_game/example/stat_generated.rs | 21 +- .../example/struct_of_structs_generated.rs | 31 +- .../struct_of_structs_of_structs_generated.rs | 25 +- .../my_game/example/test_generated.rs | 58 ++- .../test_simple_table_with_enum_generated.rs | 11 +- .../my_game/example/type_aliases_generated.rs | 70 +++- .../my_game/example/vec_3_generated.rs | 115 +++--- .../my_game/example_2/monster_generated.rs | 6 +- .../my_game/in_parent_namespace_generated.rs | 6 +- .../from_include_generated.rs | 20 +- .../other_name_space/table_b_generated.rs | 11 +- .../other_name_space/unused_generated.rs | 40 +- tests/monster_test/table_a_generated.rs | 11 +- .../my_game/example/ability_generated.rs | 58 ++- .../any_ambiguous_aliases_generated.rs | 20 +- .../my_game/example/any_generated.rs | 20 +- .../example/any_unique_aliases_generated.rs | 20 +- .../my_game/example/color_generated.rs | 30 +- .../my_game/example/long_enum_generated.rs | 30 +- .../my_game/example/monster_generated.rs | 386 +++++++++++++----- .../my_game/example/race_generated.rs | 20 +- .../my_game/example/referrable_generated.rs | 11 +- .../my_game/example/stat_generated.rs | 21 +- .../example/struct_of_structs_generated.rs | 31 +- .../struct_of_structs_of_structs_generated.rs | 25 +- .../my_game/example/test_generated.rs | 58 ++- .../test_simple_table_with_enum_generated.rs | 11 +- .../my_game/example/type_aliases_generated.rs | 70 +++- .../my_game/example/vec_3_generated.rs | 115 +++--- .../my_game/example_2/monster_generated.rs | 6 +- .../my_game/in_parent_namespace_generated.rs | 6 +- .../from_include_generated.rs | 20 +- .../other_name_space/table_b_generated.rs | 11 +- .../other_name_space/unused_generated.rs | 40 +- .../table_a_generated.rs | 11 +- tests/more_defaults/abc_generated.rs | 20 +- .../more_defaults/more_defaults_generated.rs | 40 +- .../enum_in_nested_ns_generated.rs | 20 +- .../struct_in_nested_ns_generated.rs | 58 ++- .../table_in_nested_ns_generated.rs | 11 +- .../union_in_nested_ns_generated.rs | 20 +- .../second_table_in_a_generated.rs | 11 +- .../table_in_first_ns_generated.rs | 38 +- .../namespace_c/table_in_c_generated.rs | 16 +- .../optional_byte_generated.rs | 20 +- .../scalar_stuff_generated.rs | 198 ++++++--- tests/private_annotation_test/ab_generated.rs | 20 +- .../annotations_generated.rs | 11 +- .../private_annotation_test/any_generated.rs | 20 +- .../private_annotation_test/game_generated.rs | 11 +- .../object_generated.rs | 40 +- tests/rust_serialize_test/src/main.rs | 4 +- .../benches/flatbuffers_benchmarks.rs | 8 +- .../bin/flatbuffers_alloc_check.rs | 38 +- tests/rust_usage_test/tests/arrays_test.rs | 32 +- .../rust_usage_test/tests/integration_test.rs | 377 +++++++---------- 102 files changed, 2673 insertions(+), 2035 deletions(-) diff --git a/rust/flatbuffers/Cargo.toml b/rust/flatbuffers/Cargo.toml index b3276c0cd..6279fd07b 100644 --- a/rust/flatbuffers/Cargo.toml +++ b/rust/flatbuffers/Cargo.toml @@ -17,7 +17,6 @@ no_std = ["core2", "thiserror_core2"] serialize = ["serde"] [dependencies] -smallvec = "1.6.1" bitflags = "1.2.1" serde = { version = "1.0", optional = true } thiserror = { version = "1.0.30", optional = true } diff --git a/rust/flatbuffers/src/array.rs b/rust/flatbuffers/src/array.rs index 2ce2e4713..089557440 100644 --- a/rust/flatbuffers/src/array.rs +++ b/rust/flatbuffers/src/array.rs @@ -37,14 +37,18 @@ where #[allow(clippy::len_without_is_empty)] #[allow(clippy::from_over_into)] // TODO(caspern): Go from From to Into. impl<'a, T: 'a, const N: usize> Array<'a, T, N> { + /// # Safety + /// + /// buf must be a contiguous array of `T` + /// + /// # Panics + /// + /// Panics if `buf.len()` is not `size_of::() * N` #[inline(always)] - pub fn new(buf: &'a [u8]) -> Self { - assert!(size_of::() * N == buf.len()); + pub unsafe fn new(buf: &'a [u8]) -> Self { + assert_eq!(size_of::() * N, buf.len()); - Array { - 0: buf, - 1: PhantomData, - } + Array(buf, PhantomData) } #[inline(always)] @@ -61,34 +65,39 @@ impl<'a, T: Follow<'a> + 'a, const N: usize> Array<'a, T, N> { pub fn get(&self, idx: usize) -> T::Inner { assert!(idx < N); let sz = size_of::(); - T::follow(self.0, sz * idx) + // Safety: + // self.0 was valid for length `N` on construction and have verified `idx < N` + unsafe { T::follow(self.0, sz * idx) } } #[inline(always)] pub fn iter(&self) -> VectorIter<'a, T> { - VectorIter::from_slice(self.0, self.len()) + // Safety: + // self.0 was valid for length N on construction + unsafe { VectorIter::from_slice(self.0, self.len()) } } } -impl<'a, T: Follow<'a> + Debug, const N: usize> Into<[T::Inner; N]> for Array<'a, T, N> { - #[inline(always)] - fn into(self) -> [T::Inner; N] { - array_init(|i| self.get(i)) +impl<'a, T: Follow<'a> + Debug, const N: usize> From> for [T::Inner; N] { + fn from(array: Array<'a, T, N>) -> Self { + array_init(|i| array.get(i)) } } -// TODO(caspern): Implement some future safe version of SafeSliceAccess. - /// Implement Follow for all possible Arrays that have Follow-able elements. impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> { type Inner = Array<'a, T, N>; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { Array::new(&buf[loc..loc + N * size_of::()]) } } -pub fn emplace_scalar_array( +/// Place an array of EndianScalar into the provided mutable byte slice. Performs +/// endian conversion, if necessary. +/// # Safety +/// Caller must ensure `s.len() >= size_of::<[T; N]>()` +pub unsafe fn emplace_scalar_array( buf: &mut [u8], loc: usize, src: &[T; N], @@ -96,14 +105,12 @@ pub fn emplace_scalar_array( let mut buf_ptr = buf[loc..].as_mut_ptr(); for item in src.iter() { let item_le = item.to_little_endian(); - unsafe { - core::ptr::copy_nonoverlapping( - &item_le as *const T as *const u8, - buf_ptr, - size_of::(), - ); - buf_ptr = buf_ptr.add(size_of::()); - } + core::ptr::copy_nonoverlapping( + &item_le as *const T::Scalar as *const u8, + buf_ptr, + size_of::(), + ); + buf_ptr = buf_ptr.add(size_of::()); } } @@ -124,6 +131,8 @@ where let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit(); let mut ptr_i = array.as_mut_ptr() as *mut T; + // Safety: + // array is aligned by T, and has length N unsafe { for i in 0..N { let value_i = initializer(i); @@ -134,7 +143,7 @@ where } } -#[cfg(feature="serialize")] +#[cfg(feature = "serialize")] impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N> where T: 'a + Follow<'a>, diff --git a/rust/flatbuffers/src/builder.rs b/rust/flatbuffers/src/builder.rs index 8a8b58cf0..cd7dc3633 100644 --- a/rust/flatbuffers/src/builder.rs +++ b/rust/flatbuffers/src/builder.rs @@ -14,26 +14,22 @@ * limitations under the License. */ -extern crate smallvec; - +#[cfg(feature = "no_std")] +use alloc::{vec, vec::Vec}; use core::cmp::max; use core::iter::{DoubleEndedIterator, ExactSizeIterator}; use core::marker::PhantomData; use core::ptr::write_bytes; -use core::slice::from_raw_parts; -#[cfg(feature = "no_std")] -use alloc::{vec, vec::Vec}; -use crate::endian_scalar::{emplace_scalar, read_scalar_at}; +use crate::endian_scalar::emplace_scalar; use crate::primitives::*; use crate::push::{Push, PushAlignment}; +use crate::read_scalar; use crate::table::Table; -use crate::vector::{SafeSliceAccess, Vector}; +use crate::vector::Vector; use crate::vtable::{field_index_to_field_offset, VTable}; use crate::vtable_writer::VTableWriter; -pub const N_SMALLVEC_STRING_VECTOR_CAPACITY: usize = 16; - #[derive(Clone, Copy, Debug, Eq, PartialEq)] struct FieldLoc { off: UOffsetT, @@ -121,6 +117,8 @@ impl<'fbb> FlatBufferBuilder<'fbb> { { let to_clear = self.owned_buf.len() - self.head; let ptr = (&mut self.owned_buf[self.head..]).as_mut_ptr(); + // Safety: + // Verified ptr is valid for `to_clear` above unsafe { write_bytes(ptr, 0, to_clear); } @@ -153,7 +151,9 @@ impl<'fbb> FlatBufferBuilder<'fbb> { self.make_space(sz); { let (dst, rest) = (&mut self.owned_buf[self.head..]).split_at_mut(sz); - x.push(dst, rest); + // Safety: + // Called make_space above + unsafe { x.push(dst, rest.len()) }; } WIPOffset::new(self.used_space() as UOffsetT) } @@ -309,73 +309,32 @@ impl<'fbb> FlatBufferBuilder<'fbb> { WIPOffset::new(self.used_space() as UOffsetT) } - /// Create a vector by memcpy'ing. This is much faster than calling - /// `create_vector`, but the underlying type must be represented as - /// little-endian on the host machine. This property is encoded in the - /// type system through the SafeSliceAccess trait. The following types are - /// always safe, on any platform: bool, u8, i8, and any - /// FlatBuffers-generated struct. - #[inline] - pub fn create_vector_direct<'a: 'b, 'b, T: SafeSliceAccess + Push + Sized + 'b>( - &'a mut self, - items: &'b [T], - ) -> WIPOffset> { - self.assert_not_nested( - "create_vector_direct can not be called when a table or vector is under construction", - ); - let elem_size = T::size(); - self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET)); - - let bytes = { - let ptr = items.as_ptr() as *const T as *const u8; - unsafe { from_raw_parts(ptr, items.len() * elem_size) } - }; - self.push_bytes_unprefixed(bytes); - self.push(items.len() as UOffsetT); - - WIPOffset::new(self.used_space() as UOffsetT) - } - - /// Create a vector of strings. - /// - /// Speed-sensitive users may wish to reduce memory usage by creating the - /// vector manually: use `start_vector`, `push`, and `end_vector`. - #[inline] - pub fn create_vector_of_strings<'a, 'b>( - &'a mut self, - xs: &'b [&'b str], - ) -> WIPOffset>> { - self.assert_not_nested("create_vector_of_strings can not be called when a table or vector is under construction"); - // internally, smallvec can be a stack-allocated or heap-allocated vector: - // if xs.len() > N_SMALLVEC_STRING_VECTOR_CAPACITY then it will overflow to the heap. - let mut offsets: smallvec::SmallVec<[WIPOffset<&str>; N_SMALLVEC_STRING_VECTOR_CAPACITY]> = - smallvec::SmallVec::with_capacity(xs.len()); - unsafe { - offsets.set_len(xs.len()); - } - - // note that this happens in reverse, because the buffer is built back-to-front: - for (i, &s) in xs.iter().enumerate().rev() { - let o = self.create_string(s); - offsets[i] = o; - } - self.create_vector(&offsets[..]) - } - /// Create a vector of Push-able objects. /// /// Speed-sensitive users may wish to reduce memory usage by creating the /// vector manually: use `start_vector`, `push`, and `end_vector`. #[inline] - pub fn create_vector<'a: 'b, 'b, T: Push + Copy + 'b>( + pub fn create_vector<'a: 'b, 'b, T: Push + 'b>( &'a mut self, items: &'b [T], ) -> WIPOffset> { let elem_size = T::size(); - self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET)); - for i in (0..items.len()).rev() { - self.push(items[i]); + let slice_size = items.len() * elem_size; + self.align(slice_size, T::alignment().max_of(SIZE_UOFFSET)); + self.ensure_capacity(slice_size + UOffsetT::size()); + + self.head -= slice_size; + let mut written_len = self.owned_buf.len() - self.head; + + let buf = &mut self.owned_buf[self.head..self.head + slice_size]; + for (item, out) in items.iter().zip(buf.chunks_exact_mut(elem_size)) { + written_len -= elem_size; + + // Safety: + // Called ensure_capacity and aligned to T above + unsafe { item.push(out, written_len) }; } + WIPOffset::new(self.push::(items.len() as UOffsetT).value()) } @@ -384,17 +343,18 @@ impl<'fbb> FlatBufferBuilder<'fbb> { /// Speed-sensitive users may wish to reduce memory usage by creating the /// vector manually: use `start_vector`, `push`, and `end_vector`. #[inline] - pub fn create_vector_from_iter( + pub fn create_vector_from_iter( &mut self, items: impl ExactSizeIterator + DoubleEndedIterator, ) -> WIPOffset> { let elem_size = T::size(); - let len = items.len(); - self.align(len * elem_size, T::alignment().max_of(SIZE_UOFFSET)); + self.align(items.len() * elem_size, T::alignment().max_of(SIZE_UOFFSET)); + let mut actual = 0; for item in items.rev() { self.push(item); + actual += 1; } - WIPOffset::new(self.push::(len as UOffsetT).value()) + WIPOffset::new(self.push::(actual).value()) } /// Set whether default values are stored. @@ -443,7 +403,15 @@ impl<'fbb> FlatBufferBuilder<'fbb> { assert_msg_name: &'static str, ) { let idx = self.used_space() - tab_revloc.value() as usize; - let tab = Table::new(&self.owned_buf[self.head..], idx); + + // Safety: + // The value of TableFinishedWIPOffset is the offset from the end of owned_buf + // to an SOffsetT pointing to a valid VTable + // + // `self.owned_buf.len() = self.used_space() + self.head` + // `self.owned_buf.len() - tab_revloc = self.used_space() - tab_revloc + self.head` + // `self.owned_buf.len() - tab_revloc = idx + self.head` + let tab = unsafe { Table::new(&self.owned_buf[self.head..], idx) }; let o = tab.vtable().get(slot_byte_loc) as usize; assert!(o != 0, "missing required field {}", assert_msg_name); } @@ -560,11 +528,15 @@ impl<'fbb> FlatBufferBuilder<'fbb> { } } let new_vt_bytes = &self.owned_buf[vt_start_pos..vt_end_pos]; - let found = self.written_vtable_revpos.binary_search_by(|old_vtable_revpos: &UOffsetT| { - let old_vtable_pos = self.owned_buf.len() - *old_vtable_revpos as usize; - let old_vtable = VTable::init(&self.owned_buf, old_vtable_pos); - new_vt_bytes.cmp(old_vtable.as_bytes()) - }); + let found = self + .written_vtable_revpos + .binary_search_by(|old_vtable_revpos: &UOffsetT| { + let old_vtable_pos = self.owned_buf.len() - *old_vtable_revpos as usize; + // Safety: + // Already written vtables are valid by construction + let old_vtable = unsafe { VTable::init(&self.owned_buf, old_vtable_pos) }; + new_vt_bytes.cmp(old_vtable.as_bytes()) + }); let final_vtable_revpos = match found { Ok(i) => { // The new vtable is a duplicate so clear it. @@ -581,12 +553,22 @@ impl<'fbb> FlatBufferBuilder<'fbb> { }; // Write signed offset from table to its vtable. let table_pos = self.owned_buf.len() - object_revloc_to_vtable.value() as usize; - let tmp_soffset_to_vt = unsafe { read_scalar_at::(&self.owned_buf, table_pos) }; - debug_assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0); + if cfg!(debug_assertions) { + // Safety: + // Verified slice length + let tmp_soffset_to_vt = unsafe { + read_scalar::(&self.owned_buf[table_pos..table_pos + SIZE_UOFFSET]) + }; + assert_eq!(tmp_soffset_to_vt, 0xF0F0_F0F0); + } + + let buf = &mut self.owned_buf[table_pos..table_pos + SIZE_SOFFSET]; + // Safety: + // Verified length of buf above unsafe { emplace_scalar::( - &mut self.owned_buf[table_pos..table_pos + SIZE_SOFFSET], - final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT + buf, + final_vtable_revpos as SOffsetT - object_revloc_to_vtable.value() as SOffsetT, ); } @@ -624,6 +606,8 @@ impl<'fbb> FlatBufferBuilder<'fbb> { // finally, zero out the old end data. { let ptr = (&mut self.owned_buf[..middle]).as_mut_ptr(); + // Safety: + // ptr is byte aligned and of length middle unsafe { write_bytes(ptr, 0, middle); } diff --git a/rust/flatbuffers/src/endian_scalar.rs b/rust/flatbuffers/src/endian_scalar.rs index 5f50cf1f3..dda5342cf 100644 --- a/rust/flatbuffers/src/endian_scalar.rs +++ b/rust/flatbuffers/src/endian_scalar.rs @@ -17,6 +17,24 @@ use core::mem::size_of; +mod private { + /// Types that are trivially transmutable are those where any combination of bits + /// represents a valid value of that type + /// + /// For example integral types are TriviallyTransmutable as all bit patterns are valid, + /// however, `bool` is not trivially transmutable as only `0` and `1` are valid + pub trait TriviallyTransmutable {} + + impl TriviallyTransmutable for i8 {} + impl TriviallyTransmutable for i16 {} + impl TriviallyTransmutable for i32 {} + impl TriviallyTransmutable for i64 {} + impl TriviallyTransmutable for u8 {} + impl TriviallyTransmutable for u16 {} + impl TriviallyTransmutable for u32 {} + impl TriviallyTransmutable for u64 {} +} + /// Trait for values that must be stored in little-endian byte order, but /// might be represented in memory as big-endian. Every type that implements /// EndianScalar is a valid FlatBuffers scalar value. @@ -28,144 +46,118 @@ use core::mem::size_of; /// "too much". For example, num-traits provides i128 support, but that is an /// invalid FlatBuffers type. pub trait EndianScalar: Sized + PartialEq + Copy + Clone { - fn to_little_endian(self) -> Self; - fn from_little_endian(self) -> Self; -} + type Scalar: private::TriviallyTransmutable; -/// Macro for implementing a no-op endian conversion. This is used for types -/// that are one byte wide. -macro_rules! impl_endian_scalar_noop { - ($ty:ident) => { - impl EndianScalar for $ty { - #[inline] - fn to_little_endian(self) -> Self { - self - } - #[inline] - fn from_little_endian(self) -> Self { - self - } - } - }; + fn to_little_endian(self) -> Self::Scalar; + + fn from_little_endian(v: Self::Scalar) -> Self; } /// Macro for implementing an endian conversion using the stdlib `to_le` and /// `from_le` functions. This is used for integer types. It is not used for /// floats, because the `to_le` and `from_le` are not implemented for them in /// the stdlib. -macro_rules! impl_endian_scalar_stdlib_le_conversion { +macro_rules! impl_endian_scalar { ($ty:ident) => { impl EndianScalar for $ty { + type Scalar = Self; + #[inline] - fn to_little_endian(self) -> Self { + fn to_little_endian(self) -> Self::Scalar { Self::to_le(self) } #[inline] - fn from_little_endian(self) -> Self { - Self::from_le(self) + fn from_little_endian(v: Self::Scalar) -> Self { + Self::from_le(v) } } }; } -impl_endian_scalar_noop!(bool); -impl_endian_scalar_noop!(u8); -impl_endian_scalar_noop!(i8); +impl_endian_scalar!(u8); +impl_endian_scalar!(i8); +impl_endian_scalar!(u16); +impl_endian_scalar!(u32); +impl_endian_scalar!(u64); +impl_endian_scalar!(i16); +impl_endian_scalar!(i32); +impl_endian_scalar!(i64); -impl_endian_scalar_stdlib_le_conversion!(u16); -impl_endian_scalar_stdlib_le_conversion!(u32); -impl_endian_scalar_stdlib_le_conversion!(u64); -impl_endian_scalar_stdlib_le_conversion!(i16); -impl_endian_scalar_stdlib_le_conversion!(i32); -impl_endian_scalar_stdlib_le_conversion!(i64); +impl EndianScalar for bool { + type Scalar = u8; + + fn to_little_endian(self) -> Self::Scalar { + self as u8 + } + + fn from_little_endian(v: Self::Scalar) -> Self { + v != 0 + } +} impl EndianScalar for f32 { + type Scalar = u32; /// Convert f32 from host endian-ness to little-endian. #[inline] - fn to_little_endian(self) -> Self { - #[cfg(target_endian = "little")] - { - self - } - #[cfg(not(target_endian = "little"))] - { - byte_swap_f32(self) - } + fn to_little_endian(self) -> u32 { + // Floats and Ints have the same endianness on all supported platforms. + // + self.to_bits().to_le() } /// Convert f32 from little-endian to host endian-ness. #[inline] - fn from_little_endian(self) -> Self { - #[cfg(target_endian = "little")] - { - self - } - #[cfg(not(target_endian = "little"))] - { - byte_swap_f32(self) - } + fn from_little_endian(v: u32) -> Self { + // Floats and Ints have the same endianness on all supported platforms. + // + f32::from_bits(u32::from_le(v)) } } impl EndianScalar for f64 { + type Scalar = u64; + /// Convert f64 from host endian-ness to little-endian. #[inline] - fn to_little_endian(self) -> Self { - #[cfg(target_endian = "little")] - { - self - } - #[cfg(not(target_endian = "little"))] - { - byte_swap_f64(self) - } + fn to_little_endian(self) -> u64 { + // Floats and Ints have the same endianness on all supported platforms. + // + self.to_bits().to_le() } /// Convert f64 from little-endian to host endian-ness. #[inline] - fn from_little_endian(self) -> Self { - #[cfg(target_endian = "little")] - { - self - } - #[cfg(not(target_endian = "little"))] - { - byte_swap_f64(self) - } + fn from_little_endian(v: u64) -> Self { + // Floats and Ints have the same endianness on all supported platforms. + // + f64::from_bits(u64::from_le(v)) } } -/// Swaps the bytes of an f32. -#[allow(dead_code)] -#[inline] -pub fn byte_swap_f32(x: f32) -> f32 { - f32::from_bits(x.to_bits().swap_bytes()) -} - -/// Swaps the bytes of an f64. -#[allow(dead_code)] -#[inline] -pub fn byte_swap_f64(x: f64) -> f64 { - f64::from_bits(x.to_bits().swap_bytes()) -} - /// Place an EndianScalar into the provided mutable byte slice. Performs /// endian conversion, if necessary. /// # Safety -/// Caller must ensure `s.len() > size_of::()` -/// and `x` does not overlap with `s`. +/// Caller must ensure `s.len() >= size_of::()` #[inline] pub unsafe fn emplace_scalar(s: &mut [u8], x: T) { + let size = size_of::(); + debug_assert!( + s.len() >= size, + "insufficient capacity for emplace_scalar, needed {} got {}", + size, + s.len() + ); + let x_le = x.to_little_endian(); core::ptr::copy_nonoverlapping( - &x_le as *const T as *const u8, + &x_le as *const T::Scalar as *const u8, s.as_mut_ptr() as *mut u8, - size_of::(), + size, ); } /// Read an EndianScalar from the provided byte slice at the specified location. /// Performs endian conversion, if necessary. /// # Safety -/// Caller must ensure `s.len() > loc + size_of::()`. +/// Caller must ensure `s.len() >= loc + size_of::()`. #[inline] pub unsafe fn read_scalar_at(s: &[u8], loc: usize) -> T { read_scalar(&s[loc..]) @@ -177,8 +169,20 @@ pub unsafe fn read_scalar_at(s: &[u8], loc: usize) -> T { /// Caller must ensure `s.len() > size_of::()`. #[inline] pub unsafe fn read_scalar(s: &[u8]) -> T { - let mut mem = core::mem::MaybeUninit::::uninit(); + let size = size_of::(); + debug_assert!( + s.len() >= size, + "insufficient capacity for emplace_scalar, needed {} got {}", + size, + s.len() + ); + + let mut mem = core::mem::MaybeUninit::::uninit(); // Since [u8] has alignment 1, we copy it into T which may have higher alignment. - core::ptr::copy_nonoverlapping(s.as_ptr(), mem.as_mut_ptr() as *mut u8, size_of::()); - mem.assume_init().from_little_endian() + core::ptr::copy_nonoverlapping( + s.as_ptr(), + mem.as_mut_ptr() as *mut u8, + size, + ); + T::from_little_endian(mem.assume_init()) } diff --git a/rust/flatbuffers/src/follow.rs b/rust/flatbuffers/src/follow.rs index d1d6483ae..748848759 100644 --- a/rust/flatbuffers/src/follow.rs +++ b/rust/flatbuffers/src/follow.rs @@ -29,7 +29,11 @@ use core::marker::PhantomData; /// continue traversing the FlatBuffer. pub trait Follow<'buf> { type Inner; - fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner; + /// # Safety + /// + /// `buf[loc..]` must contain a valid value of `Self` and anything it + /// transitively refers to by offset must also be valid + unsafe fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner; } /// FollowStart wraps a Follow impl in a struct type. This can make certain @@ -39,17 +43,21 @@ pub struct FollowStart(PhantomData); impl<'a, T: Follow<'a> + 'a> FollowStart { #[inline] pub fn new() -> Self { - Self { 0: PhantomData } + Self(PhantomData) } + + /// # Safety + /// + /// `buf[loc..]` must contain a valid value of `T` #[inline] - pub fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner { + pub unsafe fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner { T::follow(buf, loc) } } impl<'a, T: Follow<'a>> Follow<'a> for FollowStart { type Inner = T::Inner; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { T::follow(buf, loc) } } diff --git a/rust/flatbuffers/src/get_root.rs b/rust/flatbuffers/src/get_root.rs index 3305efade..372d02f73 100644 --- a/rust/flatbuffers/src/get_root.rs +++ b/rust/flatbuffers/src/get_root.rs @@ -45,6 +45,8 @@ where { let mut v = Verifier::new(opts, data); >::run_verifier(&mut v, 0)?; + // Safety: + // Run verifier above Ok(unsafe { root_unchecked::(data) }) } @@ -75,6 +77,8 @@ where { let mut v = Verifier::new(opts, data); >>::run_verifier(&mut v, 0)?; + // Safety: + // Run verifier above Ok(unsafe { size_prefixed_root_unchecked::(data) }) } diff --git a/rust/flatbuffers/src/lib.rs b/rust/flatbuffers/src/lib.rs index bc114e664..e28d3be90 100644 --- a/rust/flatbuffers/src/lib.rs +++ b/rust/flatbuffers/src/lib.rs @@ -48,14 +48,12 @@ mod vtable_writer; pub use crate::array::{array_init, emplace_scalar_array, Array}; pub use crate::builder::FlatBufferBuilder; -pub use crate::endian_scalar::{ - byte_swap_f32, byte_swap_f64, emplace_scalar, read_scalar, read_scalar_at, EndianScalar, -}; +pub use crate::endian_scalar::{emplace_scalar, read_scalar, read_scalar_at, EndianScalar}; pub use crate::follow::{Follow, FollowStart}; pub use crate::primitives::*; pub use crate::push::Push; pub use crate::table::{buffer_has_identifier, Table}; -pub use crate::vector::{follow_cast_ref, SafeSliceAccess, Vector, VectorIter}; +pub use crate::vector::{follow_cast_ref, Vector, VectorIter}; pub use crate::verifier::{ ErrorTraceDetail, InvalidFlatbuffer, SimpleToVerifyInSlice, Verifiable, Verifier, VerifierOptions, @@ -64,6 +62,4 @@ pub use crate::vtable::field_index_to_field_offset; pub use bitflags; pub use get_root::*; -// TODO(rw): Unify `create_vector` and `create_vector_direct` by using -// `Into>`. // TODO(rw): Split fill ops in builder into fill_small, fill_big like in C++. diff --git a/rust/flatbuffers/src/primitives.rs b/rust/flatbuffers/src/primitives.rs index 72764b213..ac35511da 100644 --- a/rust/flatbuffers/src/primitives.rs +++ b/rust/flatbuffers/src/primitives.rs @@ -112,10 +112,7 @@ impl<'a, T: 'a> WIPOffset { /// Create a new WIPOffset. #[inline] pub fn new(o: UOffsetT) -> WIPOffset { - WIPOffset { - 0: o, - 1: PhantomData, - } + WIPOffset(o, PhantomData) } /// Return a wrapped value that brings its meaning as a union WIPOffset @@ -135,11 +132,9 @@ impl Push for WIPOffset { type Output = ForwardsUOffset; #[inline(always)] - fn push(&self, dst: &mut [u8], rest: &[u8]) { - let n = (SIZE_UOFFSET + rest.len() - self.value() as usize) as UOffsetT; - unsafe { - emplace_scalar::(dst, n); - } + unsafe fn push(&self, dst: &mut [u8], written_len: usize) { + let n = (SIZE_UOFFSET + written_len - self.value() as usize) as UOffsetT; + emplace_scalar::(dst, n); } } @@ -147,8 +142,8 @@ impl Push for ForwardsUOffset { type Output = Self; #[inline(always)] - fn push(&self, dst: &mut [u8], rest: &[u8]) { - self.value().push(dst, rest); + unsafe fn push(&self, dst: &mut [u8], written_len: usize) { + self.value().push(dst, written_len); } } @@ -179,9 +174,9 @@ impl ForwardsUOffset { impl<'a, T: Follow<'a>> Follow<'a> for ForwardsUOffset { type Inner = T::Inner; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { let slice = &buf[loc..loc + SIZE_UOFFSET]; - let off = unsafe { read_scalar::(slice) as usize }; + let off = read_scalar::(slice) as usize; T::follow(buf, loc + off) } } @@ -200,9 +195,9 @@ impl ForwardsVOffset { impl<'a, T: Follow<'a>> Follow<'a> for ForwardsVOffset { type Inner = T::Inner; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { let slice = &buf[loc..loc + SIZE_VOFFSET]; - let off = unsafe { read_scalar::(slice) as usize }; + let off = read_scalar::(slice) as usize; T::follow(buf, loc + off) } } @@ -211,8 +206,8 @@ impl Push for ForwardsVOffset { type Output = Self; #[inline] - fn push(&self, dst: &mut [u8], rest: &[u8]) { - self.value().push(dst, rest); + unsafe fn push(&self, dst: &mut [u8], written_len: usize) { + self.value().push(dst, written_len); } } @@ -230,9 +225,9 @@ impl BackwardsSOffset { impl<'a, T: Follow<'a>> Follow<'a> for BackwardsSOffset { type Inner = T::Inner; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { let slice = &buf[loc..loc + SIZE_SOFFSET]; - let off = unsafe { read_scalar::(slice) }; + let off = read_scalar::(slice); T::follow(buf, (loc as SOffsetT - off) as usize) } } @@ -241,8 +236,8 @@ impl Push for BackwardsSOffset { type Output = Self; #[inline] - fn push(&self, dst: &mut [u8], rest: &[u8]) { - self.value().push(dst, rest); + unsafe fn push(&self, dst: &mut [u8], written_len: usize) { + self.value().push(dst, written_len); } } @@ -252,7 +247,7 @@ pub struct SkipSizePrefix(PhantomData); impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipSizePrefix { type Inner = T::Inner; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { T::follow(buf, loc + SIZE_SIZEPREFIX) } } @@ -263,7 +258,7 @@ pub struct SkipRootOffset(PhantomData); impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipRootOffset { type Inner = T::Inner; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { T::follow(buf, loc + SIZE_UOFFSET) } } @@ -274,7 +269,7 @@ pub struct FileIdentifier; impl<'a> Follow<'a> for FileIdentifier { type Inner = &'a [u8]; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { &buf[loc..loc + FILE_IDENTIFIER_LENGTH] } } @@ -286,7 +281,7 @@ pub struct SkipFileIdentifier(PhantomData); impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier { type Inner = T::Inner; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { T::follow(buf, loc + FILE_IDENTIFIER_LENGTH) } } @@ -294,8 +289,8 @@ impl<'a, T: Follow<'a> + 'a> Follow<'a> for SkipFileIdentifier { impl<'a> Follow<'a> for bool { type Inner = bool; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { read_scalar_at::(buf, loc) != 0 } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + read_scalar_at::(buf, loc) != 0 } } @@ -309,8 +304,8 @@ macro_rules! impl_follow_for_endian_scalar { impl<'a> Follow<'a> for $ty { type Inner = $ty; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - unsafe { read_scalar_at::<$ty>(buf, loc) } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + read_scalar_at::<$ty>(buf, loc) } } }; diff --git a/rust/flatbuffers/src/push.rs b/rust/flatbuffers/src/push.rs index 8bb8fe9a7..20bacd8e2 100644 --- a/rust/flatbuffers/src/push.rs +++ b/rust/flatbuffers/src/push.rs @@ -24,7 +24,11 @@ use crate::endian_scalar::emplace_scalar; /// types. pub trait Push: Sized { type Output; - fn push(&self, dst: &mut [u8], _rest: &[u8]); + + /// # Safety + /// + /// dst is aligned to [`Self::alignment`] and has length greater than or equal to [`Self::size`] + unsafe fn push(&self, dst: &mut [u8], written_len: usize); #[inline] fn size() -> usize { size_of::() @@ -35,13 +39,29 @@ pub trait Push: Sized { } } +impl<'a, T: Push> Push for &'a T { + type Output = T::Output; + + unsafe fn push(&self, dst: &mut [u8], written_len: usize) { + T::push(self, dst, written_len) + } + + fn size() -> usize { + T::size() + } + + fn alignment() -> PushAlignment { + T::alignment() + } +} + /// Ensure Push alignment calculations are typesafe (because this helps reduce /// implementation issues when using FlatBufferBuilder::align). pub struct PushAlignment(usize); impl PushAlignment { #[inline] pub fn new(x: usize) -> Self { - PushAlignment { 0: x } + PushAlignment(x) } #[inline] pub fn value(&self) -> usize { @@ -60,10 +80,8 @@ macro_rules! impl_push_for_endian_scalar { type Output = $ty; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { - emplace_scalar::<$ty>(dst, *self); - } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + emplace_scalar::<$ty>(dst, *self); } } }; diff --git a/rust/flatbuffers/src/table.rs b/rust/flatbuffers/src/table.rs index cfb85590d..f5001f6d1 100644 --- a/rust/flatbuffers/src/table.rs +++ b/rust/flatbuffers/src/table.rs @@ -18,23 +18,36 @@ use crate::follow::Follow; use crate::primitives::*; use crate::vtable::VTable; -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Table<'a> { - pub buf: &'a [u8], - pub loc: usize, + buf: &'a [u8], + loc: usize, } impl<'a> Table<'a> { + /// # Safety + /// + /// `buf` must contain a `soffset_t` at `loc`, which points to a valid vtable #[inline] - pub fn new(buf: &'a [u8], loc: usize) -> Self { + pub unsafe fn new(buf: &'a [u8], loc: usize) -> Self { Table { buf, loc } } + #[inline] pub fn vtable(&self) -> VTable<'a> { - >>::follow(self.buf, self.loc) + // Safety: + // Table::new is created with a valid buf and location + unsafe { >>::follow(self.buf, self.loc) } } + + /// Retrieves the value at the provided `slot_byte_loc` returning `default` + /// if no value present + /// + /// # Safety + /// + /// The value of the corresponding slot must have type T #[inline] - pub fn get + 'a>( + pub unsafe fn get + 'a>( &self, slot_byte_loc: VOffsetT, default: Option, @@ -50,19 +63,26 @@ impl<'a> Table<'a> { impl<'a> Follow<'a> for Table<'a> { type Inner = Table<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { Table { buf, loc } } } +/// Returns true if data contains a prefix of `ident` #[inline] pub fn buffer_has_identifier(data: &[u8], ident: &str, size_prefixed: bool) -> bool { assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH); let got = if size_prefixed { - >>::follow(data, 0) + assert!(data.len() >= SIZE_SIZEPREFIX + SIZE_UOFFSET + FILE_IDENTIFIER_LENGTH); + // Safety: + // Verified data has sufficient bytes + unsafe { >>::follow(data, 0) } } else { - >::follow(data, 0) + assert!(data.len() >= SIZE_UOFFSET + FILE_IDENTIFIER_LENGTH); + // Safety: + // Verified data has sufficient bytes + unsafe { >::follow(data, 0) } }; ident.as_bytes() == got diff --git a/rust/flatbuffers/src/vector.rs b/rust/flatbuffers/src/vector.rs index da04ef6fc..b486ff33c 100644 --- a/rust/flatbuffers/src/vector.rs +++ b/rust/flatbuffers/src/vector.rs @@ -17,13 +17,10 @@ use core::fmt::{Debug, Formatter, Result}; use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator}; use core::marker::PhantomData; -use core::mem::size_of; -use core::slice::from_raw_parts; +use core::mem::{align_of, size_of}; use core::str::from_utf8_unchecked; use crate::endian_scalar::read_scalar_at; -#[cfg(target_endian = "little")] -use crate::endian_scalar::EndianScalar; use crate::follow::Follow; use crate::primitives::*; @@ -55,6 +52,7 @@ where // and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>` // can always be copied, no matter that `T` you have. impl<'a, T> Copy for Vector<'a, T> {} + impl<'a, T> Clone for Vector<'a, T> { fn clone(&self) -> Self { *self @@ -62,32 +60,46 @@ impl<'a, T> Clone for Vector<'a, T> { } impl<'a, T: 'a> Vector<'a, T> { + /// # Safety + /// + /// `buf` contains a valid vector at `loc` consisting of + /// + /// - UOffsetT element count + /// - Consecutive list of `T` elements #[inline(always)] - pub fn new(buf: &'a [u8], loc: usize) -> Self { - Vector { - 0: buf, - 1: loc, - 2: PhantomData, - } + pub unsafe fn new(buf: &'a [u8], loc: usize) -> Self { + Vector(buf, loc, PhantomData) } #[inline(always)] pub fn len(&self) -> usize { + // Safety: + // Valid vector at time of construction starting with UOffsetT element count unsafe { read_scalar_at::(self.0, self.1) as usize } } + #[inline(always)] pub fn is_empty(&self) -> bool { self.len() == 0 } + + #[inline(always)] + pub fn bytes(&self) -> &'a [u8] { + let sz = size_of::(); + let len = self.len(); + &self.0[self.1 + SIZE_UOFFSET..self.1 + SIZE_UOFFSET + sz * len] + } } impl<'a, T: Follow<'a> + 'a> Vector<'a, T> { #[inline(always)] pub fn get(&self, idx: usize) -> T::Inner { - assert!(idx < self.len() as usize); + assert!(idx < self.len()); let sz = size_of::(); debug_assert!(sz > 0); - T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx) + // Safety: + // Valid vector at time of construction, verified that idx < element count + unsafe { T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx) } } #[inline(always)] @@ -96,84 +108,40 @@ impl<'a, T: Follow<'a> + 'a> Vector<'a, T> { } } -pub trait SafeSliceAccess {} -impl<'a, T: SafeSliceAccess + 'a> Vector<'a, T> { - pub fn safe_slice(self) -> &'a [T] { - let buf = self.0; - let loc = self.1; - let sz = size_of::(); - debug_assert!(sz > 0); - let len = unsafe { read_scalar_at::(buf, loc) } as usize; - let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz]; - let ptr = data_buf.as_ptr() as *const T; - let s: &'a [T] = unsafe { from_raw_parts(ptr, len) }; - s - } -} - -impl SafeSliceAccess for u8 {} -impl SafeSliceAccess for i8 {} -impl SafeSliceAccess for bool {} - -// TODO(caspern): Get rid of this. Conditional compliation is unnecessary complexity. -// Vectors of primitives just don't work on big endian machines!!! -#[cfg(target_endian = "little")] -mod le_safe_slice_impls { - impl super::SafeSliceAccess for u16 {} - impl super::SafeSliceAccess for u32 {} - impl super::SafeSliceAccess for u64 {} - - impl super::SafeSliceAccess for i16 {} - impl super::SafeSliceAccess for i32 {} - impl super::SafeSliceAccess for i64 {} - - impl super::SafeSliceAccess for f32 {} - impl super::SafeSliceAccess for f64 {} -} - -#[cfg(target_endian = "little")] -pub use self::le_safe_slice_impls::*; - -pub fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T { +/// # Safety +/// +/// `buf` must contain a value of T at `loc` and have alignment of 1 +pub unsafe fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T { + assert_eq!(align_of::(), 1); let sz = size_of::(); let buf = &buf[loc..loc + sz]; let ptr = buf.as_ptr() as *const T; - unsafe { &*ptr } + // SAFETY + // buf contains a value at loc of type T and T has no alignment requirements + &*ptr } impl<'a> Follow<'a> for &'a str { type Inner = &'a str; - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let len = unsafe { read_scalar_at::(buf, loc) } as usize; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let len = read_scalar_at::(buf, loc) as usize; let slice = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len]; - unsafe { from_utf8_unchecked(slice) } + from_utf8_unchecked(slice) } } -#[cfg(target_endian = "little")] -fn follow_slice_helper(buf: &[u8], loc: usize) -> &[T] { - let sz = size_of::(); - debug_assert!(sz > 0); - let len = unsafe { read_scalar_at::(buf, loc) as usize }; - let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz]; - let ptr = data_buf.as_ptr() as *const T; - let s: &[T] = unsafe { from_raw_parts(ptr, len) }; - s -} - -/// Implement direct slice access if the host is little-endian. -#[cfg(target_endian = "little")] -impl<'a, T: EndianScalar> Follow<'a> for &'a [T] { - type Inner = &'a [T]; - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - follow_slice_helper::(buf, loc) +impl<'a> Follow<'a> for &'a [u8] { + type Inner = &'a [u8]; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let len = read_scalar_at::(buf, loc) as usize; + &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len] } } /// Implement Follow for all possible Vectors that have Follow-able elements. impl<'a, T: Follow<'a> + 'a> Follow<'a> for Vector<'a, T> { type Inner = Vector<'a, T>; - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { Vector::new(buf, loc) } } @@ -201,8 +169,14 @@ impl<'a, T: 'a> VectorIter<'a, T> { } } + /// Creates a new `VectorIter` from the provided slice + /// + /// # Safety + /// + /// buf must contain a contiguous sequence of `items_num` values of `T` + /// #[inline] - pub fn from_slice(buf: &'a [u8], items_num: usize) -> Self { + pub unsafe fn from_slice(buf: &'a [u8], items_num: usize) -> Self { VectorIter { buf, loc: 0, @@ -235,7 +209,10 @@ impl<'a, T: Follow<'a> + 'a> Iterator for VectorIter<'a, T> { if self.remaining == 0 { None } else { - let result = T::follow(self.buf, self.loc); + // Safety: + // VectorIter can only be created from a contiguous sequence of `items_num` + // And remaining is initialized to `items_num` + let result = unsafe { T::follow(self.buf, self.loc) }; self.loc += sz; self.remaining -= 1; Some(result) @@ -272,7 +249,10 @@ impl<'a, T: Follow<'a> + 'a> DoubleEndedIterator for VectorIter<'a, T> { None } else { self.remaining -= 1; - Some(T::follow(self.buf, self.loc + sz * self.remaining)) + // Safety: + // VectorIter can only be created from a contiguous sequence of `items_num` + // And remaining is initialized to `items_num` + Some(unsafe { T::follow(self.buf, self.loc + sz * self.remaining) }) } } @@ -309,7 +289,7 @@ impl<'a, 'b, T: Follow<'a> + 'a> IntoIterator for &'b Vector<'a, T> { } } -#[cfg(feature="serialize")] +#[cfg(feature = "serialize")] impl<'a, T> serde::ser::Serialize for Vector<'a, T> where T: 'a + Follow<'a>, diff --git a/rust/flatbuffers/src/verifier.rs b/rust/flatbuffers/src/verifier.rs index 36a5775e3..ff84baa7f 100644 --- a/rust/flatbuffers/src/verifier.rs +++ b/rust/flatbuffers/src/verifier.rs @@ -1,14 +1,14 @@ +use crate::follow::Follow; +use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET}; #[cfg(feature = "no_std")] use alloc::vec::Vec; use core::ops::Range; use core::option::Option; -use crate::follow::Follow; -use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET}; -#[cfg(feature="no_std")] -use thiserror_core2::Error; -#[cfg(not(feature="no_std"))] +#[cfg(not(feature = "no_std"))] use thiserror::Error; +#[cfg(feature = "no_std")] +use thiserror_core2::Error; /// Traces the location of data errors. Not populated for Dos detecting errors. /// Useful for MissingRequiredField and Utf8Error in particular, though @@ -28,8 +28,10 @@ pub enum ErrorTraceDetail { position: usize, }, } + #[derive(PartialEq, Eq, Default, Debug, Clone)] pub struct ErrorTrace(Vec); + impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace { #[inline] fn as_ref(&self) -> &[ErrorTraceDetail] { @@ -63,7 +65,7 @@ pub enum InvalidFlatbuffer { error_trace: ErrorTrace, }, #[error("String in range [{}, {}) is missing its null terminator.\n{error_trace}", - range.start, range.end)] + range.start, range.end)] MissingNullTerminator { range: Range, error_trace: ErrorTrace, @@ -184,6 +186,7 @@ fn trace_field(res: Result, field_name: &'static str, position: usize) -> }, ) } + /// Adds a TableField trace detail if `res` is a data error. fn trace_elem(res: Result, index: usize, position: usize) -> Result { append_trace(res, ErrorTraceDetail::VectorElement { index, position }) @@ -205,6 +208,7 @@ pub struct VerifierOptions { // options to error un-recognized enums and unions? possible footgun. // Ignore nested flatbuffers, etc? } + impl Default for VerifierOptions { fn default() -> Self { Self { @@ -226,6 +230,7 @@ pub struct Verifier<'opts, 'buf> { num_tables: usize, apparent_size: usize, } + impl<'opts, 'buf> Verifier<'opts, 'buf> { pub fn new(opts: &'opts VerifierOptions, buffer: &'buf [u8]) -> Self { Self { @@ -247,9 +252,12 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> { /// memory since `buffer: &[u8]` has alignment 1. /// /// ### WARNING + /// /// This does not work for flatbuffers-structs as they have alignment 1 according to /// `core::mem::align_of` but are meant to have higher alignment within a Flatbuffer w.r.t. /// `buffer[0]`. TODO(caspern). + /// + /// Note this does not impact soundness as this crate does not assume alignment of structs #[inline] fn is_aligned(&self, pos: usize) -> Result<()> { if pos % core::mem::align_of::() == 0 { @@ -307,9 +315,9 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> { // signed offsets are subtracted. let derefed = if offset > 0 { - pos.checked_sub(offset.abs() as usize) + pos.checked_sub(offset.unsigned_abs() as usize) } else { - pos.checked_add(offset.abs() as usize) + pos.checked_add(offset.unsigned_abs() as usize) }; if let Some(x) = derefed { if x < self.buffer.len() { @@ -372,6 +380,7 @@ pub struct TableVerifier<'ver, 'opts, 'buf> { // Verifier struct which holds the surrounding state and options. verifier: &'ver mut Verifier<'opts, 'buf>, } + impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> { fn deref(&mut self, field: VOffsetT) -> Result> { let field = field as usize; @@ -439,7 +448,9 @@ impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> { } (Some(k), Some(v)) => { trace_field(Key::run_verifier(self.verifier, k), key_field_name, k)?; - let discriminant = Key::follow(self.verifier.buffer, k); + // Safety: + // Run verifier on `k` above + let discriminant = unsafe { Key::follow(self.verifier.buffer, k) }; trace_field( verify_union(discriminant, self.verifier, v), val_field_name, @@ -486,16 +497,27 @@ fn verify_vector_range(v: &mut Verifier, pos: usize) -> Result Verifiable for Vector<'_, T> { diff --git a/rust/flatbuffers/src/vtable.rs b/rust/flatbuffers/src/vtable.rs index bbb7190ae..1516153d5 100644 --- a/rust/flatbuffers/src/vtable.rs +++ b/rust/flatbuffers/src/vtable.rs @@ -33,24 +33,42 @@ impl<'a> PartialEq for VTable<'a> { } impl<'a> VTable<'a> { - pub fn init(buf: &'a [u8], loc: usize) -> Self { + /// SAFETY + /// `buf` must contain a valid vtable at `loc` + /// + /// This consists of a number of `VOffsetT` + /// - size of vtable in bytes including size element + /// - size of object in bytes including the vtable offset + /// - n fields where n is the number of fields in the table's schema when the code was compiled + pub unsafe fn init(buf: &'a [u8], loc: usize) -> Self { VTable { buf, loc } } + pub fn num_fields(&self) -> usize { (self.num_bytes() / SIZE_VOFFSET) - 2 } + pub fn num_bytes(&self) -> usize { + // Safety: + // Valid VTable at time of construction unsafe { read_scalar_at::(self.buf, self.loc) as usize } } + pub fn object_inline_num_bytes(&self) -> usize { + // Safety: + // Valid VTable at time of construction let n = unsafe { read_scalar_at::(self.buf, self.loc + SIZE_VOFFSET) }; n as usize } + pub fn get_field(&self, idx: usize) -> VOffsetT { // TODO(rw): distinguish between None and 0? if idx > self.num_fields() { return 0; } + + // Safety: + // Valid VTable at time of construction unsafe { read_scalar_at::( self.buf, @@ -58,13 +76,17 @@ impl<'a> VTable<'a> { ) } } + pub fn get(&self, byte_loc: VOffsetT) -> VOffsetT { // TODO(rw): distinguish between None and 0? - if byte_loc as usize >= self.num_bytes() { + if byte_loc as usize + 2 > self.num_bytes() { return 0; } + // Safety: + // byte_loc is within bounds of vtable, which was valid at time of construction unsafe { read_scalar_at::(self.buf, self.loc + byte_loc as usize) } } + pub fn as_bytes(&self) -> &[u8] { let len = self.num_bytes(); &self.buf[self.loc..self.loc + len] @@ -87,7 +109,7 @@ pub fn field_offset_to_field_index(field_o: VOffsetT) -> VOffsetT { impl<'a> Follow<'a> for VTable<'a> { type Inner = VTable<'a>; - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { VTable::init(buf, loc) } } diff --git a/rust/flatbuffers/src/vtable_writer.rs b/rust/flatbuffers/src/vtable_writer.rs index 9b61dac7f..4bcde9adc 100644 --- a/rust/flatbuffers/src/vtable_writer.rs +++ b/rust/flatbuffers/src/vtable_writer.rs @@ -40,8 +40,11 @@ impl<'a> VTableWriter<'a> { /// to the provided value. #[inline(always)] pub fn write_vtable_byte_length(&mut self, n: VOffsetT) { + let buf = &mut self.buf[..SIZE_VOFFSET]; + // Safety: + // Validated range above unsafe { - emplace_scalar::(&mut self.buf[..SIZE_VOFFSET], n); + emplace_scalar::(buf, n); } debug_assert_eq!(n as usize, self.buf.len()); } @@ -49,8 +52,11 @@ impl<'a> VTableWriter<'a> { /// Writes an object length (in bytes) into the vtable. #[inline(always)] pub fn write_object_inline_size(&mut self, n: VOffsetT) { + let buf = &mut self.buf[SIZE_VOFFSET..2 * SIZE_VOFFSET]; + // Safety: + // Validated range above unsafe { - emplace_scalar::(&mut self.buf[SIZE_VOFFSET..2 * SIZE_VOFFSET], n); + emplace_scalar::(buf, n); } } @@ -61,8 +67,11 @@ impl<'a> VTableWriter<'a> { #[inline(always)] pub fn write_field_offset(&mut self, vtable_offset: VOffsetT, object_data_offset: VOffsetT) { let idx = vtable_offset as usize; + let buf = &mut self.buf[idx..idx + SIZE_VOFFSET]; + // Safety: + // Validated range above unsafe { - emplace_scalar::(&mut self.buf[idx..idx + SIZE_VOFFSET], object_data_offset); + emplace_scalar::(buf, object_data_offset); } } @@ -73,6 +82,9 @@ impl<'a> VTableWriter<'a> { // This is the closest thing to memset in Rust right now. let len = self.buf.len(); let p = self.buf.as_mut_ptr() as *mut u8; + + // Safety: + // p is byte aligned and of length `len` unsafe { write_bytes(p, 0, len); } diff --git a/samples/rust_generated/my_game/sample/color_generated.rs b/samples/rust_generated/my_game/sample/color_generated.rs index 7a7d1d5b2..19e8445a5 100644 --- a/samples/rust_generated/my_game/sample/color_generated.rs +++ b/samples/rust_generated/my_game/sample/color_generated.rs @@ -59,10 +59,8 @@ impl core::fmt::Debug for Color { impl<'a> flatbuffers::Follow<'a> for Color { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for Color { impl flatbuffers::Push for Color { type Output = Color; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for Color { + type Scalar = i8; #[inline] - fn to_little_endian(self) -> Self { - let b = i8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i8::from_le(self.0); + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); Self(b) } } diff --git a/samples/rust_generated/my_game/sample/equipment_generated.rs b/samples/rust_generated/my_game/sample/equipment_generated.rs index 9898c8d4a..9f9cd3590 100644 --- a/samples/rust_generated/my_game/sample/equipment_generated.rs +++ b/samples/rust_generated/my_game/sample/equipment_generated.rs @@ -55,10 +55,8 @@ impl core::fmt::Debug for Equipment { impl<'a> flatbuffers::Follow<'a> for Equipment { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -66,21 +64,21 @@ impl<'a> flatbuffers::Follow<'a> for Equipment { impl flatbuffers::Push for Equipment { type Output = Equipment; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for Equipment { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/samples/rust_generated/my_game/sample/monster_generated.rs b/samples/rust_generated/my_game/sample/monster_generated.rs index 273212f2d..68ba6d578 100644 --- a/samples/rust_generated/my_game/sample/monster_generated.rs +++ b/samples/rust_generated/my_game/sample/monster_generated.rs @@ -19,8 +19,8 @@ pub struct Monster<'a> { impl<'a> flatbuffers::Follow<'a> for Monster<'a> { type Inner = Monster<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -41,7 +41,7 @@ impl<'a> Monster<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Monster { _tab: table } } #[allow(unused_mut)] @@ -73,7 +73,7 @@ impl<'a> Monster<'a> { x.to_string() }); let inventory = self.inventory().map(|x| { - x.to_vec() + x.into_iter().collect() }); let color = self.color(); let weapons = self.weapons().map(|x| { @@ -106,49 +106,84 @@ impl<'a> Monster<'a> { #[inline] pub fn pos(&self) -> Option<&'a Vec3> { - self._tab.get::(Monster::VT_POS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_POS, None)} } #[inline] pub fn mana(&self) -> i16 { - self._tab.get::(Monster::VT_MANA, Some(150)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_MANA, Some(150)).unwrap()} } #[inline] pub fn hp(&self) -> i16 { - self._tab.get::(Monster::VT_HP, Some(100)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_HP, Some(100)).unwrap()} } #[inline] pub fn name(&self) -> Option<&'a str> { - self._tab.get::>(Monster::VT_NAME, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_NAME, None)} } #[inline] - pub fn inventory(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_INVENTORY, None).map(|v| v.safe_slice()) + pub fn inventory(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_INVENTORY, None)} } #[inline] pub fn color(&self) -> Color { - self._tab.get::(Monster::VT_COLOR, Some(Color::Blue)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_COLOR, Some(Color::Blue)).unwrap()} } #[inline] pub fn weapons(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_WEAPONS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_WEAPONS, None)} } #[inline] pub fn equipped_type(&self) -> Equipment { - self._tab.get::(Monster::VT_EQUIPPED_TYPE, Some(Equipment::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_EQUIPPED_TYPE, Some(Equipment::NONE)).unwrap()} } #[inline] pub fn equipped(&self) -> Option> { - self._tab.get::>>(Monster::VT_EQUIPPED, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_EQUIPPED, None)} } #[inline] - pub fn path(&self) -> Option<&'a [Vec3]> { - self._tab.get::>>(Monster::VT_PATH, None).map(|v| v.safe_slice()) + pub fn path(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_PATH, None)} } #[inline] #[allow(non_snake_case)] pub fn equipped_as_weapon(&self) -> Option> { if self.equipped_type() == Equipment::Weapon { - self.equipped().map(Weapon::init_from_table) + self.equipped().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Weapon::init_from_table(t) } + }) } else { None } @@ -365,18 +400,6 @@ impl MonsterT { }) } } -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> { - unsafe { flatbuffers::root_unchecked::>(buf) } -} - -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_size_prefixed_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> { - unsafe { flatbuffers::size_prefixed_root_unchecked::>(buf) } -} - #[inline] /// Verifies that a buffer of bytes contains a `Monster` /// and returns it. diff --git a/samples/rust_generated/my_game/sample/vec_3_generated.rs b/samples/rust_generated/my_game/sample/vec_3_generated.rs index 894186b6e..185677f89 100644 --- a/samples/rust_generated/my_game/sample/vec_3_generated.rs +++ b/samples/rust_generated/my_game/sample/vec_3_generated.rs @@ -29,39 +29,25 @@ impl core::fmt::Debug for Vec3 { } impl flatbuffers::SimpleToVerifyInSlice for Vec3 {} -impl flatbuffers::SafeSliceAccess for Vec3 {} impl<'a> flatbuffers::Follow<'a> for Vec3 { type Inner = &'a Vec3; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Vec3>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Vec3 { type Inner = &'a Vec3; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Vec3 { type Output = Vec3; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Vec3 as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Vec3 { - type Output = Vec3; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Vec3 as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Vec3 as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -95,70 +81,88 @@ impl<'a> Vec3 { } pub fn x(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_x(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn y(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[4..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_y(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[4..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn z(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[8..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_z(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[8..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/samples/rust_generated/my_game/sample/weapon_generated.rs b/samples/rust_generated/my_game/sample/weapon_generated.rs index f0a709d58..93ea6b2ab 100644 --- a/samples/rust_generated/my_game/sample/weapon_generated.rs +++ b/samples/rust_generated/my_game/sample/weapon_generated.rs @@ -19,8 +19,8 @@ pub struct Weapon<'a> { impl<'a> flatbuffers::Follow<'a> for Weapon<'a> { type Inner = Weapon<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -33,7 +33,7 @@ impl<'a> Weapon<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Weapon { _tab: table } } #[allow(unused_mut)] @@ -60,11 +60,17 @@ impl<'a> Weapon<'a> { #[inline] pub fn name(&self) -> Option<&'a str> { - self._tab.get::>(Weapon::VT_NAME, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Weapon::VT_NAME, None)} } #[inline] pub fn damage(&self) -> i16 { - self._tab.get::(Weapon::VT_DAMAGE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Weapon::VT_DAMAGE, Some(0)).unwrap()} } } diff --git a/samples/sample_binary.rs b/samples/sample_binary.rs index 2f010b8d3..6c2cb0422 100644 --- a/samples/sample_binary.rs +++ b/samples/sample_binary.rs @@ -122,10 +122,7 @@ fn main() { // Get an element from the `inventory` FlatBuffer's `vector`. assert!(monster.inventory().is_some()); let inv = monster.inventory().unwrap(); - - // Note that this vector is returned as a slice, because direct access for - // this type, a u8 vector, is safe on all platforms: - let third_item = inv[2]; + let third_item = inv.get(2); assert_eq!(third_item, 2); // Get and test the `weapons` FlatBuffers's `vector`. diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index a5ce2f72a..a60046ef4 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -737,7 +737,6 @@ class RustGenerator : public BaseGenerator { code_ += "pub use self::bitflags_{{ENUM_NAMESPACE}}::{{ENUM_TY}};"; code_ += ""; - code_.SetValue("FROM_BASE", "unsafe { Self::from_bits_unchecked(b) }"); code_.SetValue("INTO_BASE", "self.bits()"); } else { // Normal, c-modelled enums. @@ -810,7 +809,6 @@ class RustGenerator : public BaseGenerator { code_ += " }"; code_ += "}"; - code_.SetValue("FROM_BASE", "Self(b)"); code_.SetValue("INTO_BASE", "self.0"); } @@ -839,35 +837,55 @@ class RustGenerator : public BaseGenerator { code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_TY}} {"; code_ += " type Inner = Self;"; code_ += " #[inline]"; - code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {"; - code_ += " let b = unsafe {"; - code_ += " flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc)"; - code_ += " };"; - code_ += " {{FROM_BASE}}"; + code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {"; + code_ += " let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc);"; + if (IsBitFlagsEnum(enum_def)) { + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 + code_ += " // Safety:"; + code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size."; + code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0"; + code_ += " // https://github.com/bitflags/bitflags/issues/262"; + code_ += " Self::from_bits_unchecked(b)"; + } else { + code_ += " Self(b)"; + } code_ += " }"; code_ += "}"; code_ += ""; code_ += "impl flatbuffers::Push for {{ENUM_TY}} {"; code_ += " type Output = {{ENUM_TY}};"; code_ += " #[inline]"; - code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {"; - code_ += - " unsafe { flatbuffers::emplace_scalar::<{{BASE_TYPE}}>" - "(dst, {{INTO_BASE}}); }"; + code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {"; + code_ += " flatbuffers::emplace_scalar::<{{BASE_TYPE}}>(dst, {{INTO_BASE}});"; code_ += " }"; code_ += "}"; code_ += ""; code_ += "impl flatbuffers::EndianScalar for {{ENUM_TY}} {"; + code_ += " type Scalar = {{BASE_TYPE}};"; code_ += " #[inline]"; - code_ += " fn to_little_endian(self) -> Self {"; - code_ += " let b = {{BASE_TYPE}}::to_le({{INTO_BASE}});"; - code_ += " {{FROM_BASE}}"; + code_ += " fn to_little_endian(self) -> {{BASE_TYPE}} {"; + code_ += " {{INTO_BASE}}.to_le()"; code_ += " }"; code_ += " #[inline]"; code_ += " #[allow(clippy::wrong_self_convention)]"; - code_ += " fn from_little_endian(self) -> Self {"; - code_ += " let b = {{BASE_TYPE}}::from_le({{INTO_BASE}});"; - code_ += " {{FROM_BASE}}"; + code_ += " fn from_little_endian(v: {{BASE_TYPE}}) -> Self {"; + code_ += " let b = {{BASE_TYPE}}::from_le(v);"; + if (IsBitFlagsEnum(enum_def)) { + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 + code_ += " // Safety:"; + code_ += " // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size."; + code_ += " // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0"; + code_ += " // https://github.com/bitflags/bitflags/issues/262"; + code_ += " unsafe { Self::from_bits_unchecked(b) }"; + } else { + code_ += " Self(b)"; + } code_ += " }"; code_ += "}"; code_ += ""; @@ -1425,11 +1443,7 @@ class RustGenerator : public BaseGenerator { case ftVectorOfBool: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); - const auto vector_type = - IsOneByte(type.VectorType().base_type) - ? "&" + lifetime + " [" + typname + "]" - : "flatbuffers::Vector<" + lifetime + ", " + typname + ">"; - return WrapOption(vector_type); + return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">"); } case ftVectorOfEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); @@ -1438,7 +1452,7 @@ class RustGenerator : public BaseGenerator { } case ftVectorOfStruct: { const auto typname = WrapInNameSpace(*type.struct_def); - return WrapOption("&" + lifetime + " [" + typname + "]"); + return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname + ">"); } case ftVectorOfTable: { const auto typname = WrapInNameSpace(*type.struct_def); @@ -1556,19 +1570,8 @@ class RustGenerator : public BaseGenerator { : "None"; const std::string unwrap = field.IsOptional() ? "" : ".unwrap()"; - const auto t = GetFullType(field.value.type); - - // TODO(caspern): Shouldn't 1byte VectorOfEnumKey be slice too? - const std::string safe_slice = - (t == ftVectorOfStruct || - ((t == ftVectorOfBool || t == ftVectorOfFloat || - t == ftVectorOfInteger) && - IsOneByte(field.value.type.VectorType().base_type))) - ? ".map(|v| v.safe_slice())" - : ""; - - return "self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset + - ", " + default_value + ")" + safe_slice + unwrap; + return "unsafe { self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset + + ", " + default_value + ")" + unwrap + "}"; } // Generates a fully-qualified name getter for use with --gen-name-strings @@ -1650,8 +1653,8 @@ class RustGenerator : public BaseGenerator { code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}}<'a> {"; code_ += " type Inner = {{STRUCT_TY}}<'a>;"; code_ += " #[inline]"; - code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {"; - code_ += " Self { _tab: flatbuffers::Table { buf, loc } }"; + code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {"; + code_ += " Self { _tab: flatbuffers::Table::new(buf, loc) }"; code_ += " }"; code_ += "}"; code_ += ""; @@ -1672,7 +1675,7 @@ class RustGenerator : public BaseGenerator { code_ += " #[inline]"; code_ += - " pub fn init_from_table(table: flatbuffers::Table<'a>) -> " + " pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> " "Self {"; code_ += " {{STRUCT_TY}} { _tab: table }"; code_ += " }"; @@ -1764,16 +1767,7 @@ class RustGenerator : public BaseGenerator { break; } case ftVectorOfInteger: - case ftVectorOfBool: { - if (IsOneByte(type.VectorType().base_type)) { - // 1 byte stuff is viewed w/ slice instead of flatbuffer::Vector - // and thus needs to be cloned out of the slice. - code_.SetValue("EXPR", "x.to_vec()"); - break; - } - code_.SetValue("EXPR", "x.into_iter().collect()"); - break; - } + case ftVectorOfBool: case ftVectorOfFloat: case ftVectorOfEnumKey: { code_.SetValue("EXPR", "x.into_iter().collect()"); @@ -1840,6 +1834,9 @@ class RustGenerator : public BaseGenerator { this->GenComment(field.doc_comment); code_ += "#[inline]"; code_ += "pub fn {{FIELD}}(&self) -> {{RETURN_TYPE}} {"; + code_ += " // Safety:"; + code_ += " // Created from valid Table for this object"; + code_ += " // which contains a valid value in this slot"; code_ += " " + GenTableAccessorFuncBody(field, "'a"); code_ += "}"; @@ -1864,16 +1861,22 @@ class RustGenerator : public BaseGenerator { code_ += "{{NESTED}}<'a> {"; code_ += " let data = self.{{FIELD}}();"; code_ += " use flatbuffers::Follow;"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid flatbuffer in this slot"; code_ += - " >>" - "::follow(data, 0)"; + " unsafe { >>" + "::follow(data.bytes(), 0) }"; } else { code_ += "Option<{{NESTED}}<'a>> {"; code_ += " self.{{FIELD}}().map(|data| {"; code_ += " use flatbuffers::Follow;"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid flatbuffer in this slot"; code_ += - " >>" - "::follow(data, 0)"; + " unsafe { >>" + "::follow(data.bytes(), 0) }"; code_ += " })"; } code_ += "}"; @@ -1909,11 +1912,17 @@ class RustGenerator : public BaseGenerator { // as of April 10, 2020 if (field.IsRequired()) { code_ += " let u = self.{{FIELD}}();"; - code_ += " Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid union in this slot"; + code_ += " Some(unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(u) })"; } else { - code_ += - " self.{{FIELD}}().map(" - "{{U_ELEMENT_TABLE_TYPE}}::init_from_table)"; + code_ +=" self.{{FIELD}}().map(|t| {"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid union in this slot"; + code_ += " unsafe { {{U_ELEMENT_TABLE_TYPE}}::init_from_table(t) }"; + code_ += " })"; } code_ += " } else {"; code_ += " None"; @@ -2282,8 +2291,8 @@ class RustGenerator : public BaseGenerator { MapNativeTableField( field, - "let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();" - "_fbb.create_vector_of_strings(&w)"); + "let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();" + "_fbb.create_vector(&w)"); return; } case ftVectorOfTable: { @@ -2374,32 +2383,6 @@ class RustGenerator : public BaseGenerator { code_.SetValue("STRUCT_FN", namer_.Function(struct_def)); code_.SetValue("STRUCT_CONST", namer_.Constant(struct_def.name)); - // The root datatype accessors: - code_ += "#[inline]"; - code_ += - "#[deprecated(since=\"2.0.0\", " - "note=\"Deprecated in favor of `root_as...` methods.\")]"; - code_ += - "pub fn get_root_as_{{STRUCT_FN}}<'a>(buf: &'a [u8])" - " -> {{STRUCT_TY}}<'a> {"; - code_ += - " unsafe { flatbuffers::root_unchecked::<{{STRUCT_TY}}" - "<'a>>(buf) }"; - code_ += "}"; - code_ += ""; - - code_ += "#[inline]"; - code_ += - "#[deprecated(since=\"2.0.0\", " - "note=\"Deprecated in favor of `root_as...` methods.\")]"; - code_ += - "pub fn get_size_prefixed_root_as_{{STRUCT_FN}}" - "<'a>(buf: &'a [u8]) -> {{STRUCT_TY}}<'a> {"; - code_ += - " unsafe { flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_TY}}" - "<'a>>(buf) }"; - code_ += "}"; - code_ += ""; // Default verifier root fns. code_ += "#[inline]"; code_ += "/// Verifies that a buffer of bytes contains a `{{STRUCT_TY}}`"; @@ -2641,43 +2624,25 @@ class RustGenerator : public BaseGenerator { // Follow for the value type, Follow for the reference type, Push for the // value type, and Push for the reference type. code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{STRUCT_TY}} {}"; - code_ += "impl flatbuffers::SafeSliceAccess for {{STRUCT_TY}} {}"; code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}} {"; code_ += " type Inner = &'a {{STRUCT_TY}};"; code_ += " #[inline]"; - code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {"; + code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {"; code_ += " <&'a {{STRUCT_TY}}>::follow(buf, loc)"; code_ += " }"; code_ += "}"; code_ += "impl<'a> flatbuffers::Follow<'a> for &'a {{STRUCT_TY}} {"; code_ += " type Inner = &'a {{STRUCT_TY}};"; code_ += " #[inline]"; - code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {"; + code_ += " unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {"; code_ += " flatbuffers::follow_cast_ref::<{{STRUCT_TY}}>(buf, loc)"; code_ += " }"; code_ += "}"; code_ += "impl<'b> flatbuffers::Push for {{STRUCT_TY}} {"; code_ += " type Output = {{STRUCT_TY}};"; code_ += " #[inline]"; - code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {"; - code_ += " let src = unsafe {"; - code_ += - " ::core::slice::from_raw_parts(" - "self as *const {{STRUCT_TY}} as *const u8, Self::size())"; - code_ += " };"; - code_ += " dst.copy_from_slice(src);"; - code_ += " }"; - code_ += "}"; - code_ += "impl<'b> flatbuffers::Push for &'b {{STRUCT_TY}} {"; - code_ += " type Output = {{STRUCT_TY}};"; - code_ += ""; - code_ += " #[inline]"; - code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {"; - code_ += " let src = unsafe {"; - code_ += - " ::core::slice::from_raw_parts(" - "*self as *const {{STRUCT_TY}} as *const u8, Self::size())"; - code_ += " };"; + code_ += " unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {"; + code_ += " let src = ::core::slice::from_raw_parts(self as *const {{STRUCT_TY}} as *const u8, Self::size());"; code_ += " dst.copy_from_slice(src);"; code_ += " }"; code_ += "}"; @@ -2754,6 +2719,9 @@ class RustGenerator : public BaseGenerator { // Getter. if (IsStruct(field.value.type)) { code_ += "pub fn {{FIELD}}(&self) -> &{{FIELD_TYPE}} {"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid struct in this slot"; code_ += " unsafe {" " &*(self.0[{{FIELD_OFFSET}}..].as_ptr() as *const" @@ -2765,20 +2733,26 @@ class RustGenerator : public BaseGenerator { code_ += "pub fn {{FIELD}}(&'a self) -> " "flatbuffers::Array<'a, {{ARRAY_ITEM}}, {{ARRAY_SIZE}}> {"; - code_ += " flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}})"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid array in this slot"; + code_ += " unsafe { flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}}) }"; } else { code_ += "pub fn {{FIELD}}(&self) -> {{FIELD_TYPE}} {"; code_ += " let mut mem = core::mem::MaybeUninit::" - "<{{FIELD_TYPE}}>::uninit();"; - code_ += " unsafe {"; + "<<{{FIELD_TYPE}} as EndianScalar>::Scalar>::uninit();"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid value in this slot"; + code_ += " EndianScalar::from_little_endian(unsafe {"; code_ += " core::ptr::copy_nonoverlapping("; code_ += " self.0[{{FIELD_OFFSET}}..].as_ptr(),"; code_ += " mem.as_mut_ptr() as *mut u8,"; - code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),"; + code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),"; code_ += " );"; code_ += " mem.assume_init()"; - code_ += " }.from_little_endian()"; + code_ += " })"; } code_ += "}\n"; // Setter. @@ -2799,13 +2773,19 @@ class RustGenerator : public BaseGenerator { code_ += "pub fn set_{{FIELD}}(&mut self, items: &{{FIELD_TYPE}}) " "{"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid array in this slot"; code_ += - " flatbuffers::emplace_scalar_array(&mut self.0, " - "{{FIELD_OFFSET}}, items);"; + " unsafe { flatbuffers::emplace_scalar_array(&mut self.0, " + "{{FIELD_OFFSET}}, items) };"; } else { code_.SetValue("FIELD_SIZE", NumToString(InlineSize(field.value.type))); code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid array in this slot"; code_ += " unsafe {"; code_ += " core::ptr::copy("; code_ += " x.as_ptr() as *const u8,"; @@ -2817,11 +2797,14 @@ class RustGenerator : public BaseGenerator { } else { code_ += "pub fn set_{{FIELD}}(&mut self, x: {{FIELD_TYPE}}) {"; code_ += " let x_le = x.to_little_endian();"; + code_ += " // Safety:"; + code_ += " // Created from a valid Table for this object"; + code_ += " // Which contains a valid value in this slot"; code_ += " unsafe {"; code_ += " core::ptr::copy_nonoverlapping("; - code_ += " &x_le as *const {{FIELD_TYPE}} as *const u8,"; + code_ += " &x_le as *const _ as *const u8,"; code_ += " self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),"; - code_ += " core::mem::size_of::<{{FIELD_TYPE}}>(),"; + code_ += " core::mem::size_of::<<{{FIELD_TYPE}} as EndianScalar>::Scalar>(),"; code_ += " );"; code_ += " }"; } diff --git a/tests/arrays_test/my_game/example/array_struct_generated.rs b/tests/arrays_test/my_game/example/array_struct_generated.rs index bf416960b..31e1f9ccc 100644 --- a/tests/arrays_test/my_game/example/array_struct_generated.rs +++ b/tests/arrays_test/my_game/example/array_struct_generated.rs @@ -32,39 +32,25 @@ impl core::fmt::Debug for ArrayStruct { } impl flatbuffers::SimpleToVerifyInSlice for ArrayStruct {} -impl flatbuffers::SafeSliceAccess for ArrayStruct {} impl<'a> flatbuffers::Follow<'a> for ArrayStruct { type Inner = &'a ArrayStruct; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a ArrayStruct>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a ArrayStruct { type Inner = &'a ArrayStruct; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for ArrayStruct { type Output = ArrayStruct; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const ArrayStruct as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b ArrayStruct { - type Output = ArrayStruct; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const ArrayStruct as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const ArrayStruct as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -104,64 +90,88 @@ impl<'a> ArrayStruct { } pub fn a(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_a(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn b(&'a self) -> flatbuffers::Array<'a, i32, 15> { - flatbuffers::Array::follow(&self.0, 4) + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::Array::follow(&self.0, 4) } } pub fn set_b(&mut self, items: &[i32; 15]) { - flatbuffers::emplace_scalar_array(&mut self.0, 4, items); + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::emplace_scalar_array(&mut self.0, 4, items) }; } pub fn c(&self) -> i8 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[64..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_c(&mut self, x: i8) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i8 as *const u8, + &x_le as *const _ as *const u8, self.0[64..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn d(&'a self) -> flatbuffers::Array<'a, NestedStruct, 2> { - flatbuffers::Array::follow(&self.0, 72) + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::Array::follow(&self.0, 72) } } pub fn set_d(&mut self, x: &[NestedStruct; 2]) { + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot unsafe { core::ptr::copy( x.as_ptr() as *const u8, @@ -172,34 +182,46 @@ impl<'a> ArrayStruct { } pub fn e(&self) -> i32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[136..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_e(&mut self, x: i32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i32 as *const u8, + &x_le as *const _ as *const u8, self.0[136..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn f(&'a self) -> flatbuffers::Array<'a, i64, 2> { - flatbuffers::Array::follow(&self.0, 144) + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::Array::follow(&self.0, 144) } } pub fn set_f(&mut self, items: &[i64; 2]) { - flatbuffers::emplace_scalar_array(&mut self.0, 144, items); + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::emplace_scalar_array(&mut self.0, 144, items) }; } pub fn unpack(&self) -> ArrayStructT { diff --git a/tests/arrays_test/my_game/example/array_table_generated.rs b/tests/arrays_test/my_game/example/array_table_generated.rs index bc78fc1a1..a9b51cd05 100644 --- a/tests/arrays_test/my_game/example/array_table_generated.rs +++ b/tests/arrays_test/my_game/example/array_table_generated.rs @@ -19,8 +19,8 @@ pub struct ArrayTable<'a> { impl<'a> flatbuffers::Follow<'a> for ArrayTable<'a> { type Inner = ArrayTable<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> ArrayTable<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { ArrayTable { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> ArrayTable<'a> { #[inline] pub fn a(&self) -> Option<&'a ArrayStruct> { - self._tab.get::(ArrayTable::VT_A, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ArrayTable::VT_A, None)} } } @@ -139,18 +142,6 @@ impl ArrayTableT { }) } } -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_root_as_array_table<'a>(buf: &'a [u8]) -> ArrayTable<'a> { - unsafe { flatbuffers::root_unchecked::>(buf) } -} - -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_size_prefixed_root_as_array_table<'a>(buf: &'a [u8]) -> ArrayTable<'a> { - unsafe { flatbuffers::size_prefixed_root_unchecked::>(buf) } -} - #[inline] /// Verifies that a buffer of bytes contains a `ArrayTable` /// and returns it. diff --git a/tests/arrays_test/my_game/example/nested_struct_generated.rs b/tests/arrays_test/my_game/example/nested_struct_generated.rs index 337affc58..0f1f54467 100644 --- a/tests/arrays_test/my_game/example/nested_struct_generated.rs +++ b/tests/arrays_test/my_game/example/nested_struct_generated.rs @@ -30,39 +30,25 @@ impl core::fmt::Debug for NestedStruct { } impl flatbuffers::SimpleToVerifyInSlice for NestedStruct {} -impl flatbuffers::SafeSliceAccess for NestedStruct {} impl<'a> flatbuffers::Follow<'a> for NestedStruct { type Inner = &'a NestedStruct; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a NestedStruct>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a NestedStruct { type Inner = &'a NestedStruct; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for NestedStruct { type Output = NestedStruct; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const NestedStruct as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b NestedStruct { - type Output = NestedStruct; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const NestedStruct as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const NestedStruct as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -98,41 +84,59 @@ impl<'a> NestedStruct { } pub fn a(&'a self) -> flatbuffers::Array<'a, i32, 2> { - flatbuffers::Array::follow(&self.0, 0) + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::Array::follow(&self.0, 0) } } pub fn set_a(&mut self, items: &[i32; 2]) { - flatbuffers::emplace_scalar_array(&mut self.0, 0, items); + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::emplace_scalar_array(&mut self.0, 0, items) }; } pub fn b(&self) -> TestEnum { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[8..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_b(&mut self, x: TestEnum) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const TestEnum as *const u8, + &x_le as *const _ as *const u8, self.0[8..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn c(&'a self) -> flatbuffers::Array<'a, TestEnum, 2> { - flatbuffers::Array::follow(&self.0, 9) + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::Array::follow(&self.0, 9) } } pub fn set_c(&mut self, x: &[TestEnum; 2]) { + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot unsafe { core::ptr::copy( x.as_ptr() as *const u8, @@ -143,11 +147,17 @@ impl<'a> NestedStruct { } pub fn d(&'a self) -> flatbuffers::Array<'a, i64, 2> { - flatbuffers::Array::follow(&self.0, 16) + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::Array::follow(&self.0, 16) } } pub fn set_d(&mut self, items: &[i64; 2]) { - flatbuffers::emplace_scalar_array(&mut self.0, 16, items); + // Safety: + // Created from a valid Table for this object + // Which contains a valid array in this slot + unsafe { flatbuffers::emplace_scalar_array(&mut self.0, 16, items) }; } pub fn unpack(&self) -> NestedStructT { diff --git a/tests/arrays_test/my_game/example/test_enum_generated.rs b/tests/arrays_test/my_game/example/test_enum_generated.rs index 5252133c6..6721484ae 100644 --- a/tests/arrays_test/my_game/example/test_enum_generated.rs +++ b/tests/arrays_test/my_game/example/test_enum_generated.rs @@ -59,10 +59,8 @@ impl core::fmt::Debug for TestEnum { impl<'a> flatbuffers::Follow<'a> for TestEnum { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for TestEnum { impl flatbuffers::Push for TestEnum { type Output = TestEnum; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for TestEnum { + type Scalar = i8; #[inline] - fn to_little_endian(self) -> Self { - let b = i8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i8::from_le(self.0); + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); Self(b) } } diff --git a/tests/include_test1/my_game/other_name_space/from_include_generated.rs b/tests/include_test1/my_game/other_name_space/from_include_generated.rs index 3c5165d17..70cb407c1 100644 --- a/tests/include_test1/my_game/other_name_space/from_include_generated.rs +++ b/tests/include_test1/my_game/other_name_space/from_include_generated.rs @@ -51,10 +51,8 @@ impl core::fmt::Debug for FromInclude { impl<'a> flatbuffers::Follow<'a> for FromInclude { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -62,21 +60,21 @@ impl<'a> flatbuffers::Follow<'a> for FromInclude { impl flatbuffers::Push for FromInclude { type Output = FromInclude; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for FromInclude { + type Scalar = i64; #[inline] - fn to_little_endian(self) -> Self { - let b = i64::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i64 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i64::from_le(self.0); + fn from_little_endian(v: i64) -> Self { + let b = i64::from_le(v); Self(b) } } diff --git a/tests/include_test1/my_game/other_name_space/table_b_generated.rs b/tests/include_test1/my_game/other_name_space/table_b_generated.rs index da7b9378b..5652195b5 100644 --- a/tests/include_test1/my_game/other_name_space/table_b_generated.rs +++ b/tests/include_test1/my_game/other_name_space/table_b_generated.rs @@ -19,8 +19,8 @@ pub struct TableB<'a> { impl<'a> flatbuffers::Follow<'a> for TableB<'a> { type Inner = TableB<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> TableB<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableB { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> TableB<'a> { #[inline] pub fn a(&self) -> Option> { - self._tab.get::>(TableB::VT_A, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableB::VT_A, None)} } } diff --git a/tests/include_test1/my_game/other_name_space/unused_generated.rs b/tests/include_test1/my_game/other_name_space/unused_generated.rs index 1e4ad9c7b..69be4869e 100644 --- a/tests/include_test1/my_game/other_name_space/unused_generated.rs +++ b/tests/include_test1/my_game/other_name_space/unused_generated.rs @@ -27,39 +27,25 @@ impl core::fmt::Debug for Unused { } impl flatbuffers::SimpleToVerifyInSlice for Unused {} -impl flatbuffers::SafeSliceAccess for Unused {} impl<'a> flatbuffers::Follow<'a> for Unused { type Inner = &'a Unused; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Unused>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Unused { type Inner = &'a Unused; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Unused { type Output = Unused; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Unused as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Unused { - type Output = Unused; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Unused as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Unused as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -89,24 +75,30 @@ impl<'a> Unused { } pub fn a(&self) -> i32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_a(&mut self, x: i32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/include_test1/table_a_generated.rs b/tests/include_test1/table_a_generated.rs index 0e6a78de1..fd979b092 100644 --- a/tests/include_test1/table_a_generated.rs +++ b/tests/include_test1/table_a_generated.rs @@ -19,8 +19,8 @@ pub struct TableA<'a> { impl<'a> flatbuffers::Follow<'a> for TableA<'a> { type Inner = TableA<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> TableA<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableA { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> TableA<'a> { #[inline] pub fn b(&self) -> Option> { - self._tab.get::>(TableA::VT_B, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableA::VT_B, None)} } } diff --git a/tests/include_test2/my_game/other_name_space/from_include_generated.rs b/tests/include_test2/my_game/other_name_space/from_include_generated.rs index 3c5165d17..70cb407c1 100644 --- a/tests/include_test2/my_game/other_name_space/from_include_generated.rs +++ b/tests/include_test2/my_game/other_name_space/from_include_generated.rs @@ -51,10 +51,8 @@ impl core::fmt::Debug for FromInclude { impl<'a> flatbuffers::Follow<'a> for FromInclude { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -62,21 +60,21 @@ impl<'a> flatbuffers::Follow<'a> for FromInclude { impl flatbuffers::Push for FromInclude { type Output = FromInclude; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for FromInclude { + type Scalar = i64; #[inline] - fn to_little_endian(self) -> Self { - let b = i64::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i64 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i64::from_le(self.0); + fn from_little_endian(v: i64) -> Self { + let b = i64::from_le(v); Self(b) } } diff --git a/tests/include_test2/my_game/other_name_space/table_b_generated.rs b/tests/include_test2/my_game/other_name_space/table_b_generated.rs index da7b9378b..5652195b5 100644 --- a/tests/include_test2/my_game/other_name_space/table_b_generated.rs +++ b/tests/include_test2/my_game/other_name_space/table_b_generated.rs @@ -19,8 +19,8 @@ pub struct TableB<'a> { impl<'a> flatbuffers::Follow<'a> for TableB<'a> { type Inner = TableB<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> TableB<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableB { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> TableB<'a> { #[inline] pub fn a(&self) -> Option> { - self._tab.get::>(TableB::VT_A, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableB::VT_A, None)} } } diff --git a/tests/include_test2/my_game/other_name_space/unused_generated.rs b/tests/include_test2/my_game/other_name_space/unused_generated.rs index 1e4ad9c7b..69be4869e 100644 --- a/tests/include_test2/my_game/other_name_space/unused_generated.rs +++ b/tests/include_test2/my_game/other_name_space/unused_generated.rs @@ -27,39 +27,25 @@ impl core::fmt::Debug for Unused { } impl flatbuffers::SimpleToVerifyInSlice for Unused {} -impl flatbuffers::SafeSliceAccess for Unused {} impl<'a> flatbuffers::Follow<'a> for Unused { type Inner = &'a Unused; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Unused>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Unused { type Inner = &'a Unused; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Unused { type Output = Unused; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Unused as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Unused { - type Output = Unused; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Unused as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Unused as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -89,24 +75,30 @@ impl<'a> Unused { } pub fn a(&self) -> i32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_a(&mut self, x: i32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/include_test2/table_a_generated.rs b/tests/include_test2/table_a_generated.rs index 0e6a78de1..fd979b092 100644 --- a/tests/include_test2/table_a_generated.rs +++ b/tests/include_test2/table_a_generated.rs @@ -19,8 +19,8 @@ pub struct TableA<'a> { impl<'a> flatbuffers::Follow<'a> for TableA<'a> { type Inner = TableA<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> TableA<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableA { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> TableA<'a> { #[inline] pub fn b(&self) -> Option> { - self._tab.get::>(TableA::VT_B, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableA::VT_B, None)} } } diff --git a/tests/keyword_test/keyword_test/abc_generated.rs b/tests/keyword_test/keyword_test/abc_generated.rs index 823b883b7..5169ab13d 100644 --- a/tests/keyword_test/keyword_test/abc_generated.rs +++ b/tests/keyword_test/keyword_test/abc_generated.rs @@ -59,10 +59,8 @@ impl core::fmt::Debug for ABC { impl<'a> flatbuffers::Follow<'a> for ABC { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for ABC { impl flatbuffers::Push for ABC { type Output = ABC; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for ABC { + type Scalar = i32; #[inline] - fn to_little_endian(self) -> Self { - let b = i32::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i32 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i32::from_le(self.0); + fn from_little_endian(v: i32) -> Self { + let b = i32::from_le(v); Self(b) } } diff --git a/tests/keyword_test/keyword_test/keywords_in_table_generated.rs b/tests/keyword_test/keyword_test/keywords_in_table_generated.rs index 74ddfba0a..4dd30dc94 100644 --- a/tests/keyword_test/keyword_test/keywords_in_table_generated.rs +++ b/tests/keyword_test/keyword_test/keywords_in_table_generated.rs @@ -19,8 +19,8 @@ pub struct KeywordsInTable<'a> { impl<'a> flatbuffers::Follow<'a> for KeywordsInTable<'a> { type Inner = KeywordsInTable<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -35,7 +35,7 @@ impl<'a> KeywordsInTable<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { KeywordsInTable { _tab: table } } #[allow(unused_mut)] @@ -66,19 +66,31 @@ impl<'a> KeywordsInTable<'a> { #[inline] pub fn is(&self) -> ABC { - self._tab.get::(KeywordsInTable::VT_IS, Some(ABC::void)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(KeywordsInTable::VT_IS, Some(ABC::void)).unwrap()} } #[inline] pub fn private(&self) -> public { - self._tab.get::(KeywordsInTable::VT_PRIVATE, Some(public::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(KeywordsInTable::VT_PRIVATE, Some(public::NONE)).unwrap()} } #[inline] pub fn type_(&self) -> i32 { - self._tab.get::(KeywordsInTable::VT_TYPE_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(KeywordsInTable::VT_TYPE_, Some(0)).unwrap()} } #[inline] pub fn default(&self) -> bool { - self._tab.get::(KeywordsInTable::VT_DEFAULT, Some(false)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(KeywordsInTable::VT_DEFAULT, Some(false)).unwrap()} } } diff --git a/tests/keyword_test/keyword_test/keywords_in_union_generated.rs b/tests/keyword_test/keyword_test/keywords_in_union_generated.rs index 78d8cd79c..ba9fcd3a6 100644 --- a/tests/keyword_test/keyword_test/keywords_in_union_generated.rs +++ b/tests/keyword_test/keyword_test/keywords_in_union_generated.rs @@ -59,10 +59,8 @@ impl core::fmt::Debug for KeywordsInUnion { impl<'a> flatbuffers::Follow<'a> for KeywordsInUnion { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for KeywordsInUnion { impl flatbuffers::Push for KeywordsInUnion { type Output = KeywordsInUnion; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for KeywordsInUnion { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/keyword_test/keyword_test/public_generated.rs b/tests/keyword_test/keyword_test/public_generated.rs index 76c6ed00c..12c3ff579 100644 --- a/tests/keyword_test/keyword_test/public_generated.rs +++ b/tests/keyword_test/keyword_test/public_generated.rs @@ -51,10 +51,8 @@ impl core::fmt::Debug for public { impl<'a> flatbuffers::Follow<'a> for public { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -62,21 +60,21 @@ impl<'a> flatbuffers::Follow<'a> for public { impl flatbuffers::Push for public { type Output = public; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for public { + type Scalar = i32; #[inline] - fn to_little_endian(self) -> Self { - let b = i32::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i32 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i32::from_le(self.0); + fn from_little_endian(v: i32) -> Self { + let b = i32::from_le(v); Self(b) } } diff --git a/tests/monster_test/my_game/example/ability_generated.rs b/tests/monster_test/my_game/example/ability_generated.rs index d1f177c51..042df75f1 100644 --- a/tests/monster_test/my_game/example/ability_generated.rs +++ b/tests/monster_test/my_game/example/ability_generated.rs @@ -28,39 +28,25 @@ impl core::fmt::Debug for Ability { } impl flatbuffers::SimpleToVerifyInSlice for Ability {} -impl flatbuffers::SafeSliceAccess for Ability {} impl<'a> flatbuffers::Follow<'a> for Ability { type Inner = &'a Ability; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Ability>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Ability { type Inner = &'a Ability; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Ability { type Output = Ability; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Ability as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Ability { - type Output = Ability; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Ability as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Ability as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -92,24 +78,30 @@ impl<'a> Ability { } pub fn id(&self) -> u32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_id(&mut self, x: u32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const u32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } @@ -125,24 +117,30 @@ impl<'a> Ability { key.cmp(&val) } pub fn distance(&self) -> u32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[4..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_distance(&mut self, x: u32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const u32 as *const u8, + &x_le as *const _ as *const u8, self.0[4..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/monster_test/my_game/example/any_ambiguous_aliases_generated.rs b/tests/monster_test/my_game/example/any_ambiguous_aliases_generated.rs index ee8cba7cb..8ff20919a 100644 --- a/tests/monster_test/my_game/example/any_ambiguous_aliases_generated.rs +++ b/tests/monster_test/my_game/example/any_ambiguous_aliases_generated.rs @@ -63,10 +63,8 @@ impl core::fmt::Debug for AnyAmbiguousAliases { impl<'a> flatbuffers::Follow<'a> for AnyAmbiguousAliases { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -74,21 +72,21 @@ impl<'a> flatbuffers::Follow<'a> for AnyAmbiguousAliases { impl flatbuffers::Push for AnyAmbiguousAliases { type Output = AnyAmbiguousAliases; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for AnyAmbiguousAliases { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/monster_test/my_game/example/any_generated.rs b/tests/monster_test/my_game/example/any_generated.rs index adddc10c5..d33337ad4 100644 --- a/tests/monster_test/my_game/example/any_generated.rs +++ b/tests/monster_test/my_game/example/any_generated.rs @@ -63,10 +63,8 @@ impl core::fmt::Debug for Any { impl<'a> flatbuffers::Follow<'a> for Any { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -74,21 +72,21 @@ impl<'a> flatbuffers::Follow<'a> for Any { impl flatbuffers::Push for Any { type Output = Any; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for Any { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/monster_test/my_game/example/any_unique_aliases_generated.rs b/tests/monster_test/my_game/example/any_unique_aliases_generated.rs index 5142d0e59..726fa8e2a 100644 --- a/tests/monster_test/my_game/example/any_unique_aliases_generated.rs +++ b/tests/monster_test/my_game/example/any_unique_aliases_generated.rs @@ -63,10 +63,8 @@ impl core::fmt::Debug for AnyUniqueAliases { impl<'a> flatbuffers::Follow<'a> for AnyUniqueAliases { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -74,21 +72,21 @@ impl<'a> flatbuffers::Follow<'a> for AnyUniqueAliases { impl flatbuffers::Push for AnyUniqueAliases { type Output = AnyUniqueAliases; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for AnyUniqueAliases { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/monster_test/my_game/example/color_generated.rs b/tests/monster_test/my_game/example/color_generated.rs index 1b9287fd4..9cd348aa5 100644 --- a/tests/monster_test/my_game/example/color_generated.rs +++ b/tests/monster_test/my_game/example/color_generated.rs @@ -29,32 +29,38 @@ pub use self::bitflags_color::Color; impl<'a> flatbuffers::Follow<'a> for Color { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; - unsafe { Self::from_bits_unchecked(b) } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 + Self::from_bits_unchecked(b) } } impl flatbuffers::Push for Color { type Output = Color; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.bits()); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.bits()); } } impl flatbuffers::EndianScalar for Color { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.bits()); - unsafe { Self::from_bits_unchecked(b) } + fn to_little_endian(self) -> u8 { + self.bits().to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.bits()); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 unsafe { Self::from_bits_unchecked(b) } } } diff --git a/tests/monster_test/my_game/example/long_enum_generated.rs b/tests/monster_test/my_game/example/long_enum_generated.rs index 6a24d74c4..d7625269c 100644 --- a/tests/monster_test/my_game/example/long_enum_generated.rs +++ b/tests/monster_test/my_game/example/long_enum_generated.rs @@ -25,32 +25,38 @@ pub use self::bitflags_long_enum::LongEnum; impl<'a> flatbuffers::Follow<'a> for LongEnum { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; - unsafe { Self::from_bits_unchecked(b) } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 + Self::from_bits_unchecked(b) } } impl flatbuffers::Push for LongEnum { type Output = LongEnum; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.bits()); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.bits()); } } impl flatbuffers::EndianScalar for LongEnum { + type Scalar = u64; #[inline] - fn to_little_endian(self) -> Self { - let b = u64::to_le(self.bits()); - unsafe { Self::from_bits_unchecked(b) } + fn to_little_endian(self) -> u64 { + self.bits().to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u64::from_le(self.bits()); + fn from_little_endian(v: u64) -> Self { + let b = u64::from_le(v); + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 unsafe { Self::from_bits_unchecked(b) } } } diff --git a/tests/monster_test/my_game/example/monster_generated.rs b/tests/monster_test/my_game/example/monster_generated.rs index dd325b28f..1ca88f069 100644 --- a/tests/monster_test/my_game/example/monster_generated.rs +++ b/tests/monster_test/my_game/example/monster_generated.rs @@ -20,8 +20,8 @@ pub struct Monster<'a> { impl<'a> flatbuffers::Follow<'a> for Monster<'a> { type Inner = Monster<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -85,7 +85,7 @@ impl<'a> Monster<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Monster { _tab: table } } #[allow(unused_mut)] @@ -161,7 +161,7 @@ impl<'a> Monster<'a> { x.to_string() }; let inventory = self.inventory().map(|x| { - x.to_vec() + x.into_iter().collect() }); let color = self.color(); let test = match self.test_type() { @@ -196,7 +196,7 @@ impl<'a> Monster<'a> { Box::new(x.unpack()) }); let testnestedflatbuffer = self.testnestedflatbuffer().map(|x| { - x.to_vec() + x.into_iter().collect() }); let testempty = self.testempty().map(|x| { Box::new(x.unpack()) @@ -211,7 +211,7 @@ impl<'a> Monster<'a> { let testhashs64_fnv1a = self.testhashs64_fnv1a(); let testhashu64_fnv1a = self.testhashu64_fnv1a(); let testarrayofbools = self.testarrayofbools().map(|x| { - x.to_vec() + x.into_iter().collect() }); let testf = self.testf(); let testf2 = self.testf2(); @@ -223,7 +223,7 @@ impl<'a> Monster<'a> { x.iter().map(|t| t.unpack()).collect() }); let flex = self.flex().map(|x| { - x.to_vec() + x.into_iter().collect() }); let test5 = self.test5().map(|x| { x.iter().map(|t| t.unpack()).collect() @@ -298,7 +298,7 @@ impl<'a> Monster<'a> { }); let signed_enum = self.signed_enum(); let testrequirednestedflatbuffer = self.testrequirednestedflatbuffer().map(|x| { - x.to_vec() + x.into_iter().collect() }); let scalar_key_sorted_tables = self.scalar_key_sorted_tables().map(|x| { x.iter().map(|t| t.unpack()).collect() @@ -364,19 +364,31 @@ impl<'a> Monster<'a> { #[inline] pub fn pos(&self) -> Option<&'a Vec3> { - self._tab.get::(Monster::VT_POS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_POS, None)} } #[inline] pub fn mana(&self) -> i16 { - self._tab.get::(Monster::VT_MANA, Some(150)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_MANA, Some(150)).unwrap()} } #[inline] pub fn hp(&self) -> i16 { - self._tab.get::(Monster::VT_HP, Some(100)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_HP, Some(100)).unwrap()} } #[inline] pub fn name(&self) -> &'a str { - self._tab.get::>(Monster::VT_NAME, None).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_NAME, None).unwrap()} } #[inline] pub fn key_compare_less_than(&self, o: &Monster) -> bool { @@ -389,220 +401,378 @@ impl<'a> Monster<'a> { key.cmp(val) } #[inline] - pub fn inventory(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_INVENTORY, None).map(|v| v.safe_slice()) + pub fn inventory(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_INVENTORY, None)} } #[inline] pub fn color(&self) -> Color { - self._tab.get::(Monster::VT_COLOR, Some(Color::Blue)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_COLOR, Some(Color::Blue)).unwrap()} } #[inline] pub fn test_type(&self) -> Any { - self._tab.get::(Monster::VT_TEST_TYPE, Some(Any::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TEST_TYPE, Some(Any::NONE)).unwrap()} } #[inline] pub fn test(&self) -> Option> { - self._tab.get::>>(Monster::VT_TEST, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TEST, None)} } #[inline] - pub fn test4(&self) -> Option<&'a [Test]> { - self._tab.get::>>(Monster::VT_TEST4, None).map(|v| v.safe_slice()) + pub fn test4(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TEST4, None)} } #[inline] pub fn testarrayofstring(&self) -> Option>> { - self._tab.get::>>>(Monster::VT_TESTARRAYOFSTRING, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_TESTARRAYOFSTRING, None)} } /// an example documentation comment: this will end up in the generated code /// multiline too #[inline] pub fn testarrayoftables(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_TESTARRAYOFTABLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_TESTARRAYOFTABLES, None)} } #[inline] pub fn enemy(&self) -> Option> { - self._tab.get::>(Monster::VT_ENEMY, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_ENEMY, None)} } #[inline] - pub fn testnestedflatbuffer(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_TESTNESTEDFLATBUFFER, None).map(|v| v.safe_slice()) + pub fn testnestedflatbuffer(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TESTNESTEDFLATBUFFER, None)} } pub fn testnestedflatbuffer_nested_flatbuffer(&'a self) -> Option> { self.testnestedflatbuffer().map(|data| { use flatbuffers::Follow; - >>::follow(data, 0) + // Safety: + // Created from a valid Table for this object + // Which contains a valid flatbuffer in this slot + unsafe { >>::follow(data.bytes(), 0) } }) } #[inline] pub fn testempty(&self) -> Option> { - self._tab.get::>(Monster::VT_TESTEMPTY, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_TESTEMPTY, None)} } #[inline] pub fn testbool(&self) -> bool { - self._tab.get::(Monster::VT_TESTBOOL, Some(false)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTBOOL, Some(false)).unwrap()} } #[inline] pub fn testhashs32_fnv1(&self) -> i32 { - self._tab.get::(Monster::VT_TESTHASHS32_FNV1, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHS32_FNV1, Some(0)).unwrap()} } #[inline] pub fn testhashu32_fnv1(&self) -> u32 { - self._tab.get::(Monster::VT_TESTHASHU32_FNV1, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHU32_FNV1, Some(0)).unwrap()} } #[inline] pub fn testhashs64_fnv1(&self) -> i64 { - self._tab.get::(Monster::VT_TESTHASHS64_FNV1, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHS64_FNV1, Some(0)).unwrap()} } #[inline] pub fn testhashu64_fnv1(&self) -> u64 { - self._tab.get::(Monster::VT_TESTHASHU64_FNV1, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHU64_FNV1, Some(0)).unwrap()} } #[inline] pub fn testhashs32_fnv1a(&self) -> i32 { - self._tab.get::(Monster::VT_TESTHASHS32_FNV1A, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHS32_FNV1A, Some(0)).unwrap()} } #[inline] pub fn testhashu32_fnv1a(&self) -> u32 { - self._tab.get::(Monster::VT_TESTHASHU32_FNV1A, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHU32_FNV1A, Some(0)).unwrap()} } #[inline] pub fn testhashs64_fnv1a(&self) -> i64 { - self._tab.get::(Monster::VT_TESTHASHS64_FNV1A, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHS64_FNV1A, Some(0)).unwrap()} } #[inline] pub fn testhashu64_fnv1a(&self) -> u64 { - self._tab.get::(Monster::VT_TESTHASHU64_FNV1A, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHU64_FNV1A, Some(0)).unwrap()} } #[inline] - pub fn testarrayofbools(&self) -> Option<&'a [bool]> { - self._tab.get::>>(Monster::VT_TESTARRAYOFBOOLS, None).map(|v| v.safe_slice()) + pub fn testarrayofbools(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TESTARRAYOFBOOLS, None)} } #[inline] pub fn testf(&self) -> f32 { - self._tab.get::(Monster::VT_TESTF, Some(3.14159)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTF, Some(3.14159)).unwrap()} } #[inline] pub fn testf2(&self) -> f32 { - self._tab.get::(Monster::VT_TESTF2, Some(3.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTF2, Some(3.0)).unwrap()} } #[inline] pub fn testf3(&self) -> f32 { - self._tab.get::(Monster::VT_TESTF3, Some(0.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTF3, Some(0.0)).unwrap()} } #[inline] pub fn testarrayofstring2(&self) -> Option>> { - self._tab.get::>>>(Monster::VT_TESTARRAYOFSTRING2, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_TESTARRAYOFSTRING2, None)} } #[inline] - pub fn testarrayofsortedstruct(&self) -> Option<&'a [Ability]> { - self._tab.get::>>(Monster::VT_TESTARRAYOFSORTEDSTRUCT, None).map(|v| v.safe_slice()) + pub fn testarrayofsortedstruct(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TESTARRAYOFSORTEDSTRUCT, None)} } #[inline] - pub fn flex(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_FLEX, None).map(|v| v.safe_slice()) + pub fn flex(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_FLEX, None)} } #[inline] - pub fn test5(&self) -> Option<&'a [Test]> { - self._tab.get::>>(Monster::VT_TEST5, None).map(|v| v.safe_slice()) + pub fn test5(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TEST5, None)} } #[inline] pub fn vector_of_longs(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_LONGS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_LONGS, None)} } #[inline] pub fn vector_of_doubles(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_DOUBLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_DOUBLES, None)} } #[inline] pub fn parent_namespace_test(&self) -> Option> { - self._tab.get::>(Monster::VT_PARENT_NAMESPACE_TEST, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_PARENT_NAMESPACE_TEST, None)} } #[inline] pub fn vector_of_referrables(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_VECTOR_OF_REFERRABLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_VECTOR_OF_REFERRABLES, None)} } #[inline] pub fn single_weak_reference(&self) -> u64 { - self._tab.get::(Monster::VT_SINGLE_WEAK_REFERENCE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_SINGLE_WEAK_REFERENCE, Some(0)).unwrap()} } #[inline] pub fn vector_of_weak_references(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_WEAK_REFERENCES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_WEAK_REFERENCES, None)} } #[inline] pub fn vector_of_strong_referrables(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_VECTOR_OF_STRONG_REFERRABLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_VECTOR_OF_STRONG_REFERRABLES, None)} } #[inline] pub fn co_owning_reference(&self) -> u64 { - self._tab.get::(Monster::VT_CO_OWNING_REFERENCE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_CO_OWNING_REFERENCE, Some(0)).unwrap()} } #[inline] pub fn vector_of_co_owning_references(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_CO_OWNING_REFERENCES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_CO_OWNING_REFERENCES, None)} } #[inline] pub fn non_owning_reference(&self) -> u64 { - self._tab.get::(Monster::VT_NON_OWNING_REFERENCE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_NON_OWNING_REFERENCE, Some(0)).unwrap()} } #[inline] pub fn vector_of_non_owning_references(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_NON_OWNING_REFERENCES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_NON_OWNING_REFERENCES, None)} } #[inline] pub fn any_unique_type(&self) -> AnyUniqueAliases { - self._tab.get::(Monster::VT_ANY_UNIQUE_TYPE, Some(AnyUniqueAliases::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_ANY_UNIQUE_TYPE, Some(AnyUniqueAliases::NONE)).unwrap()} } #[inline] pub fn any_unique(&self) -> Option> { - self._tab.get::>>(Monster::VT_ANY_UNIQUE, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_ANY_UNIQUE, None)} } #[inline] pub fn any_ambiguous_type(&self) -> AnyAmbiguousAliases { - self._tab.get::(Monster::VT_ANY_AMBIGUOUS_TYPE, Some(AnyAmbiguousAliases::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_ANY_AMBIGUOUS_TYPE, Some(AnyAmbiguousAliases::NONE)).unwrap()} } #[inline] pub fn any_ambiguous(&self) -> Option> { - self._tab.get::>>(Monster::VT_ANY_AMBIGUOUS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_ANY_AMBIGUOUS, None)} } #[inline] pub fn vector_of_enums(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_ENUMS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_ENUMS, None)} } #[inline] pub fn signed_enum(&self) -> Race { - self._tab.get::(Monster::VT_SIGNED_ENUM, Some(Race::None)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_SIGNED_ENUM, Some(Race::None)).unwrap()} } #[inline] - pub fn testrequirednestedflatbuffer(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_TESTREQUIREDNESTEDFLATBUFFER, None).map(|v| v.safe_slice()) + pub fn testrequirednestedflatbuffer(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TESTREQUIREDNESTEDFLATBUFFER, None)} } pub fn testrequirednestedflatbuffer_nested_flatbuffer(&'a self) -> Option> { self.testrequirednestedflatbuffer().map(|data| { use flatbuffers::Follow; - >>::follow(data, 0) + // Safety: + // Created from a valid Table for this object + // Which contains a valid flatbuffer in this slot + unsafe { >>::follow(data.bytes(), 0) } }) } #[inline] pub fn scalar_key_sorted_tables(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_SCALAR_KEY_SORTED_TABLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_SCALAR_KEY_SORTED_TABLES, None)} } #[inline] pub fn native_inline(&self) -> Option<&'a Test> { - self._tab.get::(Monster::VT_NATIVE_INLINE, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_NATIVE_INLINE, None)} } #[inline] pub fn long_enum_non_enum_default(&self) -> LongEnum { - self._tab.get::(Monster::VT_LONG_ENUM_NON_ENUM_DEFAULT, Some(Default::default())).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_LONG_ENUM_NON_ENUM_DEFAULT, Some(Default::default())).unwrap()} } #[inline] pub fn long_enum_normal_default(&self) -> LongEnum { - self._tab.get::(Monster::VT_LONG_ENUM_NORMAL_DEFAULT, Some(LongEnum::LongOne)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_LONG_ENUM_NORMAL_DEFAULT, Some(LongEnum::LongOne)).unwrap()} } #[inline] #[allow(non_snake_case)] pub fn test_as_monster(&self) -> Option> { if self.test_type() == Any::Monster { - self.test().map(Monster::init_from_table) + self.test().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -612,7 +782,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn test_as_test_simple_table_with_enum(&self) -> Option> { if self.test_type() == Any::TestSimpleTableWithEnum { - self.test().map(TestSimpleTableWithEnum::init_from_table) + self.test().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { TestSimpleTableWithEnum::init_from_table(t) } + }) } else { None } @@ -622,7 +797,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn test_as_my_game_example_2_monster(&self) -> Option> { if self.test_type() == Any::MyGame_Example2_Monster { - self.test().map(super::example_2::Monster::init_from_table) + self.test().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { super::example_2::Monster::init_from_table(t) } + }) } else { None } @@ -632,7 +812,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_unique_as_m(&self) -> Option> { if self.any_unique_type() == AnyUniqueAliases::M { - self.any_unique().map(Monster::init_from_table) + self.any_unique().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -642,7 +827,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_unique_as_ts(&self) -> Option> { if self.any_unique_type() == AnyUniqueAliases::TS { - self.any_unique().map(TestSimpleTableWithEnum::init_from_table) + self.any_unique().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { TestSimpleTableWithEnum::init_from_table(t) } + }) } else { None } @@ -652,7 +842,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_unique_as_m2(&self) -> Option> { if self.any_unique_type() == AnyUniqueAliases::M2 { - self.any_unique().map(super::example_2::Monster::init_from_table) + self.any_unique().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { super::example_2::Monster::init_from_table(t) } + }) } else { None } @@ -662,7 +857,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_ambiguous_as_m1(&self) -> Option> { if self.any_ambiguous_type() == AnyAmbiguousAliases::M1 { - self.any_ambiguous().map(Monster::init_from_table) + self.any_ambiguous().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -672,7 +872,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_ambiguous_as_m2(&self) -> Option> { if self.any_ambiguous_type() == AnyAmbiguousAliases::M2 { - self.any_ambiguous().map(Monster::init_from_table) + self.any_ambiguous().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -682,7 +887,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_ambiguous_as_m3(&self) -> Option> { if self.any_ambiguous_type() == AnyAmbiguousAliases::M3 { - self.any_ambiguous().map(Monster::init_from_table) + self.any_ambiguous().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -1391,7 +1601,7 @@ impl MonsterT { let w: Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w) }); let testarrayofstring = self.testarrayofstring.as_ref().map(|x|{ - let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();_fbb.create_vector_of_strings(&w) + let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();_fbb.create_vector(&w) }); let testarrayoftables = self.testarrayoftables.as_ref().map(|x|{ let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w) @@ -1421,7 +1631,7 @@ impl MonsterT { let testf2 = self.testf2; let testf3 = self.testf3; let testarrayofstring2 = self.testarrayofstring2.as_ref().map(|x|{ - let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();_fbb.create_vector_of_strings(&w) + let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();_fbb.create_vector(&w) }); let testarrayofsortedstruct = self.testarrayofsortedstruct.as_ref().map(|x|{ let w: Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w) @@ -1534,18 +1744,6 @@ impl MonsterT { }) } } -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> { - unsafe { flatbuffers::root_unchecked::>(buf) } -} - -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_size_prefixed_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> { - unsafe { flatbuffers::size_prefixed_root_unchecked::>(buf) } -} - #[inline] /// Verifies that a buffer of bytes contains a `Monster` /// and returns it. diff --git a/tests/monster_test/my_game/example/race_generated.rs b/tests/monster_test/my_game/example/race_generated.rs index 47f3855a0..dd48b4e1e 100644 --- a/tests/monster_test/my_game/example/race_generated.rs +++ b/tests/monster_test/my_game/example/race_generated.rs @@ -63,10 +63,8 @@ impl core::fmt::Debug for Race { impl<'a> flatbuffers::Follow<'a> for Race { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -74,21 +72,21 @@ impl<'a> flatbuffers::Follow<'a> for Race { impl flatbuffers::Push for Race { type Output = Race; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for Race { + type Scalar = i8; #[inline] - fn to_little_endian(self) -> Self { - let b = i8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i8::from_le(self.0); + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); Self(b) } } diff --git a/tests/monster_test/my_game/example/referrable_generated.rs b/tests/monster_test/my_game/example/referrable_generated.rs index 81a9d60ba..5a031cefa 100644 --- a/tests/monster_test/my_game/example/referrable_generated.rs +++ b/tests/monster_test/my_game/example/referrable_generated.rs @@ -19,8 +19,8 @@ pub struct Referrable<'a> { impl<'a> flatbuffers::Follow<'a> for Referrable<'a> { type Inner = Referrable<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> Referrable<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Referrable { _tab: table } } #[allow(unused_mut)] @@ -54,7 +54,10 @@ impl<'a> Referrable<'a> { #[inline] pub fn id(&self) -> u64 { - self._tab.get::(Referrable::VT_ID, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Referrable::VT_ID, Some(0)).unwrap()} } #[inline] pub fn key_compare_less_than(&self, o: &Referrable) -> bool { diff --git a/tests/monster_test/my_game/example/stat_generated.rs b/tests/monster_test/my_game/example/stat_generated.rs index 98bc33171..3fd55f9a2 100644 --- a/tests/monster_test/my_game/example/stat_generated.rs +++ b/tests/monster_test/my_game/example/stat_generated.rs @@ -19,8 +19,8 @@ pub struct Stat<'a> { impl<'a> flatbuffers::Follow<'a> for Stat<'a> { type Inner = Stat<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -34,7 +34,7 @@ impl<'a> Stat<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Stat { _tab: table } } #[allow(unused_mut)] @@ -64,15 +64,24 @@ impl<'a> Stat<'a> { #[inline] pub fn id(&self) -> Option<&'a str> { - self._tab.get::>(Stat::VT_ID, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Stat::VT_ID, None)} } #[inline] pub fn val(&self) -> i64 { - self._tab.get::(Stat::VT_VAL, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Stat::VT_VAL, Some(0)).unwrap()} } #[inline] pub fn count(&self) -> u16 { - self._tab.get::(Stat::VT_COUNT, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Stat::VT_COUNT, Some(0)).unwrap()} } #[inline] pub fn key_compare_less_than(&self, o: &Stat) -> bool { diff --git a/tests/monster_test/my_game/example/struct_of_structs_generated.rs b/tests/monster_test/my_game/example/struct_of_structs_generated.rs index bc05c77f0..77410a674 100644 --- a/tests/monster_test/my_game/example/struct_of_structs_generated.rs +++ b/tests/monster_test/my_game/example/struct_of_structs_generated.rs @@ -29,39 +29,25 @@ impl core::fmt::Debug for StructOfStructs { } impl flatbuffers::SimpleToVerifyInSlice for StructOfStructs {} -impl flatbuffers::SafeSliceAccess for StructOfStructs {} impl<'a> flatbuffers::Follow<'a> for StructOfStructs { type Inner = &'a StructOfStructs; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a StructOfStructs>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a StructOfStructs { type Inner = &'a StructOfStructs; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for StructOfStructs { type Output = StructOfStructs; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const StructOfStructs as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b StructOfStructs { - type Output = StructOfStructs; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const StructOfStructs as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const StructOfStructs as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -95,6 +81,9 @@ impl<'a> StructOfStructs { } pub fn a(&self) -> &Ability { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[0..].as_ptr() as *const Ability) } } @@ -104,6 +93,9 @@ impl<'a> StructOfStructs { } pub fn b(&self) -> &Test { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[8..].as_ptr() as *const Test) } } @@ -113,6 +105,9 @@ impl<'a> StructOfStructs { } pub fn c(&self) -> &Ability { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[12..].as_ptr() as *const Ability) } } diff --git a/tests/monster_test/my_game/example/struct_of_structs_of_structs_generated.rs b/tests/monster_test/my_game/example/struct_of_structs_of_structs_generated.rs index 9c7ae0b33..4e4597f7b 100644 --- a/tests/monster_test/my_game/example/struct_of_structs_of_structs_generated.rs +++ b/tests/monster_test/my_game/example/struct_of_structs_of_structs_generated.rs @@ -27,39 +27,25 @@ impl core::fmt::Debug for StructOfStructsOfStructs { } impl flatbuffers::SimpleToVerifyInSlice for StructOfStructsOfStructs {} -impl flatbuffers::SafeSliceAccess for StructOfStructsOfStructs {} impl<'a> flatbuffers::Follow<'a> for StructOfStructsOfStructs { type Inner = &'a StructOfStructsOfStructs; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a StructOfStructsOfStructs>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a StructOfStructsOfStructs { type Inner = &'a StructOfStructsOfStructs; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for StructOfStructsOfStructs { type Output = StructOfStructsOfStructs; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const StructOfStructsOfStructs as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b StructOfStructsOfStructs { - type Output = StructOfStructsOfStructs; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const StructOfStructsOfStructs as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const StructOfStructsOfStructs as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -89,6 +75,9 @@ impl<'a> StructOfStructsOfStructs { } pub fn a(&self) -> &StructOfStructs { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[0..].as_ptr() as *const StructOfStructs) } } diff --git a/tests/monster_test/my_game/example/test_generated.rs b/tests/monster_test/my_game/example/test_generated.rs index 1b72ee6d6..98494510b 100644 --- a/tests/monster_test/my_game/example/test_generated.rs +++ b/tests/monster_test/my_game/example/test_generated.rs @@ -28,39 +28,25 @@ impl core::fmt::Debug for Test { } impl flatbuffers::SimpleToVerifyInSlice for Test {} -impl flatbuffers::SafeSliceAccess for Test {} impl<'a> flatbuffers::Follow<'a> for Test { type Inner = &'a Test; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Test>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Test { type Inner = &'a Test; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Test { type Output = Test; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Test as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Test { - type Output = Test; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Test as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Test as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -92,47 +78,59 @@ impl<'a> Test { } pub fn a(&self) -> i16 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_a(&mut self, x: i16) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i16 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn b(&self) -> i8 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[2..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_b(&mut self, x: i8) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i8 as *const u8, + &x_le as *const _ as *const u8, self.0[2..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/monster_test/my_game/example/test_simple_table_with_enum_generated.rs b/tests/monster_test/my_game/example/test_simple_table_with_enum_generated.rs index e97dfa0a8..063392a35 100644 --- a/tests/monster_test/my_game/example/test_simple_table_with_enum_generated.rs +++ b/tests/monster_test/my_game/example/test_simple_table_with_enum_generated.rs @@ -19,8 +19,8 @@ pub struct TestSimpleTableWithEnum<'a> { impl<'a> flatbuffers::Follow<'a> for TestSimpleTableWithEnum<'a> { type Inner = TestSimpleTableWithEnum<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> TestSimpleTableWithEnum<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TestSimpleTableWithEnum { _tab: table } } #[allow(unused_mut)] @@ -54,7 +54,10 @@ impl<'a> TestSimpleTableWithEnum<'a> { #[inline] pub fn color(&self) -> Color { - self._tab.get::(TestSimpleTableWithEnum::VT_COLOR, Some(Color::Green)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TestSimpleTableWithEnum::VT_COLOR, Some(Color::Green)).unwrap()} } } diff --git a/tests/monster_test/my_game/example/type_aliases_generated.rs b/tests/monster_test/my_game/example/type_aliases_generated.rs index dfa8d56d4..4c6eef7ef 100644 --- a/tests/monster_test/my_game/example/type_aliases_generated.rs +++ b/tests/monster_test/my_game/example/type_aliases_generated.rs @@ -19,8 +19,8 @@ pub struct TypeAliases<'a> { impl<'a> flatbuffers::Follow<'a> for TypeAliases<'a> { type Inner = TypeAliases<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -43,7 +43,7 @@ impl<'a> TypeAliases<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TypeAliases { _tab: table } } #[allow(unused_mut)] @@ -79,7 +79,7 @@ impl<'a> TypeAliases<'a> { let f32_ = self.f32_(); let f64_ = self.f64_(); let v8 = self.v8().map(|x| { - x.to_vec() + x.into_iter().collect() }); let vf64 = self.vf64().map(|x| { x.into_iter().collect() @@ -102,51 +102,87 @@ impl<'a> TypeAliases<'a> { #[inline] pub fn i8_(&self) -> i8 { - self._tab.get::(TypeAliases::VT_I8_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_I8_, Some(0)).unwrap()} } #[inline] pub fn u8_(&self) -> u8 { - self._tab.get::(TypeAliases::VT_U8_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_U8_, Some(0)).unwrap()} } #[inline] pub fn i16_(&self) -> i16 { - self._tab.get::(TypeAliases::VT_I16_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_I16_, Some(0)).unwrap()} } #[inline] pub fn u16_(&self) -> u16 { - self._tab.get::(TypeAliases::VT_U16_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_U16_, Some(0)).unwrap()} } #[inline] pub fn i32_(&self) -> i32 { - self._tab.get::(TypeAliases::VT_I32_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_I32_, Some(0)).unwrap()} } #[inline] pub fn u32_(&self) -> u32 { - self._tab.get::(TypeAliases::VT_U32_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_U32_, Some(0)).unwrap()} } #[inline] pub fn i64_(&self) -> i64 { - self._tab.get::(TypeAliases::VT_I64_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_I64_, Some(0)).unwrap()} } #[inline] pub fn u64_(&self) -> u64 { - self._tab.get::(TypeAliases::VT_U64_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_U64_, Some(0)).unwrap()} } #[inline] pub fn f32_(&self) -> f32 { - self._tab.get::(TypeAliases::VT_F32_, Some(0.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_F32_, Some(0.0)).unwrap()} } #[inline] pub fn f64_(&self) -> f64 { - self._tab.get::(TypeAliases::VT_F64_, Some(0.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_F64_, Some(0.0)).unwrap()} } #[inline] - pub fn v8(&self) -> Option<&'a [i8]> { - self._tab.get::>>(TypeAliases::VT_V8, None).map(|v| v.safe_slice()) + pub fn v8(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(TypeAliases::VT_V8, None)} } #[inline] pub fn vf64(&self) -> Option> { - self._tab.get::>>(TypeAliases::VT_VF64, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(TypeAliases::VT_VF64, None)} } } diff --git a/tests/monster_test/my_game/example/vec_3_generated.rs b/tests/monster_test/my_game/example/vec_3_generated.rs index fa0ab5376..b4f076522 100644 --- a/tests/monster_test/my_game/example/vec_3_generated.rs +++ b/tests/monster_test/my_game/example/vec_3_generated.rs @@ -32,39 +32,25 @@ impl core::fmt::Debug for Vec3 { } impl flatbuffers::SimpleToVerifyInSlice for Vec3 {} -impl flatbuffers::SafeSliceAccess for Vec3 {} impl<'a> flatbuffers::Follow<'a> for Vec3 { type Inner = &'a Vec3; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Vec3>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Vec3 { type Inner = &'a Vec3; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Vec3 { type Output = Vec3; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Vec3 as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Vec3 { - type Output = Vec3; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Vec3 as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Vec3 as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -104,121 +90,154 @@ impl<'a> Vec3 { } pub fn x(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_x(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn y(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[4..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_y(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[4..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn z(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[8..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_z(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[8..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn test1(&self) -> f64 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[16..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_test1(&mut self, x: f64) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f64 as *const u8, + &x_le as *const _ as *const u8, self.0[16..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn test2(&self) -> Color { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[24..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_test2(&mut self, x: Color) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const Color as *const u8, + &x_le as *const _ as *const u8, self.0[24..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn test3(&self) -> &Test { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[26..].as_ptr() as *const Test) } } diff --git a/tests/monster_test/my_game/example_2/monster_generated.rs b/tests/monster_test/my_game/example_2/monster_generated.rs index 34e0db12a..a358d3bba 100644 --- a/tests/monster_test/my_game/example_2/monster_generated.rs +++ b/tests/monster_test/my_game/example_2/monster_generated.rs @@ -19,8 +19,8 @@ pub struct Monster<'a> { impl<'a> flatbuffers::Follow<'a> for Monster<'a> { type Inner = Monster<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -31,7 +31,7 @@ impl<'a> Monster<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Monster { _tab: table } } #[allow(unused_mut)] diff --git a/tests/monster_test/my_game/in_parent_namespace_generated.rs b/tests/monster_test/my_game/in_parent_namespace_generated.rs index 263fae76c..922048092 100644 --- a/tests/monster_test/my_game/in_parent_namespace_generated.rs +++ b/tests/monster_test/my_game/in_parent_namespace_generated.rs @@ -19,8 +19,8 @@ pub struct InParentNamespace<'a> { impl<'a> flatbuffers::Follow<'a> for InParentNamespace<'a> { type Inner = InParentNamespace<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -31,7 +31,7 @@ impl<'a> InParentNamespace<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { InParentNamespace { _tab: table } } #[allow(unused_mut)] diff --git a/tests/monster_test/my_game/other_name_space/from_include_generated.rs b/tests/monster_test/my_game/other_name_space/from_include_generated.rs index 3c5165d17..70cb407c1 100644 --- a/tests/monster_test/my_game/other_name_space/from_include_generated.rs +++ b/tests/monster_test/my_game/other_name_space/from_include_generated.rs @@ -51,10 +51,8 @@ impl core::fmt::Debug for FromInclude { impl<'a> flatbuffers::Follow<'a> for FromInclude { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -62,21 +60,21 @@ impl<'a> flatbuffers::Follow<'a> for FromInclude { impl flatbuffers::Push for FromInclude { type Output = FromInclude; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for FromInclude { + type Scalar = i64; #[inline] - fn to_little_endian(self) -> Self { - let b = i64::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i64 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i64::from_le(self.0); + fn from_little_endian(v: i64) -> Self { + let b = i64::from_le(v); Self(b) } } diff --git a/tests/monster_test/my_game/other_name_space/table_b_generated.rs b/tests/monster_test/my_game/other_name_space/table_b_generated.rs index da7b9378b..5652195b5 100644 --- a/tests/monster_test/my_game/other_name_space/table_b_generated.rs +++ b/tests/monster_test/my_game/other_name_space/table_b_generated.rs @@ -19,8 +19,8 @@ pub struct TableB<'a> { impl<'a> flatbuffers::Follow<'a> for TableB<'a> { type Inner = TableB<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> TableB<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableB { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> TableB<'a> { #[inline] pub fn a(&self) -> Option> { - self._tab.get::>(TableB::VT_A, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableB::VT_A, None)} } } diff --git a/tests/monster_test/my_game/other_name_space/unused_generated.rs b/tests/monster_test/my_game/other_name_space/unused_generated.rs index 1e4ad9c7b..69be4869e 100644 --- a/tests/monster_test/my_game/other_name_space/unused_generated.rs +++ b/tests/monster_test/my_game/other_name_space/unused_generated.rs @@ -27,39 +27,25 @@ impl core::fmt::Debug for Unused { } impl flatbuffers::SimpleToVerifyInSlice for Unused {} -impl flatbuffers::SafeSliceAccess for Unused {} impl<'a> flatbuffers::Follow<'a> for Unused { type Inner = &'a Unused; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Unused>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Unused { type Inner = &'a Unused; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Unused { type Output = Unused; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Unused as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Unused { - type Output = Unused; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Unused as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Unused as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -89,24 +75,30 @@ impl<'a> Unused { } pub fn a(&self) -> i32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_a(&mut self, x: i32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/monster_test/table_a_generated.rs b/tests/monster_test/table_a_generated.rs index 0e6a78de1..fd979b092 100644 --- a/tests/monster_test/table_a_generated.rs +++ b/tests/monster_test/table_a_generated.rs @@ -19,8 +19,8 @@ pub struct TableA<'a> { impl<'a> flatbuffers::Follow<'a> for TableA<'a> { type Inner = TableA<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> TableA<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableA { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> TableA<'a> { #[inline] pub fn b(&self) -> Option> { - self._tab.get::>(TableA::VT_B, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableA::VT_B, None)} } } diff --git a/tests/monster_test_serialize/my_game/example/ability_generated.rs b/tests/monster_test_serialize/my_game/example/ability_generated.rs index 5c8bcf815..46d24bfee 100644 --- a/tests/monster_test_serialize/my_game/example/ability_generated.rs +++ b/tests/monster_test_serialize/my_game/example/ability_generated.rs @@ -30,39 +30,25 @@ impl core::fmt::Debug for Ability { } impl flatbuffers::SimpleToVerifyInSlice for Ability {} -impl flatbuffers::SafeSliceAccess for Ability {} impl<'a> flatbuffers::Follow<'a> for Ability { type Inner = &'a Ability; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Ability>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Ability { type Inner = &'a Ability; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Ability { type Output = Ability; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Ability as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Ability { - type Output = Ability; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Ability as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Ability as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -106,24 +92,30 @@ impl<'a> Ability { } pub fn id(&self) -> u32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_id(&mut self, x: u32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const u32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } @@ -139,24 +131,30 @@ impl<'a> Ability { key.cmp(&val) } pub fn distance(&self) -> u32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[4..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_distance(&mut self, x: u32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const u32 as *const u8, + &x_le as *const _ as *const u8, self.0[4..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/monster_test_serialize/my_game/example/any_ambiguous_aliases_generated.rs b/tests/monster_test_serialize/my_game/example/any_ambiguous_aliases_generated.rs index b278ca1c8..2e4a861f3 100644 --- a/tests/monster_test_serialize/my_game/example/any_ambiguous_aliases_generated.rs +++ b/tests/monster_test_serialize/my_game/example/any_ambiguous_aliases_generated.rs @@ -74,10 +74,8 @@ impl Serialize for AnyAmbiguousAliases { impl<'a> flatbuffers::Follow<'a> for AnyAmbiguousAliases { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -85,21 +83,21 @@ impl<'a> flatbuffers::Follow<'a> for AnyAmbiguousAliases { impl flatbuffers::Push for AnyAmbiguousAliases { type Output = AnyAmbiguousAliases; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for AnyAmbiguousAliases { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/monster_test_serialize/my_game/example/any_generated.rs b/tests/monster_test_serialize/my_game/example/any_generated.rs index f67392db2..e889cf5d3 100644 --- a/tests/monster_test_serialize/my_game/example/any_generated.rs +++ b/tests/monster_test_serialize/my_game/example/any_generated.rs @@ -74,10 +74,8 @@ impl Serialize for Any { impl<'a> flatbuffers::Follow<'a> for Any { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -85,21 +83,21 @@ impl<'a> flatbuffers::Follow<'a> for Any { impl flatbuffers::Push for Any { type Output = Any; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for Any { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/monster_test_serialize/my_game/example/any_unique_aliases_generated.rs b/tests/monster_test_serialize/my_game/example/any_unique_aliases_generated.rs index 1b3d09176..5e6fe2d5b 100644 --- a/tests/monster_test_serialize/my_game/example/any_unique_aliases_generated.rs +++ b/tests/monster_test_serialize/my_game/example/any_unique_aliases_generated.rs @@ -74,10 +74,8 @@ impl Serialize for AnyUniqueAliases { impl<'a> flatbuffers::Follow<'a> for AnyUniqueAliases { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -85,21 +83,21 @@ impl<'a> flatbuffers::Follow<'a> for AnyUniqueAliases { impl flatbuffers::Push for AnyUniqueAliases { type Output = AnyUniqueAliases; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for AnyUniqueAliases { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/monster_test_serialize/my_game/example/color_generated.rs b/tests/monster_test_serialize/my_game/example/color_generated.rs index e001d4399..0f9887952 100644 --- a/tests/monster_test_serialize/my_game/example/color_generated.rs +++ b/tests/monster_test_serialize/my_game/example/color_generated.rs @@ -40,32 +40,38 @@ impl Serialize for Color { impl<'a> flatbuffers::Follow<'a> for Color { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; - unsafe { Self::from_bits_unchecked(b) } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 + Self::from_bits_unchecked(b) } } impl flatbuffers::Push for Color { type Output = Color; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.bits()); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.bits()); } } impl flatbuffers::EndianScalar for Color { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.bits()); - unsafe { Self::from_bits_unchecked(b) } + fn to_little_endian(self) -> u8 { + self.bits().to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.bits()); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 unsafe { Self::from_bits_unchecked(b) } } } diff --git a/tests/monster_test_serialize/my_game/example/long_enum_generated.rs b/tests/monster_test_serialize/my_game/example/long_enum_generated.rs index b29b97f0f..1f56c6fb8 100644 --- a/tests/monster_test_serialize/my_game/example/long_enum_generated.rs +++ b/tests/monster_test_serialize/my_game/example/long_enum_generated.rs @@ -36,32 +36,38 @@ impl Serialize for LongEnum { impl<'a> flatbuffers::Follow<'a> for LongEnum { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; - unsafe { Self::from_bits_unchecked(b) } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 + Self::from_bits_unchecked(b) } } impl flatbuffers::Push for LongEnum { type Output = LongEnum; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.bits()); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.bits()); } } impl flatbuffers::EndianScalar for LongEnum { + type Scalar = u64; #[inline] - fn to_little_endian(self) -> Self { - let b = u64::to_le(self.bits()); - unsafe { Self::from_bits_unchecked(b) } + fn to_little_endian(self) -> u64 { + self.bits().to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u64::from_le(self.bits()); + fn from_little_endian(v: u64) -> Self { + let b = u64::from_le(v); + // Safety: + // This is safe because we know bitflags is implemented with a repr transparent uint of the correct size. + // from_bits_unchecked will be replaced by an equivalent but safe from_bits_retain in bitflags 2.0 + // https://github.com/bitflags/bitflags/issues/262 unsafe { Self::from_bits_unchecked(b) } } } diff --git a/tests/monster_test_serialize/my_game/example/monster_generated.rs b/tests/monster_test_serialize/my_game/example/monster_generated.rs index 7aa3ec776..c5d709bb2 100644 --- a/tests/monster_test_serialize/my_game/example/monster_generated.rs +++ b/tests/monster_test_serialize/my_game/example/monster_generated.rs @@ -22,8 +22,8 @@ pub struct Monster<'a> { impl<'a> flatbuffers::Follow<'a> for Monster<'a> { type Inner = Monster<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -87,7 +87,7 @@ impl<'a> Monster<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Monster { _tab: table } } #[allow(unused_mut)] @@ -163,7 +163,7 @@ impl<'a> Monster<'a> { x.to_string() }; let inventory = self.inventory().map(|x| { - x.to_vec() + x.into_iter().collect() }); let color = self.color(); let test = match self.test_type() { @@ -198,7 +198,7 @@ impl<'a> Monster<'a> { Box::new(x.unpack()) }); let testnestedflatbuffer = self.testnestedflatbuffer().map(|x| { - x.to_vec() + x.into_iter().collect() }); let testempty = self.testempty().map(|x| { Box::new(x.unpack()) @@ -213,7 +213,7 @@ impl<'a> Monster<'a> { let testhashs64_fnv1a = self.testhashs64_fnv1a(); let testhashu64_fnv1a = self.testhashu64_fnv1a(); let testarrayofbools = self.testarrayofbools().map(|x| { - x.to_vec() + x.into_iter().collect() }); let testf = self.testf(); let testf2 = self.testf2(); @@ -225,7 +225,7 @@ impl<'a> Monster<'a> { x.iter().map(|t| t.unpack()).collect() }); let flex = self.flex().map(|x| { - x.to_vec() + x.into_iter().collect() }); let test5 = self.test5().map(|x| { x.iter().map(|t| t.unpack()).collect() @@ -300,7 +300,7 @@ impl<'a> Monster<'a> { }); let signed_enum = self.signed_enum(); let testrequirednestedflatbuffer = self.testrequirednestedflatbuffer().map(|x| { - x.to_vec() + x.into_iter().collect() }); let scalar_key_sorted_tables = self.scalar_key_sorted_tables().map(|x| { x.iter().map(|t| t.unpack()).collect() @@ -366,19 +366,31 @@ impl<'a> Monster<'a> { #[inline] pub fn pos(&self) -> Option<&'a Vec3> { - self._tab.get::(Monster::VT_POS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_POS, None)} } #[inline] pub fn mana(&self) -> i16 { - self._tab.get::(Monster::VT_MANA, Some(150)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_MANA, Some(150)).unwrap()} } #[inline] pub fn hp(&self) -> i16 { - self._tab.get::(Monster::VT_HP, Some(100)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_HP, Some(100)).unwrap()} } #[inline] pub fn name(&self) -> &'a str { - self._tab.get::>(Monster::VT_NAME, None).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_NAME, None).unwrap()} } #[inline] pub fn key_compare_less_than(&self, o: &Monster) -> bool { @@ -391,220 +403,378 @@ impl<'a> Monster<'a> { key.cmp(val) } #[inline] - pub fn inventory(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_INVENTORY, None).map(|v| v.safe_slice()) + pub fn inventory(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_INVENTORY, None)} } #[inline] pub fn color(&self) -> Color { - self._tab.get::(Monster::VT_COLOR, Some(Color::Blue)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_COLOR, Some(Color::Blue)).unwrap()} } #[inline] pub fn test_type(&self) -> Any { - self._tab.get::(Monster::VT_TEST_TYPE, Some(Any::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TEST_TYPE, Some(Any::NONE)).unwrap()} } #[inline] pub fn test(&self) -> Option> { - self._tab.get::>>(Monster::VT_TEST, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TEST, None)} } #[inline] - pub fn test4(&self) -> Option<&'a [Test]> { - self._tab.get::>>(Monster::VT_TEST4, None).map(|v| v.safe_slice()) + pub fn test4(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TEST4, None)} } #[inline] pub fn testarrayofstring(&self) -> Option>> { - self._tab.get::>>>(Monster::VT_TESTARRAYOFSTRING, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_TESTARRAYOFSTRING, None)} } /// an example documentation comment: this will end up in the generated code /// multiline too #[inline] pub fn testarrayoftables(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_TESTARRAYOFTABLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_TESTARRAYOFTABLES, None)} } #[inline] pub fn enemy(&self) -> Option> { - self._tab.get::>(Monster::VT_ENEMY, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_ENEMY, None)} } #[inline] - pub fn testnestedflatbuffer(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_TESTNESTEDFLATBUFFER, None).map(|v| v.safe_slice()) + pub fn testnestedflatbuffer(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TESTNESTEDFLATBUFFER, None)} } pub fn testnestedflatbuffer_nested_flatbuffer(&'a self) -> Option> { self.testnestedflatbuffer().map(|data| { use flatbuffers::Follow; - >>::follow(data, 0) + // Safety: + // Created from a valid Table for this object + // Which contains a valid flatbuffer in this slot + unsafe { >>::follow(data.bytes(), 0) } }) } #[inline] pub fn testempty(&self) -> Option> { - self._tab.get::>(Monster::VT_TESTEMPTY, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_TESTEMPTY, None)} } #[inline] pub fn testbool(&self) -> bool { - self._tab.get::(Monster::VT_TESTBOOL, Some(false)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTBOOL, Some(false)).unwrap()} } #[inline] pub fn testhashs32_fnv1(&self) -> i32 { - self._tab.get::(Monster::VT_TESTHASHS32_FNV1, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHS32_FNV1, Some(0)).unwrap()} } #[inline] pub fn testhashu32_fnv1(&self) -> u32 { - self._tab.get::(Monster::VT_TESTHASHU32_FNV1, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHU32_FNV1, Some(0)).unwrap()} } #[inline] pub fn testhashs64_fnv1(&self) -> i64 { - self._tab.get::(Monster::VT_TESTHASHS64_FNV1, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHS64_FNV1, Some(0)).unwrap()} } #[inline] pub fn testhashu64_fnv1(&self) -> u64 { - self._tab.get::(Monster::VT_TESTHASHU64_FNV1, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHU64_FNV1, Some(0)).unwrap()} } #[inline] pub fn testhashs32_fnv1a(&self) -> i32 { - self._tab.get::(Monster::VT_TESTHASHS32_FNV1A, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHS32_FNV1A, Some(0)).unwrap()} } #[inline] pub fn testhashu32_fnv1a(&self) -> u32 { - self._tab.get::(Monster::VT_TESTHASHU32_FNV1A, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHU32_FNV1A, Some(0)).unwrap()} } #[inline] pub fn testhashs64_fnv1a(&self) -> i64 { - self._tab.get::(Monster::VT_TESTHASHS64_FNV1A, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHS64_FNV1A, Some(0)).unwrap()} } #[inline] pub fn testhashu64_fnv1a(&self) -> u64 { - self._tab.get::(Monster::VT_TESTHASHU64_FNV1A, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTHASHU64_FNV1A, Some(0)).unwrap()} } #[inline] - pub fn testarrayofbools(&self) -> Option<&'a [bool]> { - self._tab.get::>>(Monster::VT_TESTARRAYOFBOOLS, None).map(|v| v.safe_slice()) + pub fn testarrayofbools(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TESTARRAYOFBOOLS, None)} } #[inline] pub fn testf(&self) -> f32 { - self._tab.get::(Monster::VT_TESTF, Some(3.14159)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTF, Some(3.14159)).unwrap()} } #[inline] pub fn testf2(&self) -> f32 { - self._tab.get::(Monster::VT_TESTF2, Some(3.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTF2, Some(3.0)).unwrap()} } #[inline] pub fn testf3(&self) -> f32 { - self._tab.get::(Monster::VT_TESTF3, Some(0.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_TESTF3, Some(0.0)).unwrap()} } #[inline] pub fn testarrayofstring2(&self) -> Option>> { - self._tab.get::>>>(Monster::VT_TESTARRAYOFSTRING2, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_TESTARRAYOFSTRING2, None)} } #[inline] - pub fn testarrayofsortedstruct(&self) -> Option<&'a [Ability]> { - self._tab.get::>>(Monster::VT_TESTARRAYOFSORTEDSTRUCT, None).map(|v| v.safe_slice()) + pub fn testarrayofsortedstruct(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TESTARRAYOFSORTEDSTRUCT, None)} } #[inline] - pub fn flex(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_FLEX, None).map(|v| v.safe_slice()) + pub fn flex(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_FLEX, None)} } #[inline] - pub fn test5(&self) -> Option<&'a [Test]> { - self._tab.get::>>(Monster::VT_TEST5, None).map(|v| v.safe_slice()) + pub fn test5(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TEST5, None)} } #[inline] pub fn vector_of_longs(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_LONGS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_LONGS, None)} } #[inline] pub fn vector_of_doubles(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_DOUBLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_DOUBLES, None)} } #[inline] pub fn parent_namespace_test(&self) -> Option> { - self._tab.get::>(Monster::VT_PARENT_NAMESPACE_TEST, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Monster::VT_PARENT_NAMESPACE_TEST, None)} } #[inline] pub fn vector_of_referrables(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_VECTOR_OF_REFERRABLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_VECTOR_OF_REFERRABLES, None)} } #[inline] pub fn single_weak_reference(&self) -> u64 { - self._tab.get::(Monster::VT_SINGLE_WEAK_REFERENCE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_SINGLE_WEAK_REFERENCE, Some(0)).unwrap()} } #[inline] pub fn vector_of_weak_references(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_WEAK_REFERENCES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_WEAK_REFERENCES, None)} } #[inline] pub fn vector_of_strong_referrables(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_VECTOR_OF_STRONG_REFERRABLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_VECTOR_OF_STRONG_REFERRABLES, None)} } #[inline] pub fn co_owning_reference(&self) -> u64 { - self._tab.get::(Monster::VT_CO_OWNING_REFERENCE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_CO_OWNING_REFERENCE, Some(0)).unwrap()} } #[inline] pub fn vector_of_co_owning_references(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_CO_OWNING_REFERENCES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_CO_OWNING_REFERENCES, None)} } #[inline] pub fn non_owning_reference(&self) -> u64 { - self._tab.get::(Monster::VT_NON_OWNING_REFERENCE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_NON_OWNING_REFERENCE, Some(0)).unwrap()} } #[inline] pub fn vector_of_non_owning_references(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_NON_OWNING_REFERENCES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_NON_OWNING_REFERENCES, None)} } #[inline] pub fn any_unique_type(&self) -> AnyUniqueAliases { - self._tab.get::(Monster::VT_ANY_UNIQUE_TYPE, Some(AnyUniqueAliases::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_ANY_UNIQUE_TYPE, Some(AnyUniqueAliases::NONE)).unwrap()} } #[inline] pub fn any_unique(&self) -> Option> { - self._tab.get::>>(Monster::VT_ANY_UNIQUE, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_ANY_UNIQUE, None)} } #[inline] pub fn any_ambiguous_type(&self) -> AnyAmbiguousAliases { - self._tab.get::(Monster::VT_ANY_AMBIGUOUS_TYPE, Some(AnyAmbiguousAliases::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_ANY_AMBIGUOUS_TYPE, Some(AnyAmbiguousAliases::NONE)).unwrap()} } #[inline] pub fn any_ambiguous(&self) -> Option> { - self._tab.get::>>(Monster::VT_ANY_AMBIGUOUS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_ANY_AMBIGUOUS, None)} } #[inline] pub fn vector_of_enums(&self) -> Option> { - self._tab.get::>>(Monster::VT_VECTOR_OF_ENUMS, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_VECTOR_OF_ENUMS, None)} } #[inline] pub fn signed_enum(&self) -> Race { - self._tab.get::(Monster::VT_SIGNED_ENUM, Some(Race::None)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_SIGNED_ENUM, Some(Race::None)).unwrap()} } #[inline] - pub fn testrequirednestedflatbuffer(&self) -> Option<&'a [u8]> { - self._tab.get::>>(Monster::VT_TESTREQUIREDNESTEDFLATBUFFER, None).map(|v| v.safe_slice()) + pub fn testrequirednestedflatbuffer(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(Monster::VT_TESTREQUIREDNESTEDFLATBUFFER, None)} } pub fn testrequirednestedflatbuffer_nested_flatbuffer(&'a self) -> Option> { self.testrequirednestedflatbuffer().map(|data| { use flatbuffers::Follow; - >>::follow(data, 0) + // Safety: + // Created from a valid Table for this object + // Which contains a valid flatbuffer in this slot + unsafe { >>::follow(data.bytes(), 0) } }) } #[inline] pub fn scalar_key_sorted_tables(&self) -> Option>>> { - self._tab.get::>>>(Monster::VT_SCALAR_KEY_SORTED_TABLES, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Monster::VT_SCALAR_KEY_SORTED_TABLES, None)} } #[inline] pub fn native_inline(&self) -> Option<&'a Test> { - self._tab.get::(Monster::VT_NATIVE_INLINE, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_NATIVE_INLINE, None)} } #[inline] pub fn long_enum_non_enum_default(&self) -> LongEnum { - self._tab.get::(Monster::VT_LONG_ENUM_NON_ENUM_DEFAULT, Some(Default::default())).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_LONG_ENUM_NON_ENUM_DEFAULT, Some(Default::default())).unwrap()} } #[inline] pub fn long_enum_normal_default(&self) -> LongEnum { - self._tab.get::(Monster::VT_LONG_ENUM_NORMAL_DEFAULT, Some(LongEnum::LongOne)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Monster::VT_LONG_ENUM_NORMAL_DEFAULT, Some(LongEnum::LongOne)).unwrap()} } #[inline] #[allow(non_snake_case)] pub fn test_as_monster(&self) -> Option> { if self.test_type() == Any::Monster { - self.test().map(Monster::init_from_table) + self.test().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -614,7 +784,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn test_as_test_simple_table_with_enum(&self) -> Option> { if self.test_type() == Any::TestSimpleTableWithEnum { - self.test().map(TestSimpleTableWithEnum::init_from_table) + self.test().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { TestSimpleTableWithEnum::init_from_table(t) } + }) } else { None } @@ -624,7 +799,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn test_as_my_game_example_2_monster(&self) -> Option> { if self.test_type() == Any::MyGame_Example2_Monster { - self.test().map(super::example_2::Monster::init_from_table) + self.test().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { super::example_2::Monster::init_from_table(t) } + }) } else { None } @@ -634,7 +814,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_unique_as_m(&self) -> Option> { if self.any_unique_type() == AnyUniqueAliases::M { - self.any_unique().map(Monster::init_from_table) + self.any_unique().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -644,7 +829,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_unique_as_ts(&self) -> Option> { if self.any_unique_type() == AnyUniqueAliases::TS { - self.any_unique().map(TestSimpleTableWithEnum::init_from_table) + self.any_unique().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { TestSimpleTableWithEnum::init_from_table(t) } + }) } else { None } @@ -654,7 +844,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_unique_as_m2(&self) -> Option> { if self.any_unique_type() == AnyUniqueAliases::M2 { - self.any_unique().map(super::example_2::Monster::init_from_table) + self.any_unique().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { super::example_2::Monster::init_from_table(t) } + }) } else { None } @@ -664,7 +859,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_ambiguous_as_m1(&self) -> Option> { if self.any_ambiguous_type() == AnyAmbiguousAliases::M1 { - self.any_ambiguous().map(Monster::init_from_table) + self.any_ambiguous().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -674,7 +874,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_ambiguous_as_m2(&self) -> Option> { if self.any_ambiguous_type() == AnyAmbiguousAliases::M2 { - self.any_ambiguous().map(Monster::init_from_table) + self.any_ambiguous().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -684,7 +889,12 @@ impl<'a> Monster<'a> { #[allow(non_snake_case)] pub fn any_ambiguous_as_m3(&self) -> Option> { if self.any_ambiguous_type() == AnyAmbiguousAliases::M3 { - self.any_ambiguous().map(Monster::init_from_table) + self.any_ambiguous().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Monster::init_from_table(t) } + }) } else { None } @@ -1610,7 +1820,7 @@ impl MonsterT { let w: Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w) }); let testarrayofstring = self.testarrayofstring.as_ref().map(|x|{ - let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();_fbb.create_vector_of_strings(&w) + let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();_fbb.create_vector(&w) }); let testarrayoftables = self.testarrayoftables.as_ref().map(|x|{ let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();_fbb.create_vector(&w) @@ -1640,7 +1850,7 @@ impl MonsterT { let testf2 = self.testf2; let testf3 = self.testf3; let testarrayofstring2 = self.testarrayofstring2.as_ref().map(|x|{ - let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();_fbb.create_vector_of_strings(&w) + let w: Vec<_> = x.iter().map(|s| _fbb.create_string(s)).collect();_fbb.create_vector(&w) }); let testarrayofsortedstruct = self.testarrayofsortedstruct.as_ref().map(|x|{ let w: Vec<_> = x.iter().map(|t| t.pack()).collect();_fbb.create_vector(&w) @@ -1753,18 +1963,6 @@ impl MonsterT { }) } } -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> { - unsafe { flatbuffers::root_unchecked::>(buf) } -} - -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_size_prefixed_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> { - unsafe { flatbuffers::size_prefixed_root_unchecked::>(buf) } -} - #[inline] /// Verifies that a buffer of bytes contains a `Monster` /// and returns it. diff --git a/tests/monster_test_serialize/my_game/example/race_generated.rs b/tests/monster_test_serialize/my_game/example/race_generated.rs index a1a674983..fe57ce0a0 100644 --- a/tests/monster_test_serialize/my_game/example/race_generated.rs +++ b/tests/monster_test_serialize/my_game/example/race_generated.rs @@ -74,10 +74,8 @@ impl Serialize for Race { impl<'a> flatbuffers::Follow<'a> for Race { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -85,21 +83,21 @@ impl<'a> flatbuffers::Follow<'a> for Race { impl flatbuffers::Push for Race { type Output = Race; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for Race { + type Scalar = i8; #[inline] - fn to_little_endian(self) -> Self { - let b = i8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i8::from_le(self.0); + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); Self(b) } } diff --git a/tests/monster_test_serialize/my_game/example/referrable_generated.rs b/tests/monster_test_serialize/my_game/example/referrable_generated.rs index 9992293b6..d3f65ad56 100644 --- a/tests/monster_test_serialize/my_game/example/referrable_generated.rs +++ b/tests/monster_test_serialize/my_game/example/referrable_generated.rs @@ -21,8 +21,8 @@ pub struct Referrable<'a> { impl<'a> flatbuffers::Follow<'a> for Referrable<'a> { type Inner = Referrable<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -34,7 +34,7 @@ impl<'a> Referrable<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Referrable { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> Referrable<'a> { #[inline] pub fn id(&self) -> u64 { - self._tab.get::(Referrable::VT_ID, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Referrable::VT_ID, Some(0)).unwrap()} } #[inline] pub fn key_compare_less_than(&self, o: &Referrable) -> bool { diff --git a/tests/monster_test_serialize/my_game/example/stat_generated.rs b/tests/monster_test_serialize/my_game/example/stat_generated.rs index fbd7ce8d7..856d9b89d 100644 --- a/tests/monster_test_serialize/my_game/example/stat_generated.rs +++ b/tests/monster_test_serialize/my_game/example/stat_generated.rs @@ -21,8 +21,8 @@ pub struct Stat<'a> { impl<'a> flatbuffers::Follow<'a> for Stat<'a> { type Inner = Stat<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -36,7 +36,7 @@ impl<'a> Stat<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Stat { _tab: table } } #[allow(unused_mut)] @@ -66,15 +66,24 @@ impl<'a> Stat<'a> { #[inline] pub fn id(&self) -> Option<&'a str> { - self._tab.get::>(Stat::VT_ID, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Stat::VT_ID, None)} } #[inline] pub fn val(&self) -> i64 { - self._tab.get::(Stat::VT_VAL, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Stat::VT_VAL, Some(0)).unwrap()} } #[inline] pub fn count(&self) -> u16 { - self._tab.get::(Stat::VT_COUNT, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Stat::VT_COUNT, Some(0)).unwrap()} } #[inline] pub fn key_compare_less_than(&self, o: &Stat) -> bool { diff --git a/tests/monster_test_serialize/my_game/example/struct_of_structs_generated.rs b/tests/monster_test_serialize/my_game/example/struct_of_structs_generated.rs index 0046447e2..669a6c865 100644 --- a/tests/monster_test_serialize/my_game/example/struct_of_structs_generated.rs +++ b/tests/monster_test_serialize/my_game/example/struct_of_structs_generated.rs @@ -31,39 +31,25 @@ impl core::fmt::Debug for StructOfStructs { } impl flatbuffers::SimpleToVerifyInSlice for StructOfStructs {} -impl flatbuffers::SafeSliceAccess for StructOfStructs {} impl<'a> flatbuffers::Follow<'a> for StructOfStructs { type Inner = &'a StructOfStructs; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a StructOfStructs>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a StructOfStructs { type Inner = &'a StructOfStructs; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for StructOfStructs { type Output = StructOfStructs; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const StructOfStructs as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b StructOfStructs { - type Output = StructOfStructs; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const StructOfStructs as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const StructOfStructs as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -110,6 +96,9 @@ impl<'a> StructOfStructs { } pub fn a(&self) -> &Ability { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[0..].as_ptr() as *const Ability) } } @@ -119,6 +108,9 @@ impl<'a> StructOfStructs { } pub fn b(&self) -> &Test { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[8..].as_ptr() as *const Test) } } @@ -128,6 +120,9 @@ impl<'a> StructOfStructs { } pub fn c(&self) -> &Ability { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[12..].as_ptr() as *const Ability) } } diff --git a/tests/monster_test_serialize/my_game/example/struct_of_structs_of_structs_generated.rs b/tests/monster_test_serialize/my_game/example/struct_of_structs_of_structs_generated.rs index 234eb919e..2cb1b5e02 100644 --- a/tests/monster_test_serialize/my_game/example/struct_of_structs_of_structs_generated.rs +++ b/tests/monster_test_serialize/my_game/example/struct_of_structs_of_structs_generated.rs @@ -29,39 +29,25 @@ impl core::fmt::Debug for StructOfStructsOfStructs { } impl flatbuffers::SimpleToVerifyInSlice for StructOfStructsOfStructs {} -impl flatbuffers::SafeSliceAccess for StructOfStructsOfStructs {} impl<'a> flatbuffers::Follow<'a> for StructOfStructsOfStructs { type Inner = &'a StructOfStructsOfStructs; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a StructOfStructsOfStructs>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a StructOfStructsOfStructs { type Inner = &'a StructOfStructsOfStructs; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for StructOfStructsOfStructs { type Output = StructOfStructsOfStructs; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const StructOfStructsOfStructs as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b StructOfStructsOfStructs { - type Output = StructOfStructsOfStructs; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const StructOfStructsOfStructs as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const StructOfStructsOfStructs as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -102,6 +88,9 @@ impl<'a> StructOfStructsOfStructs { } pub fn a(&self) -> &StructOfStructs { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[0..].as_ptr() as *const StructOfStructs) } } diff --git a/tests/monster_test_serialize/my_game/example/test_generated.rs b/tests/monster_test_serialize/my_game/example/test_generated.rs index 472bff907..835a90545 100644 --- a/tests/monster_test_serialize/my_game/example/test_generated.rs +++ b/tests/monster_test_serialize/my_game/example/test_generated.rs @@ -30,39 +30,25 @@ impl core::fmt::Debug for Test { } impl flatbuffers::SimpleToVerifyInSlice for Test {} -impl flatbuffers::SafeSliceAccess for Test {} impl<'a> flatbuffers::Follow<'a> for Test { type Inner = &'a Test; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Test>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Test { type Inner = &'a Test; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Test { type Output = Test; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Test as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Test { - type Output = Test; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Test as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Test as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -106,47 +92,59 @@ impl<'a> Test { } pub fn a(&self) -> i16 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_a(&mut self, x: i16) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i16 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn b(&self) -> i8 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[2..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_b(&mut self, x: i8) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i8 as *const u8, + &x_le as *const _ as *const u8, self.0[2..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/monster_test_serialize/my_game/example/test_simple_table_with_enum_generated.rs b/tests/monster_test_serialize/my_game/example/test_simple_table_with_enum_generated.rs index 8a7b6271a..65f159837 100644 --- a/tests/monster_test_serialize/my_game/example/test_simple_table_with_enum_generated.rs +++ b/tests/monster_test_serialize/my_game/example/test_simple_table_with_enum_generated.rs @@ -21,8 +21,8 @@ pub struct TestSimpleTableWithEnum<'a> { impl<'a> flatbuffers::Follow<'a> for TestSimpleTableWithEnum<'a> { type Inner = TestSimpleTableWithEnum<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -34,7 +34,7 @@ impl<'a> TestSimpleTableWithEnum<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TestSimpleTableWithEnum { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> TestSimpleTableWithEnum<'a> { #[inline] pub fn color(&self) -> Color { - self._tab.get::(TestSimpleTableWithEnum::VT_COLOR, Some(Color::Green)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TestSimpleTableWithEnum::VT_COLOR, Some(Color::Green)).unwrap()} } } diff --git a/tests/monster_test_serialize/my_game/example/type_aliases_generated.rs b/tests/monster_test_serialize/my_game/example/type_aliases_generated.rs index f6f7bb7b1..8cfa4ced8 100644 --- a/tests/monster_test_serialize/my_game/example/type_aliases_generated.rs +++ b/tests/monster_test_serialize/my_game/example/type_aliases_generated.rs @@ -21,8 +21,8 @@ pub struct TypeAliases<'a> { impl<'a> flatbuffers::Follow<'a> for TypeAliases<'a> { type Inner = TypeAliases<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -45,7 +45,7 @@ impl<'a> TypeAliases<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TypeAliases { _tab: table } } #[allow(unused_mut)] @@ -81,7 +81,7 @@ impl<'a> TypeAliases<'a> { let f32_ = self.f32_(); let f64_ = self.f64_(); let v8 = self.v8().map(|x| { - x.to_vec() + x.into_iter().collect() }); let vf64 = self.vf64().map(|x| { x.into_iter().collect() @@ -104,51 +104,87 @@ impl<'a> TypeAliases<'a> { #[inline] pub fn i8_(&self) -> i8 { - self._tab.get::(TypeAliases::VT_I8_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_I8_, Some(0)).unwrap()} } #[inline] pub fn u8_(&self) -> u8 { - self._tab.get::(TypeAliases::VT_U8_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_U8_, Some(0)).unwrap()} } #[inline] pub fn i16_(&self) -> i16 { - self._tab.get::(TypeAliases::VT_I16_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_I16_, Some(0)).unwrap()} } #[inline] pub fn u16_(&self) -> u16 { - self._tab.get::(TypeAliases::VT_U16_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_U16_, Some(0)).unwrap()} } #[inline] pub fn i32_(&self) -> i32 { - self._tab.get::(TypeAliases::VT_I32_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_I32_, Some(0)).unwrap()} } #[inline] pub fn u32_(&self) -> u32 { - self._tab.get::(TypeAliases::VT_U32_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_U32_, Some(0)).unwrap()} } #[inline] pub fn i64_(&self) -> i64 { - self._tab.get::(TypeAliases::VT_I64_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_I64_, Some(0)).unwrap()} } #[inline] pub fn u64_(&self) -> u64 { - self._tab.get::(TypeAliases::VT_U64_, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_U64_, Some(0)).unwrap()} } #[inline] pub fn f32_(&self) -> f32 { - self._tab.get::(TypeAliases::VT_F32_, Some(0.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_F32_, Some(0.0)).unwrap()} } #[inline] pub fn f64_(&self) -> f64 { - self._tab.get::(TypeAliases::VT_F64_, Some(0.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TypeAliases::VT_F64_, Some(0.0)).unwrap()} } #[inline] - pub fn v8(&self) -> Option<&'a [i8]> { - self._tab.get::>>(TypeAliases::VT_V8, None).map(|v| v.safe_slice()) + pub fn v8(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(TypeAliases::VT_V8, None)} } #[inline] pub fn vf64(&self) -> Option> { - self._tab.get::>>(TypeAliases::VT_VF64, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(TypeAliases::VT_VF64, None)} } } diff --git a/tests/monster_test_serialize/my_game/example/vec_3_generated.rs b/tests/monster_test_serialize/my_game/example/vec_3_generated.rs index ebbe94c9b..c080dd742 100644 --- a/tests/monster_test_serialize/my_game/example/vec_3_generated.rs +++ b/tests/monster_test_serialize/my_game/example/vec_3_generated.rs @@ -34,39 +34,25 @@ impl core::fmt::Debug for Vec3 { } impl flatbuffers::SimpleToVerifyInSlice for Vec3 {} -impl flatbuffers::SafeSliceAccess for Vec3 {} impl<'a> flatbuffers::Follow<'a> for Vec3 { type Inner = &'a Vec3; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Vec3>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Vec3 { type Inner = &'a Vec3; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Vec3 { type Output = Vec3; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Vec3 as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Vec3 { - type Output = Vec3; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Vec3 as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Vec3 as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -122,121 +108,154 @@ impl<'a> Vec3 { } pub fn x(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_x(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn y(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[4..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_y(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[4..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn z(&self) -> f32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[8..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_z(&mut self, x: f32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f32 as *const u8, + &x_le as *const _ as *const u8, self.0[8..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn test1(&self) -> f64 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[16..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_test1(&mut self, x: f64) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const f64 as *const u8, + &x_le as *const _ as *const u8, self.0[16..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn test2(&self) -> Color { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[24..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_test2(&mut self, x: Color) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const Color as *const u8, + &x_le as *const _ as *const u8, self.0[24..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn test3(&self) -> &Test { + // Safety: + // Created from a valid Table for this object + // Which contains a valid struct in this slot unsafe { &*(self.0[26..].as_ptr() as *const Test) } } diff --git a/tests/monster_test_serialize/my_game/example_2/monster_generated.rs b/tests/monster_test_serialize/my_game/example_2/monster_generated.rs index 9422b573b..8e1ce3aa0 100644 --- a/tests/monster_test_serialize/my_game/example_2/monster_generated.rs +++ b/tests/monster_test_serialize/my_game/example_2/monster_generated.rs @@ -21,8 +21,8 @@ pub struct Monster<'a> { impl<'a> flatbuffers::Follow<'a> for Monster<'a> { type Inner = Monster<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -33,7 +33,7 @@ impl<'a> Monster<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Monster { _tab: table } } #[allow(unused_mut)] diff --git a/tests/monster_test_serialize/my_game/in_parent_namespace_generated.rs b/tests/monster_test_serialize/my_game/in_parent_namespace_generated.rs index 71ceaa0be..7fbc0deb7 100644 --- a/tests/monster_test_serialize/my_game/in_parent_namespace_generated.rs +++ b/tests/monster_test_serialize/my_game/in_parent_namespace_generated.rs @@ -21,8 +21,8 @@ pub struct InParentNamespace<'a> { impl<'a> flatbuffers::Follow<'a> for InParentNamespace<'a> { type Inner = InParentNamespace<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -33,7 +33,7 @@ impl<'a> InParentNamespace<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { InParentNamespace { _tab: table } } #[allow(unused_mut)] diff --git a/tests/monster_test_serialize/my_game/other_name_space/from_include_generated.rs b/tests/monster_test_serialize/my_game/other_name_space/from_include_generated.rs index de5e5e227..153664401 100644 --- a/tests/monster_test_serialize/my_game/other_name_space/from_include_generated.rs +++ b/tests/monster_test_serialize/my_game/other_name_space/from_include_generated.rs @@ -62,10 +62,8 @@ impl Serialize for FromInclude { impl<'a> flatbuffers::Follow<'a> for FromInclude { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -73,21 +71,21 @@ impl<'a> flatbuffers::Follow<'a> for FromInclude { impl flatbuffers::Push for FromInclude { type Output = FromInclude; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for FromInclude { + type Scalar = i64; #[inline] - fn to_little_endian(self) -> Self { - let b = i64::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i64 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i64::from_le(self.0); + fn from_little_endian(v: i64) -> Self { + let b = i64::from_le(v); Self(b) } } diff --git a/tests/monster_test_serialize/my_game/other_name_space/table_b_generated.rs b/tests/monster_test_serialize/my_game/other_name_space/table_b_generated.rs index e593299c0..27f9eb6d7 100644 --- a/tests/monster_test_serialize/my_game/other_name_space/table_b_generated.rs +++ b/tests/monster_test_serialize/my_game/other_name_space/table_b_generated.rs @@ -21,8 +21,8 @@ pub struct TableB<'a> { impl<'a> flatbuffers::Follow<'a> for TableB<'a> { type Inner = TableB<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -34,7 +34,7 @@ impl<'a> TableB<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableB { _tab: table } } #[allow(unused_mut)] @@ -58,7 +58,10 @@ impl<'a> TableB<'a> { #[inline] pub fn a(&self) -> Option> { - self._tab.get::>(TableB::VT_A, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableB::VT_A, None)} } } diff --git a/tests/monster_test_serialize/my_game/other_name_space/unused_generated.rs b/tests/monster_test_serialize/my_game/other_name_space/unused_generated.rs index 2991781c9..b676318f7 100644 --- a/tests/monster_test_serialize/my_game/other_name_space/unused_generated.rs +++ b/tests/monster_test_serialize/my_game/other_name_space/unused_generated.rs @@ -29,39 +29,25 @@ impl core::fmt::Debug for Unused { } impl flatbuffers::SimpleToVerifyInSlice for Unused {} -impl flatbuffers::SafeSliceAccess for Unused {} impl<'a> flatbuffers::Follow<'a> for Unused { type Inner = &'a Unused; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Unused>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Unused { type Inner = &'a Unused; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Unused { type Output = Unused; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Unused as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Unused { - type Output = Unused; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Unused as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Unused as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -102,24 +88,30 @@ impl<'a> Unused { } pub fn a(&self) -> i32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_a(&mut self, x: i32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/monster_test_serialize/table_a_generated.rs b/tests/monster_test_serialize/table_a_generated.rs index c4bbd6925..36e739095 100644 --- a/tests/monster_test_serialize/table_a_generated.rs +++ b/tests/monster_test_serialize/table_a_generated.rs @@ -21,8 +21,8 @@ pub struct TableA<'a> { impl<'a> flatbuffers::Follow<'a> for TableA<'a> { type Inner = TableA<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -34,7 +34,7 @@ impl<'a> TableA<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableA { _tab: table } } #[allow(unused_mut)] @@ -58,7 +58,10 @@ impl<'a> TableA<'a> { #[inline] pub fn b(&self) -> Option> { - self._tab.get::>(TableA::VT_B, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableA::VT_B, None)} } } diff --git a/tests/more_defaults/abc_generated.rs b/tests/more_defaults/abc_generated.rs index f2bdbad4a..cff89ca72 100644 --- a/tests/more_defaults/abc_generated.rs +++ b/tests/more_defaults/abc_generated.rs @@ -59,10 +59,8 @@ impl core::fmt::Debug for ABC { impl<'a> flatbuffers::Follow<'a> for ABC { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for ABC { impl flatbuffers::Push for ABC { type Output = ABC; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for ABC { + type Scalar = i32; #[inline] - fn to_little_endian(self) -> Self { - let b = i32::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i32 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i32::from_le(self.0); + fn from_little_endian(v: i32) -> Self { + let b = i32::from_le(v); Self(b) } } diff --git a/tests/more_defaults/more_defaults_generated.rs b/tests/more_defaults/more_defaults_generated.rs index 27fa65ca2..99444b85c 100644 --- a/tests/more_defaults/more_defaults_generated.rs +++ b/tests/more_defaults/more_defaults_generated.rs @@ -19,8 +19,8 @@ pub struct MoreDefaults<'a> { impl<'a> flatbuffers::Follow<'a> for MoreDefaults<'a> { type Inner = MoreDefaults<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -37,7 +37,7 @@ impl<'a> MoreDefaults<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { MoreDefaults { _tab: table } } #[allow(unused_mut)] @@ -78,7 +78,7 @@ impl<'a> MoreDefaults<'a> { }; let bools = { let x = self.bools(); - x.to_vec() + x.into_iter().collect() }; MoreDefaultsT { ints, @@ -92,27 +92,45 @@ impl<'a> MoreDefaults<'a> { #[inline] pub fn ints(&self) -> flatbuffers::Vector<'a, i32> { - self._tab.get::>>(MoreDefaults::VT_INTS, Some(Default::default())).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(MoreDefaults::VT_INTS, Some(Default::default())).unwrap()} } #[inline] pub fn floats(&self) -> flatbuffers::Vector<'a, f32> { - self._tab.get::>>(MoreDefaults::VT_FLOATS, Some(Default::default())).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(MoreDefaults::VT_FLOATS, Some(Default::default())).unwrap()} } #[inline] pub fn empty_string(&self) -> &'a str { - self._tab.get::>(MoreDefaults::VT_EMPTY_STRING, Some(&"")).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(MoreDefaults::VT_EMPTY_STRING, Some(&"")).unwrap()} } #[inline] pub fn some_string(&self) -> &'a str { - self._tab.get::>(MoreDefaults::VT_SOME_STRING, Some(&"some")).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(MoreDefaults::VT_SOME_STRING, Some(&"some")).unwrap()} } #[inline] pub fn abcs(&self) -> flatbuffers::Vector<'a, ABC> { - self._tab.get::>>(MoreDefaults::VT_ABCS, Some(Default::default())).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(MoreDefaults::VT_ABCS, Some(Default::default())).unwrap()} } #[inline] - pub fn bools(&self) -> &'a [bool] { - self._tab.get::>>(MoreDefaults::VT_BOOLS, Some(Default::default())).map(|v| v.safe_slice()).unwrap() + pub fn bools(&self) -> flatbuffers::Vector<'a, bool> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(MoreDefaults::VT_BOOLS, Some(Default::default())).unwrap()} } } diff --git a/tests/namespace_test/namespace_a/namespace_b/enum_in_nested_ns_generated.rs b/tests/namespace_test/namespace_a/namespace_b/enum_in_nested_ns_generated.rs index 246d28f5f..59277bd40 100644 --- a/tests/namespace_test/namespace_a/namespace_b/enum_in_nested_ns_generated.rs +++ b/tests/namespace_test/namespace_a/namespace_b/enum_in_nested_ns_generated.rs @@ -59,10 +59,8 @@ impl core::fmt::Debug for EnumInNestedNS { impl<'a> flatbuffers::Follow<'a> for EnumInNestedNS { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for EnumInNestedNS { impl flatbuffers::Push for EnumInNestedNS { type Output = EnumInNestedNS; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for EnumInNestedNS { + type Scalar = i8; #[inline] - fn to_little_endian(self) -> Self { - let b = i8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i8::from_le(self.0); + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); Self(b) } } diff --git a/tests/namespace_test/namespace_a/namespace_b/struct_in_nested_ns_generated.rs b/tests/namespace_test/namespace_a/namespace_b/struct_in_nested_ns_generated.rs index dc13b0cfa..f2a15f4be 100644 --- a/tests/namespace_test/namespace_a/namespace_b/struct_in_nested_ns_generated.rs +++ b/tests/namespace_test/namespace_a/namespace_b/struct_in_nested_ns_generated.rs @@ -28,39 +28,25 @@ impl core::fmt::Debug for StructInNestedNS { } impl flatbuffers::SimpleToVerifyInSlice for StructInNestedNS {} -impl flatbuffers::SafeSliceAccess for StructInNestedNS {} impl<'a> flatbuffers::Follow<'a> for StructInNestedNS { type Inner = &'a StructInNestedNS; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a StructInNestedNS>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a StructInNestedNS { type Inner = &'a StructInNestedNS; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for StructInNestedNS { type Output = StructInNestedNS; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const StructInNestedNS as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b StructInNestedNS { - type Output = StructInNestedNS; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const StructInNestedNS as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const StructInNestedNS as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -92,47 +78,59 @@ impl<'a> StructInNestedNS { } pub fn a(&self) -> i32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_a(&mut self, x: i32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } pub fn b(&self) -> i32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[4..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_b(&mut self, x: i32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i32 as *const u8, + &x_le as *const _ as *const u8, self.0[4..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/namespace_test/namespace_a/namespace_b/table_in_nested_ns_generated.rs b/tests/namespace_test/namespace_a/namespace_b/table_in_nested_ns_generated.rs index 76744f9f0..5d6957a01 100644 --- a/tests/namespace_test/namespace_a/namespace_b/table_in_nested_ns_generated.rs +++ b/tests/namespace_test/namespace_a/namespace_b/table_in_nested_ns_generated.rs @@ -19,8 +19,8 @@ pub struct TableInNestedNS<'a> { impl<'a> flatbuffers::Follow<'a> for TableInNestedNS<'a> { type Inner = TableInNestedNS<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> TableInNestedNS<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableInNestedNS { _tab: table } } #[allow(unused_mut)] @@ -54,7 +54,10 @@ impl<'a> TableInNestedNS<'a> { #[inline] pub fn foo(&self) -> i32 { - self._tab.get::(TableInNestedNS::VT_FOO, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TableInNestedNS::VT_FOO, Some(0)).unwrap()} } } diff --git a/tests/namespace_test/namespace_a/namespace_b/union_in_nested_ns_generated.rs b/tests/namespace_test/namespace_a/namespace_b/union_in_nested_ns_generated.rs index a77108f28..4256cc88e 100644 --- a/tests/namespace_test/namespace_a/namespace_b/union_in_nested_ns_generated.rs +++ b/tests/namespace_test/namespace_a/namespace_b/union_in_nested_ns_generated.rs @@ -55,10 +55,8 @@ impl core::fmt::Debug for UnionInNestedNS { impl<'a> flatbuffers::Follow<'a> for UnionInNestedNS { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -66,21 +64,21 @@ impl<'a> flatbuffers::Follow<'a> for UnionInNestedNS { impl flatbuffers::Push for UnionInNestedNS { type Output = UnionInNestedNS; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for UnionInNestedNS { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/namespace_test/namespace_a/second_table_in_a_generated.rs b/tests/namespace_test/namespace_a/second_table_in_a_generated.rs index c32fdc0c1..92b11c9b1 100644 --- a/tests/namespace_test/namespace_a/second_table_in_a_generated.rs +++ b/tests/namespace_test/namespace_a/second_table_in_a_generated.rs @@ -19,8 +19,8 @@ pub struct SecondTableInA<'a> { impl<'a> flatbuffers::Follow<'a> for SecondTableInA<'a> { type Inner = SecondTableInA<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> SecondTableInA<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { SecondTableInA { _tab: table } } #[allow(unused_mut)] @@ -56,7 +56,10 @@ impl<'a> SecondTableInA<'a> { #[inline] pub fn refer_to_c(&self) -> Option> { - self._tab.get::>(SecondTableInA::VT_REFER_TO_C, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(SecondTableInA::VT_REFER_TO_C, None)} } } diff --git a/tests/namespace_test/namespace_a/table_in_first_ns_generated.rs b/tests/namespace_test/namespace_a/table_in_first_ns_generated.rs index ab46d7e6a..b7bd1c711 100644 --- a/tests/namespace_test/namespace_a/table_in_first_ns_generated.rs +++ b/tests/namespace_test/namespace_a/table_in_first_ns_generated.rs @@ -19,8 +19,8 @@ pub struct TableInFirstNS<'a> { impl<'a> flatbuffers::Follow<'a> for TableInFirstNS<'a> { type Inner = TableInFirstNS<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -36,7 +36,7 @@ impl<'a> TableInFirstNS<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableInFirstNS { _tab: table } } #[allow(unused_mut)] @@ -80,29 +80,49 @@ impl<'a> TableInFirstNS<'a> { #[inline] pub fn foo_table(&self) -> Option> { - self._tab.get::>(TableInFirstNS::VT_FOO_TABLE, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableInFirstNS::VT_FOO_TABLE, None)} } #[inline] pub fn foo_enum(&self) -> namespace_b::EnumInNestedNS { - self._tab.get::(TableInFirstNS::VT_FOO_ENUM, Some(namespace_b::EnumInNestedNS::A)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TableInFirstNS::VT_FOO_ENUM, Some(namespace_b::EnumInNestedNS::A)).unwrap()} } #[inline] pub fn foo_union_type(&self) -> namespace_b::UnionInNestedNS { - self._tab.get::(TableInFirstNS::VT_FOO_UNION_TYPE, Some(namespace_b::UnionInNestedNS::NONE)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TableInFirstNS::VT_FOO_UNION_TYPE, Some(namespace_b::UnionInNestedNS::NONE)).unwrap()} } #[inline] pub fn foo_union(&self) -> Option> { - self._tab.get::>>(TableInFirstNS::VT_FOO_UNION, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(TableInFirstNS::VT_FOO_UNION, None)} } #[inline] pub fn foo_struct(&self) -> Option<&'a namespace_b::StructInNestedNS> { - self._tab.get::(TableInFirstNS::VT_FOO_STRUCT, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(TableInFirstNS::VT_FOO_STRUCT, None)} } #[inline] #[allow(non_snake_case)] pub fn foo_union_as_table_in_nested_ns(&self) -> Option> { if self.foo_union_type() == namespace_b::UnionInNestedNS::TableInNestedNS { - self.foo_union().map(namespace_b::TableInNestedNS::init_from_table) + self.foo_union().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { namespace_b::TableInNestedNS::init_from_table(t) } + }) } else { None } diff --git a/tests/namespace_test/namespace_c/table_in_c_generated.rs b/tests/namespace_test/namespace_c/table_in_c_generated.rs index a6ba7bfae..63b84d113 100644 --- a/tests/namespace_test/namespace_c/table_in_c_generated.rs +++ b/tests/namespace_test/namespace_c/table_in_c_generated.rs @@ -19,8 +19,8 @@ pub struct TableInC<'a> { impl<'a> flatbuffers::Follow<'a> for TableInC<'a> { type Inner = TableInC<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -33,7 +33,7 @@ impl<'a> TableInC<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TableInC { _tab: table } } #[allow(unused_mut)] @@ -62,11 +62,17 @@ impl<'a> TableInC<'a> { #[inline] pub fn refer_to_a1(&self) -> Option> { - self._tab.get::>(TableInC::VT_REFER_TO_A1, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableInC::VT_REFER_TO_A1, None)} } #[inline] pub fn refer_to_a2(&self) -> Option> { - self._tab.get::>(TableInC::VT_REFER_TO_A2, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(TableInC::VT_REFER_TO_A2, None)} } } diff --git a/tests/optional_scalars/optional_scalars/optional_byte_generated.rs b/tests/optional_scalars/optional_scalars/optional_byte_generated.rs index dae13668e..9cb47c699 100644 --- a/tests/optional_scalars/optional_scalars/optional_byte_generated.rs +++ b/tests/optional_scalars/optional_scalars/optional_byte_generated.rs @@ -59,10 +59,8 @@ impl core::fmt::Debug for OptionalByte { impl<'a> flatbuffers::Follow<'a> for OptionalByte { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for OptionalByte { impl flatbuffers::Push for OptionalByte { type Output = OptionalByte; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for OptionalByte { + type Scalar = i8; #[inline] - fn to_little_endian(self) -> Self { - let b = i8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i8::from_le(self.0); + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); Self(b) } } diff --git a/tests/optional_scalars/optional_scalars/scalar_stuff_generated.rs b/tests/optional_scalars/optional_scalars/scalar_stuff_generated.rs index e201cc0b3..8916932b8 100644 --- a/tests/optional_scalars/optional_scalars/scalar_stuff_generated.rs +++ b/tests/optional_scalars/optional_scalars/scalar_stuff_generated.rs @@ -19,8 +19,8 @@ pub struct ScalarStuff<'a> { impl<'a> flatbuffers::Follow<'a> for ScalarStuff<'a> { type Inner = ScalarStuff<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -67,7 +67,7 @@ impl<'a> ScalarStuff<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { ScalarStuff { _tab: table } } #[allow(unused_mut)] @@ -194,147 +194,255 @@ impl<'a> ScalarStuff<'a> { #[inline] pub fn just_i8(&self) -> i8 { - self._tab.get::(ScalarStuff::VT_JUST_I8, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_I8, Some(0)).unwrap()} } #[inline] pub fn maybe_i8(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_I8, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_I8, None)} } #[inline] pub fn default_i8(&self) -> i8 { - self._tab.get::(ScalarStuff::VT_DEFAULT_I8, Some(42)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_I8, Some(42)).unwrap()} } #[inline] pub fn just_u8(&self) -> u8 { - self._tab.get::(ScalarStuff::VT_JUST_U8, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_U8, Some(0)).unwrap()} } #[inline] pub fn maybe_u8(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_U8, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_U8, None)} } #[inline] pub fn default_u8(&self) -> u8 { - self._tab.get::(ScalarStuff::VT_DEFAULT_U8, Some(42)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_U8, Some(42)).unwrap()} } #[inline] pub fn just_i16(&self) -> i16 { - self._tab.get::(ScalarStuff::VT_JUST_I16, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_I16, Some(0)).unwrap()} } #[inline] pub fn maybe_i16(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_I16, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_I16, None)} } #[inline] pub fn default_i16(&self) -> i16 { - self._tab.get::(ScalarStuff::VT_DEFAULT_I16, Some(42)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_I16, Some(42)).unwrap()} } #[inline] pub fn just_u16(&self) -> u16 { - self._tab.get::(ScalarStuff::VT_JUST_U16, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_U16, Some(0)).unwrap()} } #[inline] pub fn maybe_u16(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_U16, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_U16, None)} } #[inline] pub fn default_u16(&self) -> u16 { - self._tab.get::(ScalarStuff::VT_DEFAULT_U16, Some(42)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_U16, Some(42)).unwrap()} } #[inline] pub fn just_i32(&self) -> i32 { - self._tab.get::(ScalarStuff::VT_JUST_I32, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_I32, Some(0)).unwrap()} } #[inline] pub fn maybe_i32(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_I32, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_I32, None)} } #[inline] pub fn default_i32(&self) -> i32 { - self._tab.get::(ScalarStuff::VT_DEFAULT_I32, Some(42)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_I32, Some(42)).unwrap()} } #[inline] pub fn just_u32(&self) -> u32 { - self._tab.get::(ScalarStuff::VT_JUST_U32, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_U32, Some(0)).unwrap()} } #[inline] pub fn maybe_u32(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_U32, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_U32, None)} } #[inline] pub fn default_u32(&self) -> u32 { - self._tab.get::(ScalarStuff::VT_DEFAULT_U32, Some(42)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_U32, Some(42)).unwrap()} } #[inline] pub fn just_i64(&self) -> i64 { - self._tab.get::(ScalarStuff::VT_JUST_I64, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_I64, Some(0)).unwrap()} } #[inline] pub fn maybe_i64(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_I64, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_I64, None)} } #[inline] pub fn default_i64(&self) -> i64 { - self._tab.get::(ScalarStuff::VT_DEFAULT_I64, Some(42)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_I64, Some(42)).unwrap()} } #[inline] pub fn just_u64(&self) -> u64 { - self._tab.get::(ScalarStuff::VT_JUST_U64, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_U64, Some(0)).unwrap()} } #[inline] pub fn maybe_u64(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_U64, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_U64, None)} } #[inline] pub fn default_u64(&self) -> u64 { - self._tab.get::(ScalarStuff::VT_DEFAULT_U64, Some(42)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_U64, Some(42)).unwrap()} } #[inline] pub fn just_f32(&self) -> f32 { - self._tab.get::(ScalarStuff::VT_JUST_F32, Some(0.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_F32, Some(0.0)).unwrap()} } #[inline] pub fn maybe_f32(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_F32, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_F32, None)} } #[inline] pub fn default_f32(&self) -> f32 { - self._tab.get::(ScalarStuff::VT_DEFAULT_F32, Some(42.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_F32, Some(42.0)).unwrap()} } #[inline] pub fn just_f64(&self) -> f64 { - self._tab.get::(ScalarStuff::VT_JUST_F64, Some(0.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_F64, Some(0.0)).unwrap()} } #[inline] pub fn maybe_f64(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_F64, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_F64, None)} } #[inline] pub fn default_f64(&self) -> f64 { - self._tab.get::(ScalarStuff::VT_DEFAULT_F64, Some(42.0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_F64, Some(42.0)).unwrap()} } #[inline] pub fn just_bool(&self) -> bool { - self._tab.get::(ScalarStuff::VT_JUST_BOOL, Some(false)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_BOOL, Some(false)).unwrap()} } #[inline] pub fn maybe_bool(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_BOOL, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_BOOL, None)} } #[inline] pub fn default_bool(&self) -> bool { - self._tab.get::(ScalarStuff::VT_DEFAULT_BOOL, Some(true)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_BOOL, Some(true)).unwrap()} } #[inline] pub fn just_enum(&self) -> OptionalByte { - self._tab.get::(ScalarStuff::VT_JUST_ENUM, Some(OptionalByte::None)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_JUST_ENUM, Some(OptionalByte::None)).unwrap()} } #[inline] pub fn maybe_enum(&self) -> Option { - self._tab.get::(ScalarStuff::VT_MAYBE_ENUM, None) + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_MAYBE_ENUM, None)} } #[inline] pub fn default_enum(&self) -> OptionalByte { - self._tab.get::(ScalarStuff::VT_DEFAULT_ENUM, Some(OptionalByte::One)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ScalarStuff::VT_DEFAULT_ENUM, Some(OptionalByte::One)).unwrap()} } } @@ -836,18 +944,6 @@ impl ScalarStuffT { }) } } -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_root_as_scalar_stuff<'a>(buf: &'a [u8]) -> ScalarStuff<'a> { - unsafe { flatbuffers::root_unchecked::>(buf) } -} - -#[inline] -#[deprecated(since="2.0.0", note="Deprecated in favor of `root_as...` methods.")] -pub fn get_size_prefixed_root_as_scalar_stuff<'a>(buf: &'a [u8]) -> ScalarStuff<'a> { - unsafe { flatbuffers::size_prefixed_root_unchecked::>(buf) } -} - #[inline] /// Verifies that a buffer of bytes contains a `ScalarStuff` /// and returns it. diff --git a/tests/private_annotation_test/ab_generated.rs b/tests/private_annotation_test/ab_generated.rs index 6ed88504c..f2246488f 100644 --- a/tests/private_annotation_test/ab_generated.rs +++ b/tests/private_annotation_test/ab_generated.rs @@ -55,10 +55,8 @@ impl core::fmt::Debug for AB { impl<'a> flatbuffers::Follow<'a> for AB { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -66,21 +64,21 @@ impl<'a> flatbuffers::Follow<'a> for AB { impl flatbuffers::Push for AB { type Output = AB; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for AB { + type Scalar = i8; #[inline] - fn to_little_endian(self) -> Self { - let b = i8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> i8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = i8::from_le(self.0); + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); Self(b) } } diff --git a/tests/private_annotation_test/annotations_generated.rs b/tests/private_annotation_test/annotations_generated.rs index 7c5166b68..c8b4925e6 100644 --- a/tests/private_annotation_test/annotations_generated.rs +++ b/tests/private_annotation_test/annotations_generated.rs @@ -19,8 +19,8 @@ pub(crate) struct Annotations<'a> { impl<'a> flatbuffers::Follow<'a> for Annotations<'a> { type Inner = Annotations<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> Annotations<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Annotations { _tab: table } } #[allow(unused_mut)] @@ -54,7 +54,10 @@ impl<'a> Annotations<'a> { #[inline] pub fn value(&self) -> i32 { - self._tab.get::(Annotations::VT_VALUE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Annotations::VT_VALUE, Some(0)).unwrap()} } } diff --git a/tests/private_annotation_test/any_generated.rs b/tests/private_annotation_test/any_generated.rs index c3049a08d..552c38f03 100644 --- a/tests/private_annotation_test/any_generated.rs +++ b/tests/private_annotation_test/any_generated.rs @@ -59,10 +59,8 @@ impl core::fmt::Debug for Any { impl<'a> flatbuffers::Follow<'a> for Any { type Inner = Self; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - let b = unsafe { - flatbuffers::read_scalar_at::(buf, loc) - }; + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); Self(b) } } @@ -70,21 +68,21 @@ impl<'a> flatbuffers::Follow<'a> for Any { impl flatbuffers::Push for Any { type Output = Any; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); } } impl flatbuffers::EndianScalar for Any { + type Scalar = u8; #[inline] - fn to_little_endian(self) -> Self { - let b = u8::to_le(self.0); - Self(b) + fn to_little_endian(self) -> u8 { + self.0.to_le() } #[inline] #[allow(clippy::wrong_self_convention)] - fn from_little_endian(self) -> Self { - let b = u8::from_le(self.0); + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); Self(b) } } diff --git a/tests/private_annotation_test/game_generated.rs b/tests/private_annotation_test/game_generated.rs index e69661120..9ded51f87 100644 --- a/tests/private_annotation_test/game_generated.rs +++ b/tests/private_annotation_test/game_generated.rs @@ -19,8 +19,8 @@ pub(crate) struct Game<'a> { impl<'a> flatbuffers::Follow<'a> for Game<'a> { type Inner = Game<'a>; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self { _tab: flatbuffers::Table { buf, loc } } + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } } } @@ -32,7 +32,7 @@ impl<'a> Game<'a> { } #[inline] - pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Game { _tab: table } } #[allow(unused_mut)] @@ -54,7 +54,10 @@ impl<'a> Game<'a> { #[inline] pub fn value(&self) -> i32 { - self._tab.get::(Game::VT_VALUE, Some(0)).unwrap() + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Game::VT_VALUE, Some(0)).unwrap()} } } diff --git a/tests/private_annotation_test/object_generated.rs b/tests/private_annotation_test/object_generated.rs index 64419a9e0..cb93412f3 100644 --- a/tests/private_annotation_test/object_generated.rs +++ b/tests/private_annotation_test/object_generated.rs @@ -27,39 +27,25 @@ impl core::fmt::Debug for Object { } impl flatbuffers::SimpleToVerifyInSlice for Object {} -impl flatbuffers::SafeSliceAccess for Object {} impl<'a> flatbuffers::Follow<'a> for Object { type Inner = &'a Object; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a Object>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a Object { type Inner = &'a Object; #[inline] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } impl<'b> flatbuffers::Push for Object { type Output = Object; #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(self as *const Object as *const u8, Self::size()) - }; - dst.copy_from_slice(src); - } -} -impl<'b> flatbuffers::Push for &'b Object { - type Output = Object; - - #[inline] - fn push(&self, dst: &mut [u8], _rest: &[u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const Object as *const u8, Self::size()) - }; + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(self as *const Object as *const u8, Self::size()); dst.copy_from_slice(src); } } @@ -89,24 +75,30 @@ impl<'a> Object { } pub fn value(&self) -> i32 { - let mut mem = core::mem::MaybeUninit::::uninit(); - unsafe { + let mut mem = core::mem::MaybeUninit::<::Scalar>::uninit(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot + EndianScalar::from_little_endian(unsafe { core::ptr::copy_nonoverlapping( self.0[0..].as_ptr(), mem.as_mut_ptr() as *mut u8, - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); mem.assume_init() - }.from_little_endian() + }) } pub fn set_value(&mut self, x: i32) { let x_le = x.to_little_endian(); + // Safety: + // Created from a valid Table for this object + // Which contains a valid value in this slot unsafe { core::ptr::copy_nonoverlapping( - &x_le as *const i32 as *const u8, + &x_le as *const _ as *const u8, self.0[0..].as_mut_ptr(), - core::mem::size_of::(), + core::mem::size_of::<::Scalar>(), ); } } diff --git a/tests/rust_serialize_test/src/main.rs b/tests/rust_serialize_test/src/main.rs index d67cc208b..e6bdce6fb 100644 --- a/tests/rust_serialize_test/src/main.rs +++ b/tests/rust_serialize_test/src/main.rs @@ -36,8 +36,8 @@ fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::Flat ) .as_union_value(), ), - inventory: Some(builder.create_vector_direct(&[0u8, 1, 2, 3, 4][..])), - test4: Some(builder.create_vector_direct(&[ + inventory: Some(builder.create_vector(&[0u8, 1, 2, 3, 4])), + test4: Some(builder.create_vector(&[ my_game::example::Test::new(10, 20), my_game::example::Test::new(30, 40), ])), diff --git a/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs b/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs index 7d7250181..3ab3b56aa 100644 --- a/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs +++ b/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs @@ -86,8 +86,8 @@ fn create_serialized_example_with_generated_code( let mon = { let name = builder.create_string("MyMonster"); let fred_name = builder.create_string("Fred"); - let inventory = builder.create_vector_direct(&[0u8, 1, 2, 3, 4]); - let test4 = builder.create_vector_direct(&[ + let inventory = builder.create_vector(&[0u8, 1, 2, 3, 4]); + let test4 = builder.create_vector(&[ my_game::example::Test::new(10, 20), my_game::example::Test::new(30, 40), ]); @@ -156,7 +156,7 @@ fn traverse_serialized_example_with_generated_code(bytes: &[u8]) { blackbox(pos_test3.b()); blackbox(m.test_type()); let table2 = m.test().unwrap(); - let monster2 = my_game::example::Monster::init_from_table(table2); + let monster2 = unsafe { my_game::example::Monster::init_from_table(table2) }; blackbox(monster2.name()); blackbox(m.inventory()); blackbox(m.test4()); @@ -228,7 +228,7 @@ fn create_byte_vector_100_optimal(bench: &mut Bencher) { let mut i = 0; bench.iter(|| { - builder.create_vector_direct(v); + builder.create_vector(v); i += 1; if i == 10000 { builder.reset(); diff --git a/tests/rust_usage_test/bin/flatbuffers_alloc_check.rs b/tests/rust_usage_test/bin/flatbuffers_alloc_check.rs index 418783c65..36cb5be21 100644 --- a/tests/rust_usage_test/bin/flatbuffers_alloc_check.rs +++ b/tests/rust_usage_test/bin/flatbuffers_alloc_check.rs @@ -12,6 +12,7 @@ impl TrackingAllocator { unsafe { N_ALLOCS } } } + unsafe impl GlobalAlloc for TrackingAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { N_ALLOCS += 1; @@ -28,6 +29,7 @@ static A: TrackingAllocator = TrackingAllocator; // import the flatbuffers generated code: extern crate flatbuffers; + #[allow(dead_code, unused_imports)] #[path = "../../include_test1/mod.rs"] pub mod include_test1_generated; @@ -39,20 +41,22 @@ pub mod include_test2_generated; #[allow(dead_code, unused_imports, clippy::approx_constant)] #[path = "../../monster_test/mod.rs"] mod monster_test_generated; + pub use monster_test_generated::my_game; // verbatim from the test suite: fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) { let mon = { - let _ = builder.create_vector_of_strings(&[ - "these", - "unused", - "strings", - "check", - "the", - "create_vector_of_strings", - "function", - ]); + let strings = [ + builder.create_string("these"), + builder.create_string("unused"), + builder.create_string("strings"), + builder.create_string("check"), + builder.create_string("the"), + builder.create_string("create_vector_of_strings"), + builder.create_string("function") + ]; + let _ = builder.create_vector(&strings); let s0 = builder.create_string("test1"); let s1 = builder.create_string("test2"); @@ -83,10 +87,10 @@ fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::Flat ..Default::default() }, ) - .as_union_value(), + .as_union_value(), ), - inventory: Some(builder.create_vector_direct(&[0u8, 1, 2, 3, 4][..])), - test4: Some(builder.create_vector_direct(&[ + inventory: Some(builder.create_vector(&[0u8, 1, 2, 3, 4])), + test4: Some(builder.create_vector(&[ my_game::example::Test::new(10, 20), my_game::example::Test::new(30, 40), ])), @@ -151,7 +155,7 @@ fn main() { assert_eq!(pos_test3.b(), 6i8); assert_eq!(m.test_type(), my_game::example::Any::Monster); let table2 = m.test().unwrap(); - let m2 = my_game::example::Monster::init_from_table(table2); + let m2 = unsafe { my_game::example::Monster::init_from_table(table2) }; assert_eq!(m2.name(), "Fred"); @@ -162,10 +166,10 @@ fn main() { let test4 = m.test4().unwrap(); assert_eq!(test4.len(), 2); assert_eq!( - i32::from(test4[0].a()) - + i32::from(test4[1].a()) - + i32::from(test4[0].b()) - + i32::from(test4[1].b()), + i32::from(test4.get(0).a()) + + i32::from(test4.get(1).a()) + + i32::from(test4.get(0).b()) + + i32::from(test4.get(1).b()), 100 ); diff --git a/tests/rust_usage_test/tests/arrays_test.rs b/tests/rust_usage_test/tests/arrays_test.rs index e92e86245..1b4cc64cb 100644 --- a/tests/rust_usage_test/tests/arrays_test.rs +++ b/tests/rust_usage_test/tests/arrays_test.rs @@ -6,14 +6,18 @@ extern crate std; extern crate alloc; extern crate array_init; + #[allow(dead_code, unused_imports)] #[path = "../../arrays_test/mod.rs"] mod arrays_test_generated; + use alloc::format; use core::fmt::Debug; use crate::arrays_test_generated::my_game::example::*; + extern crate quickcheck; + use array_init::array_init; use core::mem::size_of; use quickcheck::{Arbitrary, Gen}; @@ -60,6 +64,7 @@ fn serialized_example_is_accessible_and_correct( } else { array_table_buffer_has_identifier(bytes) }; + assert_eq!(correct, true); } @@ -175,7 +180,7 @@ fn object_api_defaults() { a: [0, 0], b: TestEnum::default(), c: [TestEnum::default(), TestEnum::default()], - d: [0, 0] + d: [0, 0], } ); @@ -187,7 +192,7 @@ fn object_api_defaults() { c: 0, d: [NestedStructT::default(), NestedStructT::default()], e: 0, - f: [0, 0] + f: [0, 0], } ); } @@ -213,14 +218,14 @@ fn generated_code_debug_prints_correctly() { #[should_panic] fn assert_on_too_small_array_buf() { let a = [0u8; 19]; - flatbuffers::Array::::new(&a); + unsafe { flatbuffers::Array::::new(&a) }; } #[test] #[should_panic] fn assert_on_too_big_array_buf() { let a = [0u8; 21]; - flatbuffers::Array::::new(&a); + unsafe { flatbuffers::Array::::new(&a) }; } #[test] @@ -251,10 +256,10 @@ impl Arbitrary for FakeArray ( fn $fn_name(xs: FakeArray<$ty, ARRAY_SIZE>) { let mut test_buf = [0 as u8; 1024]; - flatbuffers::emplace_scalar_array(&mut test_buf, 0, &xs.0); - let arr: flatbuffers::Array<$ty, ARRAY_SIZE> = flatbuffers::Array::follow(&test_buf, 0); + let arr: flatbuffers::Array<$ty, ARRAY_SIZE> = unsafe { + flatbuffers::emplace_scalar_array(&mut test_buf, 0, &xs.0); + flatbuffers::Array::follow(&test_buf, 0) + }; let got: [$ty; ARRAY_SIZE] = arr.into(); assert_eq!(got, xs.0); } @@ -308,7 +316,7 @@ mod array_fuzz { fn arbitrary(g: &mut G) -> NestedStructWrapper { let mut x = NestedStruct::default(); x.0 = FakeArray::::arbitrary(g).0; - NestedStructWrapper{0: x} + NestedStructWrapper { 0: x } } } @@ -317,16 +325,16 @@ mod array_fuzz { let native_struct_array: [&NestedStruct; ARRAY_SIZE] = array_init::from_iter(xs.0.iter().map(|x| &x.0)).unwrap(); for i in 0..ARRAY_SIZE { let offset = i * NESTED_STRUCT_SIZE; - native_struct_array[i].push(&mut test_buf[offset..offset + NESTED_STRUCT_SIZE], &[]); + unsafe { native_struct_array[i].push(&mut test_buf[offset..offset + NESTED_STRUCT_SIZE], 0) }; } - let arr: flatbuffers::Array = flatbuffers::Array::follow(&test_buf, 0); + let arr: flatbuffers::Array = unsafe { flatbuffers::Array::follow(&test_buf, 0) }; let got: [&NestedStruct; ARRAY_SIZE] = arr.into(); assert_eq!(got, native_struct_array); } #[test] #[cfg(not(miri))] // slow. - fn test_struct() { + fn test_struct() { quickcheck::QuickCheck::new().max_tests(MAX_TESTS).quickcheck(prop_struct as fn(FakeArray)); } } diff --git a/tests/rust_usage_test/tests/integration_test.rs b/tests/rust_usage_test/tests/integration_test.rs index 73d4a1f37..e0c6a0bd0 100644 --- a/tests/rust_usage_test/tests/integration_test.rs +++ b/tests/rust_usage_test/tests/integration_test.rs @@ -229,8 +229,8 @@ fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::Flat name: Some(fred_name), ..Default::default() }).as_union_value()), - inventory: Some(builder.create_vector_direct(&[0u8, 1, 2, 3, 4][..])), - test4: Some(builder.create_vector_direct(&[my_game::example::Test::new(10, 20), + inventory: Some(builder.create_vector(&[0u8, 1, 2, 3, 4])), + test4: Some(builder.create_vector(&[my_game::example::Test::new(10, 20), my_game::example::Test::new(30, 40)])), testarrayofstring: Some(builder.create_vector(&[s0, s1])), ..Default::default() @@ -254,7 +254,11 @@ fn create_serialized_example_with_library_code(builder: &mut flatbuffers::FlatBu my_game::example::Test::new(30, 40)][..]); let name = builder.create_string("MyMonster"); - let testarrayofstring = builder.create_vector_of_strings(&["test1", "test2"][..]); + + let test1 = builder.create_string("test1"); + let test2 = builder.create_string("test2"); + + let testarrayofstring = builder.create_vector(&[test1, test2]); // begin building @@ -306,7 +310,7 @@ fn serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_require check_eq!(m.test_type(), my_game::example::Any::Monster)?; check_is_some!(m.test())?; let table2 = m.test().unwrap(); - let monster2 = my_game::example::Monster::init_from_table(table2); + let monster2 = unsafe { my_game::example::Monster::init_from_table(table2) }; check_eq!(monster2.name(), "Fred")?; @@ -319,8 +323,8 @@ fn serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_require check_is_some!(m.test4())?; let test4 = m.test4().unwrap(); check_eq!(test4.len(), 2)?; - check_eq!(test4[0].a() as i32 + test4[0].b() as i32 + - test4[1].a() as i32 + test4[1].b() as i32, 100)?; + check_eq!(test4.get(0).a() as i32 + test4.get(0).b() as i32 + + test4.get(1).a() as i32 + test4.get(1).b() as i32, 100)?; check_is_some!(m.testarrayofstring())?; let testarrayofstring = m.testarrayofstring().unwrap(); @@ -572,16 +576,16 @@ mod lifetime_correctness { // make sure values retrieved from the 'static buffer are themselves 'static let monster: my_game::example::Monster<'static> = my_game::example::root_as_monster(slice).unwrap(); // this line should compile: - let name: Option<&'static str> = monster._tab.get::>(my_game::example::Monster::VT_NAME, None); + let name: Option<&'static str> = unsafe { monster._tab.get::>(my_game::example::Monster::VT_NAME, None) }; assert_eq!(name, Some("MyMonster")); } #[test] fn table_get_field_from_static_buffer_2() { static DATA: [u8; 4] = [0, 0, 0, 0]; // some binary data - let table: flatbuffers::Table<'static> = flatbuffers::Table::new(&DATA, 0); + let table: flatbuffers::Table<'static> = unsafe { flatbuffers::Table::new(&DATA, 0) }; // this line should compile: - table.get::<&'static str>(0, None); + unsafe { table.get::<&'static str>(0, None) }; } #[test] @@ -696,8 +700,8 @@ mod roundtrip_generated_code { let mon = my_game::example::root_as_monster(b.finished_data()).unwrap(); assert_eq!(mon.name(), "bar"); assert_eq!(mon.test_type(), my_game::example::Any::Monster); - assert_eq!(my_game::example::Monster::init_from_table(mon.test().unwrap()).name(), - "foo"); + let name = unsafe { my_game::example::Monster::init_from_table(mon.test().unwrap()).name() }; + assert_eq!(name, "foo"); assert_eq!(mon.test_as_monster().unwrap().name(), "foo"); assert_eq!(mon.test_as_test_simple_table_with_enum(), None); assert_eq!(mon.test_as_my_game_example_2_monster(), None); @@ -799,9 +803,9 @@ mod roundtrip_generated_code { let m = my_game::example::root_as_monster(b1.finished_data()).unwrap(); assert!(m.testnestedflatbuffer().is_some()); - assert_eq!(m.testnestedflatbuffer().unwrap(), b0.finished_data()); + assert_eq!(m.testnestedflatbuffer().unwrap().bytes(), b0.finished_data()); - let m2_a = my_game::example::root_as_monster(m.testnestedflatbuffer().unwrap()).unwrap(); + let m2_a = my_game::example::root_as_monster(m.testnestedflatbuffer().unwrap().bytes()).unwrap(); assert_eq!(m2_a.hp(), 123); assert_eq!(m2_a.name(), "foobar"); @@ -821,7 +825,8 @@ mod roundtrip_generated_code { #[test] fn vector_of_string_store_helper_build() { let mut b = flatbuffers::FlatBufferBuilder::new(); - let v = b.create_vector_of_strings(&["foobar", "baz"]); + let strings = &[b.create_string("foobar"), b.create_string("baz")]; + let v = b.create_vector(strings); let name = b.create_string("foo"); let m = build_mon(&mut b, &my_game::example::MonsterArgs{ name: Some(name), @@ -874,8 +879,9 @@ mod roundtrip_generated_code { let name = b.create_string("foo"); let m = build_mon(&mut b, &my_game::example::MonsterArgs{ name: Some(name), - inventory: Some(v), ..Default::default()}); - assert_eq!(m.inventory().unwrap(), &[123, 234][..]); + inventory: Some(v), ..Default::default() + }); + assert_eq!(m.inventory().unwrap().bytes(), &[123, 234]); } #[test] fn vector_of_bool_store() { @@ -885,14 +891,13 @@ mod roundtrip_generated_code { let m = build_mon(&mut b, &my_game::example::MonsterArgs{ name: Some(name), testarrayofbools: Some(v), ..Default::default()}); - assert_eq!(m.testarrayofbools().unwrap(), &[false, true, false, true][..]); let rust_vec_inst = m.testarrayofbools().unwrap(); let rust_vec_iter_collect = rust_vec_inst.iter().collect::>(); - assert_eq!(rust_vec_iter_collect, &[&false, &true, &false, &true][..]); + assert_eq!(&rust_vec_iter_collect, &[false, true, false, true]); let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::>(); - assert_eq!(rust_vec_iter_rev_collect, &[&true, &false, &true, &false][..]); + assert_eq!(&rust_vec_iter_rev_collect, &[true, false, true, false]); } #[test] fn vector_of_f64_store() { @@ -922,7 +927,6 @@ mod roundtrip_generated_code { let m = build_mon(&mut b, &my_game::example::MonsterArgs{ name: Some(name), test4: Some(v), ..Default::default()}); - assert_eq!(m.test4().unwrap(), &[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123)][..]); let rust_vec_inst = m.test4().unwrap(); let rust_vec_iter_collect = rust_vec_inst.iter().collect::>(); @@ -941,7 +945,8 @@ mod roundtrip_generated_code { let m = build_mon(&mut b, &my_game::example::MonsterArgs{ name: Some(name), test4: Some(v), ..Default::default()}); - assert_eq!(m.test4().unwrap(), &[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123), my_game::example::Test::new(100, 101)][..]); + let vals: Vec<_> = m.test4().unwrap().iter().collect::>(); + assert_eq!(vals, vec![&my_game::example::Test::new(127, -128), &my_game::example::Test::new(3, 123), &my_game::example::Test::new(100, 101)]); } #[test] fn vector_of_enums_store() { @@ -1088,56 +1093,6 @@ mod generated_code_alignment_and_padding { } } -#[cfg(test)] -mod roundtrip_byteswap { - #[cfg(not(miri))] // slow. - extern crate quickcheck; - extern crate flatbuffers; - - const N: u64 = 10000; - - fn palindrome_32(x: f32) -> bool { - x == f32::from_bits(x.to_bits().swap_bytes()) - } - fn palindrome_64(x: f64) -> bool { - x == f64::from_bits(x.to_bits().swap_bytes()) - } - - fn prop_f32(x: f32) { - use flatbuffers::byte_swap_f32; - - let there = byte_swap_f32(x); - - let back_again = byte_swap_f32(there); - - if !palindrome_32(x) { - assert!(x != there); - } - - assert_eq!(x, back_again); - } - - fn prop_f64(x: f64) { - use flatbuffers::byte_swap_f64; - - let there = byte_swap_f64(x); - let back_again = byte_swap_f64(there); - - if !palindrome_64(x) { - assert!(x != there); - } - - assert_eq!(x, back_again); - } - - // TODO(rw): Replace the implementations with the new stdlib endian-conversion functions. - // TODO(rw): Re-enable these tests (currently, rare CI failures occur that seem spurious). - // #[test] - // fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f32 as fn(f32)); } - // #[test] - // fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f64 as fn(f64)); } -} - #[cfg(not(miri))] quickcheck! { fn struct_of_structs( @@ -1204,7 +1159,7 @@ mod roundtrip_vectors { let buf = b.finished_data(); - let got = >>::follow(&buf[..], 0); + let got = unsafe { >>::follow(&buf[..], 0) }; let mut result_vec: Vec = Vec::with_capacity(got.len()); for i in 0..got.len() { result_vec.push(got.get(i)); @@ -1252,54 +1207,6 @@ mod roundtrip_vectors { fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop:: as fn(Vec<_>)); } } - #[cfg(test)] - mod create_vector_direct { - #[cfg(not(miri))] // slow. - extern crate quickcheck; - extern crate flatbuffers; - - const N: u64 = 20; - - // This uses a macro because lifetimes for the trait-bounded function get too - // complicated. - macro_rules! impl_prop { - ($test_name:ident, $fn_name:ident, $ty:ident) => ( - fn $fn_name(xs: alloc::vec::Vec<$ty>) { - use flatbuffers::Follow; - - let mut b = flatbuffers::FlatBufferBuilder::new(); - b.create_vector_direct(&xs[..]); - let buf = b.unfinished_data(); - - let got = >::follow(&buf[..], 0).safe_slice(); - assert_eq!(got, &xs[..]); - } - #[test] - fn $test_name() { quickcheck::QuickCheck::new().max_tests(N).quickcheck($fn_name as fn(alloc::vec::Vec<_>)); } - ) - } - - impl_prop!(test_bool, prop_bool, bool); - impl_prop!(test_u8, prop_u8, u8); - impl_prop!(test_i8, prop_i8, i8); - - #[cfg(test)] - #[cfg(target_endian = "little")] - mod host_is_le { - const N: u64 = 20; - use super::flatbuffers; - use super::quickcheck; - impl_prop!(test_u16, prop_u16, u16); - impl_prop!(test_u32, prop_u32, u32); - impl_prop!(test_u64, prop_u64, u64); - impl_prop!(test_i16, prop_i16, i16); - impl_prop!(test_i32, prop_i32, i32); - impl_prop!(test_i64, prop_i64, i64); - impl_prop!(test_f32, prop_f32, f32); - impl_prop!(test_f64, prop_f64, f64); - } - } - #[cfg(test)] mod string_manual_build { #[cfg(not(miri))] // slow. @@ -1327,7 +1234,7 @@ mod roundtrip_vectors { b.finish_minimal(vecend); let buf = b.finished_data(); - let got = >>>::follow(buf, 0); + let got = unsafe { >>>::follow(buf, 0) }; assert_eq!(got.len(), xs.len()); for i in 0..xs.len() { @@ -1351,21 +1258,20 @@ mod roundtrip_vectors { use alloc::vec::Vec; fn prop(input: Vec) { - let xs: Vec<&str> = input.iter().map(|s: &String| &s[..]).collect(); - use flatbuffers::Follow; let mut b = flatbuffers::FlatBufferBuilder::new(); - let vecend = b.create_vector_of_strings(&xs[..]); + let xs: Vec<_> = input.iter().map(|s: &String| b.create_string(s)).collect(); + let vecend = b.create_vector(&xs); b.finish_minimal(vecend); let buf = b.finished_data(); - let got = >>>::follow(buf, 0); + let got = unsafe { >>>::follow(buf, 0) }; assert_eq!(got.len(), xs.len()); - for i in 0..xs.len() { - assert_eq!(got.get(i), &xs[i][..]); + for (idx, s) in input.iter().enumerate() { + assert_eq!(got.get(idx), s); } } @@ -1516,7 +1422,7 @@ mod roundtrip_table { let table = { let buf = builder.unfinished_data(); let loc = buf.len() as flatbuffers::UOffsetT - objects[i]; - flatbuffers::Table::new(buf, loc as usize) + unsafe { flatbuffers::Table::new(buf, loc as usize) } }; let fields_per_object = (lcg.next() % (max_fields_per_object as u64)) as flatbuffers::VOffsetT; @@ -1528,19 +1434,21 @@ mod roundtrip_table { let f = flatbuffers::field_index_to_field_offset(j); - match choice { - 0 => { assert_eq!(bool_val, table.get::(f, Some(false)).unwrap()); } - 1 => { assert_eq!(char_val, table.get::(f, Some(0)).unwrap()); } - 2 => { assert_eq!(uchar_val, table.get::(f, Some(0)).unwrap()); } - 3 => { assert_eq!(short_val, table.get::(f, Some(0)).unwrap()); } - 4 => { assert_eq!(ushort_val, table.get::(f, Some(0)).unwrap()); } - 5 => { assert_eq!(int_val, table.get::(f, Some(0)).unwrap()); } - 6 => { assert_eq!(uint_val, table.get::(f, Some(0)).unwrap()); } - 7 => { assert_eq!(long_val, table.get::(f, Some(0)).unwrap()); } - 8 => { assert_eq!(ulong_val, table.get::(f, Some(0)).unwrap()); } - 9 => { assert_eq!(float_val, table.get::(f, Some(0.0)).unwrap()); } - 10 => { assert_eq!(double_val, table.get::(f, Some(0.0)).unwrap()); } - _ => { panic!("unknown choice: {}", choice); } + unsafe { + match choice { + 0 => { assert_eq!(bool_val, table.get::(f, Some(false)).unwrap()); } + 1 => { assert_eq!(char_val, table.get::(f, Some(0)).unwrap()); } + 2 => { assert_eq!(uchar_val, table.get::(f, Some(0)).unwrap()); } + 3 => { assert_eq!(short_val, table.get::(f, Some(0)).unwrap()); } + 4 => { assert_eq!(ushort_val, table.get::(f, Some(0)).unwrap()); } + 5 => { assert_eq!(int_val, table.get::(f, Some(0)).unwrap()); } + 6 => { assert_eq!(uint_val, table.get::(f, Some(0)).unwrap()); } + 7 => { assert_eq!(long_val, table.get::(f, Some(0)).unwrap()); } + 8 => { assert_eq!(ulong_val, table.get::(f, Some(0)).unwrap()); } + 9 => { assert_eq!(float_val, table.get::(f, Some(0.0)).unwrap()); } + 10 => { assert_eq!(double_val, table.get::(f, Some(0.0)).unwrap()); } + _ => { panic!("unknown choice: {}", choice); } + } } } } @@ -1576,13 +1484,13 @@ mod roundtrip_table { // use let buf = b.finished_data(); - let tab = >::follow(buf, 0); + let tab = unsafe { >::follow(buf, 0) }; for i in 0..xs.len() { - let v = tab.get::>>(fi2fo(i as flatbuffers::VOffsetT), None); + let v = unsafe { tab.get::>>(fi2fo(i as flatbuffers::VOffsetT), None) }; assert!(v.is_some()); - let v2 = v.unwrap().safe_slice(); - assert_eq!(v2, &xs[i][..]); + let v2 = v.unwrap(); + assert_eq!(v2.bytes(), &xs[i]); } } prop(vec![vec![1,2,3]]); @@ -1613,10 +1521,10 @@ mod roundtrip_table { // use let buf = b.finished_data(); - let tab = >::follow(buf, 0); + let tab = unsafe { >::follow(buf, 0) }; for i in 0..xs.len() { - let v = tab.get::>(fi2fo(i as flatbuffers::VOffsetT), None); + let v = unsafe { tab.get::>(fi2fo(i as flatbuffers::VOffsetT), None) }; assert_eq!(v, Some(&xs[i][..])); } } @@ -1669,10 +1577,10 @@ mod roundtrip_table { // use let buf = b.finished_data(); - let tab = >::follow(buf, 0); + let tab = unsafe { >::follow(buf, 0) }; for i in 0..vecs.len() { - let got = tab.get::>>(fi2fo(i as flatbuffers::VOffsetT), None); + let got = unsafe { tab.get::>>(fi2fo(i as flatbuffers::VOffsetT), None) }; assert!(got.is_some()); let got2 = got.unwrap(); let mut got3: Vec = Vec::with_capacity(got2.len()); @@ -1774,9 +1682,9 @@ mod roundtrip_push_follow_scalars { ($fn_name:ident, $ty:ident) => ( fn $fn_name(x: $ty) { let mut buf = vec![0u8; ::core::mem::size_of::<$ty>()]; - x.push(&mut buf[..], &[][..]); + unsafe { x.push(&mut buf[..], 0) }; let fs: flatbuffers::FollowStart<$ty> = flatbuffers::FollowStart::new(); - assert_eq!(fs.self_follow(&buf[..], 0), x); + assert_eq!(unsafe { fs.self_follow(&buf[..], 0) }, x); } ) } @@ -2120,7 +2028,7 @@ mod builder_asserts { struct foo { } impl<'b> flatbuffers::Push for &'b foo { type Output = foo; - fn push<'a>(&'a self, _dst: &'a mut [u8], _rest: &'a [u8]) { } + unsafe fn push<'a>(&'a self, _dst: &'a mut [u8], _written_len: usize) { } } let mut b = flatbuffers::FlatBufferBuilder::new(); b.push_slot_always(0, &foo{}); @@ -2173,18 +2081,17 @@ mod follow_impls { } } } - impl flatbuffers::SafeSliceAccess for FooStruct {} impl<'a> flatbuffers::Follow<'a> for FooStruct { type Inner = &'a FooStruct; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { <&'a FooStruct>::follow(buf, loc) } } impl<'a> flatbuffers::Follow<'a> for &'a FooStruct { type Inner = &'a FooStruct; #[inline(always)] - fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { flatbuffers::follow_cast_ref::(buf, loc) } } @@ -2193,88 +2100,67 @@ mod follow_impls { fn to_u8() { let vec: Vec = vec![255, 3]; let fs: flatbuffers::FollowStart = flatbuffers::FollowStart::new(); - assert_eq!(fs.self_follow(&vec[..], 1), 3); + assert_eq!(unsafe { fs.self_follow(&vec[..], 1) }, 3); } #[test] fn to_u16() { let vec: Vec = vec![255, 255, 3, 4]; let fs: flatbuffers::FollowStart = flatbuffers::FollowStart::new(); - assert_eq!(fs.self_follow(&vec[..], 2), 1027); + assert_eq!(unsafe { fs.self_follow(&vec[..], 2) }, 1027); } #[test] fn to_f32() { let vec: Vec = vec![255, 255, 255, 255, /* start of value */ 208, 15, 73, 64]; let fs: flatbuffers::FollowStart = flatbuffers::FollowStart::new(); - assert_eq!(fs.self_follow(&vec[..], 4), 3.14159); + assert_eq!(unsafe { fs.self_follow(&vec[..], 4) }, 3.14159); } #[test] fn to_string() { let vec: Vec = vec![255,255,255,255, 3, 0, 0, 0, 'f' as u8, 'o' as u8, 'o' as u8, 0]; let off: flatbuffers::FollowStart<&str> = flatbuffers::FollowStart::new(); - assert_eq!(off.self_follow(&vec[..], 4), "foo"); + assert_eq!(unsafe { off.self_follow(&vec[..], 4) }, "foo"); } #[test] fn to_byte_slice() { let vec: Vec = vec![255, 255, 255, 255, 4, 0, 0, 0, 1, 2, 3, 4]; let off: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3, 4][..]); - } - - #[test] - fn to_byte_vector() { - let vec: Vec = vec![255, 255, 255, 255, 4, 0, 0, 0, 1, 2, 3, 4]; - let off: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3, 4][..]); - } - - #[test] - fn to_byte_string_zero_teriminated() { - let vec: Vec = vec![255, 255, 255, 255, 3, 0, 0, 0, 1, 2, 3, 0]; - let off: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3][..]); + assert_eq!(unsafe { off.self_follow(&vec[..], 4).bytes() }, &[1, 2, 3, 4][..]); } #[test] fn to_vector_of_u16() { let vec: Vec = vec![255, 255, 255, 255, 2, 0, 0, 0, 1, 2, 3, 4]; let off: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - assert_eq!(off.self_follow(&vec[..], 4).len(), 2); - assert_eq!(off.self_follow(&vec[..], 4).get(0), 513); - assert_eq!(off.self_follow(&vec[..], 4).get(1), 1027); + assert_eq!(unsafe { off.self_follow(&vec[..], 4).len() }, 2); + assert_eq!(unsafe { off.self_follow(&vec[..], 4).get(0) }, 513); + assert_eq!(unsafe { off.self_follow(&vec[..], 4).get(1) }, 1027); } #[test] fn to_struct() { let vec: Vec = vec![255, 255, 255, 255, 1, 2, 3, 4]; let off: flatbuffers::FollowStart<&FooStruct> = flatbuffers::FollowStart::new(); - assert_eq!(*off.self_follow(&vec[..], 4), FooStruct::new(1, 2, 1027)); + assert_eq!(unsafe { *off.self_follow(&vec[..], 4) }, FooStruct::new(1, 2, 1027)); } #[test] fn to_vector_of_offset_to_string_elements() { let buf: Vec = vec![/* vec len */ 1, 0, 0, 0, /* offset to string */ 4, 0, 0, 0, /* str length */ 3, 0, 0, 0, 'f' as u8, 'o' as u8, 'o' as u8, 0]; let s: flatbuffers::FollowStart>> = flatbuffers::FollowStart::new(); - assert_eq!(s.self_follow(&buf[..], 0).len(), 1); - assert_eq!(s.self_follow(&buf[..], 0).get(0), "foo"); - } - - #[test] - fn to_slice_of_struct_elements() { - let buf: Vec = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4]; - let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - assert_eq!(fs.self_follow(&buf[..], 0).safe_slice(), &vec![FooStruct::new(1, 2, 1027)][..]); + assert_eq!(unsafe {s.self_follow(&buf[..], 0).len() }, 1); + assert_eq!(unsafe { s.self_follow(&buf[..], 0).get(0) }, "foo"); } #[test] fn to_vector_of_struct_elements() { let buf: Vec = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4]; let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - assert_eq!(fs.self_follow(&buf[..], 0).len(), 1); - assert_eq!(fs.self_follow(&buf[..], 0).get(0), &FooStruct::new(1, 2, 1027)); + assert_eq!(unsafe { fs.self_follow(&buf[..], 0).len() }, 1); + assert_eq!(unsafe { fs.self_follow(&buf[..], 0).get(0) }, &FooStruct::new(1, 2, 1027)); } #[test] @@ -2288,8 +2174,10 @@ mod follow_impls { // enter table 8, 0, 0, 0, // vtable location ]; - let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - assert_eq!(fs.self_follow(&buf[..], 0), flatbuffers::Table::new(&buf[..], 12)); + unsafe { + let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); + assert_eq!(fs.self_follow(&buf[..], 0), flatbuffers::Table::new(&buf[..], 12)); + } } #[test] @@ -2305,9 +2193,11 @@ mod follow_impls { 10, 0, 0, 0, // vtable location 0, 99 // value (with padding) ]; - let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - let tab = fs.self_follow(&buf[..], 0); - assert_eq!(tab.get::(fi2fo(0), Some(123)), Some(99)); + unsafe { + let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); + let tab = fs.self_follow(&buf[..], 0); + assert_eq!(tab.get::(fi2fo(0), Some(123)), Some(99)); + } } #[test] @@ -2321,9 +2211,11 @@ mod follow_impls { // enter table 8, 0, 0, 0, // vtable location ]; - let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - let tab = fs.self_follow(&buf[..], 0); - assert_eq!(tab.get::(fi2fo(0), Some(123)), Some(123)); + unsafe { + let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); + let tab = fs.self_follow(&buf[..], 0); + assert_eq!(tab.get::(fi2fo(0), Some(123)), Some(123)); + } } #[test] @@ -2338,9 +2230,11 @@ mod follow_impls { // enter table 10, 0, 0, 0, // vtable location ]; - let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); - let tab = fs.self_follow(&buf[..], 0); - assert_eq!(tab.get::(fi2fo(0), Some(123)), Some(123)); + unsafe { + let fs: flatbuffers::FollowStart> = flatbuffers::FollowStart::new(); + let tab = fs.self_follow(&buf[..], 0); + assert_eq!(tab.get::(fi2fo(0), Some(123)), Some(123)); + } } #[test] @@ -2360,15 +2254,17 @@ mod follow_impls { // enter string 3, 0, 0, 0, 109, 111, 111, 0 // string length and contents ]; - let tab = >::follow(&buf[..], 0); - assert_eq!(tab.get::>(fi2fo(0), None), Some("moo")); - let byte_vec = tab.get::>>(fi2fo(0), None).unwrap().safe_slice(); - assert_eq!(byte_vec, &vec![109, 111, 111][..]); - let v = tab.get::>>(fi2fo(0), None).unwrap(); - assert_eq!(v.len(), 3); - assert_eq!(v.get(0), 109); - assert_eq!(v.get(1), 111); - assert_eq!(v.get(2), 111); + unsafe { + let tab = >::follow(&buf[..], 0); + assert_eq!(tab.get::>(fi2fo(0), None), Some("moo")); + let byte_vec = tab.get::>>(fi2fo(0), None).unwrap().bytes(); + assert_eq!(byte_vec, &vec![109, 111, 111][..]); + let v = tab.get::>>(fi2fo(0), None).unwrap(); + assert_eq!(v.len(), 3); + assert_eq!(v.get(0), 109); + assert_eq!(v.get(1), 111); + assert_eq!(v.get(2), 111); + } } #[test] @@ -2382,20 +2278,23 @@ mod follow_impls { // enter table 8, 0, 0, 0, // vtable location ]; - let tab = >::follow(&buf[..], 0); - assert_eq!(tab.get::>(fi2fo(0), Some("abc")), Some("abc")); - #[cfg(target_endian = "little")] - { - assert_eq!(tab.get::>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..])); - } - let default_vec_buf: Vec = vec![3, 0, 0, 0, 70, 71, 72, 0]; - let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0); - let v = tab.get::>>(fi2fo(0), Some(default_vec)).unwrap(); - assert_eq!(v.len(), 3); - assert_eq!(v.get(0), 70); - assert_eq!(v.get(1), 71); - assert_eq!(v.get(2), 72); + unsafe { + let tab = >::follow(&buf[..], 0); + assert_eq!(tab.get::>(fi2fo(0), Some("abc")), Some("abc")); + #[cfg(target_endian = "little")] + { + assert_eq!(tab.get::>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..])); + } + + let default_vec_buf: Vec = vec![3, 0, 0, 0, 70, 71, 72, 0]; + let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0); + let v = tab.get::>>(fi2fo(0), Some(default_vec)).unwrap(); + assert_eq!(v.len(), 3); + assert_eq!(v.get(0), 70); + assert_eq!(v.get(1), 71); + assert_eq!(v.get(2), 72); + } } #[test] @@ -2410,20 +2309,22 @@ mod follow_impls { // enter table 10, 0, 0, 0, // vtable location ]; - let tab = >::follow(&buf[..], 0); - assert_eq!(tab.get::>(fi2fo(0), Some("abc")), Some("abc")); - #[cfg(target_endian = "little")] - { - assert_eq!(tab.get::>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..])); - } + unsafe { + let tab = >::follow(&buf[..], 0); + assert_eq!(tab.get::>(fi2fo(0), Some("abc")), Some("abc")); + #[cfg(target_endian = "little")] + { + assert_eq!(tab.get::>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..])); + } - let default_vec_buf: Vec = vec![3, 0, 0, 0, 70, 71, 72, 0]; - let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0); - let v = tab.get::>>(fi2fo(0), Some(default_vec)).unwrap(); - assert_eq!(v.len(), 3); - assert_eq!(v.get(0), 70); - assert_eq!(v.get(1), 71); - assert_eq!(v.get(2), 72); + let default_vec_buf: Vec = vec![3, 0, 0, 0, 70, 71, 72, 0]; + let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0); + let v = tab.get::>>(fi2fo(0), Some(default_vec)).unwrap(); + assert_eq!(v.len(), 3); + assert_eq!(v.get(0), 70); + assert_eq!(v.get(1), 71); + assert_eq!(v.get(2), 72); + } } } @@ -2923,10 +2824,8 @@ mod byte_layouts { assert_eq!(::core::mem::size_of::(), 16); impl<'b> flatbuffers::Push for &'b foo { type Output = foo; - fn push<'a>(&'a self, dst: &'a mut [u8], _rest: &'a [u8]) { - let src = unsafe { - ::core::slice::from_raw_parts(*self as *const foo as *const u8, ::core::mem::size_of::()) - }; + unsafe fn push<'a>(&'a self, dst: &'a mut [u8], _written_len: usize) { + let src = ::core::slice::from_raw_parts(*self as *const foo as *const u8, ::core::mem::size_of::()); dst.copy_from_slice(src); } }