From aff818cebfbf998288ebb448ec9d564b03180cd9 Mon Sep 17 00:00:00 2001 From: Marcin Witkowski Date: Thu, 20 Jan 2022 17:49:02 +0100 Subject: [PATCH] rust: Allow for usage in no_std environment (#6989) --- rust/flatbuffers/Cargo.toml | 10 ++++-- rust/flatbuffers/src/array.rs | 6 ++-- rust/flatbuffers/src/builder.rs | 12 ++++--- rust/flatbuffers/src/endian_scalar.rs | 2 +- rust/flatbuffers/src/follow.rs | 2 +- rust/flatbuffers/src/lib.rs | 5 +++ rust/flatbuffers/src/primitives.rs | 6 ++-- rust/flatbuffers/src/push.rs | 4 +-- rust/flatbuffers/src/vector.rs | 12 +++---- rust/flatbuffers/src/verifier.rs | 36 +++++++++++-------- rust/flatbuffers/src/vtable_writer.rs | 2 +- tests/RustTest.sh | 2 ++ tests/rust_usage_test/Cargo.toml | 7 +++- .../rust_usage_test/tests/integration_test.rs | 4 +++ 14 files changed, 70 insertions(+), 40 deletions(-) diff --git a/rust/flatbuffers/Cargo.toml b/rust/flatbuffers/Cargo.toml index b3114bd76..ebe8a8802 100644 --- a/rust/flatbuffers/Cargo.toml +++ b/rust/flatbuffers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flatbuffers" -version = "2.0.0" +version = "2.1.0" edition = "2018" authors = ["Robert Winslow ", "FlatBuffers Maintainers"] license = "Apache-2.0" @@ -11,7 +11,13 @@ keywords = ["flatbuffers", "serialization", "zero-copy"] categories = ["encoding", "data-structures", "memory-management"] rust = "1.51" +[features] +default = ["thiserror"] +no_std = ["core2", "thiserror_core2"] + [dependencies] smallvec = "1.6.1" bitflags = "1.2.1" -thiserror = "1.0.23" +thiserror = { version = "1.0.23", optional = true } +core2 = { version = "0.3.3", optional = true } +thiserror_core2 = { git = "https://github.com/antmicro/thiserror-core2.git", branch = "remaining-errors", optional = true } diff --git a/rust/flatbuffers/src/array.rs b/rust/flatbuffers/src/array.rs index f00a56036..3765a5fcf 100644 --- a/rust/flatbuffers/src/array.rs +++ b/rust/flatbuffers/src/array.rs @@ -17,9 +17,9 @@ use crate::follow::Follow; use crate::vector::VectorIter; use crate::EndianScalar; -use std::fmt::{Debug, Formatter, Result}; -use std::marker::PhantomData; -use std::mem::size_of; +use core::fmt::{Debug, Formatter, Result}; +use core::marker::PhantomData; +use core::mem::size_of; #[derive(Copy, Clone)] pub struct Array<'a, T: 'a, const N: usize>(&'a [u8], PhantomData); diff --git a/rust/flatbuffers/src/builder.rs b/rust/flatbuffers/src/builder.rs index 930987711..8a8b58cf0 100644 --- a/rust/flatbuffers/src/builder.rs +++ b/rust/flatbuffers/src/builder.rs @@ -16,11 +16,13 @@ extern crate smallvec; -use std::cmp::max; -use std::iter::{DoubleEndedIterator, ExactSizeIterator}; -use std::marker::PhantomData; -use std::ptr::write_bytes; -use std::slice::from_raw_parts; +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::primitives::*; diff --git a/rust/flatbuffers/src/endian_scalar.rs b/rust/flatbuffers/src/endian_scalar.rs index 7e8d8e3e4..5f50cf1f3 100644 --- a/rust/flatbuffers/src/endian_scalar.rs +++ b/rust/flatbuffers/src/endian_scalar.rs @@ -15,7 +15,7 @@ */ #![allow(clippy::wrong_self_convention)] -use std::mem::size_of; +use core::mem::size_of; /// 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 diff --git a/rust/flatbuffers/src/follow.rs b/rust/flatbuffers/src/follow.rs index a09003d7d..d1d6483ae 100644 --- a/rust/flatbuffers/src/follow.rs +++ b/rust/flatbuffers/src/follow.rs @@ -14,7 +14,7 @@ * limitations under the License. */ -use std::marker::PhantomData; +use core::marker::PhantomData; /// Follow is a trait that allows us to access FlatBuffers in a declarative, /// type safe, and fast way. They compile down to almost no code (after diff --git a/rust/flatbuffers/src/lib.rs b/rust/flatbuffers/src/lib.rs index 465e16906..bc114e664 100644 --- a/rust/flatbuffers/src/lib.rs +++ b/rust/flatbuffers/src/lib.rs @@ -28,6 +28,11 @@ //! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: //! (On OSX, you can install FlatBuffers from `HEAD` with the Homebrew package manager.) +#![cfg_attr(feature = "no_std", no_std)] + +#[cfg(feature = "no_std")] +extern crate alloc; + mod array; mod builder; mod endian_scalar; diff --git a/rust/flatbuffers/src/primitives.rs b/rust/flatbuffers/src/primitives.rs index b7b4942d6..72764b213 100644 --- a/rust/flatbuffers/src/primitives.rs +++ b/rust/flatbuffers/src/primitives.rs @@ -14,9 +14,9 @@ * limitations under the License. */ -use std::marker::PhantomData; -use std::mem::size_of; -use std::ops::Deref; +use core::marker::PhantomData; +use core::mem::size_of; +use core::ops::Deref; use crate::endian_scalar::{emplace_scalar, read_scalar, read_scalar_at}; use crate::follow::Follow; diff --git a/rust/flatbuffers/src/push.rs b/rust/flatbuffers/src/push.rs index 72ff88cd7..8bb8fe9a7 100644 --- a/rust/flatbuffers/src/push.rs +++ b/rust/flatbuffers/src/push.rs @@ -14,8 +14,8 @@ * limitations under the License. */ -use std::cmp::max; -use std::mem::{align_of, size_of}; +use core::cmp::max; +use core::mem::{align_of, size_of}; use crate::endian_scalar::emplace_scalar; diff --git a/rust/flatbuffers/src/vector.rs b/rust/flatbuffers/src/vector.rs index 0f29e6b60..eb6dd15e2 100644 --- a/rust/flatbuffers/src/vector.rs +++ b/rust/flatbuffers/src/vector.rs @@ -14,12 +14,12 @@ * limitations under the License. */ -use std::fmt::{Debug, Formatter, Result}; -use std::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator}; -use std::marker::PhantomData; -use std::mem::size_of; -use std::slice::from_raw_parts; -use std::str::from_utf8_unchecked; +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::str::from_utf8_unchecked; use crate::endian_scalar::read_scalar_at; #[cfg(target_endian = "little")] diff --git a/rust/flatbuffers/src/verifier.rs b/rust/flatbuffers/src/verifier.rs index 12a02f965..d5e31df5d 100644 --- a/rust/flatbuffers/src/verifier.rs +++ b/rust/flatbuffers/src/verifier.rs @@ -1,6 +1,12 @@ +#[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}; -use std::ops::Range; + +#[cfg(feature="no_std")] +extern crate thiserror_core2 as thiserror; use thiserror::Error; /// Traces the location of data errors. Not populated for Dos detecting errors. @@ -23,7 +29,7 @@ pub enum ErrorTraceDetail { } #[derive(PartialEq, Eq, Default, Debug, Clone)] pub struct ErrorTrace(Vec); -impl std::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace { +impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace { #[inline] fn as_ref(&self) -> &[ErrorTraceDetail] { &self.0 @@ -51,7 +57,7 @@ pub enum InvalidFlatbuffer { #[error("Utf8 error for string in {range:?}: {error}\n{error_trace}")] Utf8Error { #[source] - error: std::str::Utf8Error, + error: core::str::Utf8Error, range: Range, error_trace: ErrorTrace, }, @@ -90,8 +96,8 @@ pub enum InvalidFlatbuffer { DepthLimitReached, } -impl std::fmt::Display for ErrorTrace { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Display for ErrorTrace { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { use ErrorTraceDetail::*; for e in self.0.iter() { match e { @@ -125,7 +131,7 @@ impl std::fmt::Display for ErrorTrace { } } -pub type Result = std::prelude::v1::Result; +pub type Result = core::result::Result; impl InvalidFlatbuffer { fn new_range_oob(start: usize, end: usize) -> Result { @@ -245,11 +251,11 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> { /// `buffer[0]`. TODO(caspern). #[inline] fn is_aligned(&self, pos: usize) -> Result<()> { - if pos % std::mem::align_of::() == 0 { + if pos % core::mem::align_of::() == 0 { Ok(()) } else { Err(InvalidFlatbuffer::Unaligned { - unaligned_type: std::any::type_name::(), + unaligned_type: core::any::type_name::(), position: pos, error_trace: Default::default(), }) @@ -271,7 +277,7 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> { #[inline] pub fn in_buffer(&mut self, pos: usize) -> Result<()> { self.is_aligned::(pos)?; - self.range_in_buffer(pos, std::mem::size_of::()) + self.range_in_buffer(pos, core::mem::size_of::()) } #[inline] fn get_u16(&mut self, pos: usize) -> Result { @@ -416,7 +422,7 @@ impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> { where Key: Follow<'buf> + Verifiable, UnionVerifier: - (std::ops::FnOnce(>::Inner, &mut Verifier, usize) -> Result<()>), + (core::ops::FnOnce(>::Inner, &mut Verifier, usize) -> Result<()>), // NOTE: >::Inner == Key { // TODO(caspern): how to trace vtable errors? @@ -468,14 +474,14 @@ impl Verifiable for ForwardsUOffset { } /// Checks and returns the range containing the flatbuffers vector. -fn verify_vector_range(v: &mut Verifier, pos: usize) -> Result> { +fn verify_vector_range(v: &mut Verifier, pos: usize) -> Result> { let len = v.get_uoffset(pos)? as usize; let start = pos.saturating_add(SIZE_UOFFSET); v.is_aligned::(start)?; - let size = len.saturating_mul(std::mem::size_of::()); + let size = len.saturating_mul(core::mem::size_of::()); let end = start.saturating_add(size); v.range_in_buffer(start, size)?; - Ok(std::ops::Range { start, end }) + Ok(core::ops::Range { start, end }) } pub trait SimpleToVerifyInSlice {} @@ -509,7 +515,7 @@ impl Verifiable for Vector<'_, ForwardsUOffset> { #[inline] fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()> { let range = verify_vector_range::>(v, pos)?; - let size = std::mem::size_of::>(); + let size = core::mem::size_of::>(); for (i, element_pos) in range.step_by(size).enumerate() { trace_elem( >::run_verifier(v, element_pos), @@ -526,7 +532,7 @@ impl<'a> Verifiable for &'a str { fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()> { let range = verify_vector_range::(v, pos)?; let has_null_terminator = v.buffer.get(range.end).map(|&b| b == 0).unwrap_or(false); - let s = std::str::from_utf8(&v.buffer[range.clone()]); + let s = core::str::from_utf8(&v.buffer[range.clone()]); if let Err(error) = s { return Err(InvalidFlatbuffer::Utf8Error { error, diff --git a/rust/flatbuffers/src/vtable_writer.rs b/rust/flatbuffers/src/vtable_writer.rs index 92e8522eb..9b61dac7f 100644 --- a/rust/flatbuffers/src/vtable_writer.rs +++ b/rust/flatbuffers/src/vtable_writer.rs @@ -14,7 +14,7 @@ * limitations under the License. */ -use std::ptr::write_bytes; +use core::ptr::write_bytes; use crate::endian_scalar::emplace_scalar; use crate::primitives::*; diff --git a/tests/RustTest.sh b/tests/RustTest.sh index 7a7894ad6..d2dd229f4 100755 --- a/tests/RustTest.sh +++ b/tests/RustTest.sh @@ -35,6 +35,8 @@ cd ./rust_usage_test cargo test $TARGET_FLAG -- --quiet check_test_result "Rust tests" +cargo test $TARGET_FLAG --no-default-features --features no_std -- --quiet +check_test_result "Rust tests (no_std)" cargo run $TARGET_FLAG --bin=flatbuffers_alloc_check check_test_result "Rust flatbuffers heap alloc test" diff --git a/tests/rust_usage_test/Cargo.toml b/tests/rust_usage_test/Cargo.toml index 22b259084..47a83388a 100644 --- a/tests/rust_usage_test/Cargo.toml +++ b/tests/rust_usage_test/Cargo.toml @@ -6,11 +6,16 @@ authors = ["Robert Winslow ", "FlatBuffers Maintainers"] [dependencies] -flatbuffers = { path = "../../rust/flatbuffers" } +flatbuffers = { path = "../../rust/flatbuffers", default-features = false } flexbuffers = { path = "../../rust/flexbuffers" } serde_derive = "1.0" serde = "1.0" serde_bytes = "0.11" +libc_alloc = { version = "1.0.3", optional = true } + +[features] +default = ["flatbuffers/default"] +no_std = ["flatbuffers/no_std", "libc_alloc"] [[bin]] name = "monster_example" diff --git a/tests/rust_usage_test/tests/integration_test.rs b/tests/rust_usage_test/tests/integration_test.rs index 49c0390d2..de4c09264 100644 --- a/tests/rust_usage_test/tests/integration_test.rs +++ b/tests/rust_usage_test/tests/integration_test.rs @@ -15,6 +15,10 @@ * limitations under the License. */ +#[cfg(feature = "no_std")] +#[global_allocator] +static ALLOCATOR: libc_alloc::LibcAlloc = libc_alloc::LibcAlloc; + #[macro_use] #[cfg(not(miri))] // slow. extern crate quickcheck;