Merge pull request #3 from MarcusGrass/no-std-support

master
Avril 2 years ago committed by GitHub
commit 1a3887c560
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -17,10 +17,12 @@ panic = "unwind"
strip=true strip=true
[features] [features]
default = ["std"]
std = []
# TODO: maybe add an FFI feature, to allow C projects to use it? idk if that's worth it really... # TODO: maybe add an FFI feature, to allow C projects to use it? idk if that's worth it really...
[dependencies] [dependencies]
serde = {version = "1.0.116", features = ["derive"], optional = true} serde = {version = "1.0.116", default-features = false, features = ["derive", "alloc"], optional = true}
# TODO: optional smallvec feature: instead of heap-allocating the first page, it can be placed on the stack. # TODO: optional smallvec feature: instead of heap-allocating the first page, it can be placed on the stack.

@ -33,7 +33,7 @@ where K: Collapse
/// Replace the held value with another, yielding the old one /// Replace the held value with another, yielding the old one
pub fn insert(&mut self, value: V) -> V pub fn insert(&mut self, value: V) -> V
{ {
std::mem::replace(&mut self.0.as_mut().unwrap().1, value) core::mem::replace(&mut self.0.as_mut().unwrap().1, value)
} }
/// Remove this entry from the `Map`, yielding the removed value /// Remove this entry from the `Map`, yielding the removed value
pub fn remove(self) -> V pub fn remove(self) -> V

@ -2,7 +2,7 @@
use super::*; use super::*;
/// An iterator over `Page`s /// An iterator over `Page`s
pub struct Pages<'a, K, V>(pub(crate) std::slice::Iter<'a, Page<K,V>>); pub struct Pages<'a, K, V>(pub(crate) core::slice::Iter<'a, Page<K,V>>);
impl<'a, K, V> Iterator for Pages<'a,K,V> impl<'a, K, V> Iterator for Pages<'a,K,V>
{ {
@ -18,7 +18,7 @@ impl<'a, K, V> Iterator for Pages<'a,K,V>
} }
/// A mutable iterator over `Page`s /// A mutable iterator over `Page`s
pub struct PagesMut<'a, K, V>(pub(crate) std::slice::IterMut<'a, Page<K,V>>); pub struct PagesMut<'a, K, V>(pub(crate) core::slice::IterMut<'a, Page<K,V>>);
impl<'a, K, V> Iterator for PagesMut<'a,K,V> impl<'a, K, V> Iterator for PagesMut<'a,K,V>
{ {
@ -34,10 +34,10 @@ impl<'a, K, V> Iterator for PagesMut<'a,K,V>
} }
impl<'a, K, V> ExactSizeIterator for PagesMut<'a,K,V>{} impl<'a, K, V> ExactSizeIterator for PagesMut<'a,K,V>{}
impl<'a, K, V> std::iter::FusedIterator for PagesMut<'a,K,V>{} impl<'a, K, V> core::iter::FusedIterator for PagesMut<'a,K,V>{}
/// An iterator over elements in a `Page`. /// An iterator over elements in a `Page`.
pub struct PageElements<'a, K, V>(pub(crate) std::slice::Iter<'a, Option<(K,V)>>); pub struct PageElements<'a, K, V>(pub(crate) core::slice::Iter<'a, Option<(K,V)>>);
impl<'a, K, V> Iterator for PageElements<'a,K,V> impl<'a, K, V> Iterator for PageElements<'a,K,V>
{ {
@ -57,10 +57,10 @@ impl<'a, K, V> Iterator for PageElements<'a,K,V>
(0, self.0.size_hint().1) (0, self.0.size_hint().1)
} }
} }
impl<'a, K, V> std::iter::FusedIterator for PageElements<'a,K,V>{} impl<'a, K, V> core::iter::FusedIterator for PageElements<'a,K,V>{}
/// A mutable iterator over elements in a `Page`. /// A mutable iterator over elements in a `Page`.
pub struct PageElementsMut<'a, K, V>(pub(crate) std::slice::IterMut<'a, Option<(K,V)>>); pub struct PageElementsMut<'a, K, V>(pub(crate) core::slice::IterMut<'a, Option<(K,V)>>);
impl<'a, K, V> Iterator for PageElementsMut<'a,K,V> impl<'a, K, V> Iterator for PageElementsMut<'a,K,V>
{ {
@ -79,7 +79,7 @@ impl<'a, K, V> Iterator for PageElementsMut<'a,K,V>
(0, self.0.size_hint().1) (0, self.0.size_hint().1)
} }
} }
impl<'a, K, V> std::iter::FusedIterator for PageElementsMut<'a,K,V>{} impl<'a, K, V> core::iter::FusedIterator for PageElementsMut<'a,K,V>{}
/// A consuming iterator over elements in a `Page`. /// A consuming iterator over elements in a `Page`.
pub struct IntoPageElements<K,V>(pub(crate) [Option<(K,V)>; MAX], pub(crate) usize); pub struct IntoPageElements<K,V>(pub(crate) [Option<(K,V)>; MAX], pub(crate) usize);
@ -104,7 +104,7 @@ impl<K,V> Iterator for IntoPageElements<K,V>
(0, Some(self.0.len())) (0, Some(self.0.len()))
} }
} }
impl<K, V> std::iter::FusedIterator for IntoPageElements<K,V>{} impl<K, V> core::iter::FusedIterator for IntoPageElements<K,V>{}
/// An iterator over entries in a `Map`. /// An iterator over entries in a `Map`.
pub struct Iter<'a, K, V>(pub(crate) Option<PageElements<'a,K,V>>, pub(crate) Pages<'a, K,V>); pub struct Iter<'a, K, V>(pub(crate) Option<PageElements<'a,K,V>>, pub(crate) Pages<'a, K,V>);
@ -131,7 +131,7 @@ where K: Collapse
(0, self.1.size_hint().1.map(|x| x * MAX)) (0, self.1.size_hint().1.map(|x| x * MAX))
} }
} }
impl<'a, K: Collapse, V> std::iter::FusedIterator for Iter<'a, K,V>{} impl<'a, K: Collapse, V> core::iter::FusedIterator for Iter<'a, K,V>{}
/// A mutable iterator over entries in a `Map`. /// A mutable iterator over entries in a `Map`.
pub struct IterMut<'a, K, V>(pub(crate) Option<PageElementsMut<'a,K,V>>, pub(crate) PagesMut<'a, K,V>); pub struct IterMut<'a, K, V>(pub(crate) Option<PageElementsMut<'a,K,V>>, pub(crate) PagesMut<'a, K,V>);
@ -158,10 +158,10 @@ where K: Collapse
(0, self.1.size_hint().1.map(|x| x * MAX)) (0, self.1.size_hint().1.map(|x| x * MAX))
} }
} }
impl<'a, K: Collapse, V> std::iter::FusedIterator for IterMut<'a, K,V>{} impl<'a, K: Collapse, V> core::iter::FusedIterator for IterMut<'a, K,V>{}
/// A consuming iterator over entries in a `Map`. /// A consuming iterator over entries in a `Map`.
pub struct IntoIter<K, V>(pub(crate) Option<IntoPageElements<K,V>>, pub(crate) std::vec::IntoIter<Page<K,V>>); pub struct IntoIter<K, V>(pub(crate) Option<IntoPageElements<K,V>>, pub(crate) vec::IntoIter<Page<K,V>>);
impl<K, V> Iterator for IntoIter<K,V> impl<K, V> Iterator for IntoIter<K,V>
where K: Collapse where K: Collapse
@ -187,7 +187,7 @@ where K: Collapse
} }
} }
impl<K: Collapse, V> std::iter::FusedIterator for IntoIter<K,V>{} impl<K: Collapse, V> core::iter::FusedIterator for IntoIter<K,V>{}
#[cfg(test)] #[cfg(test)]
mod tests mod tests

@ -26,16 +26,19 @@
//! //!
//! ### When not to use //! ### When not to use
//! Generally don't use this if your key would have a lot of collisions being represents in 8 bits, otherwise it might be a faster alternative to hash-based maps. You should check yourself before sticking with this crate instead of `std`'s vectorised map implementations. //! Generally don't use this if your key would have a lot of collisions being represents in 8 bits, otherwise it might be a faster alternative to hash-based maps. You should check yourself before sticking with this crate instead of `std`'s vectorised map implementations.
#![cfg_attr(any(not(test), not(feature = "std")), no_std)]
#![cfg_attr(nightly, feature(test))] #![cfg_attr(nightly, feature(test))]
#![cfg_attr(nightly, feature(drain_filter))] #![cfg_attr(nightly, feature(drain_filter))]
#![cfg_attr(nightly, feature(never_type))] #![cfg_attr(nightly, feature(never_type))]
#[cfg(nightly)] extern crate test; #[cfg(all(nightly, test))] extern crate test;
extern crate alloc;
const MAX: usize = 256; const MAX: usize = 256;
use std::borrow::Borrow; use alloc::vec;
use alloc::vec::Vec;
use core::borrow::Borrow;
pub mod iter; pub mod iter;
use iter::*; use iter::*;
@ -138,7 +141,7 @@ where K: Collapse
/// This is a count that iterates over all slots, if possible store it in a temporary instead of re-calling it many times. /// This is a count that iterates over all slots, if possible store it in a temporary instead of re-calling it many times.
pub fn len(&self) -> usize pub fn len(&self) -> usize
{ {
self.0.iter().map(Option::as_ref).filter_map(std::convert::identity).count() self.0.iter().map(Option::as_ref).filter_map(core::convert::identity).count()
} }
/// An iterator over all entries currently in this page /// An iterator over all entries currently in this page
@ -166,11 +169,11 @@ where K: Collapse
fn replace(&mut self, k: K, v: V) -> Option<(K,V)> fn replace(&mut self, k: K, v: V) -> Option<(K,V)>
{ {
std::mem::replace(&mut self.0[usize::from(k.collapse())], Some((k,v))) core::mem::replace(&mut self.0[usize::from(k.collapse())], Some((k,v)))
} }
} }
impl<K: Collapse, V> std::iter::FromIterator<(K, V)> for Map<K,V> impl<K: Collapse, V> core::iter::FromIterator<(K, V)> for Map<K,V>
{ {
fn from_iter<I: IntoIterator<Item=(K, V)>>(iter: I) -> Self fn from_iter<I: IntoIterator<Item=(K, V)>>(iter: I) -> Self
{ {
@ -210,10 +213,50 @@ where K: Collapse
/// A small hashtable-like map with byte sized key indecies. /// A small hashtable-like map with byte sized key indecies.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))]
// TODO: Replace with `SmallVec<[Page<TKey, TValue>; 1]>` when feature that adds `smallvec` is enabled (this will allocate the first page on the stack, and the rest on the heap. // TODO: Replace with `SmallVec<[Page<TKey, TValue>; 1]>` when feature that adds `smallvec` is enabled (this will allocate the first page on the stack, and the rest on the heap.
pub struct Map<TKey, TValue>(Vec<Page<TKey,TValue>>); pub struct Map<TKey, TValue>(Vec<Page<TKey,TValue>>);
#[cfg(feature = "serde")]
struct MapVisitor<TKey, TValue> {
_pd: core::marker::PhantomData<(TKey, TValue)>,
}
#[cfg(feature = "serde")]
impl<'de, TKey, TValue> serde::de::Deserialize<'de> for Map<TKey, TValue> where TKey: Collapse + serde::Deserialize<'de>, TValue: serde::Deserialize<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
deserializer.deserialize_map(MapVisitor { _pd: core::marker::PhantomData::default() })
}
}
/// Just taken from [serde.rs' examples](https://serde.rs/deserialize-map.html)
#[cfg(feature = "serde")]
impl<'de, TKey, TValue> serde::de::Visitor<'de> for MapVisitor<TKey, TValue> where TKey: Collapse + serde::Deserialize<'de>, TValue: serde::Deserialize<'de> {
type Value = Map<TKey, TValue>;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("A map")
}
fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error> where A: serde::de::MapAccess<'de> {
let mut map = Map::with_capacity(access.size_hint().unwrap_or(1));
while let Some((key, value)) = access.next_entry()? {
map.insert(key, value);
}
Ok(map)
}
}
#[cfg(feature = "serde")]
impl<TKey, TValue> serde::Serialize for Map<TKey, TValue> where TKey: Collapse + serde::Serialize, TValue: serde::Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
let mut m = serializer.serialize_map(Some(self.len()))?;
for (k, v) in self.iter() {
m.serialize_entry(k, v)?;
}
m.end()
}
}
impl<K,V> Map<K,V> impl<K,V> Map<K,V>
{ {
/// Returns the currently allocated size of the map in bytes (including currently unused reserved space.) /// Returns the currently allocated size of the map in bytes (including currently unused reserved space.)
@ -221,8 +264,8 @@ impl<K,V> Map<K,V>
#[allow(dead_code)] // Used in test cases, but compiler still warns about it #[allow(dead_code)] // Used in test cases, but compiler still warns about it
pub(crate) fn internal_size_bytes(&self) -> usize pub(crate) fn internal_size_bytes(&self) -> usize
{ {
self.0.capacity() * std::mem::size_of::<Page<K,V>>() self.0.capacity() * core::mem::size_of::<Page<K,V>>()
//self.0.iter().map(std::mem::size_of_val).sum::<usize>() //self.0.iter().map(core::mem::size_of_val).sum::<usize>()
} }
} }
@ -432,7 +475,7 @@ where K: Collapse
{ {
match page.search_mut(&key) { match page.search_mut(&key) {
Some((ref ok, ov)) if ok.eq(&key) => { Some((ref ok, ov)) if ok.eq(&key) => {
return Some(std::mem::replace(ov, value)); return Some(core::mem::replace(ov, value));
}, },
empty @ None => { empty @ None => {
return empty.replace((key, value)) return empty.replace((key, value))
@ -484,7 +527,7 @@ impl<K: Collapse, V> IntoIterator for Map<K,V>
} }
} }
impl<K: Collapse, V> std::iter::Extend<(K,V)> for Map<K,V> impl<K: Collapse, V> core::iter::Extend<(K,V)> for Map<K,V>
{ {
fn extend<T: IntoIterator<Item = (K,V)>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = (K,V)>>(&mut self, iter: T) {
// we can probably optimise this better, right? // we can probably optimise this better, right?
@ -495,8 +538,10 @@ impl<K: Collapse, V> std::iter::Extend<(K,V)> for Map<K,V>
} }
} }
use std::hash::{Hash, Hasher,}; use core::hash::{Hash, Hasher,};
use std::ops::{Index, IndexMut}; use core::ops::{Index, IndexMut};
#[cfg(feature = "serde")]
use serde::ser::SerializeMap;
impl<T: ?Sized + Hash + Eq> Collapse for T impl<T: ?Sized + Hash + Eq> Collapse for T
{ {

@ -1,6 +1,6 @@
//! Because we can't #derive big arrays on stable smh //! Because we can't #derive big arrays on stable smh
use super::*; use super::*;
use std::{ use core::{
fmt::{self, Debug,}, fmt::{self, Debug,},
hash, hash,
}; };
@ -49,7 +49,7 @@ impl<K: hash::Hash, V: hash::Hash> hash::Hash for Page<K,V> {
#[cfg(feature="serde")] #[cfg(feature="serde")]
const _: () = { const _: () = {
use serde::*; use serde::*;
use std::marker::PhantomData; use core::marker::PhantomData;
impl<K,V> serde::Serialize for Page<K,V> impl<K,V> serde::Serialize for Page<K,V>
where K:Serialize, V: Serialize where K:Serialize, V: Serialize
@ -93,7 +93,7 @@ const _: () = {
Ok(Page(elems)) Ok(Page(elems))
} else { } else {
use serde::de::Error; use serde::de::Error;
Err(A::Error::custom(format!("Expected {} elemts, got {}", MAX, i))) Err(A::Error::custom(alloc::format!("Expected {} elemts, got {}", MAX, i)))
} }
} }
} }

@ -6,7 +6,7 @@
//! //!
//! If/when Rust gets specialisation, this will be unneeded. //! If/when Rust gets specialisation, this will be unneeded.
use super::*; use super::*;
use std::num::*; use core::num::*;
/// Sealed trait allowing for wrapping primitive types with a more efficient implemntation for the `Collapse` trait. /// Sealed trait allowing for wrapping primitive types with a more efficient implemntation for the `Collapse` trait.
/// This should not be used for much directly, instead use the newtype shim `Primitive<T>`. /// This should not be used for much directly, instead use the newtype shim `Primitive<T>`.

@ -12,12 +12,12 @@ use super::*;
/// A set of only non-zero bytes. /// A set of only non-zero bytes.
/// ///
/// This type is entirely space efficient and will only ever allocate `256` bytes of memory. /// This type is entirely space efficient and will only ever allocate `256` bytes of memory.
pub type NonZeroByteSet = Set<std::num::NonZeroU8>; pub type NonZeroByteSet = Set<core::num::NonZeroU8>;
/// A set of non-zero signed 8-bit integers. /// A set of non-zero signed 8-bit integers.
/// ///
/// This type is entirely space efficient and will only ever allocate `256` bytes of memory. /// This type is entirely space efficient and will only ever allocate `256` bytes of memory.
pub type NonZeroI8Set = Set<std::num::NonZeroI8>; pub type NonZeroI8Set = Set<core::num::NonZeroI8>;
/// A set of non-zero unsigned 8-bit integers. /// A set of non-zero unsigned 8-bit integers.
/// ///

Loading…
Cancel
Save