rust: Allow for usage in no_std environment (#6989)
authorMarcin Witkowski <marwit97@gmail.com>
Thu, 20 Jan 2022 16:49:02 +0000 (17:49 +0100)
committerGitHub <noreply@github.com>
Thu, 20 Jan 2022 16:49:02 +0000 (11:49 -0500)
14 files changed:
rust/flatbuffers/Cargo.toml
rust/flatbuffers/src/array.rs
rust/flatbuffers/src/builder.rs
rust/flatbuffers/src/endian_scalar.rs
rust/flatbuffers/src/follow.rs
rust/flatbuffers/src/lib.rs
rust/flatbuffers/src/primitives.rs
rust/flatbuffers/src/push.rs
rust/flatbuffers/src/vector.rs
rust/flatbuffers/src/verifier.rs
rust/flatbuffers/src/vtable_writer.rs
tests/RustTest.sh
tests/rust_usage_test/Cargo.toml
tests/rust_usage_test/tests/integration_test.rs

index b3114bd..ebe8a88 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "flatbuffers"
-version = "2.0.0"
+version = "2.1.0"
 edition = "2018"
 authors = ["Robert Winslow <hello@rwinslow.com>", "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 }
index f00a560..3765a5f 100644 (file)
@@ -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<T>);
index 9309877..8a8b58c 100644 (file)
 
 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::*;
index 7e8d8e3..5f50cf1 100644 (file)
@@ -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
index a09003d..d1d6483 100644 (file)
@@ -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
index 465e169..bc114e6 100644 (file)
 //! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: <https://github.com/google/flatbuffers>
 //! (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;
index b7b4942..72764b2 100644 (file)
@@ -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;
index 72ff88c..8bb8fe9 100644 (file)
@@ -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;
 
index 0f29e6b..eb6dd15 100644 (file)
  * 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")]
index 12a02f9..d5e31df 100644 (file)
@@ -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<ErrorTraceDetail>);
-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<usize>,
         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<T> = std::prelude::v1::Result<T, InvalidFlatbuffer>;
+pub type Result<T> = core::result::Result<T, InvalidFlatbuffer>;
 
 impl InvalidFlatbuffer {
     fn new_range_oob<T>(start: usize, end: usize) -> Result<T> {
@@ -245,11 +251,11 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
     /// `buffer[0]`. TODO(caspern).
     #[inline]
     fn is_aligned<T>(&self, pos: usize) -> Result<()> {
-        if pos % std::mem::align_of::<T>() == 0 {
+        if pos % core::mem::align_of::<T>() == 0 {
             Ok(())
         } else {
             Err(InvalidFlatbuffer::Unaligned {
-                unaligned_type: std::any::type_name::<T>(),
+                unaligned_type: core::any::type_name::<T>(),
                 position: pos,
                 error_trace: Default::default(),
             })
@@ -271,7 +277,7 @@ impl<'opts, 'buf> Verifier<'opts, 'buf> {
     #[inline]
     pub fn in_buffer<T>(&mut self, pos: usize) -> Result<()> {
         self.is_aligned::<T>(pos)?;
-        self.range_in_buffer(pos, std::mem::size_of::<T>())
+        self.range_in_buffer(pos, core::mem::size_of::<T>())
     }
     #[inline]
     fn get_u16(&mut self, pos: usize) -> Result<u16> {
@@ -416,7 +422,7 @@ impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
     where
         Key: Follow<'buf> + Verifiable,
         UnionVerifier:
-            (std::ops::FnOnce(<Key as Follow<'buf>>::Inner, &mut Verifier, usize) -> Result<()>),
+            (core::ops::FnOnce(<Key as Follow<'buf>>::Inner, &mut Verifier, usize) -> Result<()>),
         // NOTE: <Key as Follow<'buf>>::Inner == Key
     {
         // TODO(caspern): how to trace vtable errors?
@@ -468,14 +474,14 @@ impl<T: Verifiable> Verifiable for ForwardsUOffset<T> {
 }
 
 /// Checks and returns the range containing the flatbuffers vector.
-fn verify_vector_range<T>(v: &mut Verifier, pos: usize) -> Result<std::ops::Range<usize>> {
+fn verify_vector_range<T>(v: &mut Verifier, pos: usize) -> Result<core::ops::Range<usize>> {
     let len = v.get_uoffset(pos)? as usize;
     let start = pos.saturating_add(SIZE_UOFFSET);
     v.is_aligned::<T>(start)?;
-    let size = len.saturating_mul(std::mem::size_of::<T>());
+    let size = len.saturating_mul(core::mem::size_of::<T>());
     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<T: Verifiable> Verifiable for Vector<'_, ForwardsUOffset<T>> {
     #[inline]
     fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()> {
         let range = verify_vector_range::<ForwardsUOffset<T>>(v, pos)?;
-        let size = std::mem::size_of::<ForwardsUOffset<T>>();
+        let size = core::mem::size_of::<ForwardsUOffset<T>>();
         for (i, element_pos) in range.step_by(size).enumerate() {
             trace_elem(
                 <ForwardsUOffset<T>>::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::<u8>(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,
index 92e8522..9b61dac 100644 (file)
@@ -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::*;
index 7a7894a..d2dd229 100755 (executable)
@@ -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"
index 22b2590..47a8338 100644 (file)
@@ -6,11 +6,16 @@ authors = ["Robert Winslow <hello@rwinslow.com>",
            "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"
index 49c0390..de4c092 100644 (file)
  * 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;