alloc-traits-0.1.1/Cargo.toml.orig010064400017500001750000000010651361416362600152310ustar0000000000000000[package] name = "alloc-traits" version = "0.1.1" description = "Traits to replace or supplement the alloc module in no_std" authors = ["Andreas Molzer "] edition = "2018" license = "MIT" documentation = "https://docs.rs/static-alloc" repository = "https://github.com/HeroicKatora/static-alloc" categories = ["embedded", "memory-management", "no-std"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "alloc_traits" [dependencies] [package.metadata.docs.rs] all-features = true alloc-traits-0.1.1/Cargo.toml0000644000000017401361416435100115330ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "alloc-traits" version = "0.1.1" authors = ["Andreas Molzer "] description = "Traits to replace or supplement the alloc module in no_std" documentation = "https://docs.rs/static-alloc" categories = ["embedded", "memory-management", "no-std"] license = "MIT" repository = "https://github.com/HeroicKatora/static-alloc" [package.metadata.docs.rs] all-features = true [lib] name = "alloc_traits" [dependencies] alloc-traits-0.1.1/Changes.md010064400017500001750000000002311361416406100142200ustar0000000000000000# v0.1.1 - Exposes default implementations in `utils`. - Fixed a leak in the default implementation of `LocalAlloc::realloc` # v0.1.0 Initial version alloc-traits-0.1.1/Readme.md010064400017500001750000000015731360770417200140640ustar0000000000000000# alloc-traits Defines `no_std` and bare metal usable traits that can be implemented to defined different kinds of allocators, similar to `alloc::GlobalAlloc`. But unlike the standard library trait they do not presume global uniqueness and static lifetime of the memory resource provider. In return, the allocators are not required to implement the `Sync` bound and can easily be built without operating system support to be usable. There are additional independent crates with additional abstractions on-top: * [`static-alloc`]: A simple allocator drawing from a memory region statically embedded within the compiled binary. * [`without-alloc`]: A set of data structures (`Box`, `Vec`, `Rc`, ...) that can be allocated from the implementors of the traits defined here. [`static-alloc`]: https://crates.io/crates/static-alloc [`without-alloc`]: https://crates.io/crates/without-alloc alloc-traits-0.1.1/src/global.rs010064400017500001750000000037151361171012700147320ustar0000000000000000use core::ptr::NonNull; use super::{Allocation, AllocTime, NonZeroLayout}; pub struct Global; impl crate::LocalAlloc<'_> for Global { fn alloc(&self, layout: NonZeroLayout) -> Option> { // SAFETY: the layout is not empty due to `NonZeroLayout`. let ptr = unsafe { alloc::alloc::alloc(layout.into()) }; from_global_ptr(ptr, layout) } unsafe fn dealloc(&self, alloc: Allocation<'_>) { // SAFETY: all preconditions have been propagated. alloc::alloc::dealloc(alloc.ptr.as_ptr(), alloc.layout.into()) } unsafe fn alloc_zeroed(&self, layout: NonZeroLayout) -> Option> { // SAFETY: the layout is not empty due to `NonZeroLayout`. let ptr = { alloc::alloc::alloc_zeroed(layout.into()) }; from_global_ptr(ptr, layout) } unsafe fn realloc(&self, alloc: Allocation<'_>, layout: NonZeroLayout) -> Option> { // We can't change the alignment, sadly. if layout.align() != alloc.layout.align() { return None; } // A new requirement that we did not propagate: We can not allow the new layout to overflow // if sized according to its alignment. That is, we should manually check the precondition. // For some reason this is not part of the original `alloc` requirements. let align_offset = usize::from(layout.size()).wrapping_neg() % layout.align(); if usize::max_value() - align_offset < layout.size().into() { return None; } let ptr = alloc::alloc::realloc( alloc.ptr.as_ptr(), alloc.layout.into(), layout.size().into()); from_global_ptr(ptr, layout) } } fn from_global_ptr<'any>(ptr: *mut u8, layout: NonZeroLayout) -> Option> { let ptr = NonNull::new(ptr)?; Some(Allocation { ptr, layout: layout, lifetime: AllocTime::default(), }) } alloc-traits-0.1.1/src/layout.rs010064400017500001750000000046411361171012700150060ustar0000000000000000use core::{alloc, convert}; use core::num::NonZeroUsize; /// Layout of an allocated block of memory. /// /// Wraps the `Layout` structure from core but extends it in a few ways that would otherwise depend /// on nightly compiler. #[derive(Clone, Copy, Debug, PartialEq)] pub struct Layout(alloc::Layout); /// A non-empty layout which can be allocated. #[derive(Clone, Copy, Debug, PartialEq)] pub struct NonZeroLayout(Layout); #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct EmptyLayoutError; impl Layout { /// Create the layout for a type. pub fn new() -> Self { Layout(alloc::Layout::new::()) } /// Return the size of the layout. pub fn size(&self) -> usize { self.0.size() } /// Return the alignment of the layout. pub fn align(&self) -> usize { self.0.align() } } impl NonZeroLayout { /// Create the layout for a type. /// /// This succeeds exactly if the type is not a zero-sized type. Otherwise this constructor /// returns `None`. pub fn new() -> Option { Self::from_layout(Layout::new::()) } /// Creates a non-empty layout if the given layout is not empty. pub fn from_layout(layout: Layout) -> Option { if layout.size() == 0 { None } else { Some(NonZeroLayout(layout)) } } /// Return the size of the layout. pub fn size(&self) -> NonZeroUsize { NonZeroUsize::new(self.0.size()).unwrap() } /// Return the alignment of the layout. pub fn align(&self) -> usize { self.0.align() } } impl From for alloc::Layout { fn from(layout: Layout) -> alloc::Layout { layout.0 } } impl From for alloc::Layout { fn from(layout: NonZeroLayout) -> alloc::Layout { layout.0.into() } } impl From for Layout { fn from(layout: alloc::Layout) -> Layout { Layout(layout) } } impl convert::TryFrom for NonZeroLayout { type Error = EmptyLayoutError; fn try_from(layout: Layout) -> Result { NonZeroLayout::from_layout(layout).ok_or(EmptyLayoutError) } } impl convert::TryFrom for NonZeroLayout { type Error = EmptyLayoutError; fn try_from(layout: alloc::Layout) -> Result { NonZeroLayout::try_from(Layout::from(layout)) } } alloc-traits-0.1.1/src/lib.rs010064400017500001750000000023221361416370300142360ustar0000000000000000//! Traits to replace or supplement the alloc module in `no_std`. //! //! Defines traits, similar to `alloc::GlobalAlloc`, that can be implemented to defined different //! kinds of allocators. Unlike the standard library one they do not presume global uniqueness and //! static lifetime of the memory resource provider. In return, the allocators are not required to //! implement the `Sync` bound and can easily be built without operating system support to be //! usable. //! //! There are additional independent crates with additional abstractions on-top: //! * [`static-alloc`]: A simple allocator drawing from a memory region statically //! embedded within the compiled binary. //! * [`without-alloc`]: A set of data structures (`Box`, `Vec`, `Rc`, ...) that can //! be allocated from the implementors of the traits defined here. //! //! [`static-alloc`]: https://crates.io/crates/static-alloc //! [`without-alloc`]: https://crates.io/crates/without-alloc // Copyright 2019 Andreas Molzer #![no_std] #![deny(missing_docs)] mod layout; mod local; pub mod util; pub use crate::layout::{Layout, NonZeroLayout}; pub use crate::local::{AllocTime, Allocation, LocalAlloc}; #[allow(deprecated)] pub use crate::local::Invariant; alloc-traits-0.1.1/src/local.rs010064400017500001750000000064661361416340600145770ustar0000000000000000use core::fmt; use core::marker::PhantomData; use core::ptr::NonNull; use crate::NonZeroLayout; use crate::util::defaults; /// A marker struct denoting a lifetime that is not simply coercible to another. #[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct AllocTime<'lt> { marker: PhantomData<&'lt fn(&'lt ())>, } /// A marker struct denoting a lifetime that is not simply coercible to another. #[deprecated = "Use the new name 'AllocTime' instead"] pub type Invariant<'lt> = AllocTime<'lt>; /// An allocation valid for a particular lifetime. /// /// It is advisable to try and deallocate it before the end of the lifetime instead of leaking the /// allocation. #[derive(Clone, Copy, Debug, PartialEq)] pub struct Allocation<'alloc> { /// A pointer to the allocated and potentially uninitialized bytes. pub ptr: NonNull, /// The allocated layout. pub layout: NonZeroLayout, /// The lifetime of the allocation. pub lifetime: AllocTime<'alloc>, } /// An allocator providing memory regions valid for a particular lifetime. /// /// It is useful to compare this trait to `std::alloc::GlobalAlloc`. Similar to the trait it is /// required that the implementors adhere to the contract of the methods. pub unsafe trait LocalAlloc<'alloc> { /// Allocate one block of memory. /// /// The callee guarantees that a successful return contains a pointer that is valid for **at /// least** the layout requested by the caller. fn alloc(&'alloc self, layout: NonZeroLayout) -> Option>; /// Deallocate a block previously allocated. /// # Safety /// The caller must ensure that: /// * `alloc` has been previously returned from a call to `alloc`. /// * There are no more pointer to the allocation. unsafe fn dealloc(&'alloc self, alloc: Allocation<'alloc>); /// Allocate a block of memory initialized with zeros. /// /// The callee guarantees that a successful return contains a pointer that is valid for **at /// least** the layout requested by the caller and the contiguous region of bytes, starting at /// the pointer and with the size of the returned layout, is initialized and zeroed. fn alloc_zeroed(&'alloc self, layout: NonZeroLayout) -> Option> { defaults::local::alloc_zeroed(self, layout) } /// Change the layout of a block previously allocated. /// /// The callee guarantees that a successful return contains a pointer that is valid for **at /// least** the layout requested by the caller and the contiguous region of bytes, starting at /// the pointer and with the size of the returned layout, is initialized with the prefix of the /// previous allocation that is still valid. /// /// Note that it is *NOT* safe to elide the methods call for changing the alignment of the /// layout to a less strict one, or to an incidentally fulfilled stricter version. The /// allocator might make use of the alignment during deallocation. unsafe fn realloc(&'alloc self, alloc: Allocation<'alloc>, layout: NonZeroLayout) -> Option> { defaults::local::realloc(self, alloc, layout) } } impl fmt::Debug for AllocTime<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad("AllocTime") } } alloc-traits-0.1.1/src/util.rs010064400017500001750000000052741361416340600144560ustar0000000000000000//! Various utilities such as default implementations. /// Implementations of default items of traits. /// /// It is expected that these might be used as a fallback 'super' call of sorts on trait /// implementors to opportunistically do some form of optimization. pub mod defaults { /// Default implementations for the `LocalAlloc` trait. /// /// See [`LocalAlloc`] for more information. The methods called by the functions in this module /// are documented and will not change between non-breaking releases, if at all. Rather new /// variants may be added that call additional methods that might be more efficient. This /// avoids accidentally creating a dependency loop in implementors. /// /// [`LocalAlloc`]: ../../../trait.LocalAlloc.html pub mod local { use core::ptr::{copy_nonoverlapping, write_bytes}; use crate::NonZeroLayout; use crate::local::{LocalAlloc, Allocation}; /// Allocate a block of memory initialized with zeros. /// /// See [`LocalAlloc::alloc_zeroed`] for more information. This is a default implementation /// that might be less efficient than a dedicated one. It only uses the `alloc` method. /// /// [`LocalAlloc::alloc_zeroed`]: ../../../trait.LocalAlloc.html pub fn alloc_zeroed<'alloc, Alloc>( this: &'alloc Alloc, layout: NonZeroLayout ) -> Option> where Alloc: LocalAlloc<'alloc> + ?Sized, { let allocation = this.alloc(layout)?; unsafe { write_bytes(allocation.ptr.as_ptr(), 0u8, allocation.layout.size().into()); } Some(allocation) } /// Change the layout of a block previously allocated. /// /// See [`LocalAlloc::realloc`] for more information. This is a default implementation that /// might be less efficient than a dedicated one. It only uses the `alloc` and `dealloc` /// methods. /// /// # Safety /// See the trait. /// /// [`LocalAlloc::realloc`]: ../../../trait.LocalAlloc.html pub unsafe fn realloc<'alloc, Alloc>( this: &'alloc Alloc, alloc: Allocation<'alloc>, layout: NonZeroLayout ) -> Option> where Alloc: LocalAlloc<'alloc> + ?Sized, { let new_alloc = this.alloc(layout)?; copy_nonoverlapping( alloc.ptr.as_ptr(), new_alloc.ptr.as_ptr(), core::cmp::min(layout.size(), alloc.layout.size()).get()); this.dealloc(alloc); Some(new_alloc) } } } alloc-traits-0.1.1/.cargo_vcs_info.json0000644000000001121361416435100135250ustar00{ "git": { "sha1": "209bfbc8050c83dcee16f9078e30176e4a9ae185" } }