no_std support
I’m quite pleased with how this has turned out. Given the stability-despite-instability of hashbrown (that the API surface we’re depending on hasn’t changed since 0.1.1), and the deliberate altered SemVer guarantees for it, it was very tempting to leave the hashbrown range open, `version = ">=0.1.1"` or at least `version = ">=0.1.1, <1"`, but for some reason or other I ended up deciding not to. I’m still of two minds about it, really.
This commit is contained in:
parent
98f2816e62
commit
0a1c85f865
|
@ -1,9 +1,12 @@
|
|||
language: rust
|
||||
rust:
|
||||
- 1.34.0
|
||||
- 1.36.0
|
||||
- nightly
|
||||
- stable
|
||||
script:
|
||||
- if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo bench; fi
|
||||
- if [[ "$(rustc --version)" =~ 1.36.0 ]]; then cp test-oldest-Cargo.lock Cargo.lock; fi
|
||||
- cargo test
|
||||
- cargo test --release
|
||||
- cargo test --no-default-features --features hashbrown
|
||||
- cargo test --release --no-default-features --features hashbrown
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
|
||||
- Relicensed from MIT/Apache-2.0 to BlueOak-1.0.0/MIT/Apache-2.0.
|
||||
|
||||
- Increased the minimum supported version of Rust from 1.7.0 to 1.34.0.
|
||||
- Increased the minimum supported version of Rust from 1.7.0 to 1.36.0.
|
||||
|
||||
- no_std is now possible in the usual way (default Cargo feature 'std'),
|
||||
depending on alloc and hashbrown.
|
||||
|
||||
- Removed the `bench` Cargo feature which was mostly to work around historical
|
||||
Cargo limitations, but was solved by moving benchmarks from `src/lib.rs` to
|
||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -3,10 +3,18 @@ name = "anymap"
|
|||
version = "0.12.1"
|
||||
authors = ["Chris Morgan <rust@chrismorgan.info>"]
|
||||
edition = "2018"
|
||||
rust-version = "1.34"
|
||||
rust-version = "1.36"
|
||||
description = "A safe and convenient store for one value of each type"
|
||||
repository = "https://github.com/chris-morgan/anymap"
|
||||
keywords = ["container", "any", "map"]
|
||||
categories = ["rust-patterns", "data-structures"]
|
||||
categories = ["rust-patterns", "data-structures", "no-std"]
|
||||
license = "BlueOak-1.0.0 OR MIT OR Apache-2.0"
|
||||
exclude = ["test", "benches", ".travis.yml", ".gitignore"]
|
||||
include = ["/README.md", "/COPYING", "/CHANGELOG.md", "/src"]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
|
||||
[dependencies]
|
||||
# The hashbrown feature, disabled by default, is exposed under different stability guarantees than the usual SemVer ones: by preference the version range will only be extended, but it may be shrunk in a MINOR release. See README.md.
|
||||
hashbrown = { version = ">=0.1.1, <0.13", optional = true }
|
||||
|
|
20
README.md
20
README.md
|
@ -10,6 +10,26 @@ The ``AnyMap`` type is a friendly wrapper around a ``HashMap<TypeId, Box<dyn Any
|
|||
|
||||
What this means is that in an ``AnyMap`` you may store zero or one values for every type.
|
||||
|
||||
## Cargo features/dependencies/usage
|
||||
|
||||
Typical Cargo.toml usage:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
anymap = "1.0.0-beta.1"
|
||||
```
|
||||
|
||||
No-std usage, using `alloc` and the [hashbrown](https://rust-lang.github.io/hashbrown) crate instead of `std::collections::HashMap`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
anymap = { version = "1.0.0-beta.1", default-features = false, features = ["hashbrown"] }
|
||||
```
|
||||
|
||||
The `std` feature is enabled by default. The `hashbrown` feature overrides it. At least one of the two must be enabled.
|
||||
|
||||
**On stability:** hashbrown is still pre-1.0.0 and experiencing breaking changes. Because it’s useful for a small fraction of users, I am retaining it, but with *different compatibility guarantees to the typical SemVer ones*. Where possible, I will just widen the range for new releases of hashbrown (e.g. change `0.12` to `>=0.12, <0.14` when they release 0.13.0), but if an incompatible change occurs, I may drop support for older versions of hashbrown with a bump to the *minor* part of the anymap version number (e.g. 1.1.0, 1.2.0). Iff you’re using this feature, this is cause to *consider* using a tilde requirement like `"~1.0"` (or spell it out as `>=1, <1.1`).
|
||||
|
||||
## Unsafe code in this library
|
||||
|
||||
This library uses a fair bit of unsafe code for several reasons:
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use core::fmt;
|
||||
use core::any::Any;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait CloneToAny {
|
||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -4,9 +4,20 @@
|
|||
|
||||
#![warn(missing_docs, unused_results)]
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use core::any::{Any, TypeId};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "hashbrown")))]
|
||||
compile_error!("anymap: you must enable the 'std' feature or the 'hashbrown' feature");
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use raw::RawMap;
|
||||
use any::{UncheckedAnyExt, IntoBox};
|
||||
pub use any::CloneAny;
|
||||
|
|
13
src/raw.rs
13
src/raw.rs
|
@ -4,7 +4,12 @@
|
|||
|
||||
use core::any::{Any, TypeId};
|
||||
use core::borrow::Borrow;
|
||||
#[cfg(all(feature = "std", not(feature = "hashbrown")))]
|
||||
use std::collections::hash_map::{self, HashMap};
|
||||
#[cfg(feature = "hashbrown")]
|
||||
use hashbrown::hash_map::{self, HashMap};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::boxed::Box;
|
||||
use core::convert::TryInto;
|
||||
use core::hash::Hash;
|
||||
use core::hash::{Hasher, BuildHasherDefault};
|
||||
|
@ -35,6 +40,8 @@ impl Hasher for TypeIdHasher {
|
|||
|
||||
#[test]
|
||||
fn type_id_hasher() {
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
fn verify_hashing_with(type_id: TypeId) {
|
||||
let mut hasher = TypeIdHasher::default();
|
||||
type_id.hash(&mut hasher);
|
||||
|
@ -260,12 +267,18 @@ impl<A: ?Sized + UncheckedAnyExt> IntoIterator for RawMap<A> {
|
|||
|
||||
/// A view into a single occupied location in a `RawMap`.
|
||||
pub struct OccupiedEntry<'a, A: ?Sized + UncheckedAnyExt> {
|
||||
#[cfg(all(feature = "std", not(feature = "hashbrown")))]
|
||||
inner: hash_map::OccupiedEntry<'a, TypeId, Box<A>>,
|
||||
#[cfg(feature = "hashbrown")]
|
||||
inner: hash_map::OccupiedEntry<'a, TypeId, Box<A>, BuildHasherDefault<TypeIdHasher>>,
|
||||
}
|
||||
|
||||
/// A view into a single empty location in a `RawMap`.
|
||||
pub struct VacantEntry<'a, A: ?Sized + UncheckedAnyExt> {
|
||||
#[cfg(all(feature = "std", not(feature = "hashbrown")))]
|
||||
inner: hash_map::VacantEntry<'a, TypeId, Box<A>>,
|
||||
#[cfg(feature = "hashbrown")]
|
||||
inner: hash_map::VacantEntry<'a, TypeId, Box<A>, BuildHasherDefault<TypeIdHasher>>,
|
||||
}
|
||||
|
||||
/// A view into a single location in a `RawMap`, which may be vacant or occupied.
|
||||
|
|
24
test
24
test
|
@ -2,9 +2,25 @@
|
|||
set -e
|
||||
export RUSTFLAGS="-D warnings"
|
||||
export RUSTDOCFLAGS="-D warnings"
|
||||
cargo +1.34.0 test
|
||||
cargo +1.34.0 test --release
|
||||
run_tests() {
|
||||
for release in "" "--release"; do
|
||||
cargo $1 test $release --no-default-features --features hashbrown
|
||||
cargo $1 test $release --features hashbrown
|
||||
# (2>/dev/null because otherwise you’ll keep seeing errors and double-guessing whether they were supposed to happen or whether the script failed to exit nonzero.)
|
||||
! 2>/dev/null cargo $1 test $release --no-default-features || ! echo "'cargo $1 test $release --no-default-features' failed to fail (sorry, its stderr is suppressed, try it manually)"
|
||||
cargo $1 test $release
|
||||
done
|
||||
}
|
||||
|
||||
# We’d like to test with the oldest declared-supported version of *all* our dependencies.
|
||||
# That means Rust 1.36.0 + hashbrown 0.1.1.
|
||||
# Hence the different lock file.
|
||||
# (Also Rust 1.36.0 can’t read the latest lock file format.)
|
||||
cp test-oldest-Cargo.lock Cargo.lock
|
||||
run_tests +1.36.0
|
||||
rm Cargo.lock
|
||||
run_tests
|
||||
|
||||
cargo clippy
|
||||
cargo test
|
||||
cargo test --release
|
||||
cargo bench
|
||||
cargo doc
|
||||
|
|
32
test-oldest-Cargo.lock
generated
Normal file
32
test-oldest-Cargo.lock
generated
Normal file
|
@ -0,0 +1,32 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "anymap"
|
||||
version = "1.0.0-beta.1"
|
||||
dependencies = [
|
||||
"hashbrown 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum byteorder 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
"checksum hashbrown 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2dfb69c301cead891d010536c7d1b3affe792f5a2be5d6fbd0fcaf7fa0976962"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
Loading…
Reference in a new issue