1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! Macros useful for work with types that implement `BinaryKey` and `BinaryValue` traits.

/// Fast concatenation of byte arrays and/or keys that implements
/// `BinaryKey` trait.
///
/// ```
/// let prefix = vec![0_u8; 10];
/// let key = PublicKey::zero();
///
/// let _result = concat_keys!(prefix, key);
/// ```
macro_rules! concat_keys {
    (@capacity $key:expr) => ( $key.size() );
    (@capacity $key:expr, $($tail:expr),+) => (
        BinaryKey::size($key) + concat_keys!(@capacity $($tail),+)
    );
    ($($key:expr),+) => ({
        let capacity = concat_keys!(@capacity $($key),+);

        let mut buf = vec![0; capacity];
        let mut _pos = 0;
        $(
            _pos += BinaryKey::write($key, &mut buf[_pos.._pos + BinaryKey::size($key)]);
        )*
        buf
    });
}

// Think about bincode instead of protobuf. [ECR-3222]
/// Implements `BinaryKey` trait for any type that implements `BinaryValue`.
#[macro_export]
macro_rules! impl_binary_key_for_binary_value {
    ($type:ty) => {
        impl matterdb::BinaryKey for $type {
            fn size(&self) -> usize {
                matterdb::BinaryValue::to_bytes(self).len()
            }

            fn write(&self, buffer: &mut [u8]) -> usize {
                let mut bytes = matterdb::BinaryValue::to_bytes(self);
                buffer.swap_with_slice(&mut bytes);
                bytes.len()
            }

            fn read(buffer: &[u8]) -> Self::Owned {
                // `unwrap` is safe because only this code uses for
                // serialize and deserialize these keys.
                <Self as matterdb::BinaryValue>::from_bytes(buffer.into()).unwrap()
            }
        }
    };
}

/// Hex conversions for the given `BinaryValue`.
///
/// Implements `hex::FromHex` and `hex::ToHex` conversions for the given `BinaryValue` and uses them in
/// the implementation of the following traits:
///
/// `FromStr`, `Display`, `Serialize`, `Deserialize`.
///
/// Pay attention that macro uses `serde_str` under the hood.
#[macro_export]
macro_rules! impl_serde_hex_for_binary_value {
    ($name:ident) => {
        impl hex::ToHex for $name {
            fn encode_hex<T: std::iter::FromIterator<char>>(&self) -> T {
                use $crate::BinaryValue;
                BinaryValue::to_bytes(self).encode_hex()
            }

            fn encode_hex_upper<T: std::iter::FromIterator<char>>(&self) -> T {
                use $crate::BinaryValue;
                BinaryValue::to_bytes(self).encode_hex_upper()
            }
        }

        impl hex::FromHex for $name {
            type Error = $crate::_reexports::Error;

            fn from_hex<T: AsRef<[u8]>>(v: T) -> Result<Self, Self::Error> {
                use $crate::BinaryValue;

                let bytes = Vec::<u8>::from_hex(v)?;
                <Self as BinaryValue>::from_bytes(bytes.into()).map_err(From::from)
            }
        }

        impl std::fmt::Display for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                use hex::ToHex;
                write!(f, "{}", <Self as ToHex>::encode_hex::<String>(self))
            }
        }

        impl std::str::FromStr for $name {
            type Err = $crate::_reexports::Error;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                use hex::FromHex;
                <Self as FromHex>::from_hex(s)
            }
        }

        impl<'de> serde::Deserialize<'de> for $name {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::de::Deserializer<'de>,
            {
                serde_str::deserialize(deserializer)
            }
        }

        impl serde::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                serde_str::serialize(self, serializer)
            }
        }
    };
}