Skip to content

Commit 5792623

Browse files
authored
Rust fix compilation for no_std targets #2 (#7553)
* Fix nightly no_std * Fix nightly no_std
1 parent 0edb275 commit 5792623

File tree

11 files changed

+187
-35
lines changed

11 files changed

+187
-35
lines changed

rust/flatbuffers/Cargo.toml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@ categories = ["encoding", "data-structures", "memory-management"]
1212
rust = "1.51"
1313

1414
[features]
15-
default = ["thiserror"]
16-
no_std = ["core2", "thiserror_core2"]
15+
default = ["std"]
16+
std = []
1717
serialize = ["serde"]
1818

1919
[dependencies]
2020
bitflags = "1.2.1"
2121
serde = { version = "1.0", optional = true }
22-
thiserror = { version = "1.0.30", optional = true }
23-
core2 = { version = "0.4.0", optional = true }
24-
# This version is compliant with mainline 1.0.30
25-
thiserror_core2 = { version = "2.0.0", default-features = false, optional = true }
22+
23+
[build-dependencies]
24+
rustc_version = "0.4.0"

rust/flatbuffers/build.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use rustc_version::{version_meta, Channel};
2+
3+
fn main() {
4+
let version_meta = version_meta().unwrap();
5+
6+
// To use nightly features we declare this and then we can use
7+
// #[cfg(nightly)]
8+
// for nightly only features
9+
if version_meta.channel == Channel::Nightly {
10+
println!("cargo:rustc-cfg=nightly")
11+
}
12+
}

rust/flatbuffers/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
#[cfg(feature = "no_std")]
17+
#[cfg(not(feature = "std"))]
1818
use alloc::{vec, vec::Vec};
1919
use core::cmp::max;
2020
use core::iter::{DoubleEndedIterator, ExactSizeIterator};

rust/flatbuffers/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
//! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: <https://github.com/google/flatbuffers>
2929
//! (On OSX, you can install FlatBuffers from `HEAD` with the Homebrew package manager.)
3030
31-
#![cfg_attr(feature = "no_std", no_std)]
31+
#![cfg_attr(not(feature = "std"), no_std)]
32+
#![cfg_attr(all(nightly, not(feature = "std")), feature(error_in_core))]
3233

33-
#[cfg(feature = "no_std")]
34+
#[cfg(not(feature = "std"))]
3435
extern crate alloc;
3536

3637
mod array;

rust/flatbuffers/src/verifier.rs

Lines changed: 98 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
use crate::follow::Follow;
22
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
3-
#[cfg(feature = "no_std")]
3+
#[cfg(not(feature = "std"))]
44
use alloc::vec::Vec;
55
use core::ops::Range;
66
use core::option::Option;
77

8-
#[cfg(not(feature = "no_std"))]
9-
use thiserror::Error;
10-
#[cfg(feature = "no_std")]
11-
use thiserror_core2::Error;
8+
#[cfg(all(nightly, not(feature = "std")))]
9+
use core::error::Error;
10+
#[cfg(feature = "std")]
11+
use std::error::Error;
1212

1313
/// Traces the location of data errors. Not populated for Dos detecting errors.
1414
/// Useful for MissingRequiredField and Utf8Error in particular, though
@@ -41,64 +41,138 @@ impl core::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
4141

4242
/// Describes how a flatuffer is invalid and, for data errors, roughly where. No extra tracing
4343
/// information is given for DoS detecting errors since it will probably be a lot.
44-
#[derive(Clone, Error, Debug, PartialEq, Eq)]
44+
#[derive(Clone, Debug, PartialEq, Eq)]
4545
pub enum InvalidFlatbuffer {
46-
#[error("Missing required field `{required}`.\n{error_trace}")]
4746
MissingRequiredField {
4847
required: &'static str,
4948
error_trace: ErrorTrace,
5049
},
51-
#[error(
52-
"Union exactly one of union discriminant (`{field_type}`) and value \
53-
(`{field}`) are present.\n{error_trace}"
54-
)]
5550
InconsistentUnion {
5651
field: &'static str,
5752
field_type: &'static str,
5853
error_trace: ErrorTrace,
5954
},
60-
#[error("Utf8 error for string in {range:?}: {error}\n{error_trace}")]
6155
Utf8Error {
62-
#[source]
6356
error: core::str::Utf8Error,
6457
range: Range<usize>,
6558
error_trace: ErrorTrace,
6659
},
67-
#[error("String in range [{}, {}) is missing its null terminator.\n{error_trace}",
68-
range.start, range.end)]
6960
MissingNullTerminator {
7061
range: Range<usize>,
7162
error_trace: ErrorTrace,
7263
},
73-
#[error("Type `{unaligned_type}` at position {position} is unaligned.\n{error_trace}")]
7464
Unaligned {
7565
position: usize,
7666
unaligned_type: &'static str,
7767
error_trace: ErrorTrace,
7868
},
79-
#[error("Range [{}, {}) is out of bounds.\n{error_trace}", range.start, range.end)]
8069
RangeOutOfBounds {
8170
range: Range<usize>,
8271
error_trace: ErrorTrace,
8372
},
84-
#[error(
85-
"Signed offset at position {position} has value {soffset} which points out of bounds.\
86-
\n{error_trace}"
87-
)]
8873
SignedOffsetOutOfBounds {
8974
soffset: SOffsetT,
9075
position: usize,
9176
error_trace: ErrorTrace,
9277
},
9378
// Dos detecting errors. These do not get error traces since it will probably be very large.
94-
#[error("Too many tables.")]
9579
TooManyTables,
96-
#[error("Apparent size too large.")]
9780
ApparentSizeTooLarge,
98-
#[error("Nested table depth limit reached.")]
9981
DepthLimitReached,
10082
}
10183

84+
#[cfg(any(nightly, feature = "std"))]
85+
impl Error for InvalidFlatbuffer {
86+
fn source(&self) -> Option<&(dyn Error + 'static)> {
87+
if let InvalidFlatbuffer::Utf8Error { error: source, .. } = self {
88+
Some(source)
89+
} else {
90+
None
91+
}
92+
}
93+
}
94+
95+
impl core::fmt::Display for InvalidFlatbuffer {
96+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
97+
match self {
98+
InvalidFlatbuffer::MissingRequiredField {
99+
required,
100+
error_trace,
101+
} => {
102+
writeln!(f, "Missing required field `{}`.\n{}", required, error_trace)?;
103+
}
104+
InvalidFlatbuffer::InconsistentUnion {
105+
field,
106+
field_type,
107+
error_trace,
108+
} => {
109+
writeln!(
110+
f,
111+
"Exactly one of union discriminant (`{}`) and value (`{}`) are present.\n{}",
112+
field_type, field, error_trace
113+
)?;
114+
}
115+
InvalidFlatbuffer::Utf8Error {
116+
error,
117+
range,
118+
error_trace,
119+
} => {
120+
writeln!(
121+
f,
122+
"Utf8 error for string in {:?}: {}\n{}",
123+
range, error, error_trace
124+
)?;
125+
}
126+
InvalidFlatbuffer::MissingNullTerminator { range, error_trace } => {
127+
writeln!(
128+
f,
129+
"String in range [{}, {}) is missing its null terminator.\n{}",
130+
range.start, range.end, error_trace
131+
)?;
132+
}
133+
InvalidFlatbuffer::Unaligned {
134+
position,
135+
unaligned_type,
136+
error_trace,
137+
} => {
138+
writeln!(
139+
f,
140+
"Type `{}` at position {} is unaligned.\n{}",
141+
unaligned_type, position, error_trace
142+
)?;
143+
}
144+
InvalidFlatbuffer::RangeOutOfBounds { range, error_trace } => {
145+
writeln!(
146+
f,
147+
"Range [{}, {}) is out of bounds.\n{}",
148+
range.start, range.end, error_trace
149+
)?;
150+
}
151+
InvalidFlatbuffer::SignedOffsetOutOfBounds {
152+
soffset,
153+
position,
154+
error_trace,
155+
} => {
156+
writeln!(
157+
f,
158+
"Signed offset at position {} has value {} which points out of bounds.\n{}",
159+
position, soffset, error_trace
160+
)?;
161+
}
162+
InvalidFlatbuffer::TooManyTables {} => {
163+
writeln!(f, "Too many tables.")?;
164+
}
165+
InvalidFlatbuffer::ApparentSizeTooLarge {} => {
166+
writeln!(f, "Apparent size too large.")?;
167+
}
168+
InvalidFlatbuffer::DepthLimitReached {} => {
169+
writeln!(f, "Nested table depth limit reached.")?;
170+
}
171+
}
172+
Ok(())
173+
}
174+
}
175+
102176
impl core::fmt::Display for ErrorTrace {
103177
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
104178
use ErrorTraceDetail::*;

tests/RustTest.bat

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,10 @@ cargo run --bin=flatbuffers_alloc_check || exit /b 1
2121
cargo run --bin=flexbuffers_alloc_check || exit /b 1
2222
cargo run --bin=monster_example || exit /b 1
2323
cd ..
24+
25+
cd rust_no_std_compilation_test
26+
rustup install nightly
27+
rustup component add rust-src --toolchain nightly
28+
rustup target add thumbv7m-none-eabi
29+
cargo build || exit /b 1
30+
cd ..

tests/RustTest.sh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,18 @@ cd ./rust_serialize_test
3535
cargo run $TARGET_FLAG -- --quiet
3636
check_test_result "Rust serde tests"
3737

38+
cd ../rust_no_std_compilation_test
39+
rustup install nightly
40+
rustup component add rust-src --toolchain nightly
41+
rustup target add thumbv7m-none-eabi
42+
cargo +nightly build
43+
check_test_result "Rust flatbuffers test no_std compilation"
44+
3845
cd ../rust_usage_test
3946
cargo test $TARGET_FLAG -- --quiet
4047
check_test_result "Rust tests"
4148

42-
cargo test $TARGET_FLAG --no-default-features --features no_std -- --quiet
49+
cargo test $TARGET_FLAG --no-default-features -- --quiet
4350
check_test_result "Rust tests (no_std)"
4451

4552
cargo run $TARGET_FLAG --bin=flatbuffers_alloc_check
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[build]
2+
target = "thumbv7m-none-eabi"
3+
4+
[unstable]
5+
build-std = ["core", "alloc"]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "rust_test_no_std_compilation"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
flatbuffers = { path = "../../rust/flatbuffers", default-features = false }
8+
9+
[profile.dev]
10+
panic = "abort"
11+
12+
[profile.release]
13+
panic = "abort"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#![no_std]
2+
#![no_main]
3+
#![feature(default_alloc_error_handler)]
4+
5+
// Include flatbuffers purely to check that it compiles in a no_std binary
6+
#[allow(unused_imports)]
7+
use flatbuffers;
8+
9+
// The rest is just no_std boilerplate
10+
11+
use core::alloc::{GlobalAlloc, Layout};
12+
13+
struct NullAllocator;
14+
unsafe impl GlobalAlloc for NullAllocator {
15+
unsafe fn alloc(&self, _lt: Layout) -> *mut u8 {
16+
core::ptr::null_mut()
17+
}
18+
unsafe fn dealloc(&self, _ptr: *mut u8, _lt: Layout) {
19+
panic!("won't deallocate: we never allocated!");
20+
}
21+
}
22+
23+
#[global_allocator]
24+
static A: NullAllocator = NullAllocator;
25+
26+
#[panic_handler]
27+
fn panic(_info: &core::panic::PanicInfo) -> ! {
28+
loop {}
29+
}
30+
31+
#[no_mangle]
32+
pub extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 {
33+
0
34+
}

tests/rust_usage_test/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ libc_alloc = { version = "1.0.3", optional = true }
1616

1717
[features]
1818
default = ["flatbuffers/default"]
19-
no_std = ["flatbuffers/no_std", "libc_alloc"]
19+
no_std = ["libc_alloc"]
2020

2121
[[bin]]
2222
name = "monster_example"

0 commit comments

Comments
 (0)