1use std::{cell::OnceCell, hash::Hasher, ptr::addr_of};23use educe::Educe;4use jrsonnet_gcmodule::{Cc, Trace};56use crate::{Result, bail, error::ErrorKind::InfiniteRecursionDetected, val::ThunkValue};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 21 22 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 31 32 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) -> Result<Self::Output> {44 let Some(value) = self.0.get() else {45 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}