casper_types/contracts/
named_keys.rs

1use alloc::{collections::BTreeMap, string::String, vec::Vec};
2
3#[cfg(feature = "datasize")]
4use datasize::DataSize;
5#[cfg(feature = "json-schema")]
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8use serde_map_to_array::{BTreeMapToArray, KeyValueLabels};
9
10#[cfg(feature = "json-schema")]
11use crate::execution::execution_result_v1::NamedKey;
12use crate::{
13    bytesrepr::{self, FromBytes, ToBytes},
14    CLType, CLTyped, Key,
15};
16
17/// A collection of named keys.
18#[derive(Clone, Eq, PartialEq, Default, Serialize, Deserialize, Debug)]
19#[cfg_attr(feature = "datasize", derive(DataSize))]
20#[cfg_attr(feature = "json-schema", derive(JsonSchema))]
21#[serde(deny_unknown_fields)]
22#[rustfmt::skip]
23pub struct NamedKeys(
24    #[serde(with = "BTreeMapToArray::<String, Key, Labels>")]
25    #[cfg_attr(feature = "json-schema", schemars(with = "Vec<NamedKey>"))]
26    BTreeMap<String, Key>,
27);
28
29impl NamedKeys {
30    /// Constructs a new, empty `NamedKeys`.
31    pub const fn new() -> Self {
32        NamedKeys(BTreeMap::new())
33    }
34
35    /// Consumes `self`, returning the wrapped map.
36    pub fn into_inner(self) -> BTreeMap<String, Key> {
37        self.0
38    }
39
40    /// Inserts a named key.
41    ///
42    /// If the map did not have this name present, `None` is returned.  If the map did have this
43    /// name present, the `Key` is updated, and the old `Key` is returned.
44    pub fn insert(&mut self, name: String, key: Key) -> Option<Key> {
45        self.0.insert(name, key)
46    }
47
48    /// Moves all elements from `other` into `self`.
49    pub fn append(&mut self, mut other: Self) {
50        self.0.append(&mut other.0)
51    }
52
53    /// Removes a named `Key`, returning the `Key` if it existed in the collection.
54    pub fn remove(&mut self, name: &str) -> Option<Key> {
55        self.0.remove(name)
56    }
57
58    /// Returns a reference to the `Key` under the given `name` if any.
59    pub fn get(&self, name: &str) -> Option<&Key> {
60        self.0.get(name)
61    }
62
63    /// Returns `true` if the named `Key` exists in the collection.
64    pub fn contains(&self, name: &str) -> bool {
65        self.0.contains_key(name)
66    }
67
68    /// Returns an iterator over the names.
69    pub fn names(&self) -> impl Iterator<Item = &String> {
70        self.0.keys()
71    }
72
73    /// Returns an iterator over the `Key`s (i.e. the map's values).
74    pub fn keys(&self) -> impl Iterator<Item = &Key> {
75        self.0.values()
76    }
77
78    /// Returns a mutable iterator over the `Key`s (i.e. the map's values).
79    pub fn keys_mut(&mut self) -> impl Iterator<Item = &mut Key> {
80        self.0.values_mut()
81    }
82
83    /// Returns an iterator over the name-key pairs.
84    pub fn iter(&self) -> impl Iterator<Item = (&String, &Key)> {
85        self.0.iter()
86    }
87
88    /// Returns the number of named `Key`s.
89    pub fn len(&self) -> usize {
90        self.0.len()
91    }
92
93    /// Returns `true` if there are no named `Key`s.
94    pub fn is_empty(&self) -> bool {
95        self.0.is_empty()
96    }
97}
98
99impl From<BTreeMap<String, Key>> for NamedKeys {
100    fn from(value: BTreeMap<String, Key>) -> Self {
101        NamedKeys(value)
102    }
103}
104
105impl ToBytes for NamedKeys {
106    fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
107        self.0.write_bytes(writer)
108    }
109
110    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
111        let mut buffer = bytesrepr::allocate_buffer(self)?;
112        self.write_bytes(&mut buffer)?;
113        Ok(buffer)
114    }
115
116    fn serialized_length(&self) -> usize {
117        self.0.serialized_length()
118    }
119}
120
121impl FromBytes for NamedKeys {
122    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
123        let (named_keys, remainder) = BTreeMap::<String, Key>::from_bytes(bytes)?;
124        Ok((NamedKeys(named_keys), remainder))
125    }
126}
127
128impl CLTyped for NamedKeys {
129    fn cl_type() -> CLType {
130        BTreeMap::<String, Key>::cl_type()
131    }
132}
133
134struct Labels;
135
136impl KeyValueLabels for Labels {
137    const KEY: &'static str = "name";
138    const VALUE: &'static str = "key";
139}
140
141#[cfg(test)]
142mod tests {
143    use rand::Rng;
144
145    use super::*;
146    use crate::testing::TestRng;
147
148    /// `NamedKeys` was previously (pre node v2.0.0) just an alias for `BTreeMap<String, Key>`.
149    /// Check if we serialize as the old form, that can deserialize to the new.
150    #[test]
151    fn should_be_backwards_compatible() {
152        let rng = &mut TestRng::new();
153        let mut named_keys = NamedKeys::new();
154        assert!(named_keys.insert("a".to_string(), rng.gen()).is_none());
155        assert!(named_keys.insert("bb".to_string(), rng.gen()).is_none());
156        assert!(named_keys.insert("ccc".to_string(), rng.gen()).is_none());
157
158        let serialized_old = bincode::serialize(&named_keys.0).unwrap();
159        let parsed_new = bincode::deserialize(&serialized_old).unwrap();
160        assert_eq!(named_keys, parsed_new);
161
162        let serialized_old = bytesrepr::serialize(&named_keys.0).unwrap();
163        let parsed_new = bytesrepr::deserialize(serialized_old).unwrap();
164        assert_eq!(named_keys, parsed_new);
165    }
166
167    #[test]
168    fn should_match_field_names() {
169        // this test was written to ensure that the schema generated by schemars matches the serde
170        // encoding, both are configured using attributes and they can get out of sync
171        let mut named_keys = NamedKeys::new();
172        named_keys.insert("key".to_string(), Key::Hash([0u8; 32]));
173        assert_eq!(
174            serde_json::to_value(&named_keys).expect("should serialize"),
175            serde_json::json!([{
176                        Labels::KEY: "key",
177                        Labels::VALUE: "hash-0000000000000000000000000000000000000000000000000000000000000000"
178            }])
179        );
180    }
181}