snarkvm_algorithms/polycommit/
optional_rng.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM 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
16use core::num::NonZeroU32;
17use rand_core::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.
25pub struct OptionalRng<R>(pub Option<R>);
26
27impl<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_core::Error> {
45        match &mut self.0 {
46            Some(r) => r.try_fill_bytes(dest),
47            None => Err(NonZeroU32::new(rand_core::Error::CUSTOM_START).unwrap().into()),
48        }
49    }
50}
51
52impl<R: RngCore> From<R> for OptionalRng<R> {
53    fn from(other: R) -> Self {
54        Self(Some(other))
55    }
56}