git.delta.rocks / jrsonnet / refs/commits / 5ac33cfd81f9

difftreelog

source

crates/jrsonnet-evaluator/src/dynamic.rs1.3 KiBsourcehistory
1use std::ptr::addr_of;2use std::{cell::OnceCell, hash::Hasher};34use educe::Educe;5use jrsonnet_gcmodule::{Cc, Trace};67use crate::{bail, error::ErrorKind::InfiniteRecursionDetected, val::ThunkValue, Result};89#[derive(Trace, Educe)]10#[educe(Clone)]11pub struct Pending<V: Trace + 'static>(pub Cc<OnceCell<V>>);12impl<T: Trace + 'static> Pending<T> {13	pub fn new() -> Self {14		Self(Cc::new(OnceCell::new()))15	}16	pub fn new_filled(v: T) -> Self {17		let cell = OnceCell::new();18		let _ = cell.set(v);19		Self(Cc::new(cell))20	}21	/// # Panics22	/// If wrapper is filled already23	pub fn fill(self, value: T) {24		self.025			.set(value)26			.map_err(|_| ())27			.expect("wrapper is filled already");28	}29}30impl<T: Trace + 'static + Clone> Pending<T> {31	/// # Panics32	/// If wrapper is not yet filled33	pub fn unwrap(&self) -> T {34		self.0.get().cloned().expect("pending was not filled")35	}36	pub fn try_get(&self) -> Option<T> {37		self.0.get().cloned()38	}39}4041impl<T: Trace + Clone> ThunkValue for Pending<T> {42	type Output = T;4344	fn get(self: Box<Self>) -> Result<Self::Output> {45		let Some(value) = self.0.get() else {46			bail!(InfiniteRecursionDetected);47		};48		Ok(value.clone())49	}50}5152impl<T: Trace + 'static> Default for Pending<T> {53	fn default() -> Self {54		Self::new()55	}56}5758pub fn identity_hash<T, H: Hasher>(v: &Cc<T>, hasher: &mut H) {59	hasher.write_usize(addr_of!(**v) as usize);60}