cosmwasm_std/storage_keys/
length_prefixed.rs1use crate::prelude::*;
8
9pub fn to_length_prefixed(namespace_component: &[u8]) -> Vec<u8> {
12 let mut out = Vec::with_capacity(namespace_component.len() + 2);
13 out.extend_from_slice(&encode_length(namespace_component));
14 out.extend_from_slice(namespace_component);
15 out
16}
17
18pub fn to_length_prefixed_nested(namespace: &[&[u8]]) -> Vec<u8> {
21 let mut size = 0;
22 for component in namespace {
23 size += component.len() + 2;
24 }
25
26 let mut out = Vec::with_capacity(size);
27 for component in namespace {
28 out.extend_from_slice(&encode_length(component));
29 out.extend_from_slice(component);
30 }
31 out
32}
33
34fn encode_length(namespace_component: &[u8]) -> [u8; 2] {
37 if namespace_component.len() > 0xFFFF {
38 panic!("only supports namespace components up to length 0xFFFF")
39 }
40 let length_bytes = (namespace_component.len() as u32).to_be_bytes();
41 [length_bytes[2], length_bytes[3]]
42}
43
44pub fn namespace_with_key(namespace: &[&[u8]], key: &[u8]) -> Vec<u8> {
50 let mut size = key.len();
53 for component in namespace {
54 size += 2 + component.len() ;
55 }
56
57 let mut out = Vec::with_capacity(size);
58 for component in namespace {
59 out.extend_from_slice(&encode_length(component));
60 out.extend_from_slice(component);
61 }
62 out.extend_from_slice(key);
63 out
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn to_length_prefixed_works() {
72 assert_eq!(to_length_prefixed(b""), b"\x00\x00");
73 assert_eq!(to_length_prefixed(b"a"), b"\x00\x01a");
74 assert_eq!(to_length_prefixed(b"ab"), b"\x00\x02ab");
75 assert_eq!(to_length_prefixed(b"abc"), b"\x00\x03abc");
76 }
77
78 #[test]
79 fn to_length_prefixed_works_for_long_prefix() {
80 let long_namespace1 = vec![0; 256];
81 let prefix1 = to_length_prefixed(&long_namespace1);
82 assert_eq!(prefix1.len(), 256 + 2);
83 assert_eq!(&prefix1[0..2], b"\x01\x00");
84
85 let long_namespace2 = vec![0; 30000];
86 let prefix2 = to_length_prefixed(&long_namespace2);
87 assert_eq!(prefix2.len(), 30000 + 2);
88 assert_eq!(&prefix2[0..2], b"\x75\x30");
89
90 let long_namespace3 = vec![0; 0xFFFF];
91 let prefix3 = to_length_prefixed(&long_namespace3);
92 assert_eq!(prefix3.len(), 0xFFFF + 2);
93 assert_eq!(&prefix3[0..2], b"\xFF\xFF");
94 }
95
96 #[test]
97 #[should_panic(expected = "only supports namespace components up to length 0xFFFF")]
98 fn to_length_prefixed_panics_for_too_long_prefix() {
99 let limit = 0xFFFF;
100 let long_namespace = vec![0; limit + 1];
101 to_length_prefixed(&long_namespace);
102 }
103
104 #[test]
105 fn to_length_prefixed_calculates_capacity_correctly() {
106 let key = to_length_prefixed(b"");
110 assert_eq!(key.capacity(), key.len());
111
112 let key = to_length_prefixed(b"h");
113 assert_eq!(key.capacity(), key.len());
114
115 let key = to_length_prefixed(b"hij");
116 assert_eq!(key.capacity(), key.len());
117 }
118
119 #[test]
120 fn to_length_prefixed_nested_works() {
121 assert_eq!(to_length_prefixed_nested(&[]), b"");
122 assert_eq!(to_length_prefixed_nested(&[b""]), b"\x00\x00");
123 assert_eq!(to_length_prefixed_nested(&[b"", b""]), b"\x00\x00\x00\x00");
124
125 assert_eq!(to_length_prefixed_nested(&[b"a"]), b"\x00\x01a");
126 assert_eq!(
127 to_length_prefixed_nested(&[b"a", b"ab"]),
128 b"\x00\x01a\x00\x02ab"
129 );
130 assert_eq!(
131 to_length_prefixed_nested(&[b"a", b"ab", b"abc"]),
132 b"\x00\x01a\x00\x02ab\x00\x03abc"
133 );
134 }
135
136 #[test]
137 fn to_length_prefixed_nested_returns_the_same_as_to_length_prefixed_for_one_element() {
138 let tests = [b"" as &[u8], b"x" as &[u8], b"abababab" as &[u8]];
139
140 for test in tests {
141 assert_eq!(to_length_prefixed_nested(&[test]), to_length_prefixed(test));
142 }
143 }
144
145 #[test]
146 fn to_length_prefixed_nested_allows_many_long_namespaces() {
147 let long_namespace1 = vec![0xaa; 0xFFFD];
150 let long_namespace2 = vec![0xbb; 0xFFFE];
151 let long_namespace3 = vec![0xcc; 0xFFFF];
152
153 let prefix =
154 to_length_prefixed_nested(&[&long_namespace1, &long_namespace2, &long_namespace3]);
155 assert_eq!(&prefix[0..2], b"\xFF\xFD");
156 assert_eq!(&prefix[2..(2 + 0xFFFD)], long_namespace1.as_slice());
157 assert_eq!(&prefix[(2 + 0xFFFD)..(2 + 0xFFFD + 2)], b"\xFF\xFe");
158 assert_eq!(
159 &prefix[(2 + 0xFFFD + 2)..(2 + 0xFFFD + 2 + 0xFFFE)],
160 long_namespace2.as_slice()
161 );
162 assert_eq!(
163 &prefix[(2 + 0xFFFD + 2 + 0xFFFE)..(2 + 0xFFFD + 2 + 0xFFFE + 2)],
164 b"\xFF\xFf"
165 );
166 assert_eq!(
167 &prefix[(2 + 0xFFFD + 2 + 0xFFFE + 2)..(2 + 0xFFFD + 2 + 0xFFFE + 2 + 0xFFFF)],
168 long_namespace3.as_slice()
169 );
170 }
171
172 #[test]
173 fn to_length_prefixed_nested_calculates_capacity_correctly() {
174 let key = to_length_prefixed_nested(&[]);
178 assert_eq!(key.capacity(), key.len());
179
180 let key = to_length_prefixed_nested(&[b""]);
181 assert_eq!(key.capacity(), key.len());
182
183 let key = to_length_prefixed_nested(&[b"a"]);
184 assert_eq!(key.capacity(), key.len());
185
186 let key = to_length_prefixed_nested(&[b"a", b"bc"]);
187 assert_eq!(key.capacity(), key.len());
188
189 let key = to_length_prefixed_nested(&[b"a", b"bc", b"def"]);
190 assert_eq!(key.capacity(), key.len());
191 }
192
193 #[test]
194 fn encode_length_works() {
195 assert_eq!(encode_length(b""), *b"\x00\x00");
196 assert_eq!(encode_length(b"a"), *b"\x00\x01");
197 assert_eq!(encode_length(b"aa"), *b"\x00\x02");
198 assert_eq!(encode_length(b"aaa"), *b"\x00\x03");
199 assert_eq!(encode_length(&vec![1; 255]), *b"\x00\xff");
200 assert_eq!(encode_length(&vec![1; 256]), *b"\x01\x00");
201 assert_eq!(encode_length(&vec![1; 12345]), *b"\x30\x39");
202 assert_eq!(encode_length(&vec![1; 65535]), *b"\xff\xff");
203 }
204
205 #[test]
206 #[should_panic(expected = "only supports namespace components up to length 0xFFFF")]
207 fn encode_length_panics_for_large_values() {
208 encode_length(&vec![1; 65536]);
209 }
210
211 #[test]
212 fn namespace_with_key_works() {
213 let enc = namespace_with_key(&[], b"foo");
215 assert_eq!(enc, b"foo");
216 let enc = namespace_with_key(&[], b"");
217 assert_eq!(enc, b"");
218
219 let enc = namespace_with_key(&[b"bar"], b"foo");
221 assert_eq!(enc, b"\x00\x03barfoo");
222 let enc = namespace_with_key(&[b"bar"], b"");
223 assert_eq!(enc, b"\x00\x03bar");
224
225 let enc = namespace_with_key(&[b"bar", b"cool"], b"foo");
227 assert_eq!(enc, b"\x00\x03bar\x00\x04coolfoo");
228 let enc = namespace_with_key(&[b"bar", b"cool"], b"");
229 assert_eq!(enc, b"\x00\x03bar\x00\x04cool");
230 }
231}