use std::collections::btree_map;
use amplify::confinement::{SmallBlob, TinyOrdMap};
use amplify::{confinement, Wrapper};
use strict_encoding::DefaultBasedStrictDumb;
use crate::commit_verify::{CommitEncode, CommitEngine, StrictHash};
use crate::{schema, LIB_NAME_RGB_COMMIT};
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum MetadataError {
AlreadyExists(schema::MetaType),
#[from(confinement::Error)]
TooManyValues,
}
#[derive(
Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Default, From
)]
#[display(LowerHex)]
#[wrapper(Deref, AsSlice, BorrowSlice, Hex)]
#[wrapper_mut(DerefMut)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_COMMIT)]
pub struct MetaValue(SmallBlob);
impl DefaultBasedStrictDumb for MetaValue {}
#[cfg(feature = "serde")]
mod _serde {
use amplify::hex::FromHex;
use serde_crate::de::Error;
use serde_crate::{Deserialize, Deserializer, Serialize, Serializer};
use super::*;
impl Serialize for MetaValue {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for MetaValue {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
let s = String::deserialize(deserializer)?;
Self::from_hex(&s).map_err(D::Error::custom)
}
}
}
#[derive(Wrapper, WrapperMut, Clone, PartialEq, Eq, Hash, Default, Debug, From)]
#[wrapper(Deref)]
#[wrapper_mut(DerefMut)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_COMMIT)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", transparent)
)]
pub struct Metadata(TinyOrdMap<schema::MetaType, MetaValue>);
impl CommitEncode for Metadata {
type CommitmentId = StrictHash;
fn commit_encode(&self, e: &mut CommitEngine) { e.commit_to_serialized(&self); }
}
impl DefaultBasedStrictDumb for Metadata {}
impl Metadata {
pub fn add_value(
&mut self,
ty: schema::MetaType,
meta: MetaValue,
) -> Result<(), MetadataError> {
if self.0.contains_key(&ty) {
return Err(MetadataError::AlreadyExists(ty));
}
self.0.insert(ty, meta)?;
Ok(())
}
}
impl<'a> IntoIterator for &'a Metadata {
type Item = (&'a schema::MetaType, &'a MetaValue);
type IntoIter = btree_map::Iter<'a, schema::MetaType, MetaValue>;
fn into_iter(self) -> Self::IntoIter { self.0.iter() }
}