diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 1dbac58..9edd895 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -30,9 +30,18 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - run: rustup toolchain add 1.63 + - run: rustup toolchain add 1.81 - name: Build - run: cargo +1.63 check --lib --all-features + run: cargo +1.81 check --lib --all-features + check_no_std: + name: Check no_std + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: rustup update + - run: rustup toolchain add 1.81 + - run: rustup target add x86_64-unknown-none --toolchain 1.81 + - run: cargo +1.81 check --no-default-features --features alloc,derive --target x86_64-unknown-none clippy: name: Clippy runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 7902497..7bd31cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,14 +17,21 @@ description = "The trait for generating structured data from unstructured data" license = "MIT OR Apache-2.0" repository = "https://github.com/rust-fuzz/arbitrary/" documentation = "https://docs.rs/arbitrary/" -rust-version = "1.63.0" # Keep in sync with version documented in the README.md +rust-version = "1.81.0" # Keep in sync with version documented in the README.md [dependencies] -derive_arbitrary = { version = "~1.4.0", path = "./derive", optional = true } +derive_arbitrary = { version = "~1.4.0", path = "./derive", default-features = false, optional = true } [features] +default = ["std", "recursive_count"] # Turn this feature on to enable support for `#[derive(Arbitrary)]`. derive = ["derive_arbitrary"] +# Enables support for the `std` crate. +std = ["alloc"] +# Enables support for the `alloc` crate. +alloc = [] +# Checks for unbounded recursion at runtime. This does nothing without the "derive" feature. +recursive_count = ["derive_arbitrary?/recursive_count"] [[example]] name = "derive_enum" @@ -40,3 +47,8 @@ members = ["./fuzz"] [dev-dependencies] exhaustigen = "0.1.0" + +[lints.clippy] +alloc_instead_of_core = "warn" +std_instead_of_alloc = "warn" +std_instead_of_core = "warn" diff --git a/README.md b/README.md index 5d75f31..a2a6c9c 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ impl<'a> Arbitrary<'a> for Rgb { -This crate is guaranteed to compile on stable Rust **1.63.0** and up. It might +This crate is guaranteed to compile on stable Rust **1.81.0** and up. It might compile with older versions but that may change in any new patch release. We reserve the right to increment the MSRV on minor releases, however we will diff --git a/derive/Cargo.toml b/derive/Cargo.toml index c92a941..5957903 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -16,7 +16,7 @@ description = "Derives arbitrary traits" license = "MIT OR Apache-2.0" repository = "https://github.com/rust-fuzz/arbitrary" documentation = "https://docs.rs/arbitrary/" -rust-version = "1.63.0" +rust-version = "1.81.0" [dependencies] proc-macro2 = "1.0" @@ -25,3 +25,8 @@ syn = { version = "2", features = ['derive', 'parsing', 'extra-traits'] } [lib] proc-macro = true + +[features] +default = ["recursive_count"] +# Checks for unbounded recursion at runtime. Requires `std`. +recursive_count = [] diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 81c0274..678b269 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -29,13 +29,18 @@ fn expand_derive_arbitrary(input: syn::DeriveInput) -> Result { let (lifetime_without_bounds, lifetime_with_bounds) = build_arbitrary_lifetime(input.generics.clone()); + #[cfg(feature = "recursive_count")] let recursive_count = syn::Ident::new( &format!("RECURSIVE_COUNT_{}", input.ident), Span::call_site(), ); - let arbitrary_method = - gen_arbitrary_method(&input, lifetime_without_bounds.clone(), &recursive_count)?; + let arbitrary_method = gen_arbitrary_method( + &input, + lifetime_without_bounds.clone(), + #[cfg(feature = "recursive_count")] + &recursive_count, + )?; let size_hint_method = gen_size_hint_method(&input)?; let name = input.ident; @@ -56,12 +61,22 @@ fn expand_derive_arbitrary(input: syn::DeriveInput) -> Result { // Build TypeGenerics and WhereClause without a lifetime let (_, ty_generics, where_clause) = generics.split_for_impl(); + #[cfg(feature = "recursive_count")] + let recursive_count_preamble = quote! { + extern crate std; + + ::std::thread_local! { + #[allow(non_upper_case_globals)] + static #recursive_count: ::core::cell::Cell = ::core::cell::Cell::new(0); + } + }; + + #[cfg(not(feature = "recursive_count"))] + let recursive_count_preamble = TokenStream::new(); + Ok(quote! { const _: () = { - ::std::thread_local! { - #[allow(non_upper_case_globals)] - static #recursive_count: ::core::cell::Cell = ::core::cell::Cell::new(0); - } + #recursive_count_preamble #[automatically_derived] impl #impl_generics arbitrary::Arbitrary<#lifetime_without_bounds> for #name #ty_generics #where_clause { @@ -148,9 +163,10 @@ fn add_trait_bounds(mut generics: Generics, lifetime: LifetimeParam) -> Generics } fn with_recursive_count_guard( - recursive_count: &syn::Ident, + #[cfg(feature = "recursive_count")] recursive_count: &syn::Ident, expr: impl quote::ToTokens, ) -> impl quote::ToTokens { + #[cfg(feature = "recursive_count")] quote! { let guard_against_recursion = u.is_empty(); if guard_against_recursion { @@ -173,25 +189,35 @@ fn with_recursive_count_guard( result } + + #[cfg(not(feature = "recursive_count"))] + quote! { (|| { #expr })() } } fn gen_arbitrary_method( input: &DeriveInput, lifetime: LifetimeParam, - recursive_count: &syn::Ident, + #[cfg(feature = "recursive_count")] recursive_count: &syn::Ident, ) -> Result { fn arbitrary_structlike( fields: &Fields, ident: &syn::Ident, lifetime: LifetimeParam, - recursive_count: &syn::Ident, + #[cfg(feature = "recursive_count")] recursive_count: &syn::Ident, ) -> Result { let arbitrary = construct(fields, |_idx, field| gen_constructor_for_field(field))?; - let body = with_recursive_count_guard(recursive_count, quote! { Ok(#ident #arbitrary) }); + let body = with_recursive_count_guard( + #[cfg(feature = "recursive_count")] + recursive_count, + quote! { Ok(#ident #arbitrary) }, + ); let arbitrary_take_rest = construct_take_rest(fields)?; - let take_rest_body = - with_recursive_count_guard(recursive_count, quote! { Ok(#ident #arbitrary_take_rest) }); + let take_rest_body = with_recursive_count_guard( + #[cfg(feature = "recursive_count")] + recursive_count, + quote! { Ok(#ident #arbitrary_take_rest) }, + ); Ok(quote! { fn arbitrary(u: &mut arbitrary::Unstructured<#lifetime>) -> arbitrary::Result { @@ -214,12 +240,13 @@ fn gen_arbitrary_method( } fn arbitrary_enum_method( - recursive_count: &syn::Ident, unstructured: TokenStream, variants: &[TokenStream], + #[cfg(feature = "recursive_count")] recursive_count: &syn::Ident, ) -> impl quote::ToTokens { let count = variants.len() as u64; with_recursive_count_guard( + #[cfg(feature = "recursive_count")] recursive_count, quote! { // Use a multiply + shift to generate a ranged random number @@ -237,7 +264,7 @@ fn gen_arbitrary_method( DataEnum { variants, .. }: &DataEnum, enum_name: &Ident, lifetime: LifetimeParam, - recursive_count: &syn::Ident, + #[cfg(feature = "recursive_count")] recursive_count: &syn::Ident, ) -> Result { let filtered_variants = variants.iter().filter(not_skipped); @@ -275,8 +302,18 @@ fn gen_arbitrary_method( (!variants.is_empty()) .then(|| { // TODO: Improve dealing with `u` vs. `&mut u`. - let arbitrary = arbitrary_enum_method(recursive_count, quote! { u }, &variants); - let arbitrary_take_rest = arbitrary_enum_method(recursive_count, quote! { &mut u }, &variants_take_rest); + let arbitrary = arbitrary_enum_method( + quote! { u }, + &variants, + #[cfg(feature = "recursive_count")] + recursive_count, + ); + let arbitrary_take_rest = arbitrary_enum_method( + quote! { &mut u }, + &variants_take_rest, + #[cfg(feature = "recursive_count")] + recursive_count, + ); quote! { fn arbitrary(u: &mut arbitrary::Unstructured<#lifetime>) -> arbitrary::Result { @@ -296,14 +333,27 @@ fn gen_arbitrary_method( let ident = &input.ident; match &input.data { - Data::Struct(data) => arbitrary_structlike(&data.fields, ident, lifetime, recursive_count), + Data::Struct(data) => arbitrary_structlike( + &data.fields, + ident, + lifetime, + #[cfg(feature = "recursive_count")] + recursive_count, + ), Data::Union(data) => arbitrary_structlike( &Fields::Named(data.fields.clone()), ident, lifetime, + #[cfg(feature = "recursive_count")] + recursive_count, + ), + Data::Enum(data) => arbitrary_enum( + data, + ident, + lifetime, + #[cfg(feature = "recursive_count")] recursive_count, ), - Data::Enum(data) => arbitrary_enum(data, ident, lifetime, recursive_count), } } diff --git a/src/error.rs b/src/error.rs index 6ca8f19..4cf49ae 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,4 @@ -use std::{error, fmt}; +use core::fmt; /// An enumeration of buffer creation errors #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -32,20 +32,24 @@ impl fmt::Display for Error { } } -impl error::Error for Error {} +impl core::error::Error for Error {} /// A `Result` with the error type fixed as `arbitrary::Error`. /// /// Either an `Ok(T)` or `Err(arbitrary::Error)`. -pub type Result = std::result::Result; +pub type Result = core::result::Result; #[cfg(test)] mod tests { + #[cfg(feature = "alloc")] + use alloc::string::String; + // Often people will import our custom `Result` type because 99.9% of // results in a file will be `arbitrary::Result` but then have that one last // 0.1% that want to have a custom error type. Don't make them prefix that - // 0.1% as `std::result::Result`; instead, let `arbitrary::Result` have an + // 0.1% as `core::result::Result`; instead, let `arbitrary::Result` have an // overridable error type. + #[cfg(feature = "alloc")] #[test] fn can_use_custom_error_types_with_result() -> super::Result<(), String> { Ok(()) diff --git a/src/foreign/alloc/borrow.rs b/src/foreign/alloc/borrow.rs index b5b1e22..617afcb 100644 --- a/src/foreign/alloc/borrow.rs +++ b/src/foreign/alloc/borrow.rs @@ -1,6 +1,6 @@ use { crate::{size_hint, Arbitrary, Result, Unstructured}, - std::borrow::{Cow, ToOwned}, + alloc::borrow::{Cow, ToOwned}, }; impl<'a, A> Arbitrary<'a> for Cow<'a, A> diff --git a/src/foreign/alloc/boxed.rs b/src/foreign/alloc/boxed.rs index c3014a3..f397557 100644 --- a/src/foreign/alloc/boxed.rs +++ b/src/foreign/alloc/boxed.rs @@ -1,6 +1,6 @@ use { crate::{size_hint, Arbitrary, Result, Unstructured}, - std::boxed::Box, + alloc::{boxed::Box, string::String}, }; impl<'a, A> Arbitrary<'a> for Box diff --git a/src/foreign/alloc/collections/binary_heap.rs b/src/foreign/alloc/collections/binary_heap.rs index 25a0384..02ef3fc 100644 --- a/src/foreign/alloc/collections/binary_heap.rs +++ b/src/foreign/alloc/collections/binary_heap.rs @@ -1,6 +1,6 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::collections::binary_heap::BinaryHeap, + alloc::collections::binary_heap::BinaryHeap, }; impl<'a, A> Arbitrary<'a> for BinaryHeap diff --git a/src/foreign/alloc/collections/btree_map.rs b/src/foreign/alloc/collections/btree_map.rs index 21b93a4..65790c1 100644 --- a/src/foreign/alloc/collections/btree_map.rs +++ b/src/foreign/alloc/collections/btree_map.rs @@ -1,6 +1,6 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::collections::btree_map::BTreeMap, + alloc::collections::btree_map::BTreeMap, }; impl<'a, K, V> Arbitrary<'a> for BTreeMap diff --git a/src/foreign/alloc/collections/btree_set.rs b/src/foreign/alloc/collections/btree_set.rs index 8c6e92f..b862a0f 100644 --- a/src/foreign/alloc/collections/btree_set.rs +++ b/src/foreign/alloc/collections/btree_set.rs @@ -1,6 +1,6 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::collections::btree_set::BTreeSet, + alloc::collections::btree_set::BTreeSet, }; impl<'a, A> Arbitrary<'a> for BTreeSet diff --git a/src/foreign/alloc/collections/linked_list.rs b/src/foreign/alloc/collections/linked_list.rs index 6bf2e98..7bb6425 100644 --- a/src/foreign/alloc/collections/linked_list.rs +++ b/src/foreign/alloc/collections/linked_list.rs @@ -1,6 +1,6 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::collections::linked_list::LinkedList, + alloc::collections::linked_list::LinkedList, }; impl<'a, A> Arbitrary<'a> for LinkedList diff --git a/src/foreign/alloc/collections/vec_deque.rs b/src/foreign/alloc/collections/vec_deque.rs index 40e0413..44a37b6 100644 --- a/src/foreign/alloc/collections/vec_deque.rs +++ b/src/foreign/alloc/collections/vec_deque.rs @@ -1,6 +1,6 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::collections::vec_deque::VecDeque, + alloc::collections::vec_deque::VecDeque, }; impl<'a, A> Arbitrary<'a> for VecDeque diff --git a/src/foreign/alloc/ffi/c_str.rs b/src/foreign/alloc/ffi/c_str.rs index a1b2383..275d48f 100644 --- a/src/foreign/alloc/ffi/c_str.rs +++ b/src/foreign/alloc/ffi/c_str.rs @@ -1,6 +1,8 @@ +use alloc::ffi::CString; + use { crate::{Arbitrary, Result, Unstructured}, - std::ffi::CString, + alloc::vec::Vec, }; impl<'a> Arbitrary<'a> for CString { diff --git a/src/foreign/alloc/mod.rs b/src/foreign/alloc/mod.rs index a04b62c..1296385 100644 --- a/src/foreign/alloc/mod.rs +++ b/src/foreign/alloc/mod.rs @@ -9,5 +9,6 @@ mod collections; mod ffi; mod rc; mod string; +#[cfg(target_has_atomic = "ptr")] mod sync; mod vec; diff --git a/src/foreign/alloc/rc.rs b/src/foreign/alloc/rc.rs index 6d58167..2243be4 100644 --- a/src/foreign/alloc/rc.rs +++ b/src/foreign/alloc/rc.rs @@ -1,6 +1,6 @@ use { crate::{size_hint, Arbitrary, Result, Unstructured}, - std::rc::Rc, + alloc::rc::Rc, }; impl<'a, A> Arbitrary<'a> for Rc diff --git a/src/foreign/alloc/string.rs b/src/foreign/alloc/string.rs index a579784..47ea9eb 100644 --- a/src/foreign/alloc/string.rs +++ b/src/foreign/alloc/string.rs @@ -1,6 +1,6 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::string::String, + alloc::string::String, }; impl<'a> Arbitrary<'a> for String { diff --git a/src/foreign/alloc/sync.rs b/src/foreign/alloc/sync.rs index c8ca1db..64d2dcd 100644 --- a/src/foreign/alloc/sync.rs +++ b/src/foreign/alloc/sync.rs @@ -1,6 +1,6 @@ use { crate::{size_hint, Arbitrary, Result, Unstructured}, - std::sync::Arc, + alloc::sync::Arc, }; impl<'a, A> Arbitrary<'a> for Arc diff --git a/src/foreign/alloc/vec.rs b/src/foreign/alloc/vec.rs index 63313ba..2985712 100644 --- a/src/foreign/alloc/vec.rs +++ b/src/foreign/alloc/vec.rs @@ -1,6 +1,6 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::vec::Vec, + alloc::vec::Vec, }; impl<'a, A> Arbitrary<'a> for Vec diff --git a/src/foreign/core/mod.rs b/src/foreign/core/mod.rs index 60089e9..70cc717 100644 --- a/src/foreign/core/mod.rs +++ b/src/foreign/core/mod.rs @@ -9,6 +9,7 @@ mod char; mod cmp; mod iter; mod marker; +mod net; mod num; mod ops; mod option; diff --git a/src/foreign/std/net.rs b/src/foreign/core/net.rs similarity index 94% rename from src/foreign/std/net.rs rename to src/foreign/core/net.rs index 41e1f8a..014592d 100644 --- a/src/foreign/std/net.rs +++ b/src/foreign/core/net.rs @@ -1,7 +1,6 @@ -use { - crate::{size_hint, Arbitrary, Result, Unstructured}, - std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, -}; +use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; + +use crate::{size_hint, Arbitrary, Result, Unstructured}; impl<'a> Arbitrary<'a> for Ipv4Addr { fn arbitrary(u: &mut Unstructured<'a>) -> Result { diff --git a/src/foreign/mod.rs b/src/foreign/mod.rs index b1c42be..3868936 100644 --- a/src/foreign/mod.rs +++ b/src/foreign/mod.rs @@ -2,6 +2,8 @@ //! //! [`Arbitrary`]: crate::Arbitrary +#[cfg(feature = "alloc")] mod alloc; mod core; +#[cfg(feature = "std")] mod std; diff --git a/src/foreign/std/collections/hash_map.rs b/src/foreign/std/collections/hash_map.rs index d2e77af..85afe3a 100644 --- a/src/foreign/std/collections/hash_map.rs +++ b/src/foreign/std/collections/hash_map.rs @@ -1,9 +1,7 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::{ - collections::hash_map::HashMap, - hash::{BuildHasher, Hash}, - }, + core::hash::{BuildHasher, Hash}, + std::collections::hash_map::HashMap, }; impl<'a, K, V, S> Arbitrary<'a> for HashMap diff --git a/src/foreign/std/collections/hash_set.rs b/src/foreign/std/collections/hash_set.rs index 5cb63d2..07c4c8a 100644 --- a/src/foreign/std/collections/hash_set.rs +++ b/src/foreign/std/collections/hash_set.rs @@ -1,9 +1,7 @@ use { crate::{Arbitrary, Result, Unstructured}, - std::{ - collections::hash_set::HashSet, - hash::{BuildHasher, Hash}, - }, + core::hash::{BuildHasher, Hash}, + std::collections::hash_set::HashSet, }; impl<'a, A, S> Arbitrary<'a> for HashSet diff --git a/src/foreign/std/ffi/os_str.rs b/src/foreign/std/ffi/os_str.rs index 9fa0cb3..83a3b27 100644 --- a/src/foreign/std/ffi/os_str.rs +++ b/src/foreign/std/ffi/os_str.rs @@ -1,5 +1,6 @@ use { crate::{Arbitrary, Result, Unstructured}, + alloc::string::String, std::ffi::OsString, }; diff --git a/src/foreign/std/mod.rs b/src/foreign/std/mod.rs index bc85aa2..7731262 100644 --- a/src/foreign/std/mod.rs +++ b/src/foreign/std/mod.rs @@ -5,6 +5,5 @@ mod collections; mod ffi; -mod net; mod path; mod sync; diff --git a/src/lib.rs b/src/lib.rs index 2535d3a..ea155cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,13 @@ #![deny(rust_2018_compatibility)] #![deny(rust_2018_idioms)] #![deny(unused)] +#![no_std] + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "alloc")] +extern crate alloc; mod error; mod foreign; @@ -49,7 +56,7 @@ impl core::fmt::Display for MaxRecursionReached { } } -impl std::error::Error for MaxRecursionReached {} +impl core::error::Error for MaxRecursionReached {} /// Generate arbitrary structured values from raw, unstructured data. /// @@ -122,9 +129,9 @@ impl std::error::Error for MaxRecursionReached {} /// /// ``` /// # #[cfg(feature = "derive")] mod foo { -/// # pub struct MyCollection { _t: std::marker::PhantomData } +/// # pub struct MyCollection { _t: core::marker::PhantomData } /// # impl MyCollection { -/// # pub fn new() -> Self { MyCollection { _t: std::marker::PhantomData } } +/// # pub fn new() -> Self { MyCollection { _t: core::marker::PhantomData } } /// # pub fn insert(&mut self, element: T) {} /// # } /// use arbitrary::{Arbitrary, Result, Unstructured}; diff --git a/src/size_hint.rs b/src/size_hint.rs index 95707ee..9f73346 100644 --- a/src/size_hint.rs +++ b/src/size_hint.rs @@ -67,10 +67,10 @@ pub fn and_all(hints: &[(usize, Option)]) -> (usize, Option) { /// `lhs` and `rhs` size hints. #[inline] pub fn or(lhs: (usize, Option), rhs: (usize, Option)) -> (usize, Option) { - let lower = std::cmp::min(lhs.0, rhs.0); + let lower = core::cmp::min(lhs.0, rhs.0); let upper = lhs .1 - .and_then(|lhs| rhs.1.map(|rhs| std::cmp::max(lhs, rhs))); + .and_then(|lhs| rhs.1.map(|rhs| core::cmp::max(lhs, rhs))); (lower, upper) } diff --git a/src/tests.rs b/src/tests.rs index 7746715..9d998ab 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,12 +1,23 @@ +use super::{Arbitrary, Result, Unstructured}; + +#[cfg(feature = "std")] use { - super::{Arbitrary, Result, Unstructured}, - std::{collections::HashSet, fmt::Debug, hash::Hash, rc::Rc, sync::Arc}, + alloc::vec, + core::{fmt::Debug, hash::Hash}, + std::collections::HashSet, }; +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, rc::Rc, string::String, vec::Vec}; + +#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))] +use alloc::sync::Arc; + /// Assert that the given expected values are all generated. /// /// Exhaustively enumerates all buffers up to length 10 containing the /// following bytes: `0x00`, `0x01`, `0x61` (aka ASCII 'a'), and `0xff` +#[cfg(feature = "std")] fn assert_generates(expected_values: impl IntoIterator) where T: Clone + Debug + Hash + Eq + for<'a> Arbitrary<'a>, @@ -26,7 +37,7 @@ where buf.clear(); buf.extend( - std::iter::repeat_with(|| { + core::iter::repeat_with(|| { let index = g.gen(bytes.len() - 1); bytes[index] }) @@ -116,6 +127,7 @@ fn finite_buffer_fill_buffer() { assert_eq!(z, [0, 0]); } +#[cfg(feature = "std")] #[test] fn arbitrary_for_integers() { let x = [1, 2, 3, 4]; @@ -153,6 +165,7 @@ fn arbitrary_take_rest_for_bytes() { assert_eq!(expected, actual); } +#[cfg(feature = "std")] #[test] fn arbitrary_for_vec_u8() { assert_generates::>([ @@ -174,6 +187,7 @@ fn arbitrary_for_vec_u8() { ]); } +#[cfg(feature = "std")] #[test] fn arbitrary_for_vec_vec_u8() { assert_generates::>>([ @@ -192,6 +206,7 @@ fn arbitrary_for_vec_vec_u8() { ]); } +#[cfg(feature = "std")] #[test] fn arbitrary_for_vec_vec_vec_u8() { assert_generates::>>>([ @@ -216,6 +231,7 @@ fn arbitrary_for_vec_vec_vec_u8() { ]); } +#[cfg(feature = "std")] #[test] fn arbitrary_for_string() { assert_generates::(["".into(), "a".into(), "aa".into(), "aaa".into()]); @@ -230,26 +246,32 @@ fn arbitrary_collection() { checked_arbitrary::<&[u8]>(&mut Unstructured::new(&x)).unwrap(), &[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3] ); + #[cfg(feature = "alloc")] assert_eq!( checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), &[2, 4, 6, 8, 1] ); + #[cfg(feature = "alloc")] assert_eq!( &*checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), &[2, 4, 6, 8, 1] ); + #[cfg(feature = "alloc")] assert_eq!( &*checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), &[2, 4, 6, 8, 1] ); + #[cfg(feature = "alloc")] assert_eq!( &*checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), &[2, 4, 6, 8, 1] ); + #[cfg(feature = "alloc")] assert_eq!( checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), &[84148994] ); + #[cfg(feature = "alloc")] assert_eq!( checked_arbitrary::(&mut Unstructured::new(&x)).unwrap(), "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x01\x02\x03" @@ -264,26 +286,32 @@ fn arbitrary_take_rest() { checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&x)).unwrap(), &[1, 2, 3, 4] ); + #[cfg(feature = "alloc")] assert_eq!( checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), &[2, 4] ); + #[cfg(feature = "alloc")] assert_eq!( &*checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), &[2, 4] ); + #[cfg(feature = "alloc")] assert_eq!( &*checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), &[2, 4] ); + #[cfg(feature = "alloc")] assert_eq!( &*checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), &[2, 4] ); + #[cfg(feature = "alloc")] assert_eq!( checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), &[0x040302] ); + #[cfg(feature = "alloc")] assert_eq!( checked_arbitrary_take_rest::(Unstructured::new(&x)).unwrap(), "\x01\x02\x03\x04" @@ -294,18 +322,21 @@ fn arbitrary_take_rest() { checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&[])).unwrap(), &[] ); + #[cfg(feature = "alloc")] assert_eq!( checked_arbitrary_take_rest::>(Unstructured::new(&[])).unwrap(), &[] ); // Cannot consume all but can consume part of the input + #[cfg(feature = "alloc")] assert_eq!( checked_arbitrary_take_rest::(Unstructured::new(&[1, 0xFF, 2])).unwrap(), "\x01" ); } +#[cfg(feature = "alloc")] #[test] fn size_hint_for_tuples() { assert_eq!( diff --git a/src/unstructured.rs b/src/unstructured.rs index b31f523..db03b60 100644 --- a/src/unstructured.rs +++ b/src/unstructured.rs @@ -9,9 +9,9 @@ //! Wrappers around raw, unstructured bytes. use crate::{Arbitrary, Error, Result}; -use std::marker::PhantomData; -use std::ops::ControlFlow; -use std::{mem, ops}; +use core::marker::PhantomData; +use core::ops::ControlFlow; +use core::{mem, ops}; /// A source of unstructured data. /// @@ -186,9 +186,9 @@ impl<'a> Unstructured<'a> { /// /// ``` /// use arbitrary::{Arbitrary, Result, Unstructured}; - /// # pub struct MyCollection { _t: std::marker::PhantomData } + /// # pub struct MyCollection { _t: core::marker::PhantomData } /// # impl MyCollection { - /// # pub fn with_capacity(capacity: usize) -> Self { MyCollection { _t: std::marker::PhantomData } } + /// # pub fn with_capacity(capacity: usize) -> Self { MyCollection { _t: core::marker::PhantomData } } /// # pub fn insert(&mut self, element: T) {} /// # } /// @@ -218,7 +218,7 @@ impl<'a> Unstructured<'a> { let byte_size = self.arbitrary_byte_size()?; let (lower, upper) = ::size_hint(0); let elem_size = upper.unwrap_or(lower * 2); - let elem_size = std::cmp::max(1, elem_size); + let elem_size = core::cmp::max(1, elem_size); Ok(byte_size / elem_size) } @@ -424,7 +424,10 @@ impl<'a> Unstructured<'a> { /// Selecting a random item from a set: /// /// ``` - /// use std::collections::BTreeSet; + /// # #[cfg(feature = "std")] + /// # { + /// # extern crate alloc; + /// use alloc::collections::BTreeSet; /// use arbitrary::Unstructured; /// /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); @@ -433,6 +436,7 @@ impl<'a> Unstructured<'a> { /// let choice = u.choose_iter(set.iter()).unwrap(); /// /// println!("chose {}", choice); + /// # } /// ``` pub fn choose_iter(&mut self, choices: I) -> Result where @@ -556,7 +560,7 @@ impl<'a> Unstructured<'a> { /// assert_eq!(buf, [0, 0]); /// ``` pub fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<()> { - let n = std::cmp::min(buffer.len(), self.data.len()); + let n = core::cmp::min(buffer.len(), self.data.len()); buffer[..n].copy_from_slice(&self.data[..n]); for byte in buffer[n..].iter_mut() { *byte = 0; @@ -672,8 +676,8 @@ impl<'a> Unstructured<'a> { /// times the function is called. /// /// You may break out of the loop early by returning - /// `Ok(std::ops::ControlFlow::Break)`. To continue the loop, return - /// `Ok(std::ops::ControlFlow::Continue)`. + /// `Ok(core::ops::ControlFlow::Break)`. To continue the loop, return + /// `Ok(core::ops::ControlFlow::Continue)`. /// /// # Panics /// @@ -686,7 +690,7 @@ impl<'a> Unstructured<'a> { /// /// ``` /// use arbitrary::{Result, Unstructured}; - /// use std::ops::ControlFlow; + /// use core::ops::ControlFlow; /// /// enum Type { /// /// A boolean type. @@ -800,7 +804,7 @@ impl<'a, ElementType: Arbitrary<'a>> Iterator for ArbitraryTakeRestIter<'a, Elem /// Don't implement this trait yourself. pub trait Int: Copy - + std::fmt::Debug + + core::fmt::Debug + PartialOrd + Ord + ops::Sub @@ -904,8 +908,12 @@ impl_int! { #[cfg(test)] mod tests { + #[cfg(feature = "alloc")] + use alloc::vec; + use super::*; + #[cfg(feature = "alloc")] #[test] fn test_byte_size() { let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 6]); diff --git a/tests/derive.rs b/tests/derive.rs index c45cc24..5a378f9 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -290,6 +290,7 @@ fn two_lifetimes() { assert_eq!(upper, None); } +#[cfg(feature = "recursive_count")] #[test] fn recursive_and_empty_input() { // None of the following derives should result in a stack overflow. See