rgbstd/
reserved.rs

1// RGB standard library for working with smart contracts on Bitcoin & Lightning
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2023 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14//     http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22use amplify::hex::ToHex;
23use amplify::Wrapper;
24use strict_encoding::{DecodeError, StrictDecode, TypedRead};
25
26use crate::LIB_NAME_RGB_STD;
27
28#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
29#[derive(StrictType, StrictEncode)]
30#[strict_type(lib = LIB_NAME_RGB_STD)]
31pub struct ReservedBytes<const VAL: u8, const LEN: usize>([u8; LEN]);
32
33impl<const VAL: u8, const LEN: usize> Wrapper for ReservedBytes<VAL, LEN> {
34    type Inner = [u8; LEN];
35    fn from_inner(inner: Self::Inner) -> Self { Self::from(inner) }
36    fn as_inner(&self) -> &Self::Inner { &self.0 }
37    fn into_inner(self) -> Self::Inner { self.0 }
38}
39
40impl<const VAL: u8, const LEN: usize> From<[u8; LEN]> for ReservedBytes<VAL, LEN> {
41    fn from(value: [u8; LEN]) -> Self {
42        assert_eq!(value, [VAL; LEN]);
43        Self(value)
44    }
45}
46
47impl<const VAL: u8, const LEN: usize> Default for ReservedBytes<VAL, LEN> {
48    fn default() -> Self { ReservedBytes([VAL; LEN]) }
49}
50
51impl<const VAL: u8, const LEN: usize> StrictDecode for ReservedBytes<VAL, LEN> {
52    fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
53        let me = reader.read_newtype::<Self>()?;
54        if me.0 != [VAL; LEN] {
55            Err(DecodeError::DataIntegrityError(format!(
56                "reserved bytes required to have value [{VAL}; {LEN}] while {} was found",
57                me.0.to_hex()
58            )))
59        } else {
60            Ok(me)
61        }
62    }
63}
64
65#[cfg(feature = "serde")]
66mod _serde {
67    use std::fmt;
68
69    use serde_crate::de::Visitor;
70    use serde_crate::{de, Deserialize, Deserializer, Serialize, Serializer};
71
72    use super::*;
73
74    impl<const VAL: u8, const LEN: usize> Serialize for ReservedBytes<VAL, LEN> {
75        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
76        where S: Serializer {
77            // Doing nothing
78            serializer.serialize_unit()
79        }
80    }
81
82    impl<'de, const VAL: u8, const LEN: usize> Deserialize<'de> for ReservedBytes<VAL, LEN> {
83        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
84        where D: Deserializer<'de> {
85            #[derive(Default)]
86            pub struct UntaggedUnitVisitor;
87
88            impl<'de> Visitor<'de> for UntaggedUnitVisitor {
89                type Value = ();
90
91                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
92                    write!(formatter, "reserved unit")
93                }
94
95                fn visit_none<E>(self) -> Result<(), E>
96                where E: de::Error {
97                    Ok(())
98                }
99
100                fn visit_unit<E>(self) -> Result<(), E>
101                where E: de::Error {
102                    Ok(())
103                }
104            }
105
106            deserializer.deserialize_unit(UntaggedUnitVisitor)?;
107            Ok(default!())
108        }
109    }
110}