diff --git a/Cargo.toml b/Cargo.toml index 360a8ddb..3d7862f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ categories = ["algorithms", "science", "no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/kaidokert/num-traits" name = "const-num-traits" -version = "0.1.0" +version = "0.1.1" readme = "README.md" # Include-list of the files that ship. Anything not listed here is never packaged. include = [ diff --git a/src/lib.rs b/src/lib.rs index 394eea50..391cda40 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -142,7 +142,9 @@ pub use crate::ops::wrapping::{ WrappingAbs, WrappingAdd, WrappingDiv, WrappingMul, WrappingNeg, WrappingPow, WrappingRem, WrappingShl, WrappingShr, WrappingSub, }; -pub use crate::personality::{Ct, Nct, Personality, PersonalityMarker, PersonalityTag}; +pub use crate::personality::{ + Ct, HasPersonality, Nct, Personality, PersonalityMarker, PersonalityTag, +}; pub use crate::pow::{Pow, checked_pow, pow}; pub use crate::sign::{Signed, Signum, Unsigned, abs, abs_sub, signum}; diff --git a/src/personality.rs b/src/personality.rs index e6fb875a..32ede147 100644 --- a/src/personality.rs +++ b/src/personality.rs @@ -90,6 +90,40 @@ impl Personality for Ct { /// Use as `_p: PersonalityMarker

` in struct definitions. pub type PersonalityMarker

= PhantomData P>; +/// Projects a carrier type's [`Personality`] at the type level. +/// +/// Implemented by carrier types whose implementation shape is selected +/// by a personality parameter (a bigint parameterized over its +/// personality projects that parameter), and by the primitive integers, +/// which project [`Nct`]: they expose a single hardware-backed +/// implementation, select no constant-time variant, and make no +/// constant-time guarantee — integer division in particular has +/// operand-dependent latency on common CPUs. +/// +/// Consumers bound on the projection to gate algorithm choice by +/// personality: `T: HasPersonality

` admits a type into +/// variable-time code paths, `P = Ct` into constant-time-only ones. +/// The declaration is the carrier author's contract; there is no way +/// to verify it structurally. +pub trait HasPersonality { + /// The carrier's personality. + type P: Personality; +} + +macro_rules! impl_has_personality_nct { + ($($t:ty),*) => { + $( + impl HasPersonality for $t { + type P = Nct; + } + )* + }; +} + +impl_has_personality_nct!( + u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize +); + #[cfg(test)] mod tests { use super::*; @@ -102,6 +136,16 @@ mod tests { assert_eq!(Ct, Ct); } + #[test] + fn has_personality_projects_nct_for_primitives() { + fn assert_nct>() {} + assert_nct::(); + assert_nct::(); + assert_nct::(); + assert_nct::(); + assert_nct::(); + } + #[test] fn const_tag_dispatch() { const fn dispatched() -> u32 {