From 5593c2bdd37c907e7520c7bd97a8c488c2454de3 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 10 May 2026 12:21:44 -0600 Subject: [PATCH] module-lattice: add `MaybeBox` --- module-lattice/Cargo.toml | 1 + module-lattice/src/lib.rs | 7 +++++ module-lattice/src/maybe_box.rs | 56 +++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 module-lattice/src/maybe_box.rs diff --git a/module-lattice/Cargo.toml b/module-lattice/Cargo.toml index 516722a8..1c48d9a0 100644 --- a/module-lattice/Cargo.toml +++ b/module-lattice/Cargo.toml @@ -27,6 +27,7 @@ zeroize = { version = "1.8.1", optional = true, default-features = false } getrandom = { version = "0.4", features = ["sys_rng"] } [features] +alloc = [] ctutils = ["dep:ctutils", "array/ctutils"] zeroize = ["array/zeroize", "dep:zeroize"] diff --git a/module-lattice/src/lib.rs b/module-lattice/src/lib.rs index 9bdbc357..0e3203b1 100644 --- a/module-lattice/src/lib.rs +++ b/module-lattice/src/lib.rs @@ -6,6 +6,9 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" )] +#[cfg(feature = "alloc")] +extern crate alloc; + /// Linear algebra with degree-256 polynomials over a prime-order field, vectors of such /// polynomials, and NTT polynomials / vectors. mod algebra; @@ -13,6 +16,9 @@ mod algebra; /// Packing of polynomials into coefficients with a specified number of bits. mod encoding; +/// Support for optional heap offload gated on the `alloc` feature. +mod maybe_box; + /// Integer truncation support. mod truncate; @@ -23,6 +29,7 @@ pub use encoding::{ ArraySize, DecodedValue, Encode, EncodedPolynomial, EncodedPolynomialSize, EncodedVector, EncodedVectorSize, EncodingSize, VectorEncodingSize, byte_decode, byte_encode, }; +pub use maybe_box::MaybeBox; pub use truncate::Truncate; #[cfg(feature = "ctutils")] diff --git a/module-lattice/src/maybe_box.rs b/module-lattice/src/maybe_box.rs new file mode 100644 index 00000000..8d7dcc41 --- /dev/null +++ b/module-lattice/src/maybe_box.rs @@ -0,0 +1,56 @@ +use core::ops::{Deref, DerefMut}; + +/// `Box`-like type providing opportunistic heap allocation when the `alloc` feature is available +/// that falls back to stack allocation when it's unavailable. +#[derive(Clone, Debug, PartialEq)] +pub struct MaybeBox { + #[cfg(not(feature = "alloc"))] + inner: T, + #[cfg(feature = "alloc")] + inner: alloc::boxed::Box, +} + +impl MaybeBox { + /// Create a new `MaybeBox`, using `Box` if `alloc` is available. + #[inline] + pub fn new(inner: T) -> Self { + #[cfg(not(feature = "alloc"))] + { + Self { inner } + } + #[cfg(feature = "alloc")] + Self { + inner: alloc::boxed::Box::new(inner), + } + } + + /// Move the contents out of a [`MaybeBox`]. + /// + /// This emulates the compiler magic that allows moving out of a box with `*my_box`. + #[inline] + #[must_use] + pub fn into_inner(self) -> T { + #[cfg(not(feature = "alloc"))] + { + self.inner + } + #[cfg(feature = "alloc")] + { + *self.inner + } + } +} + +impl Deref for MaybeBox { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for MaybeBox { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +}