git.delta.rocks / jrsonnet / refs/commits / d5d04bbaa62b

difftreelog

source

crates/jrsonnet-evaluator/src/dynamic.rs1.3 KiBsourcehistory
1use std::{cell::OnceCell, hash::Hasher, ptr::addr_of};23use educe::Educe;4use jrsonnet_gcmodule::{Cc, Trace};56use crate::{bail, error::ErrorKind::InfiniteRecursionDetected, val::ThunkValue, Result};78#[derive(Trace, Educe)]9#[educe(Clone)]10pub struct Pending<V: Trace + 'static>(pub Cc<OnceCell<V>>);11impl<T: Trace + 'static> Pending<T> {12	pub fn new() -> Self {13		Self(Cc::new(OnceCell::new()))14	}15	pub fn new_filled(v: T) -> Self {16		let cell = OnceCell::new();17		let _ = cell.set(v);18		Self(Cc::new(cell))19	}20	/// # Panics21	/// If wrapper is filled already22	pub fn fill(self, value: T) {23		self.024			.set(value)25			.map_err(|_| ())26			.expect("wrapper is filled already");27	}28}29impl<T: Trace + 'static + Clone> Pending<T> {30	/// # Panics31	/// If wrapper is not yet filled32	pub fn unwrap(&self) -> T {33		self.0.get().cloned().expect("pending was not filled")34	}35	pub fn try_get(&self) -> Option<T> {36		self.0.get().cloned()37	}38}3940impl<T: Trace + Clone> ThunkValue for Pending<T> {41	type Output = T;4243	fn get(self: Box<Self>) -> Result<Self::Output> {44		let Some(value) = self.0.get() else {45			bail!(InfiniteRecursionDetected);46		};47		Ok(value.clone())48	}49}5051impl<T: Trace + 'static> Default for Pending<T> {52	fn default() -> Self {53		Self::new()54	}55}5657pub fn identity_hash<T, H: Hasher>(v: &Cc<T>, hasher: &mut H) {58	hasher.write_usize(addr_of!(**v) as usize);59}