use std::sync::Arc;
use foundry_compilers::artifacts::ContractDefinition;
use once_cell::sync::OnceCell;
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use serde::{Deserialize, Serialize};
use crate::analysis::macros::universal_id;
universal_id! {
UCID => 0
}
#[derive(Debug, Clone)]
pub struct ContractRef {
inner: Arc<RwLock<Contract>>,
name: OnceCell<String>,
definition: OnceCell<ContractDefinition>,
}
impl From<Contract> for ContractRef {
fn from(contract: Contract) -> Self {
Self::new(contract)
}
}
impl ContractRef {
pub fn new(inner: Contract) -> Self {
Self {
inner: Arc::new(RwLock::new(inner)),
name: OnceCell::new(),
definition: OnceCell::new(),
}
}
}
impl ContractRef {
pub fn name(&self) -> &String {
self.name.get_or_init(|| self.inner.read().definition.name.to_string())
}
pub fn definition(&self) -> &ContractDefinition {
self.definition.get_or_init(|| self.inner.read().definition.clone())
}
}
#[allow(unused)]
impl ContractRef {
pub(crate) fn read(&self) -> RwLockReadGuard<'_, Contract> {
self.inner.read()
}
pub(crate) fn write(&self) -> RwLockWriteGuard<'_, Contract> {
self.inner.write()
}
}
impl Serialize for ContractRef {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.inner.read().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for ContractRef {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let contract = Contract::deserialize(deserializer)?;
Ok(Self::new(contract))
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Contract {
pub ucid: UCID,
pub definition: ContractDefinition,
}
impl Contract {
pub fn new(definition: ContractDefinition) -> Self {
Self { ucid: UCID::next(), definition }
}
}