rgbcore/operation/
meta.rs1use std::collections::btree_map;
24
25use amplify::confinement::{SmallBlob, TinyOrdMap};
26use amplify::{confinement, Wrapper};
27use commit_verify::StrictHash;
28
29use crate::{schema, LIB_NAME_RGB_COMMIT};
30
31#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, Error, From)]
32#[display(doc_comments)]
33pub enum MetadataError {
34 AlreadyExists(schema::MetaType),
36
37 #[from(confinement::Error)]
39 TooManyValues,
40}
41
42#[derive(
43 Wrapper, WrapperMut, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Default, From
44)]
45#[display(LowerHex)]
46#[wrapper(Deref, AsSlice, BorrowSlice, Hex)]
47#[wrapper_mut(DerefMut)]
48#[derive(StrictType, StrictEncode, StrictDecode)]
49#[strict_type(lib = LIB_NAME_RGB_COMMIT)]
50pub struct MetaValue(SmallBlob);
51
52#[cfg(feature = "serde")]
53mod _serde {
54 use amplify::hex::FromHex;
55 use serde_crate::de::Error;
56 use serde_crate::{Deserialize, Deserializer, Serialize, Serializer};
57
58 use super::*;
59
60 impl Serialize for MetaValue {
61 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
62 where S: Serializer {
63 serializer.serialize_str(&self.to_string())
64 }
65 }
66
67 impl<'de> Deserialize<'de> for MetaValue {
68 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69 where D: Deserializer<'de> {
70 let s = String::deserialize(deserializer)?;
71 Self::from_hex(&s).map_err(D::Error::custom)
72 }
73 }
74}
75
76#[derive(Wrapper, WrapperMut, Clone, PartialEq, Eq, Hash, Default, Debug, From)]
77#[wrapper(Deref)]
78#[wrapper_mut(DerefMut)]
79#[derive(StrictType, StrictEncode, StrictDecode)]
80#[strict_type(lib = LIB_NAME_RGB_COMMIT)]
81#[derive(CommitEncode)]
82#[commit_encode(strategy = strict, id = StrictHash)]
83#[cfg_attr(
84 feature = "serde",
85 derive(Serialize, Deserialize),
86 serde(crate = "serde_crate", transparent)
87)]
88pub struct Metadata(TinyOrdMap<schema::MetaType, MetaValue>);
89
90impl Metadata {
91 pub fn add_value(
92 &mut self,
93 ty: schema::MetaType,
94 meta: MetaValue,
95 ) -> Result<(), MetadataError> {
96 if self.0.contains_key(&ty) {
97 return Err(MetadataError::AlreadyExists(ty));
98 }
99 self.0.insert(ty, meta)?;
100 Ok(())
101 }
102}
103
104impl<'a> IntoIterator for &'a Metadata {
105 type Item = (&'a schema::MetaType, &'a MetaValue);
106 type IntoIter = btree_map::Iter<'a, schema::MetaType, MetaValue>;
107
108 fn into_iter(self) -> Self::IntoIter { self.0.iter() }
109}