diff --git a/.travis.yml b/.travis.yml index c6ae7ef2..462920d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,20 +8,28 @@ matrix: # (we only use it in benchmarks anyway...) - cargo generate-lockfile - cargo update -p lazy_static --precise 1.0.2 + env: + - FEATURES='force_std' - rust: stable env: - FEATURES='serde-1' + - TEST_FEATURES='force_std' - rust: beta + env: + - TEST_FEATURES='force_std' - rust: nightly + env: + - TEST_FEATURES='force_std' - rust: nightly env: - FEATURES='test_low_transition_point' + - TEST_FEATURES='force_std' branches: only: - master script: - | cargo build --verbose --features "$FEATURES" && - cargo test --verbose --features "$FEATURES" && - cargo test --release --verbose --features "$FEATURES" && + cargo test --verbose --features "$FEATURES $TEST_FEATURES" && + cargo test --release --verbose --features "$FEATURES $TEST_FEATURES" && cargo doc --verbose --features "$FEATURES" diff --git a/Cargo.toml b/Cargo.toml index a0548389..854c0b40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,12 @@ indexmap. keywords = ["hashmap"] categories = ["data-structures"] +[package.metadata.release] +no-dev-version = true + +[package.metadata.docs.rs] +features = ["serde-1"] + [lib] bench = false @@ -31,7 +37,7 @@ bench = false serde = { version = "1.0", optional = true } [dev-dependencies] -itertools = "0.7.0" # 0.8 not compiles on Rust 1.18 +itertools = "0.7.0" rand = "0.4" quickcheck = { version = "0.6", default-features = false } fnv = "1.0" @@ -46,11 +52,34 @@ serde-1 = ["serde"] test_low_transition_point = [] test_debug = [] +force_std = [] + [profile.bench] debug = true -[package.metadata.release] -no-dev-version = true +[build-dependencies] +autocfg = "0.1.5" -[package.metadata.docs.rs] -features = ["serde-1"] +[[test]] +name = "tests" +required-features = [ "force_std" ] + +[[test]] +name = "serde" +required-features = [ "force_std" ] + +[[test]] +name = "quick" +required-features = [ "force_std" ] + +[[test]] +name = "equivalent_trait" +required-features = [ "force_std" ] + +[[bench]] +name = "bench" +required-features = [ "force_std" ] + +[[bench]] +name = "faststring" +required-features = [ "force_std" ] diff --git a/benches/bench.rs b/benches/bench.rs index b3e9915f..ae1a4dac 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -580,7 +580,7 @@ fn remove_ordermap_100_000(b: &mut Bencher) { b.iter(|| { let mut map = map.clone(); for key in &keys { - map.remove(key).is_some(); + let _ = map.remove(key).is_some(); } assert_eq!(map.len(), 0); map diff --git a/build.rs b/build.rs new file mode 100644 index 00000000..320cb495 --- /dev/null +++ b/build.rs @@ -0,0 +1,9 @@ +extern crate autocfg; + +fn main() { + //let ac = autocfg::new(); + //ac.emit_sysroot_crate("std"); + //ac.emit_sysroot_crate("alloc"); + autocfg::emit("std"); + //autocfg::emit("alloc"); +} diff --git a/src/equivalent.rs b/src/equivalent.rs index d72b2ef3..12b1f0b4 100644 --- a/src/equivalent.rs +++ b/src/equivalent.rs @@ -1,5 +1,5 @@ -use std::borrow::Borrow; +use core::borrow::Borrow; /// Key equivalence trait. /// diff --git a/src/lib.rs b/src/lib.rs index 1a0655e3..fc3e06ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,19 @@ //! upgrade policy, where in a later 1.x version, we will raise the minimum //! required Rust version. +#![cfg_attr(all(not(test), has_alloc, not(feature = "force_std")), no_std)] + +extern crate core; + +#[cfg(all(has_alloc, not(feature = "force_std")))] +extern crate alloc; + +#[cfg(all(has_alloc, has_std))] +extern crate std; + +#[cfg(any(not(has_alloc), feature = "force_std"))] +extern crate std as alloc; + #[macro_use] mod macros; #[cfg(feature = "serde-1")] diff --git a/src/macros.rs b/src/macros.rs index b8c6f9b1..553a3ae3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,10 +1,10 @@ - #[macro_export] -/// Create an `IndexMap` from a list of key-value pairs +/// Create an `IndexMap` from a list of key-value pairs. Requires `std` to be available. /// /// ## Example /// /// ``` +/// /// #[macro_use] extern crate indexmap; /// # fn main() { /// @@ -20,6 +20,7 @@ /// assert_eq!(map.keys().next(), Some(&"a")); /// # } /// ``` +#[cfg(any(has_std, feature = "force_std", test))] macro_rules! indexmap { (@single $($x:tt)*) => (()); (@count $($rest:expr),*) => (<[()]>::len(&[$(indexmap!(@single $rest)),*])); @@ -58,6 +59,7 @@ macro_rules! indexmap { /// assert_eq!(set.iter().next(), Some(&"a")); /// # } /// ``` +#[cfg(any(has_std, feature = "force_std", test))] macro_rules! indexset { (@single $($x:tt)*) => (()); (@count $($rest:expr),*) => (<[()]>::len(&[$(indexset!(@single $rest)),*])); diff --git a/src/map.rs b/src/map.rs index a52d3d88..8c26fba1 100644 --- a/src/map.rs +++ b/src/map.rs @@ -3,17 +3,20 @@ pub use mutable_keys::MutableKeys; -use std::hash::Hash; -use std::hash::BuildHasher; -use std::hash::Hasher; -use std::iter::FromIterator; -use std::collections::hash_map::RandomState; -use std::ops::RangeFull; - -use std::cmp::{max, Ordering}; -use std::fmt; -use std::mem::{replace}; -use std::marker::PhantomData; +use core::hash::Hash; +use core::hash::BuildHasher; +use core::hash::Hasher; +use core::iter::FromIterator; +use core::ops::RangeFull; + +use core::cmp::{max, Ordering}; +use core::fmt; +use core::mem::{replace}; +use core::marker::PhantomData; + +use alloc::vec::Vec; +use alloc::boxed::Box; +use alloc::vec; use util::{third, ptrdistance, enumerate}; use equivalent::Equivalent; @@ -246,6 +249,7 @@ impl ShortHashProxy /// # Examples /// /// ``` +/// # extern crate indexmap; /// use indexmap::IndexMap; /// /// // count the frequency of each letter in a sentence. @@ -260,7 +264,15 @@ impl ShortHashProxy /// assert_eq!(letters.get(&'y'), None); /// ``` #[derive(Clone)] -pub struct IndexMap { +#[cfg(any(has_std, feature = "force_std", test))] +pub struct IndexMap { + core: OrderMapCore, + hash_builder: S, +} + +#[derive(Clone)] +#[cfg(not(any(has_std, feature = "force_std", test)))] +pub struct IndexMap { core: OrderMapCore, hash_builder: S, } @@ -351,7 +363,8 @@ macro_rules! probe_loop { } } -impl IndexMap { +#[cfg(any(has_std, feature = "force_std", test))] +impl IndexMap { /// Create a new map. (Does not allocate.) pub fn new() -> Self { Self::with_capacity(0) @@ -1492,9 +1505,9 @@ fn find_existing_entry_at(indices: &[Pos], hash: HashValue, }); } -use std::slice::Iter as SliceIter; -use std::slice::IterMut as SliceIterMut; -use std::vec::IntoIter as VecIntoIter; +use core::slice::Iter as SliceIter; +use core::slice::IterMut as SliceIterMut; +use alloc::vec::IntoIter as VecIntoIter; /// An iterator over the keys of a `IndexMap`. /// @@ -1730,7 +1743,7 @@ impl fmt::Debug for IntoIter { /// [`drain`]: struct.IndexMap.html#method.drain /// [`IndexMap`]: struct.IndexMap.html pub struct Drain<'a, K, V> where K: 'a, V: 'a { - pub(crate) iter: ::std::vec::Drain<'a, Bucket> + pub(crate) iter: ::alloc::vec::Drain<'a, Bucket> } impl<'a, K, V> Iterator for Drain<'a, K, V> { @@ -1779,7 +1792,7 @@ impl IntoIterator for IndexMap } } -use std::ops::{Index, IndexMut}; +use core::ops::{Index, IndexMut}; impl<'a, K, V, Q: ?Sized, S> Index<&'a Q> for IndexMap where Q: Hash + Equivalent, diff --git a/src/mutable_keys.rs b/src/mutable_keys.rs index 9291f96f..fc1f16f0 100644 --- a/src/mutable_keys.rs +++ b/src/mutable_keys.rs @@ -1,6 +1,6 @@ -use std::hash::Hash; -use std::hash::BuildHasher; +use core::hash::Hash; +use core::hash::BuildHasher; use super::{IndexMap, Equivalent}; diff --git a/src/set.rs b/src/set.rs index 7d1a956a..97b6c95e 100644 --- a/src/set.rs +++ b/src/set.rs @@ -1,14 +1,13 @@ //! A hash set implemented using `IndexMap` -use std::cmp::Ordering; -use std::collections::hash_map::RandomState; -use std::fmt; -use std::iter::{FromIterator, Chain}; -use std::hash::{Hash, BuildHasher}; -use std::ops::RangeFull; -use std::ops::{BitAnd, BitOr, BitXor, Sub}; -use std::slice; -use std::vec; +use core::cmp::Ordering; +use core::fmt; +use core::iter::{FromIterator, Chain}; +use core::hash::{Hash, BuildHasher}; +use core::ops::RangeFull; +use core::ops::{BitAnd, BitOr, BitXor, Sub}; +use core::slice; +use alloc::vec; use super::{IndexMap, Equivalent}; @@ -45,6 +44,7 @@ type Bucket = super::Bucket; /// # Examples /// /// ``` +/// # extern crate indexmap; /// use indexmap::IndexSet; /// /// // Collects which letters appear in a sentence. @@ -56,7 +56,14 @@ type Bucket = super::Bucket; /// assert!(!letters.contains(&'y')); /// ``` #[derive(Clone)] -pub struct IndexSet { +#[cfg(any(has_std, feature = "force_std", test))] +pub struct IndexSet { + map: IndexMap, +} + +#[derive(Clone)] +#[cfg(not(any(has_std, feature = "force_std", test)))] +pub struct IndexSet { map: IndexMap, } @@ -74,6 +81,7 @@ impl fmt::Debug for IndexSet } } +#[cfg(any(has_std, feature = "force_std", test))] impl IndexSet { /// Create a new set. (Does not allocate.) pub fn new() -> Self { diff --git a/src/util.rs b/src/util.rs index 90d3e7e3..6d36971c 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,6 @@ -use std::iter::Enumerate; -use std::mem::size_of; +use core::iter::Enumerate; +use core::mem::size_of; pub fn third(t: (A, B, C)) -> C { t.2 }