rust: Allow for usage in no_std environment (#6989)

This commit is contained in:
Marcin Witkowski 2022-01-20 17:49:02 +01:00 committed by GitHub
parent d7b75417fc
commit aff818cebf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 70 additions and 40 deletions

View 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 }

View 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>);

View File

@ -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::*;

View 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

View 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

View File

@ -28,6 +28,11 @@
//! 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;

View 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;

View 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;

View File

@ -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")]

View 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,

View 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::*;

View File

@ -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"

View 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"

View File

@ -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;