/ algorithms / src / polycommit / optional_rng.rs
optional_rng.rs
 1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
 2  // This file is part of the deltavm library.
 3  
 4  // Licensed under the Apache License, Version 2.0 (the "License");
 5  // you may not use this file except in compliance with the License.
 6  // You may obtain a copy of the License at:
 7  
 8  // http://www.apache.org/licenses/LICENSE-2.0
 9  
10  // Unless required by applicable law or agreed to in writing, software
11  // distributed under the License is distributed on an "AS IS" BASIS,
12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  // See the License for the specific language governing permissions and
14  // limitations under the License.
15  
16  use core::num::NonZeroU32;
17  use rand::RngCore;
18  
19  /// `OptionalRng` is a hack that is necessary because `Option<&mut R>` is not
20  /// implicitly reborrowed like `&mut R` is. This causes problems when a variable
21  /// of type `Option<&mut R>` is moved (eg, in a loop).
22  ///
23  /// To overcome this, we define the wrapper `OptionalRng` here that can be
24  /// borrowed mutably, without fear of being moved.
25  pub struct OptionalRng<R>(pub Option<R>);
26  
27  impl<R: RngCore> RngCore for OptionalRng<R> {
28      #[inline]
29      fn next_u32(&mut self) -> u32 {
30          self.0.as_mut().map(|r| r.next_u32()).expect("Rng was invoked in a non-hiding context")
31      }
32  
33      #[inline]
34      fn next_u64(&mut self) -> u64 {
35          self.0.as_mut().map(|r| r.next_u64()).expect("Rng was invoked in a non-hiding context")
36      }
37  
38      #[inline]
39      fn fill_bytes(&mut self, dest: &mut [u8]) {
40          self.0.as_mut().map(|r| r.fill_bytes(dest)).expect("Rng was invoked in a non-hiding context")
41      }
42  
43      #[inline]
44      fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
45          match &mut self.0 {
46              Some(r) => r.try_fill_bytes(dest),
47              None => Err(NonZeroU32::new(rand::Error::CUSTOM_START).unwrap().into()),
48          }
49      }
50  }
51  
52  impl<R: RngCore> From<R> for OptionalRng<R> {
53      fn from(other: R) -> Self {
54          Self(Some(other))
55      }
56  }