contract_metadata/
byte_str.rs

1// Copyright (C) Use Ink (UK) Ltd.
2// This file is part of cargo-contract.
3//
4// cargo-contract is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// cargo-contract is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with cargo-contract.  If not, see <http://www.gnu.org/licenses/>.
16
17use impl_serde::serialize as serde_hex;
18
19/// Serializes the given bytes as byte string.
20pub fn serialize_as_byte_str<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
21where
22    S: serde::Serializer,
23{
24    if bytes.is_empty() {
25        // Return empty string without prepended `0x`.
26        return serializer.serialize_str("")
27    }
28    serde_hex::serialize(bytes, serializer)
29}
30
31/// Deserializes the given hex string with optional `0x` prefix.
32pub fn deserialize_from_byte_str<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
33where
34    D: serde::Deserializer<'de>,
35{
36    struct Visitor;
37
38    impl serde::de::Visitor<'_> for Visitor {
39        type Value = Vec<u8>;
40
41        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
42            write!(formatter, "hex string with optional 0x prefix")
43        }
44
45        fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
46            let result = from_hex(v);
47            result.map_err(E::custom)
48        }
49
50        fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Self::Value, E> {
51            self.visit_str(&v)
52        }
53    }
54
55    deserializer.deserialize_str(Visitor)
56}
57
58/// Deserializes the given hex string with optional `0x` prefix.
59pub fn deserialize_from_byte_str_array<'de, D>(
60    deserializer: D,
61) -> Result<[u8; 32], D::Error>
62where
63    D: serde::Deserializer<'de>,
64{
65    struct Visitor;
66
67    impl serde::de::Visitor<'_> for Visitor {
68        type Value = [u8; 32];
69
70        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
71            write!(formatter, "hex string with optional 0x prefix")
72        }
73
74        fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
75            let result = from_hex(v).map_err(E::custom)?;
76            if result.len() != 32 {
77                Err(E::custom("Expected exactly 32 bytes"))
78            } else {
79                let mut arr = [0u8; 32];
80                arr.copy_from_slice(&result[..]);
81                Ok(arr)
82            }
83        }
84
85        fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Self::Value, E> {
86            self.visit_str(&v)
87        }
88    }
89
90    deserializer.deserialize_str(Visitor)
91}
92
93fn from_hex(v: &str) -> Result<Vec<u8>, serde_hex::FromHexError> {
94    if v.starts_with("0x") {
95        serde_hex::from_hex(v)
96    } else {
97        serde_hex::from_hex(&format!("0x{v}"))
98    }
99}