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 }