diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03c5aac..3866d38 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,7 @@ jobs: - uses: actions/checkout@v4 - run: RUSTFLAGS="--deny warnings" cargo build - run: RUSTFLAGS="--deny warnings" cargo build --all-features + - run: RUSTFLAGS="--deny warnings" cargo build --no-default-features tests: name: Run careful tests @@ -55,4 +56,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - run: RUSTDOCFLAGS="--deny warnings" cargo doc --lib \ No newline at end of file + - run: RUSTDOCFLAGS="--deny warnings" cargo doc --lib --all-features + + docrs: + name: Build docrs + runs-on: ubuntu-latest + steps: + - uses: dtolnay/rust-toolchain@nightly + - uses: actions/checkout@v4 + - run: + RUSTFLAGS="--deny warnings" + RUSTDOCFLAGS="--cfg docsrs" + cargo +nightly doc --lib --all-features \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 80e2720..354d8fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog ## 0.14.0 +### Added +- Now library `no_std` friendly. + ### Removed - Helpers `any_value::move_out`, `any_value::move_out_w_size` removed as redundant. diff --git a/Cargo.toml b/Cargo.toml index 26b646f..1791bb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,15 +6,24 @@ version = "0.13.0" edition = "2021" description = "Type erased vector. Most operations can be done without type knowledge. Mostly zero overhead." repository = "https://github.com/tower120/any_vec" -keywords = ["vec", "any", "container"] -categories = ["data-structures"] +keywords = ["vec", "any", "container", "no_std"] +categories = ["data-structures", "no-std", "no-std::no-alloc"] exclude = [".github"] +[features] +default = ["alloc"] +# Include alloc crate. This allows to use mem::Heap. +alloc = [] + +[package.metadata.docs.rs] +features = [] +rustdoc-args = ["--cfg", "docsrs"] + [dependencies] [dev-dependencies] -itertools = "0.10.3" -criterion = "0.3.5" +itertools = "0.12.1" +criterion = "0.5.1" rand = "0.8.5" impls = "1.0.3" diff --git a/Readme.md b/Readme.md index f5aa8be..1dd4f57 100644 --- a/Readme.md +++ b/Readme.md @@ -95,6 +95,10 @@ fn self_push_first_element(any_vec: &mut AnyVec){ `MemBuilder` interface, being stateful, allow to make `Mem`, which can work with complex custom allocators. +## no_std + no_alloc + +This is `no_std` library, which can work without `alloc` too. + ### Changelog See [CHANGELOG.md](CHANGELOG.md) for version differences. diff --git a/doc.bat b/doc.bat new file mode 100644 index 0000000..6754b5c --- /dev/null +++ b/doc.bat @@ -0,0 +1,5 @@ +@echo off +setlocal +set RUSTDOCFLAGS=--cfg docsrs +cargo +nightly doc --lib --no-deps %1 +endlocal \ No newline at end of file diff --git a/src/any_value/lazy_clone.rs b/src/any_value/lazy_clone.rs index 9779507..a1170d7 100644 --- a/src/any_value/lazy_clone.rs +++ b/src/any_value/lazy_clone.rs @@ -1,4 +1,4 @@ -use std::any::TypeId; +use core::any::TypeId; use crate::any_value::{AnyValue, AnyValueCloneable, AnyValueTypeless, AnyValueSizeless}; /// Makes [`AnyValueCloneable`] actually [`Clone`]able. diff --git a/src/any_value/mod.rs b/src/any_value/mod.rs index 243f6d5..cf44f7d 100644 --- a/src/any_value/mod.rs +++ b/src/any_value/mod.rs @@ -28,9 +28,9 @@ pub use lazy_clone::LazyClone; pub use wrapper::AnyValueWrapper; pub use raw::{AnyValueRaw, AnyValueSizelessRaw, AnyValueTypelessRaw}; -use std::any::TypeId; -use std::{mem, ptr}; -use std::mem::{MaybeUninit, size_of}; +use core::any::TypeId; +use core::{mem, ptr, slice}; +use core::mem::{MaybeUninit, size_of}; /// Marker for unknown type. pub struct Unknown; @@ -98,7 +98,7 @@ pub trait AnyValueTypeless: AnyValueSizeless { /// Aligned. #[inline] fn as_bytes(&self) -> &[u8]{ - unsafe{std::slice::from_raw_parts( + unsafe{slice::from_raw_parts( self.as_bytes_ptr(), self.size() )} @@ -151,7 +151,7 @@ pub trait AnyValueSizelessMut: AnyValueSizeless { pub trait AnyValueTypelessMut: AnyValueTypeless + AnyValueSizelessMut { #[inline(always)] fn as_bytes_mut(&mut self) -> &mut [u8]{ - unsafe{std::slice::from_raw_parts_mut( + unsafe{slice::from_raw_parts_mut( self.as_bytes_mut_ptr(), self.size() )} diff --git a/src/any_value/raw.rs b/src/any_value/raw.rs index 8742796..6f139fb 100644 --- a/src/any_value/raw.rs +++ b/src/any_value/raw.rs @@ -1,5 +1,5 @@ -use std::any::TypeId; -use std::ptr::NonNull; +use core::any::TypeId; +use core::ptr::NonNull; use crate::any_value::{AnyValue, AnyValueMut, AnyValueTypelessMut, AnyValueTypeless, AnyValueSizeless, AnyValueSizelessMut}; use crate::any_value::Unknown; diff --git a/src/any_value/wrapper.rs b/src/any_value/wrapper.rs index 2095d79..d76694d 100644 --- a/src/any_value/wrapper.rs +++ b/src/any_value/wrapper.rs @@ -1,5 +1,5 @@ -use std::any::TypeId; -use std::mem::size_of; +use core::any::TypeId; +use core::mem::size_of; use crate::any_value::{AnyValue, AnyValueMut, AnyValueTypelessMut, AnyValueTypeless, AnyValueSizeless, AnyValueSizelessMut}; /// Helper struct to convert concrete type to [`AnyValueMut`]. diff --git a/src/any_vec.rs b/src/any_vec.rs index 7db7eab..088d91d 100644 --- a/src/any_vec.rs +++ b/src/any_vec.rs @@ -1,12 +1,12 @@ -use std::alloc::Layout; -use std::any::TypeId; -use std::fmt::{Debug, Formatter}; -use std::marker::PhantomData; -use std::mem::{ManuallyDrop, MaybeUninit}; -use std::ops::{Deref, DerefMut, Range, RangeBounds}; -use std::ptr::NonNull; -use std::{ptr, slice}; -use std::slice::{from_raw_parts, from_raw_parts_mut}; +use core::alloc::Layout; +use core::any::TypeId; +use core::fmt::{Debug, Formatter}; +use core::marker::PhantomData; +use core::mem::{ManuallyDrop, MaybeUninit}; +use core::ops::{Deref, DerefMut, Range, RangeBounds}; +use core::ptr::NonNull; +use core::{fmt, ptr, slice}; +use core::slice::{from_raw_parts, from_raw_parts_mut}; use crate::{AnyVecTyped, into_range, mem, ops}; use crate::any_value::{AnyValue, AnyValueSizeless}; use crate::any_vec_raw::{AnyVecRaw, DropFn}; @@ -49,9 +49,9 @@ pub mod traits{ /// Does not enforce anything. Default. pub trait None {} - pub use std::marker::Sync; + pub use core::marker::Sync; - pub use std::marker::Send; + pub use core::marker::Send; /// Enforce type [`Clone`]-ability. pub trait Cloneable{} @@ -95,7 +95,7 @@ impl SatisfyTraits for T{} /// You can get it with [`AnyVec::into_raw_parts`], or build/edit /// it manually. And with [`AnyVec::from_raw_parts`], you can construct /// [`AnyVec`]. -pub struct RawParts +pub struct RawParts where M::Mem: MemRawParts { @@ -622,7 +622,7 @@ impl AnyVec /// If the returned [`TempValue`] goes out of scope without being dropped (due to /// [`mem::forget`], for example), the vector will lost and leak last element. /// - /// [`mem::forget`]: std::mem::forget + /// [`mem::forget`]: core::mem::forget /// #[inline] pub fn pop(&mut self) -> Option> { @@ -645,7 +645,7 @@ impl AnyVec /// [`mem::forget`], for example), the vector may have lost and leaked /// elements with indices >= index. /// - /// [`mem::forget`]: std::mem::forget + /// [`mem::forget`]: core::mem::forget /// #[inline] pub fn remove(&mut self, index: usize) -> Remove { @@ -666,7 +666,7 @@ impl AnyVec /// [`mem::forget`], for example), the vector may have lost and leaked /// elements with indices >= index. /// - /// [`mem::forget`]: std::mem::forget + /// [`mem::forget`]: core::mem::forget /// #[inline] pub fn swap_remove(&mut self, index: usize) -> SwapRemove { @@ -694,7 +694,7 @@ impl AnyVec /// [`mem::forget`], for example), the vector may have lost and leaked /// elements with indices in and past the range. /// - /// [`mem::forget`]: std::mem::forget + /// [`mem::forget`]: core::mem::forget /// #[inline] pub fn drain(&mut self, range: impl RangeBounds) -> Drain { @@ -725,7 +725,7 @@ impl AnyVec /// [`mem::forget`], for example), the vector may have lost and leaked /// elements with indices in and past the range. /// - /// [`mem::forget`]: std::mem::forget + /// [`mem::forget`]: core::mem::forget /// #[inline] pub fn splice(&mut self, range: impl RangeBounds, replace_with: I) @@ -814,7 +814,7 @@ impl Clone for AnyVec Debug for AnyVec{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("AnyVec") .field("typeid", &self.element_typeid()) .field("len", &self.len()) @@ -873,7 +873,7 @@ impl<'a, T: 'static, M: MemBuilder + 'a> IntoIterator for AnyVecRef<'a, T, M>{ } } impl<'a, T: 'static + Debug, M: MemBuilder + 'a> Debug for AnyVecRef<'a, T, M>{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } @@ -909,7 +909,7 @@ impl<'a, T: 'static, M: MemBuilder + 'a> IntoIterator for AnyVecMut<'a, T, M>{ } } impl<'a, T: 'static + Debug, M: MemBuilder + 'a> Debug for AnyVecMut<'a, T, M>{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } \ No newline at end of file diff --git a/src/any_vec_ptr.rs b/src/any_vec_ptr.rs index 879544e..4f4ade7 100644 --- a/src/any_vec_ptr.rs +++ b/src/any_vec_ptr.rs @@ -1,7 +1,7 @@ //! Type dispatched analog of `enum{*AnyVecRaw, *AnyVec}`. -use std::marker::PhantomData; -use std::ptr::NonNull; +use core::marker::PhantomData; +use core::ptr::NonNull; use crate::any_value::Unknown; use crate::any_vec_raw::AnyVecRaw; use crate::AnyVec; @@ -121,10 +121,10 @@ impl IAnyVecPtr for AnyVecPtr /// /// All unsafe, because dereferencing pointer is unsafe. pub(crate) mod utils{ - use std::{mem, ptr}; - use std::any::TypeId; - use std::mem::size_of; - use std::ptr::NonNull; + use core::{mem, ptr}; + use core::any::TypeId; + use core::mem::size_of; + use core::ptr::NonNull; use crate::any_value::Unknown; use crate::any_vec_ptr::IAnyVecRawPtr; use crate::AnyVecTyped; diff --git a/src/any_vec_raw.rs b/src/any_vec_raw.rs index 36b8cf4..d75d3c5 100644 --- a/src/any_vec_raw.rs +++ b/src/any_vec_raw.rs @@ -1,7 +1,7 @@ -use std::{cmp, mem, ptr}; -use std::alloc::Layout; -use std::any::TypeId; -use std::mem::size_of; +use core::{cmp, mem, ptr}; +use core::alloc::Layout; +use core::any::TypeId; +use core::mem::size_of; use crate::any_value::{AnyValue, Unknown, AnyValueSizeless}; use crate::assert_types_equal; use crate::clone_type::CloneFn; diff --git a/src/any_vec_typed.rs b/src/any_vec_typed.rs index 1d9120d..d2b2f84 100644 --- a/src/any_vec_typed.rs +++ b/src/any_vec_typed.rs @@ -1,9 +1,9 @@ -use std::fmt::{Debug, Formatter}; -use std::marker::PhantomData; -use std::mem::MaybeUninit; -use std::ops::{Range, RangeBounds}; -use std::ptr::NonNull; -use std::slice; +use core::fmt::{Debug, Formatter}; +use core::marker::PhantomData; +use core::mem::MaybeUninit; +use core::ops::{Range, RangeBounds}; +use core::ptr::NonNull; +use core::{fmt, slice}; use crate::any_value::{AnyValueSizeless, AnyValueWrapper}; use crate::any_vec_raw::AnyVecRaw; use crate::ops::{Iter, pop, remove, swap_remove, TempValue}; @@ -284,7 +284,7 @@ impl<'a, T: 'static, M: MemBuilder + 'a> AnyVecTyped<'a, T, M>{ } impl<'a, T: 'static + Debug, M: MemBuilder> Debug for AnyVecTyped<'a, T, M>{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { (*self.as_slice()).fmt(f) } } diff --git a/src/element.rs b/src/element.rs index 7355174..48a3314 100644 --- a/src/element.rs +++ b/src/element.rs @@ -1,8 +1,8 @@ -use std::any::TypeId; -use std::marker::PhantomData; -use std::mem::ManuallyDrop; -use std::ops::{Deref, DerefMut}; -use std::ptr::NonNull; +use core::any::TypeId; +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use core::ops::{Deref, DerefMut}; +use core::ptr::NonNull; use crate::any_value::{AnyValue, AnyValueCloneable, AnyValueMut, AnyValueTypelessMut, AnyValueTypeless, AnyValueSizeless, AnyValueSizelessMut}; use crate::any_vec_raw::AnyVecRaw; use crate::any_vec_ptr::{AnyVecPtr, IAnyVecPtr, IAnyVecRawPtr}; diff --git a/src/iter.rs b/src/iter.rs index cd998ce..6609b53 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -1,7 +1,7 @@ -use std::iter::{FusedIterator}; -use std::marker::PhantomData; -use std::mem::ManuallyDrop; -use std::ptr::NonNull; +use core::iter::{FusedIterator}; +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use core::ptr::NonNull; use crate::any_vec_ptr::{AnyVecPtr, AnyVecRawPtr, IAnyVecRawPtr}; use crate::any_vec_ptr::utils::element_ptr_at; use crate::any_vec_raw::AnyVecRaw; diff --git a/src/lib.rs b/src/lib.rs index 6f19169..16e57fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ +#![no_std] #![cfg_attr(miri, feature(alloc_layout_extra) )] +#![cfg_attr(docsrs, feature(doc_cfg))] //! Type erased vector [`AnyVec`]. Allow to store elements of the same type. -//! Have same performance and *operations* as [`std::vec::Vec`]. +//! Have same performance and *operations* as `std::vec::Vec`. //! //! You can downcast type erased [`AnyVec`] to concrete [`AnyVecTyped`] with `downcast`-family. //! Or use [`AnyVec`] type erased operations, which works with [`any_value`]. @@ -115,7 +117,7 @@ //! //! [`MemBuilder`]: mem::MemBuilder //! [`Mem`]: mem::Mem -//! [`Allocator`]: std::alloc::Allocator +//! [`Allocator`]: core::alloc::Allocator //! [`clone_empty_in`]: AnyVec::clone_empty_in //! //! # AnyValue @@ -135,6 +137,16 @@ //! [AnyValue]: any_value::AnyValue //! [AnyValueMut]: any_value::AnyValueMut //! [AnyValueCloneable]: any_value::AnyValueCloneable +//! +//! # No `alloc` +//! +//! This library is `no_std` and can work without `alloc`. +//! For this - disable default `alloc` feature. [mem::Heap] will become unavailable +//! after that, and you'll have to specify [MemBuilder] for [AnyVec]. You can use +//! [mem::Stack], or specify your own [Mem]. +//! +//! [MemBuilder]: mem::MemBuilder +//! [Mem]: mem::Mem mod any_vec; mod clone_type; @@ -143,7 +155,7 @@ mod any_vec_raw; mod any_vec_typed; mod iter; -use std::any::TypeId; +use core::any::TypeId; pub use crate::any_vec::{AnyVec, AnyVecMut, AnyVecRef, RawParts, SatisfyTraits, traits}; pub use any_vec_typed::AnyVecTyped; pub use iter::{ElementIterator, Iter, IterMut, IterRef}; @@ -153,8 +165,8 @@ pub mod any_value; pub mod ops; pub mod element; -use std::ptr; -use std::ops::{Bound, Range, RangeBounds}; +use core::ptr; +use core::ops::{Bound, Range, RangeBounds}; use crate::any_value::Unknown; /// This is faster then ptr::copy, diff --git a/src/mem/empty.rs b/src/mem/empty.rs index 72e0883..c1b5bb6 100644 --- a/src/mem/empty.rs +++ b/src/mem/empty.rs @@ -1,4 +1,4 @@ -use std::alloc::Layout; +use core::alloc::Layout; use crate::mem::{dangling, Mem, MemBuilder, MemRawParts}; /// Zero-size memory. diff --git a/src/mem/heap.rs b/src/mem/heap.rs index b0efad4..d4ff94b 100644 --- a/src/mem/heap.rs +++ b/src/mem/heap.rs @@ -1,7 +1,9 @@ -use std::alloc::{alloc, dealloc, handle_alloc_error, Layout, realloc}; -use std::cmp; -use std::mem::ManuallyDrop; -use std::ptr::NonNull; +extern crate alloc; + +use alloc::alloc::{alloc, dealloc, handle_alloc_error, Layout, realloc}; +use core::cmp; +use core::mem::ManuallyDrop; +use core::ptr::NonNull; use crate::mem::{dangling, Mem, MemBuilder, MemBuilderSizeable, MemRawParts, MemResizable}; /// Heap allocated memory. diff --git a/src/mem/mod.rs b/src/mem/mod.rs index b8a2d05..ada9645 100644 --- a/src/mem/mod.rs +++ b/src/mem/mod.rs @@ -1,17 +1,23 @@ +#[cfg(feature="alloc")] mod heap; mod stack; mod stack_n; mod empty; +#[cfg(feature="alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] pub use heap::Heap; pub use stack::Stack; pub use stack_n::StackN; pub use empty::Empty; +#[cfg(feature="alloc")] pub(crate) type Default = Heap; +#[cfg(not(feature="alloc"))] +pub(crate) type Default = Empty; -use std::alloc::Layout; -use std::ptr::NonNull; +use core::alloc::Layout; +use core::ptr::NonNull; /// This is [`Mem`] builder. /// diff --git a/src/mem/stack.rs b/src/mem/stack.rs index 57b4e83..519b681 100644 --- a/src/mem/stack.rs +++ b/src/mem/stack.rs @@ -1,5 +1,5 @@ -use std::alloc::Layout; -use std::mem::MaybeUninit; +use core::alloc::Layout; +use core::mem::MaybeUninit; use crate::mem::{Mem, MemBuilder}; /// Fixed `SIZE` capacity on-stack memory. diff --git a/src/mem/stack_n.rs b/src/mem/stack_n.rs index fd4a4b3..d06f792 100644 --- a/src/mem/stack_n.rs +++ b/src/mem/stack_n.rs @@ -1,5 +1,5 @@ -use std::alloc::Layout; -use std::mem::MaybeUninit; +use core::alloc::Layout; +use core::mem::MaybeUninit; use crate::mem::{Mem, MemBuilder}; /// Fixed `SIZE` capacity on-stack memory for `N` elements. diff --git a/src/ops/iter.rs b/src/ops/iter.rs index 26fb1c5..3c2fb33 100644 --- a/src/ops/iter.rs +++ b/src/ops/iter.rs @@ -1,4 +1,4 @@ -use std::iter::FusedIterator; +use core::iter::FusedIterator; pub trait Iterable { type Iter: Iterator; diff --git a/src/ops/pop.rs b/src/ops/pop.rs index 59c5cba..579bdc4 100644 --- a/src/ops/pop.rs +++ b/src/ops/pop.rs @@ -1,4 +1,4 @@ -use std::marker::PhantomData; +use core::marker::PhantomData; use crate::any_vec_ptr::IAnyVecRawPtr; use crate::any_vec_ptr::utils::element_ptr_at; use crate::any_vec_raw::AnyVecRaw; diff --git a/src/ops/remove.rs b/src/ops/remove.rs index e7210ec..b7a459e 100644 --- a/src/ops/remove.rs +++ b/src/ops/remove.rs @@ -1,5 +1,5 @@ -use std::marker::PhantomData; -use std::ptr; +use core::marker::PhantomData; +use core::ptr; use crate::any_value::Unknown; use crate::any_vec_ptr::IAnyVecRawPtr; use crate::any_vec_ptr::utils::element_ptr_at; diff --git a/src/ops/swap_remove.rs b/src/ops/swap_remove.rs index 07b240e..946f775 100644 --- a/src/ops/swap_remove.rs +++ b/src/ops/swap_remove.rs @@ -1,4 +1,4 @@ -use std::marker::PhantomData; +use core::marker::PhantomData; use crate::copy_nonoverlapping_value; use crate::any_vec_ptr::IAnyVecRawPtr; use crate::any_vec_ptr::utils::{element_mut_ptr_at, element_ptr_at}; diff --git a/src/ops/temp.rs b/src/ops/temp.rs index a54794e..842eb01 100644 --- a/src/ops/temp.rs +++ b/src/ops/temp.rs @@ -1,5 +1,5 @@ -use std::any::TypeId; -use std::{mem, ptr}; +use core::any::TypeId; +use core::{mem, ptr}; use crate::any_value::{AnyValue, AnyValueCloneable, AnyValueMut, AnyValueSizeless, AnyValueSizelessMut, AnyValueTypeless, AnyValueTypelessMut, Unknown}; use crate::any_vec_raw::AnyVecRaw; use crate::any_vec_ptr::{IAnyVecPtr, IAnyVecRawPtr};