use std::{fmt, sync::OnceLock};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::DeserializeOwned};
use serde_json::value::RawValue;
pub struct Lazy<T> {
raw: Box<RawValue>,
parsed: OnceLock<Option<Box<T>>>,
}
impl<T: DeserializeOwned> Lazy<T> {
pub fn get(&self) -> Option<&T> {
self.parsed
.get_or_init(|| self.parse().ok().map(Box::new))
.as_deref()
}
pub fn parse(&self) -> serde_json::Result<T> {
serde_json::from_slice(self.raw.get().as_bytes())
}
}
impl<T: Serialize> Lazy<T> {
pub fn new(value: T) -> serde_json::Result<Self> {
Ok(Self {
raw: serde_json::value::to_raw_value(&value)?,
parsed: OnceLock::from(Some(Box::new(value))),
})
}
}
impl<T> Lazy<T> {
pub fn raw(&self) -> &RawValue {
&self.raw
}
}
impl<T> Clone for Lazy<T> {
fn clone(&self) -> Self {
Self {
raw: self.raw.clone(),
parsed: OnceLock::new(),
}
}
}
impl<T> fmt::Debug for Lazy<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Lazy").field(&self.raw.get()).finish()
}
}
impl<'de, T> Deserialize<'de> for Lazy<T> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Ok(Self {
raw: Box::<RawValue>::deserialize(deserializer)?,
parsed: OnceLock::new(),
})
}
}
impl<T> Serialize for Lazy<T> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.raw.serialize(serializer)
}
}