rgbcore/operation/
meta.rs

1// RGB Core Library: consensus layer for RGB smart contracts.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved.
9// Copyright (C) 2019-2024 Dr Maxim Orlovsky. All rights reserved.
10//
11// Licensed under the Apache License, Version 2.0 (the "License");
12// you may not use this file except in compliance with the License.
13// You may obtain a copy of the License at
14//
15//     http://www.apache.org/licenses/LICENSE-2.0
16//
17// Unless required by applicable law or agreed to in writing, software
18// distributed under the License is distributed on an "AS IS" BASIS,
19// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20// See the License for the specific language governing permissions and
21// limitations under the License.
22
23use 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    /// value of metadata type #{0} is already set.
35    AlreadyExists(schema::MetaType),
36
37    /// too many metadata values.
38    #[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}