11use crate :: { Choice , CtEq , CtSelect } ;
22use core:: ops:: { Deref , DerefMut } ;
33
4+ /// Helper macro for providing behavior like the `unwrap_or` combinator that works in a `const fn`
5+ /// context.
6+ ///
7+ /// Requires a provided selector function to do the constant-time selection.
8+ #[ macro_export]
9+ macro_rules! unwrap_or {
10+ ( $opt: expr, $default: expr, $select: path) => {
11+ $select( & $default, $opt. as_inner_unchecked( ) , $opt. is_some( ) )
12+ } ;
13+ }
14+
415/// Equivalent of [`Option`] but predicated on a [`Choice`] with combinators that allow for
516/// constant-time operations which always perform the same sequence of instructions regardless of
617/// the value of `is_some`.
@@ -23,6 +34,21 @@ impl<T> CtOption<T> {
2334 Self { value, is_some }
2435 }
2536
37+ /// Construct a new [`CtOption`] where `self.is_some()` is [`Choice::TRUE`].
38+ #[ inline]
39+ pub const fn some ( value : T ) -> CtOption < T > {
40+ Self :: new ( value, Choice :: TRUE )
41+ }
42+
43+ /// Construct a new [`CtOption`] with the [`Default`] value, and where `self.is_some()` is
44+ /// [`Choice::FALSE`].
45+ pub fn none ( ) -> CtOption < T >
46+ where
47+ T : Default ,
48+ {
49+ Self :: new ( Default :: default ( ) , Choice :: FALSE )
50+ }
51+
2652 /// Convert from a `&mut CtOption<T>` to `CtOption<&mut T>`.
2753 #[ inline]
2854 pub const fn as_mut ( & mut self ) -> CtOption < & mut T > {
@@ -99,7 +125,7 @@ impl<T> CtOption<T> {
99125 pub const fn expect_ref ( & self , msg : & str ) -> & T {
100126 // TODO(tarcieri): use `self.is_some().to_bool()` when MSRV is 1.86
101127 assert ! ( self . is_some. to_bool_vartime( ) , "{}" , msg) ;
102- & self . value
128+ self . as_inner_unchecked ( )
103129 }
104130
105131 /// Convert the [`CtOption`] wrapper into an [`Option`], depending on whether
@@ -146,6 +172,13 @@ impl<T> CtOption<T> {
146172 optb
147173 }
148174
175+ /// Apply an additional [`Choice`] requirement to `is_some`.
176+ #[ inline]
177+ pub const fn and_choice ( mut self , is_some : Choice ) -> Self {
178+ self . is_some = self . is_some . and ( is_some) ;
179+ self
180+ }
181+
149182 /// Calls the provided callback with the wrapped inner value, returning the resulting
150183 /// [`CtOption`] value in the event that `self.is_some()` is [`Choice::TRUE`], or if not
151184 /// returns a [`CtOption`] with `self.is_none()`.
@@ -164,6 +197,34 @@ impl<T> CtOption<T> {
164197 ret
165198 }
166199
200+ /// Obtain a reference to the inner value without first checking that `self.is_some()` is
201+ /// [`Choice::TRUE`].
202+ ///
203+ /// This method is primarily intended for use in `const fn` scenarios where it's not yet
204+ /// possible to use the safe combinator methods, and returns a reference to avoid issues with
205+ /// `const fn` destructors.
206+ ///
207+ /// <div class="warning">
208+ /// <b>Use with care!</b>
209+ ///
210+ /// This method does not ensure the `value` is actually valid. Callers of this method should
211+ /// take great care to ensure that `self.is_some()` is checked elsewhere.
212+ /// </div>
213+ #[ inline]
214+ pub const fn as_inner_unchecked ( & self ) -> & T {
215+ & self . value
216+ }
217+
218+ /// DEPRECATED: legacy compatibility method for `crypto-bigint`
219+ // TODO(tarcieri): deprecate this!
220+ #[ inline]
221+ pub const fn components_ref ( & self ) -> ( & T , Choice ) {
222+ // Since Rust is not smart enough to tell that we would be moving the value,
223+ // and hence no destructors will be called, we have to return a reference instead.
224+ // See https://github.com/rust-lang/rust/issues/66753
225+ ( & self . value , self . is_some )
226+ }
227+
167228 /// Calls the provided callback with the wrapped inner value, which computes a [`Choice`],
168229 /// and updates `self.is_some()`.
169230 ///
@@ -247,6 +308,27 @@ impl<T> CtOption<T> {
247308 }
248309 }
249310
311+ /// Obtain a copy of the inner value without first checking that `self.is_some()` is
312+ /// [`Choice::TRUE`].
313+ ///
314+ /// This method is primarily intended for use in `const fn` scenarios where it's not yet
315+ /// possible to use the safe combinator methods, and uses a `Copy` bound to avoid issues with
316+ /// `const fn` destructors.
317+ ///
318+ /// <div class="warning">
319+ /// <b>Use with care!</b>
320+ ///
321+ /// This method does not ensure the `value` is actually valid. Callers of this method should
322+ /// take great care to ensure that `self.is_some()` is checked elsewhere.
323+ /// </div>
324+ #[ inline]
325+ pub const fn to_inner_unchecked ( & self ) -> T
326+ where
327+ T : Copy ,
328+ {
329+ self . value
330+ }
331+
250332 /// Return the contained value, consuming the `self` value.
251333 ///
252334 /// Use of this function is discouraged due to panic potential. Instead, prefer non-panicking
@@ -400,6 +482,12 @@ impl<T: CtSelect> CtSelect for CtOption<T> {
400482 }
401483}
402484
485+ impl < T : Default > Default for CtOption < T > {
486+ fn default ( ) -> Self {
487+ Self :: none ( )
488+ }
489+ }
490+
403491/// Convert the [`CtOption`] wrapper into an [`Option`], depending on whether
404492/// [`CtOption::is_some`] is a truthy or falsy [`Choice`].
405493///
0 commit comments