Skip to content

Commit f900391

Browse files
authoredJan 28, 2024··
Merge pull request #122 from greyblake/no-std-support
Support no_std
2 parents 1bc35f9 + 5b259e4 commit f900391

File tree

15 files changed

+280
-18
lines changed

15 files changed

+280
-18
lines changed
 

‎.github/workflows/ci.yml

+11-2
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,20 @@ jobs:
103103
uses: actions-rs/toolchain@v1
104104
with:
105105
toolchain: stable
106+
target: thumbv7m-none-eabi # Needed for no_std_example
106107

107108
- name: Run examples
108109
run: |
109-
for example in $(ls ./examples/); do
110-
cargo run --bin $example
110+
set -euxo pipefail
111+
ROOT_DIR=$(pwd)
112+
for EXAMPLE in `ls examples`; do
113+
cd $ROOT_DIR/examples/$EXAMPLE;
114+
if [[ "$EXAMPLE" == "no_std_example" ]]
115+
then
116+
cargo build
117+
else
118+
cargo run
119+
fi
111120
done
112121
113122
typos:

‎CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
### v0.4.1 - xxxx-xx-xx
22

3+
* Support `no_std` ( the dependency needs to be declared as `nutype = { default-features = false }` )
34
* Support integration with [`arbitrary`](https://crates.io/crates/arbitrary) crate (see `arbitrary` feature).
45
* Support `Arbitrary` for integer types
56
* Support `Arbitrary` for float types

‎Cargo.toml

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,16 @@ members = [
77
"nutype_macros",
88
"test_suite",
99
"dummy",
10-
"examples/*",
10+
11+
# All examples except "no_std_example" are tested in the test suite
12+
"examples/any_arbitrary",
13+
"examples/float_arbitrary",
14+
"examples/float_sortable",
15+
"examples/integer_arbitrary",
16+
"examples/integer_bounded",
17+
"examples/new_unchecked_example",
18+
# "examples/no_std_example",
19+
"examples/serde_complex",
20+
"examples/string_bounded_len",
21+
"examples/string_regex_email",
1122
]

‎Justfile

+12-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,18 @@ clippy:
2727
cargo clippy -- -D warnings
2828

2929
examples:
30-
for example in `ls examples`; do cargo run --bin $example; done
30+
#!/usr/bin/env bash
31+
set -euxo pipefail
32+
ROOT_DIR=$(pwd)
33+
for EXAMPLE in `ls examples`; do
34+
cd $ROOT_DIR/examples/$EXAMPLE;
35+
if [[ "$EXAMPLE" == "no_std_example" ]]
36+
then
37+
cargo build
38+
else
39+
cargo run
40+
fi
41+
done
3142
3243
typos:
3344
which typos >/dev/null || cargo install typos-cli

‎README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,12 @@ assert_eq!(name.into_inner(), " boo ");
354354

355355
## Feature flags
356356

357-
* `serde` - integrations with [`serde`](https://crates.io/crates/serde) crate. Allows to derive `Serialize` and `Deserialize` traits.
357+
* `arbitrary` - enables derive of [`arbitrary::Arbitrary`](https://docs.rs/arbitrary/latest/arbitrary/trait.Arbitrary.html).
358+
* `new_unchecked` - enables generation of unsafe `::new_unchecked()` function.
358359
* `regex` - allows to use `regex = ` validation on string-based types. Note: your crate also has to explicitly have `regex` and `lazy_static` within dependencies.
360+
* `serde` - integrations with [`serde`](https://crates.io/crates/serde) crate. Allows to derive `Serialize` and `Deserialize` traits.
359361
* `schemars08` - allows to derive [`JsonSchema`](https://docs.rs/schemars/0.8.12/schemars/trait.JsonSchema.html) trait of [schemars](https://crates.io/crates/schemars) crate. Note that at the moment validation rules are not respected.
360-
* `new_unchecked` - enables generation of unsafe `::new_unchecked()` function.
362+
* `std` - enabled by default. Use `default-features = false` to disable.
361363

362364
## When nutype is a good fit for you?
363365

‎examples/no_std_example/.cargo/config

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[build]
2+
target = "thumbv7m-none-eabi"

‎examples/no_std_example/Cargo.lock

+112
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/no_std_example/Cargo.toml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "no_std_example"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
nutype = { path = "../../nutype", default-features = false }
10+
11+
# Exclude this package from the common workspace, since it's no_std.
12+
[workspace]

‎examples/no_std_example/src/main.rs

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// This example exists to ensure that code generated by nutype macro
2+
// can compile in no_std environment.
3+
#![no_main]
4+
#![no_std]
5+
6+
use core::panic::PanicInfo;
7+
use nutype::nutype;
8+
9+
#[panic_handler]
10+
fn panic(_panic: &PanicInfo<'_>) -> ! {
11+
loop {}
12+
}
13+
14+
// Integer
15+
#[nutype(
16+
validate(greater_or_equal = 1, less_or_equal = 6),
17+
sanitize(with = |x| x),
18+
derive(
19+
Debug,
20+
Clone,
21+
PartialEq,
22+
Eq,
23+
PartialOrd,
24+
Ord,
25+
FromStr,
26+
AsRef,
27+
Deref,
28+
TryFrom,
29+
Into,
30+
Hash,
31+
Borrow,
32+
Display,
33+
Default,
34+
),
35+
default = 4
36+
)]
37+
struct GermanTaxClass(i64);
38+
39+
// Float
40+
#[nutype(
41+
validate(greater_or_equal = 0.0, less_or_equal = 1024.0, finite),
42+
sanitize(with = |x| x),
43+
derive(
44+
Debug,
45+
Clone,
46+
PartialEq,
47+
Eq,
48+
PartialOrd,
49+
Ord,
50+
FromStr,
51+
AsRef,
52+
Deref,
53+
TryFrom,
54+
Into,
55+
Borrow,
56+
Display,
57+
Default,
58+
),
59+
default = 0.0
60+
)]
61+
struct Width(f64);
62+
63+
// NOTE: strings are not working yet with no_std
64+
65+
// Any other type
66+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
67+
pub struct Point {
68+
x: i32,
69+
y: i32,
70+
}
71+
#[nutype(derive(
72+
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, AsRef, Into, From, Deref, Borrow, Hash
73+
))]
74+
pub struct Location(Point);

‎nutype/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ categories = ["data-structures", "rust-patterns"]
1818
nutype_macros = { version = "0.4.0", path = "../nutype_macros" }
1919

2020
[features]
21+
default = ["std"]
22+
23+
std = ["nutype_macros/std"]
2124
serde = ["nutype_macros/serde"]
2225
regex = ["nutype_macros/regex"]
2326
schemars08 = ["nutype_macros/schemars08"]

‎nutype/src/lib.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -383,10 +383,12 @@
383383
//!
384384
//! ## Feature flags
385385
//!
386-
//! * `serde` - integrations with [`serde`](https://crates.io/crates/serde) crate. Allows to derive `Serialize` and `Deserialize` traits.
386+
//! * `arbitrary` - enables derive of [`arbitrary::Arbitrary`](https://docs.rs/arbitrary/latest/arbitrary/trait.Arbitrary.html).
387387
//! * `new_unchecked` - enables generation of unsafe `::new_unchecked()` function.
388-
//! * `schemars08` - allows to derive [`JsonSchema`](https://docs.rs/schemars/0.8.12/schemars/trait.JsonSchema.html) trait of [schemars](https://crates.io/crates/schemars) crate. Note that at the moment validation rules are not respected.
389388
//! * `regex` - allows to use `regex = ` validation on string-based types. Note: your crate also has to explicitly have `regex` and `lazy_static` within dependencies.
389+
//! * `serde` - integrations with [`serde`](https://crates.io/crates/serde) crate. Allows to derive `Serialize` and `Deserialize` traits.
390+
//! * `schemars08` - allows to derive [`JsonSchema`](https://docs.rs/schemars/0.8.12/schemars/trait.JsonSchema.html) trait of [schemars](https://crates.io/crates/schemars) crate. Note that at the moment validation rules are not respected.
391+
//! * `std` - enabled by default. Use `default-features = false` to disable.
390392
//!
391393
//! ## Support Ukrainian military forces 🇺🇦
392394
//!
@@ -404,6 +406,9 @@
404406
//!
405407
//! Thank you.
406408
409+
// Set `no_std` flag if `std` feature is disabled.
410+
#![cfg_attr(not(feature = "std"), no_std)]
411+
407412
pub use nutype_macros::nutype;
408413

409414
#[cfg(test)]

‎nutype_macros/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ urlencoding = "2.0"
3030
proc-macro = true
3131

3232
[features]
33+
std = []
3334
serde = []
3435
schemars08 = []
3536
new_unchecked = []

‎nutype_macros/src/common/gen/error.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use cfg_if::cfg_if;
12
use proc_macro2::TokenStream;
23
use quote::{format_ident, quote};
34

@@ -8,12 +9,21 @@ pub fn gen_error_type_name(type_name: &TypeName) -> ErrorTypeName {
89
ErrorTypeName::new(ident)
910
}
1011

12+
// NOTE: There is no `::core::error::Error` yet in stable Rust.
13+
// So for `no_std` we just don't implement `Error` trait.
14+
#[allow(unused_variables)]
1115
pub fn gen_impl_error_trait(error_type_name: &ErrorTypeName) -> TokenStream {
12-
quote! {
13-
impl ::std::error::Error for #error_type_name {
14-
fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
15-
None
16+
cfg_if! {
17+
if #[cfg(feature = "std")] {
18+
quote! {
19+
impl ::std::error::Error for #error_type_name {
20+
fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
21+
None
22+
}
23+
}
1624
}
25+
} else {
26+
quote!{}
1727
}
1828
}
1929
}

‎nutype_macros/src/common/gen/parse_error.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use cfg_if::cfg_if;
12
use proc_macro2::TokenStream;
23
use quote::{format_ident, quote};
34

@@ -55,11 +56,19 @@ pub fn gen_def_parse_error(
5556
}
5657
};
5758

58-
let impl_std_error = quote! {
59-
impl ::std::error::Error for #parse_error_type_name {
60-
fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
61-
None
62-
}
59+
cfg_if! {
60+
if #[cfg(feature = "std")] {
61+
let impl_std_error = quote! {
62+
impl ::std::error::Error for #parse_error_type_name {
63+
fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
64+
None
65+
}
66+
}
67+
};
68+
} else {
69+
// NOTE: There is no `::core::error::Error` yet in stable Rust.
70+
// So for `no_std` we just don't implement `Error` trait.
71+
let impl_std_error = quote! {};
6372
}
6473
};
6574

‎nutype_macros/src/float/gen/traits/arbitrary.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ fn generate_float_with_condition(
373373
for i in 0..1000 {
374374
// With every iteration we modify next single byte by adding `i` value to
375375
// it.
376-
let index = i % std::mem::size_of::<#inner_type>();
376+
let index = i % core::mem::size_of::<#inner_type>();
377377
bytes[index] = bytes[index].wrapping_add((i % 256) as u8);
378378

379379
// Try to convert the bytes back to float in both BE and NE formats and see

0 commit comments

Comments
 (0)
Please sign in to comment.