forked from BigfootDev/flatbuffers
* Fix nightly no_std * Fix nightly no_std
This commit is contained in:
@@ -12,14 +12,13 @@ categories = ["encoding", "data-structures", "memory-management"]
|
||||
rust = "1.51"
|
||||
|
||||
[features]
|
||||
default = ["thiserror"]
|
||||
no_std = ["core2", "thiserror_core2"]
|
||||
default = ["std"]
|
||||
std = []
|
||||
serialize = ["serde"]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.2.1"
|
||||
serde = { version = "1.0", optional = true }
|
||||
thiserror = { version = "1.0.30", optional = true }
|
||||
core2 = { version = "0.4.0", optional = true }
|
||||
# This version is compliant with mainline 1.0.30
|
||||
thiserror_core2 = { version = "2.0.0", default-features = false, optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.4.0"
|
||||
|
||||
12
rust/flatbuffers/build.rs
Normal file
12
rust/flatbuffers/build.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use rustc_version::{version_meta, Channel};
|
||||
|
||||
fn main() {
|
||||
let version_meta = version_meta().unwrap();
|
||||
|
||||
// To use nightly features we declare this and then we can use
|
||||
// #[cfg(nightly)]
|
||||
// for nightly only features
|
||||
if version_meta.channel == Channel::Nightly {
|
||||
println!("cargo:rustc-cfg=nightly")
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#[cfg(feature = "no_std")]
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{vec, vec::Vec};
|
||||
use core::cmp::max;
|
||||
use core::iter::{DoubleEndedIterator, ExactSizeIterator};
|
||||
|
||||
@@ -28,9 +28,10 @@
|
||||
//! 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_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(all(nightly, not(feature = "std")), feature(error_in_core))]
|
||||
|
||||
#[cfg(feature = "no_std")]
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
mod array;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use crate::follow::Follow;
|
||||
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
|
||||
#[cfg(feature = "no_std")]
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
use core::ops::Range;
|
||||
use core::option::Option;
|
||||
|
||||
#[cfg(not(feature = "no_std"))]
|
||||
use thiserror::Error;
|
||||
#[cfg(feature = "no_std")]
|
||||
use thiserror_core2::Error;
|
||||
#[cfg(all(nightly, not(feature = "std")))]
|
||||
use core::error::Error;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
|
||||
/// Traces the location of data errors. Not populated for Dos detecting errors.
|
||||
/// Useful for MissingRequiredField and Utf8Error in particular, though
|
||||
@@ -41,64 +41,138 @@ impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
|
||||
|
||||
/// Describes how a flatuffer is invalid and, for data errors, roughly where. No extra tracing
|
||||
/// information is given for DoS detecting errors since it will probably be a lot.
|
||||
#[derive(Clone, Error, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum InvalidFlatbuffer {
|
||||
#[error("Missing required field `{required}`.\n{error_trace}")]
|
||||
MissingRequiredField {
|
||||
required: &'static str,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error(
|
||||
"Union exactly one of union discriminant (`{field_type}`) and value \
|
||||
(`{field}`) are present.\n{error_trace}"
|
||||
)]
|
||||
InconsistentUnion {
|
||||
field: &'static str,
|
||||
field_type: &'static str,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error("Utf8 error for string in {range:?}: {error}\n{error_trace}")]
|
||||
Utf8Error {
|
||||
#[source]
|
||||
error: core::str::Utf8Error,
|
||||
range: Range<usize>,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error("String in range [{}, {}) is missing its null terminator.\n{error_trace}",
|
||||
range.start, range.end)]
|
||||
MissingNullTerminator {
|
||||
range: Range<usize>,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error("Type `{unaligned_type}` at position {position} is unaligned.\n{error_trace}")]
|
||||
Unaligned {
|
||||
position: usize,
|
||||
unaligned_type: &'static str,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error("Range [{}, {}) is out of bounds.\n{error_trace}", range.start, range.end)]
|
||||
RangeOutOfBounds {
|
||||
range: Range<usize>,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
#[error(
|
||||
"Signed offset at position {position} has value {soffset} which points out of bounds.\
|
||||
\n{error_trace}"
|
||||
)]
|
||||
SignedOffsetOutOfBounds {
|
||||
soffset: SOffsetT,
|
||||
position: usize,
|
||||
error_trace: ErrorTrace,
|
||||
},
|
||||
// Dos detecting errors. These do not get error traces since it will probably be very large.
|
||||
#[error("Too many tables.")]
|
||||
TooManyTables,
|
||||
#[error("Apparent size too large.")]
|
||||
ApparentSizeTooLarge,
|
||||
#[error("Nested table depth limit reached.")]
|
||||
DepthLimitReached,
|
||||
}
|
||||
|
||||
#[cfg(any(nightly, feature = "std"))]
|
||||
impl Error for InvalidFlatbuffer {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
if let InvalidFlatbuffer::Utf8Error { error: source, .. } = self {
|
||||
Some(source)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for InvalidFlatbuffer {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
match self {
|
||||
InvalidFlatbuffer::MissingRequiredField {
|
||||
required,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(f, "Missing required field `{}`.\n{}", required, error_trace)?;
|
||||
}
|
||||
InvalidFlatbuffer::InconsistentUnion {
|
||||
field,
|
||||
field_type,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"Exactly one of union discriminant (`{}`) and value (`{}`) are present.\n{}",
|
||||
field_type, field, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::Utf8Error {
|
||||
error,
|
||||
range,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"Utf8 error for string in {:?}: {}\n{}",
|
||||
range, error, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::MissingNullTerminator { range, error_trace } => {
|
||||
writeln!(
|
||||
f,
|
||||
"String in range [{}, {}) is missing its null terminator.\n{}",
|
||||
range.start, range.end, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::Unaligned {
|
||||
position,
|
||||
unaligned_type,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"Type `{}` at position {} is unaligned.\n{}",
|
||||
unaligned_type, position, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::RangeOutOfBounds { range, error_trace } => {
|
||||
writeln!(
|
||||
f,
|
||||
"Range [{}, {}) is out of bounds.\n{}",
|
||||
range.start, range.end, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::SignedOffsetOutOfBounds {
|
||||
soffset,
|
||||
position,
|
||||
error_trace,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"Signed offset at position {} has value {} which points out of bounds.\n{}",
|
||||
position, soffset, error_trace
|
||||
)?;
|
||||
}
|
||||
InvalidFlatbuffer::TooManyTables {} => {
|
||||
writeln!(f, "Too many tables.")?;
|
||||
}
|
||||
InvalidFlatbuffer::ApparentSizeTooLarge {} => {
|
||||
writeln!(f, "Apparent size too large.")?;
|
||||
}
|
||||
InvalidFlatbuffer::DepthLimitReached {} => {
|
||||
writeln!(f, "Nested table depth limit reached.")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for ErrorTrace {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
use ErrorTraceDetail::*;
|
||||
|
||||
@@ -21,3 +21,10 @@ cargo run --bin=flatbuffers_alloc_check || exit /b 1
|
||||
cargo run --bin=flexbuffers_alloc_check || exit /b 1
|
||||
cargo run --bin=monster_example || exit /b 1
|
||||
cd ..
|
||||
|
||||
cd rust_no_std_compilation_test
|
||||
rustup install nightly
|
||||
rustup component add rust-src --toolchain nightly
|
||||
rustup target add thumbv7m-none-eabi
|
||||
cargo build || exit /b 1
|
||||
cd ..
|
||||
|
||||
@@ -35,11 +35,18 @@ cd ./rust_serialize_test
|
||||
cargo run $TARGET_FLAG -- --quiet
|
||||
check_test_result "Rust serde tests"
|
||||
|
||||
cd ../rust_no_std_compilation_test
|
||||
rustup install nightly
|
||||
rustup component add rust-src --toolchain nightly
|
||||
rustup target add thumbv7m-none-eabi
|
||||
cargo +nightly build
|
||||
check_test_result "Rust flatbuffers test no_std compilation"
|
||||
|
||||
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
|
||||
cargo test $TARGET_FLAG --no-default-features -- --quiet
|
||||
check_test_result "Rust tests (no_std)"
|
||||
|
||||
cargo run $TARGET_FLAG --bin=flatbuffers_alloc_check
|
||||
|
||||
5
tests/rust_no_std_compilation_test/.cargo/config.toml
Normal file
5
tests/rust_no_std_compilation_test/.cargo/config.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
||||
|
||||
[unstable]
|
||||
build-std = ["core", "alloc"]
|
||||
13
tests/rust_no_std_compilation_test/Cargo.toml
Normal file
13
tests/rust_no_std_compilation_test/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "rust_test_no_std_compilation"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
flatbuffers = { path = "../../rust/flatbuffers", default-features = false }
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
34
tests/rust_no_std_compilation_test/src/main.rs
Normal file
34
tests/rust_no_std_compilation_test/src/main.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(default_alloc_error_handler)]
|
||||
|
||||
// Include flatbuffers purely to check that it compiles in a no_std binary
|
||||
#[allow(unused_imports)]
|
||||
use flatbuffers;
|
||||
|
||||
// The rest is just no_std boilerplate
|
||||
|
||||
use core::alloc::{GlobalAlloc, Layout};
|
||||
|
||||
struct NullAllocator;
|
||||
unsafe impl GlobalAlloc for NullAllocator {
|
||||
unsafe fn alloc(&self, _lt: Layout) -> *mut u8 {
|
||||
core::ptr::null_mut()
|
||||
}
|
||||
unsafe fn dealloc(&self, _ptr: *mut u8, _lt: Layout) {
|
||||
panic!("won't deallocate: we never allocated!");
|
||||
}
|
||||
}
|
||||
|
||||
#[global_allocator]
|
||||
static A: NullAllocator = NullAllocator;
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 {
|
||||
0
|
||||
}
|
||||
@@ -16,7 +16,7 @@ libc_alloc = { version = "1.0.3", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["flatbuffers/default"]
|
||||
no_std = ["flatbuffers/no_std", "libc_alloc"]
|
||||
no_std = ["libc_alloc"]
|
||||
|
||||
[[bin]]
|
||||
name = "monster_example"
|
||||
|
||||
Reference in New Issue
Block a user