pub struct Poly<T, A = GlobalAllocator>where
T: ?Sized,
A: AllocatorCore,{ /* private fields */ }Expand description
An owning pointer type like std::Box that supports custom allocators.
§Examples
§Creating and Mutating a Simple Type
This example demonstrates that Poly behaves pretty much like a Box with allocator
support for simple types.
use diskann_quantization::alloc::{Poly, GlobalAllocator};
// `Poly` constructors can fail due to allocator errors, so return `Results`.
let mut x = Poly::new(10usize, GlobalAllocator).unwrap();
assert_eq!(*x, 10);
*x = 50;
assert_eq!(*x, 50);§Creating and Mutating a Slice
The standard library trait FromIterator is not implemented for Poly because an
allocator is required for all construction operations. Instead, the inherent method
Poly::from_iter can be used, provided the iterator is one of the select few for
which TrustedIter is implemented, indicating that the length of the iterator can
be relied on in unsafe code.
use diskann_quantization::alloc::{Poly, GlobalAllocator};
let v = vec![
"foo".to_string(),
"bar".to_string(),
"baz".to_string(),
];
let poly = Poly::from_iter(v.into_iter(), GlobalAllocator).unwrap();
assert_eq!(poly.len(), 3);
assert_eq!(poly[0], "foo");
assert_eq!(poly[1], "bar");
assert_eq!(poly[2], "baz");§Using a Custom Allocator
This crate provides a handful of custom allocators, including the super::BumpAllocator.
It can be used to group together allocations into a single arena.
use diskann_quantization::{
alloc::{Poly, BumpAllocator},
num::PowerOfTwo
};
let dim = 10;
// Estimate how many bytes are needed to create two such slices. We can control the
// alignment of the base pointer for the `BumpAllocator` to avoid extra memory used
// to satisfy alignment.
let alloc = BumpAllocator::new(
dim * (std::mem::size_of::<f64>() + std::mem::size_of::<u8>()),
PowerOfTwo::new(64).unwrap(),
).unwrap();
let foo = Poly::<[f64], _>::from_iter(
(0..dim).map(|i| i as f64),
alloc.clone(),
).unwrap();
let bar = Poly::<[u8], _>::from_iter(
(0..dim).map(|i| i as u8),
alloc.clone(),
).unwrap();
// The base pointer for the allocated object in `foo` is the base pointer of the arena
// owned by the BumpAllocator.
assert_eq!(alloc.as_ptr(), Poly::as_ptr(&foo).cast::<u8>());
// The base pointer for the allocated object in `bar` is also within the arena owned
// by the BumpAllocator as well.
assert_eq!(
unsafe { alloc.as_ptr().add(std::mem::size_of_val(&*foo)) },
Poly::as_ptr(&bar).cast::<u8>(),
);
// The allocator is now full - so further allocations will fail.
assert!(Poly::new(10usize, alloc.clone()).is_err());
// If we drop the allocator, the clones inside the `Poly` containers will keep the
// backing memory alive.
std::mem::forget(alloc);
assert!(foo.iter().enumerate().all(|(i, v)| i as f64 == *v));
assert!(bar.iter().enumerate().all(|(i, v)| i as u8 == *v));§Using Trait Object
Poly is compatible with trait objects as well using the crate::poly! macro.
A macro is needed because traits such as
Unsize and
CoerceUnsized are
unstable.
use diskann_quantization::{
poly,
alloc::BumpAllocator,
num::PowerOfTwo,
};
use std::fmt::Display;
let message = "hello world";
let alloc = BumpAllocator::new(512, PowerOfTwo::new(64).unwrap()).unwrap();
// Create a new `Poly` trait object for `std::fmt::Display`. Due to limitations in the
// macro matching rules, identifiers are needed for the object and allocator.
let clone = alloc.clone();
let poly = poly!(std::fmt::Display, message, clone).unwrap();
assert_eq!(poly.to_string(), "hello world");
// Here - we demonstrate the full type of the returned `Poly`.
let clone = alloc.clone();
let _: diskann_quantization::alloc::Poly<dyn Display, _> = poly!(
Display,
message,
clone
).unwrap();
// If additional auto traits are needed like `Send`, the brace-style syntax can be used
let clone = alloc.clone();
let poly = poly!({ std::fmt::Display + Send + Sync }, message, clone).unwrap();
// Existing `Poly` objects can be converted using the same macro.
let poly = diskann_quantization::alloc::Poly::new(message, alloc.clone()).unwrap();
let poly = poly!(std::fmt::Display, poly);
assert_eq!(poly.to_string(), "hello world");Naturally, the implementation of the trait is checked for validity.
Implementations§
Source§impl<T, A> Poly<T, A>where
A: AllocatorCore,
impl<T, A> Poly<T, A>where
A: AllocatorCore,
Sourcepub fn new(value: T, allocator: A) -> Result<Self, AllocatorError>
pub fn new(value: T, allocator: A) -> Result<Self, AllocatorError>
Allocate memory from allocator and place value into that location.
Sourcepub fn new_with<F, E>(f: F, allocator: A) -> Result<Self, CompoundError<E>>
pub fn new_with<F, E>(f: F, allocator: A) -> Result<Self, CompoundError<E>>
Allocate memory from allocator for T, then run the provided closure, moving
the result into the allocated memory.
Because this allocates the storage for the object first, it can be used in situations where the object to be allocated will use the same allocator, but should be allocated after the base.
Sourcepub fn new_uninit(
allocator: A,
) -> Result<Poly<MaybeUninit<T>, A>, AllocatorError>
pub fn new_uninit( allocator: A, ) -> Result<Poly<MaybeUninit<T>, A>, AllocatorError>
Construct a new Poly with uninitialized contents in allocator.
Source§impl<T, A> Poly<T, A>where
T: ?Sized,
A: AllocatorCore,
impl<T, A> Poly<T, A>where
T: ?Sized,
A: AllocatorCore,
Sourcepub fn into_raw(this: Self) -> (NonNull<T>, A)
pub fn into_raw(this: Self) -> (NonNull<T>, A)
Consume Self, returning the wrapped pointer and allocator.
This function does not trigger any drop logic nor deallocation.
Sourcepub unsafe fn from_raw(ptr: NonNull<T>, allocator: A) -> Self
pub unsafe fn from_raw(ptr: NonNull<T>, allocator: A) -> Self
Construct a Poly from a raw pointer and allocator.
After calling this function, the returned Poly will assume ownership of the
provided pointer.
§Safety
The value of ptr must have runtime alignment compatible with
std::mem::Layout::for_value(&*ptr.as_ptr())and point to a valid object of type T.
The pointer must point to memory currently allocated in allocator.
Source§impl<T, A> Poly<MaybeUninit<T>, A>where
A: AllocatorCore,
impl<T, A> Poly<MaybeUninit<T>, A>where
A: AllocatorCore,
Sourcepub unsafe fn assume_init(self) -> Poly<T, A>
pub unsafe fn assume_init(self) -> Poly<T, A>
Source§impl<T, A> Poly<[T], A>where
A: AllocatorCore,
impl<T, A> Poly<[T], A>where
A: AllocatorCore,
Sourcepub fn new_uninit_slice(
len: usize,
allocator: A,
) -> Result<Poly<[MaybeUninit<T>], A>, AllocatorError>
pub fn new_uninit_slice( len: usize, allocator: A, ) -> Result<Poly<[MaybeUninit<T>], A>, AllocatorError>
Construct a new Poly containing an uninitialized slice of length len with
memory allocated from allocator.
Sourcepub fn from_iter<I>(iter: I, allocator: A) -> Result<Self, AllocatorError>where
I: TrustedIter<Item = T>,
pub fn from_iter<I>(iter: I, allocator: A) -> Result<Self, AllocatorError>where
I: TrustedIter<Item = T>,
Construct a new Poly from the iterator.
Source§impl<T, A> Poly<[MaybeUninit<T>], A>where
A: AllocatorCore,
impl<T, A> Poly<[MaybeUninit<T>], A>where
A: AllocatorCore,
Sourcepub unsafe fn assume_init(self) -> Poly<[T], A>
pub unsafe fn assume_init(self) -> Poly<[T], A>
Trait Implementations§
Source§impl<A> Allocator for Poly<[u8], A>where
A: Allocator,
Available on crate feature flatbuffers only.
impl<A> Allocator for Poly<[u8], A>where
A: Allocator,
flatbuffers only.Source§impl<T, A> AsMutPtr for Poly<[T], A>where
A: AllocatorCore,
Safety: Slices never return a null pointer. A mutable reference to self signals
an exclusive borrow - so the underlying pointer is indeed mutable.
impl<T, A> AsMutPtr for Poly<[T], A>where
A: AllocatorCore,
Safety: Slices never return a null pointer. A mutable reference to self signals
an exclusive borrow - so the underlying pointer is indeed mutable.
fn as_mut_ptr(&mut self) -> *mut T
Source§impl<T, A> AsPtr for Poly<[T], A>where
A: AllocatorCore,
Safety: Slices never return a null pointer.
impl<T, A> AsPtr for Poly<[T], A>where
A: AllocatorCore,
Safety: Slices never return a null pointer.
impl<T, A> Send for Poly<T, A>
impl<T, A> Sync for Poly<T, A>
Auto Trait Implementations§
impl<T, A> Freeze for Poly<T, A>
impl<T, A> RefUnwindSafe for Poly<T, A>
impl<T, A> Unpin for Poly<T, A>
impl<T, A> UnsafeUnpin for Poly<T, A>where
A: UnsafeUnpin,
T: ?Sized,
impl<T, A> UnwindSafe for Poly<T, A>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<R> Rng for R
impl<R> Rng for R
Source§fn random<T>(&mut self) -> Twhere
StandardUniform: Distribution<T>,
fn random<T>(&mut self) -> Twhere
StandardUniform: Distribution<T>,
StandardUniform distribution. Read moreSource§fn random_iter<T>(self) -> Iter<StandardUniform, Self, T>
fn random_iter<T>(self) -> Iter<StandardUniform, Self, T>
Source§fn random_range<T, R>(&mut self, range: R) -> Twhere
T: SampleUniform,
R: SampleRange<T>,
fn random_range<T, R>(&mut self, range: R) -> Twhere
T: SampleUniform,
R: SampleRange<T>,
Source§fn random_bool(&mut self, p: f64) -> bool
fn random_bool(&mut self, p: f64) -> bool
p of being true. Read moreSource§fn random_ratio(&mut self, numerator: u32, denominator: u32) -> bool
fn random_ratio(&mut self, numerator: u32, denominator: u32) -> bool
numerator/denominator of being
true. Read moreSource§fn sample<T, D>(&mut self, distr: D) -> Twhere
D: Distribution<T>,
fn sample<T, D>(&mut self, distr: D) -> Twhere
D: Distribution<T>,
Source§fn sample_iter<T, D>(self, distr: D) -> Iter<D, Self, T>where
D: Distribution<T>,
Self: Sized,
fn sample_iter<T, D>(self, distr: D) -> Iter<D, Self, T>where
D: Distribution<T>,
Self: Sized,
Source§fn gen<T>(&mut self) -> Twhere
StandardUniform: Distribution<T>,
fn gen<T>(&mut self) -> Twhere
StandardUniform: Distribution<T>,
random to avoid conflict with the new gen keyword in Rust 2024.Rng::random.Source§fn gen_range<T, R>(&mut self, range: R) -> Twhere
T: SampleUniform,
R: SampleRange<T>,
fn gen_range<T, R>(&mut self, range: R) -> Twhere
T: SampleUniform,
R: SampleRange<T>,
random_rangeRng::random_range.Source§impl<R> TryRngCore for R
impl<R> TryRngCore for R
Source§type Error = Infallible
type Error = Infallible
Source§fn try_next_u32(&mut self) -> Result<u32, <R as TryRngCore>::Error>
fn try_next_u32(&mut self) -> Result<u32, <R as TryRngCore>::Error>
u32.Source§fn try_next_u64(&mut self) -> Result<u64, <R as TryRngCore>::Error>
fn try_next_u64(&mut self) -> Result<u64, <R as TryRngCore>::Error>
u64.Source§fn try_fill_bytes(
&mut self,
dst: &mut [u8],
) -> Result<(), <R as TryRngCore>::Error>
fn try_fill_bytes( &mut self, dst: &mut [u8], ) -> Result<(), <R as TryRngCore>::Error>
dest entirely with random data.Source§fn unwrap_mut(&mut self) -> UnwrapMut<'_, Self>
fn unwrap_mut(&mut self) -> UnwrapMut<'_, Self>
UnwrapMut wrapper.Source§fn read_adapter(&mut self) -> RngReadAdapter<'_, Self>where
Self: Sized,
fn read_adapter(&mut self) -> RngReadAdapter<'_, Self>where
Self: Sized,
std only.RngCore to a RngReadAdapter.