rust: Allow for usage in no_std environment (#6989)
This commit is contained in:
parent
d7b75417fc
commit
aff818cebf
|
@ -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 }
|
||||
|
|
|
@ -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>);
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue