Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No std (extends 2018 edition) #18

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ keywords = ["slotmap", "storage", "allocator", "stable", "reference"]
categories = ["data-structures", "memory-management", "caching"]

[features]
default = ["std"]
serde-alloc = ["serde/alloc"]
serde-std = ["serde/std"]
std = []
unstable = []

[dependencies]
serde = { version = "1.0", optional = true, features = ["derive"] }
serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }

[dev-dependencies]
serde = "1.0"
Expand Down
22 changes: 12 additions & 10 deletions src/hop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
//! The trade-off is that compared to a regular `SlotMap` insertion/removal is
//! roughly twice as slow. Random indexing has identical performance for both.

use std;
use std::iter::FusedIterator;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::{Index, IndexMut};
use std::{fmt, ptr};
use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ops::{Index, IndexMut};
use core::{fmt, ptr};

#[cfg(not(feature = "std"))]
use crate::alloc::prelude::*;
#[cfg(feature = "unstable")]
use std::collections::CollectionAllocErr;
use crate::alloc::collections::CollectionAllocErr;

use crate::{DefaultKey, Key, KeyData, Slottable};

Expand Down Expand Up @@ -88,7 +90,7 @@ impl<T: Slottable> Slot<T> {

impl<T: Slottable> Drop for Slot<T> {
fn drop(&mut self) {
if std::mem::needs_drop::<T>() && self.occupied() {
if core::mem::needs_drop::<T>() && self.occupied() {
// This is safe because we checked that we're occupied.
unsafe {
ManuallyDrop::drop(&mut self.u.value);
Expand Down Expand Up @@ -375,7 +377,7 @@ impl<K: Key, V: Slottable> HopSlotMap<K, V> {
{
// In case f panics, we don't make any changes until we have the value.
let new_num_elems = self.num_elems + 1;
if new_num_elems == std::u32::MAX {
if new_num_elems == core::u32::MAX {
panic!("HopSlotMap number of elements overflow");
}

Expand Down Expand Up @@ -455,7 +457,7 @@ impl<K: Key, V: Slottable> HopSlotMap<K, V> {
// contiguous block to the left or right, merging the two blocks to the
// left and right or inserting a new block.
let i = idx as u32;
// use std::hint::unreachable_unchecked;
// use core::hint::unreachable_unchecked;

match (left_vacant, right_vacant) {
(false, false) => {
Expand Down
24 changes: 20 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#![doc(html_root_url = "https://docs.rs/slotmap/0.3.0")]
#![crate_name = "slotmap"]
#![cfg_attr(feature = "unstable", feature(untagged_unions, try_reserve))]
#![cfg_attr(not(feature = "std"), feature(alloc))]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW: I had no_std last night, but that wasn't cargo idiomatic as cargo features are additive, so std is more correct (and common).

#![cfg_attr(any(test, not(feature = "std")), no_std)]

//! # slotmap
//!
Expand Down Expand Up @@ -155,6 +157,18 @@
//! [`slab`]: https://github.com/carllerche/slab
//! [`DefaultKey`]: struct.DefaultKey.html

#[cfg(all(feature = "serde", feature = "std", not(feature = "serde-std")))]
compile_error!("features 'serde' and 'std' are enabled but you also need 'serde-std'!");

#[cfg(not(feature = "std"))]
extern crate alloc;

#[cfg(feature = "std")]
mod alloc {
pub use std::collections;
pub use std::vec;
}

#[cfg(feature = "serde")]
extern crate serde;

Expand All @@ -181,10 +195,12 @@ pub use crate::hop::HopSlotMap;
pub mod secondary;
pub use crate::secondary::SecondaryMap;

#[cfg(feature = "std")]
pub mod sparse_secondary;
#[cfg(feature = "std")]
pub use crate::sparse_secondary::SparseSecondaryMap;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HashMap currently requires std because it assumes the default RandomState, which relies on OSRng. rust-lang/rust#56192


use std::num::NonZeroU32;
use core::num::NonZeroU32;

/// A trait for items that can go in a slot map. Due to current stable Rust
/// restrictions a type must be [`Copy`] to be placed in a slot map. If you must
Expand Down Expand Up @@ -249,11 +265,11 @@ impl KeyData {
}

fn null() -> Self {
Self::new(std::u32::MAX, 1)
Self::new(core::u32::MAX, 1)
}

fn is_null(self) -> bool {
self.idx == std::u32::MAX
self.idx == core::u32::MAX
}

/// Returns the key data as a 64-bit integer. No guarantees about its value
Expand Down Expand Up @@ -485,7 +501,7 @@ mod serialize {
let mut ser_key: SerKey = Deserialize::deserialize(deserializer)?;

// Ensure a.is_null() && b.is_null() implies a == b.
if ser_key.idx == std::u32::MAX {
if ser_key.idx == core::u32::MAX {
ser_key.version = 1;
}

Expand Down
26 changes: 14 additions & 12 deletions src/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@

//! Contains the slot map implementation.

use std;
use std::iter::{Enumerate, FusedIterator};
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::{Index, IndexMut};
use std::{fmt, ptr};
use core::iter::{Enumerate, FusedIterator};
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ops::{Index, IndexMut};
use core::{fmt, ptr};

#[cfg(not(feature = "std"))]
use crate::alloc::prelude::*;
#[cfg(feature = "unstable")]
use std::collections::CollectionAllocErr;
use crate::alloc::collections::CollectionAllocErr;

use crate::{DefaultKey, Key, KeyData, Slottable};

Expand Down Expand Up @@ -71,7 +73,7 @@ impl<T: Slottable> Slot<T> {

impl<T: Slottable> Drop for Slot<T> {
fn drop(&mut self) {
if std::mem::needs_drop::<T>() && self.occupied() {
if core::mem::needs_drop::<T>() && self.occupied() {
// This is safe because we checked that we're occupied.
unsafe {
ManuallyDrop::drop(&mut self.u.value);
Expand Down Expand Up @@ -350,7 +352,7 @@ impl<K: Key, V: Slottable> SlotMap<K, V> {
{
// In case f panics, we don't make any changes until we have the value.
let new_num_elems = self.num_elems + 1;
if new_num_elems == std::u32::MAX {
if new_num_elems == core::u32::MAX {
panic!("SlotMap number of elements overflow");
}

Expand Down Expand Up @@ -791,23 +793,23 @@ pub struct Drain<'a, K: 'a + Key, V: 'a + Slottable> {
#[derive(Debug)]
pub struct IntoIter<K: Key, V: Slottable> {
num_left: usize,
slots: Enumerate<std::vec::IntoIter<Slot<V>>>,
slots: Enumerate<crate::alloc::vec::IntoIter<Slot<V>>>,
_k: PhantomData<fn(K) -> K>,
}

/// An iterator over the key-value pairs in a `SlotMap`.
#[derive(Debug)]
pub struct Iter<'a, K: 'a + Key, V: 'a + Slottable> {
num_left: usize,
slots: Enumerate<std::slice::Iter<'a, Slot<V>>>,
slots: Enumerate<crate::alloc::slice::Iter<'a, Slot<V>>>,
_k: PhantomData<fn(K) -> K>,
}

/// A mutable iterator over the key-value pairs in a `SlotMap`.
#[derive(Debug)]
pub struct IterMut<'a, K: 'a + Key, V: 'a + Slottable> {
num_left: usize,
slots: Enumerate<std::slice::IterMut<'a, Slot<V>>>,
slots: Enumerate<crate::alloc::slice::IterMut<'a, Slot<V>>>,
_k: PhantomData<fn(K) -> K>,
}

Expand Down
29 changes: 16 additions & 13 deletions src/secondary.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
//! Contains the secondary map implementation.

use super::{is_older_version, Key, KeyData};
use std;
use std::hint::unreachable_unchecked;
use std::iter::{Enumerate, Extend, FromIterator, FusedIterator};
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};

use core::hint::unreachable_unchecked;
use core::iter::{Enumerate, Extend, FromIterator, FusedIterator};
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};

#[cfg(not(feature = "std"))]
use crate::alloc::prelude::*;
#[cfg(feature = "unstable")]
use std::collections::CollectionAllocErr;
use crate::alloc::collections::CollectionAllocErr;

// We could use unions to remove the memory overhead of Option here as well, but
// until non-Copy elements inside unions stabilize it's better to give users at
Expand Down Expand Up @@ -281,7 +284,7 @@ impl<K: Key, V> SecondaryMap<K, V> {

let slot = &mut self.slots[key.idx as usize];
if slot.version == key.version.get() {
return std::mem::replace(&mut slot.value, Some(value));
return core::mem::replace(&mut slot.value, Some(value));
}

if slot.occupied() {
Expand Down Expand Up @@ -336,7 +339,7 @@ impl<K: Key, V> SecondaryMap<K, V> {
// denied as outdated.
slot.version -= 1;
self.num_elems -= 1;
return Some(std::mem::replace(&mut slot.value, None).unwrap());
return Some(core::mem::replace(&mut slot.value, None).unwrap());
}
}

Expand Down Expand Up @@ -773,23 +776,23 @@ pub struct Drain<'a, K: Key + 'a, V: 'a> {
#[derive(Debug)]
pub struct IntoIter<K: Key, V> {
num_left: usize,
slots: Enumerate<std::vec::IntoIter<Slot<V>>>,
slots: Enumerate<crate::alloc::vec::IntoIter<Slot<V>>>,
_k: PhantomData<fn(K) -> K>,
}

/// An iterator over the key-value pairs in a `SecondaryMap`.
#[derive(Debug)]
pub struct Iter<'a, K: Key + 'a, V: 'a> {
num_left: usize,
slots: Enumerate<std::slice::Iter<'a, Slot<V>>>,
slots: Enumerate<core::slice::Iter<'a, Slot<V>>>,
_k: PhantomData<fn(K) -> K>,
}

/// A mutable iterator over the key-value pairs in a `SecondaryMap`.
#[derive(Debug)]
pub struct IterMut<'a, K: Key + 'a, V: 'a> {
num_left: usize,
slots: Enumerate<std::slice::IterMut<'a, Slot<V>>>,
slots: Enumerate<core::slice::IterMut<'a, Slot<V>>>,
_k: PhantomData<fn(K) -> K>,
}

Expand Down Expand Up @@ -820,7 +823,7 @@ impl<'a, K: Key, V> Iterator for Drain<'a, K, V> {
let idx = self.cur;
self.cur += 1;

if let Some(value) = std::mem::replace(&mut self.sm.slots[idx].value, None) {
if let Some(value) = core::mem::replace(&mut self.sm.slots[idx].value, None) {
let key = KeyData::new(idx as u32, self.sm.slots[idx].version);
self.sm.slots[idx].version -= 1;
self.sm.num_elems -= 1;
Expand Down Expand Up @@ -848,7 +851,7 @@ impl<K: Key, V> Iterator for IntoIter<K, V> {

fn next(&mut self) -> Option<(K, V)> {
while let Some((idx, mut slot)) = self.slots.next() {
if let Some(value) = std::mem::replace(&mut slot.value, None) {
if let Some(value) = core::mem::replace(&mut slot.value, None) {
let key = KeyData::new(idx as u32, slot.version);
self.num_left -= 1;
return Some((key.into(), value));
Expand Down
16 changes: 9 additions & 7 deletions src/sparse_secondary.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
//! Contains the sparse secondary map implementation.

use super::{is_older_version, Key, KeyData};
use std::hash;
use std::collections::hash_map::{self, HashMap};
use std::iter::{Extend, FromIterator, FusedIterator};
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};

use core::iter::{Extend, FromIterator, FusedIterator};
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use core::hash;

use crate::alloc::collections::hash_map::{self, HashMap};

#[cfg(feature = "unstable")]
use std::collections::CollectionAllocErr;
use crate::alloc::collections::CollectionAllocErr;

#[derive(Debug)]
struct Slot<T> {
Expand Down Expand Up @@ -283,7 +285,7 @@ impl<K: Key, V, S: hash::BuildHasher> SparseSecondaryMap<K, V, S> {

if let Some(slot) = self.slots.get_mut(&key.idx) {
if slot.version == key.version.get() {
return Some(std::mem::replace(&mut slot.value, value));
return Some(core::mem::replace(&mut slot.value, value));
}

// Don't replace existing newer values.
Expand Down