Skip to main content

Poly

Struct Poly 

Source
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,

Source

pub fn new(value: T, allocator: A) -> Result<Self, AllocatorError>

Allocate memory from allocator and place value into that location.

Source

pub fn new_with<F, E>(f: F, allocator: A) -> Result<Self, CompoundError<E>>
where F: FnOnce(A) -> Result<T, E>, A: Clone,

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.

Source

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,

Source

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.

Source

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

pub fn as_ptr(this: &Self) -> *const T

Return a pointer to the object managed by this Poly.

Source

pub fn allocator(&self) -> &A

Return a reference to the underlying allocator.

Source§

impl<T, A> Poly<MaybeUninit<T>, A>
where A: AllocatorCore,

Source

pub unsafe fn assume_init(self) -> Poly<T, A>

Converts to Poly<T, A>.

§Safety

The caller must ensure that the value has truly been initialized.

Source§

impl<T, A> Poly<[T], A>
where A: AllocatorCore,

Source

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.

Source

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,

Source

pub unsafe fn assume_init(self) -> Poly<[T], A>

Converts to Poly<[T], A>.

§Safety

The caller must ensure that the value has truly been initialized.

Source§

impl<T, A> Poly<[T], A>
where A: AllocatorCore, T: Clone,

Source

pub fn broadcast( value: T, len: usize, allocator: A, ) -> Result<Self, AllocatorError>

Construct a new Poly slice with each entry initialized to value.

Trait Implementations§

Source§

impl<A> Allocator for Poly<[u8], A>
where A: Allocator,

Available on crate feature flatbuffers only.
Source§

type Error = AllocatorError

A type describing allocation failures
Source§

fn grow_downwards(&mut self) -> Result<(), Self::Error>

Grows the buffer, with the old contents being moved to the end. Read more
Source§

fn len(&self) -> usize

Returns the size of the internal buffer in bytes.
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.

Source§

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.

Source§

type Type = T

Source§

fn as_ptr(&self) -> *const T

Source§

impl<T, A> Debug for Poly<T, A>
where T: ?Sized + Debug, A: AllocatorCore + Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T, A> Deref for Poly<T, A>
where T: ?Sized, A: AllocatorCore,

Source§

type Target = T

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<T, A> DerefMut for Poly<T, A>
where T: ?Sized, A: AllocatorCore,

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
Source§

impl<T, A> Drop for Poly<T, A>
where T: ?Sized, A: AllocatorCore,

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T> From<Box<[T]>> for Poly<[T], GlobalAllocator>

Source§

fn from(value: Box<[T]>) -> Self

Converts to this type from the input type.
Source§

impl<T, A> PartialEq for Poly<T, A>
where T: ?Sized + PartialEq, A: AllocatorCore,

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T, A> Send for Poly<T, A>
where T: ?Sized + Send, A: AllocatorCore + Send,

Source§

impl<T, A> Sync for Poly<T, A>
where T: ?Sized + Sync, A: AllocatorCore + Sync,

Auto Trait Implementations§

§

impl<T, A> Freeze for Poly<T, A>
where A: Freeze, T: ?Sized,

§

impl<T, A> RefUnwindSafe for Poly<T, A>

§

impl<T, A> Unpin for Poly<T, A>
where A: Unpin, T: ?Sized,

§

impl<T, A> UnsafeUnpin for Poly<T, A>
where A: UnsafeUnpin, T: ?Sized,

§

impl<T, A> UnwindSafe for Poly<T, A>
where A: UnwindSafe, T: RefUnwindSafe + ?Sized,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<R> Rng for R
where R: RngCore + ?Sized,

Source§

fn random<T>(&mut self) -> T

Return a random value via the StandardUniform distribution. Read more
Source§

fn random_iter<T>(self) -> Iter<StandardUniform, Self, T>

Return an iterator over random variates Read more
Source§

fn random_range<T, R>(&mut self, range: R) -> T
where T: SampleUniform, R: SampleRange<T>,

Generate a random value in the given range. Read more
Source§

fn random_bool(&mut self, p: f64) -> bool

Return a bool with a probability p of being true. Read more
Source§

fn random_ratio(&mut self, numerator: u32, denominator: u32) -> bool

Return a bool with a probability of numerator/denominator of being true. Read more
Source§

fn sample<T, D>(&mut self, distr: D) -> T
where D: Distribution<T>,

Sample a new value, using the given distribution. Read more
Source§

fn sample_iter<T, D>(self, distr: D) -> Iter<D, Self, T>
where D: Distribution<T>, Self: Sized,

Create an iterator that generates values using the given distribution. Read more
Source§

fn fill<T>(&mut self, dest: &mut T)
where T: Fill + ?Sized,

Fill any type implementing Fill with random data Read more
Source§

fn gen<T>(&mut self) -> T

👎Deprecated since 0.9.0: Renamed to random to avoid conflict with the new gen keyword in Rust 2024.
Alias for Rng::random.
Source§

fn gen_range<T, R>(&mut self, range: R) -> T
where T: SampleUniform, R: SampleRange<T>,

👎Deprecated since 0.9.0: Renamed to random_range
Source§

fn gen_bool(&mut self, p: f64) -> bool

👎Deprecated since 0.9.0: Renamed to random_bool
Alias for Rng::random_bool.
Source§

fn gen_ratio(&mut self, numerator: u32, denominator: u32) -> bool

👎Deprecated since 0.9.0: Renamed to random_ratio
Source§

impl<T> RngCore for T
where T: DerefMut, <T as Deref>::Target: RngCore,

Source§

fn next_u32(&mut self) -> u32

Return the next random u32. Read more
Source§

fn next_u64(&mut self) -> u64

Return the next random u64. Read more
Source§

fn fill_bytes(&mut self, dst: &mut [u8])

Fill dest with random data. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<R> TryRngCore for R
where R: RngCore + ?Sized,

Source§

type Error = Infallible

The type returned in the event of a RNG error.
Source§

fn try_next_u32(&mut self) -> Result<u32, <R as TryRngCore>::Error>

Return the next random u32.
Source§

fn try_next_u64(&mut self) -> Result<u64, <R as TryRngCore>::Error>

Return the next random u64.
Source§

fn try_fill_bytes( &mut self, dst: &mut [u8], ) -> Result<(), <R as TryRngCore>::Error>

Fill dest entirely with random data.
Source§

fn unwrap_err(self) -> UnwrapErr<Self>
where Self: Sized,

Wrap RNG with the UnwrapErr wrapper.
Source§

fn unwrap_mut(&mut self) -> UnwrapMut<'_, Self>

Wrap RNG with the UnwrapMut wrapper.
Source§

fn read_adapter(&mut self) -> RngReadAdapter<'_, Self>
where Self: Sized,

Available on crate feature std only.
Convert an RngCore to a RngReadAdapter.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> AsyncFriendly for T
where T: Send + Sync + 'static,

Source§

impl<T> CryptoRng for T
where T: DerefMut, <T as Deref>::Target: CryptoRng,

Source§

impl<R> TryCryptoRng for R
where R: CryptoRng + ?Sized,