use serde::{Deserialize, Serialize};
use simd_json::{base::ValueAsScalar, borrowed, json_typed, lazy};
use super::id::entity_id::EntityId;
use crate::{
entities::identity::Identity,
replica::{
Replica,
entity::{id::Id, read},
},
};
#[allow(clippy::unsafe_derive_deserialize)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
pub struct IdentityStub {
pub(crate) id: EntityId<Identity>,
}
impl IdentityStub {
#[must_use]
pub fn id(&self) -> EntityId<Identity> {
self.id
}
pub fn resolve(self, replica: &Replica) -> Result<Identity, read::Error<Identity>> {
replica.get(self.id)
}
}
impl IdentityStub {
#[must_use]
pub fn as_value(&self) -> borrowed::Value<'_> {
json_typed!(borrowed, {
"id": borrowed::Value::String(self.id.as_id().to_string().into())
})
}
pub fn from_value(value: &lazy::Value<'_, '_, '_>) -> Result<Self, from_value::Error> {
let base_id = value
.get("id")
.ok_or_else(|| from_value::Error::MissingId {
data: value.clone().into_value().into(),
})?;
let base_id_str = base_id
.as_str()
.ok_or_else(|| from_value::Error::IdNotString {
id: base_id.clone().into_value().into(),
})?;
let id =
Id::from_hex(base_id_str.as_bytes()).map_err(|err| from_value::Error::IdParse {
err,
id: base_id_str.to_owned(),
})?;
Ok(Self {
id: unsafe { EntityId::from_id(id) },
})
}
}
#[allow(missing_docs)]
pub mod from_value {
use simd_json::OwnedValue;
use crate::replica::entity::id;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Missing Id in identity stub data: {data}")]
MissingId { data: OwnedValue },
#[error("The id field in the Identity stub, was not a string but: {id}")]
IdNotString { id: OwnedValue },
#[error("Failed to parse the id field ('{id}') in the identity stub as Id: {err}")]
IdParse { err: id::decode::Error, id: String },
}
}