radix_engine/blueprints/models/
keys.rs1use crate::internal_prelude::*;
2
3macro_rules! declare_key_new_type {
4 (
6 content_trait: SortedIndexKeyContentSource,
7 payload_trait: SortedIndexKeyPayload,
8 full_key_content: {
9 full_content_type: $full_content_type:ty,
10 sort_prefix_property_name: $sort_prefix_property_name:ident
11 $(,)?
12 },
13 ----
14 $(#[$attributes:meta])*
15 $vis:vis struct $payload_type_name:ident
16 $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? $( = $deflt:tt)? ),+ >)?
17 ($content_type:ty)$(;)?
18 ) => {
19 $(#[$attributes])*
20 $vis struct $payload_type_name
22 $(< $( $lt $( : $clt $(+ $dlt )* )? $( = $deflt)? ),+ >)?
23 {
24 pub $sort_prefix_property_name: u16,
25 pub content: $content_type,
26 }
27
28 impl $payload_type_name {
29 pub fn new($sort_prefix_property_name: u16, content: $content_type) -> Self {
30 Self {
31 $sort_prefix_property_name,
32 content,
33 }
34 }
35
36 pub fn sort_prefix(&self) -> u16 {
37 self.$sort_prefix_property_name
38 }
39 }
40
41 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
42 core::convert::AsRef<$content_type>
43 for $payload_type_name $(< $( $lt ),+ >)?
44 {
45 fn as_ref(&self) -> &$content_type {
46 &self.content
47 }
48 }
49
50 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
51 core::convert::AsMut<$content_type>
52 for $payload_type_name $(< $( $lt ),+ >)?
53 {
54 fn as_mut(&mut self) -> &mut $content_type {
55 &mut self.content
56 }
57 }
58
59 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
60 SortedIndexKeyPayload
61 for $payload_type_name $(< $( $lt ),+ >)?
62 {
63 type Content = $content_type;
64 type FullContent = $full_content_type;
65
66 fn into_sort_key_and_content(self) -> (u16, Self::Content) {
67 (self.sort_prefix(), self.content)
68 }
69
70 fn as_sort_key_and_content(&self) -> (u16, &Self::Content) {
71 (self.sort_prefix(), &self.content)
72 }
73
74 fn from_sort_key_and_content(sort_prefix: u16, content: Self::Content) -> Self {
75 Self {
76 $sort_prefix_property_name: sort_prefix,
77 content,
78 }
79 }
80 }
81
82 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
83 TryFrom<&SubstateKey>
84 for $payload_type_name $(< $( $lt ),+ >)?
85 {
86 type Error = ();
87
88 fn try_from(substate_key: &SubstateKey) -> Result<Self, Self::Error> {
89 let (sort_prefix, payload_bytes) = substate_key.for_sorted().ok_or(())?;
90 let content = scrypto_decode(payload_bytes).map_err(|_| ())?;
91 Ok(Self::from_sort_key_and_content(u16::from_be_bytes(*sort_prefix), content))
92 }
93 }
94
95 };
100 (
101 content_trait: SortedIndexKeyContentSource,
102 payload_trait: SortedIndexKeyPayload,
103 ----
104 $(#[$attributes:meta])*
105 $vis:vis struct $payload_type_name:ident
106 $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? $( = $deflt:tt)? ),+ >)?
107 ($content_type:ty)$(;)?
108 ) => {
109 compile_error!(
110 "Make sure to add a `full_key_content: { full_content_type: <ident>, sort_prefix_property_name: <..>}` property after the `key_type` property for SortedIndex collection definitions"
111 )
112 };
113 (
114 content_trait: $content_trait:ident,
115 payload_trait: $payload_trait:ident,
116 full_key_content: $full_key_content:tt,
117 ----
118 $(#[$attributes:meta])*
119 $vis:vis struct $payload_type_name:ident
120 $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? $( = $deflt:tt)? ),+ >)?
121 ($content_type:ty)$(;)?
122 ) => {
123 compile_error!(
124 "Only add a `full_key_content` property for SortedIndex collection definitions"
125 )
126 };
127 (
129 content_trait: $content_trait:ident,
130 payload_trait: $payload_trait:ident,
131 ----
132 $(#[$attributes:meta])*
133 $vis:vis struct $payload_type_name:ident
134 $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? $( = $deflt:tt)? ),+ >)?
135 ($content_type:ty)$(;)?
136 ) => {
137 $(#[$attributes])*
138 #[sbor(transparent, transparent_name)]
139 $vis struct $payload_type_name
141 $(< $( $lt $( : $clt $(+ $dlt )* )? $( = $deflt)? ),+ >)?
142 {
143 pub content: $content_type,
144 }
145
146 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
147 core::convert::From<$content_type>
148 for $payload_type_name $(< $( $lt ),+ >)?
149 {
150 fn from(value: $content_type) -> Self {
151 Self {
152 content: value,
153 }
154 }
155 }
156
157 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
158 core::convert::AsRef<$content_type>
159 for $payload_type_name $(< $( $lt ),+ >)?
160 {
161 fn as_ref(&self) -> &$content_type {
162 &self.content
163 }
164 }
165
166 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
167 core::convert::AsMut<$content_type>
168 for $payload_type_name $(< $( $lt ),+ >)?
169 {
170 fn as_mut(&mut self) -> &mut $content_type {
171 &mut self.content
172 }
173 }
174
175 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
176 TryFrom<&SubstateKey>
177 for $payload_type_name $(< $( $lt ),+ >)?
178 {
179 type Error = ();
180
181 fn try_from(substate_key: &SubstateKey) -> Result<Self, Self::Error> {
182 let key = substate_key.for_map().ok_or(())?;
183 scrypto_decode::<Self>(&key).map_err(|_| ())
184 }
185 }
186
187 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
188 $payload_trait
189 for $payload_type_name $(< $( $lt ),+ >)?
190 {
191 type Content = $content_type;
192
193 fn into_content(self) -> Self::Content {
194 self.content
195 }
196 }
197
198 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
199 $content_trait<$payload_type_name$(< $( $lt ),+ >)?>
200 for $content_type
201 {
202 fn into_content(self) -> $content_type {
203 self
204 }
205 }
206 }
207}
208#[allow(unused)]
209pub(crate) use declare_key_new_type;
210
211pub trait KeyValueKeyPayload:
214 Sized + AsRef<Self::Content> + AsMut<Self::Content> + From<Self::Content>
215{
216 type Content: KeyValueKeyContentSource<Self>;
217
218 fn into_content(self) -> Self::Content;
219 fn from_content(inner_content: Self::Content) -> Self {
220 Self::from(inner_content)
221 }
222
223 fn from_content_source<T: KeyValueKeyContentSource<Self>>(content: T) -> Self {
224 Self::from_content(content.into_content())
225 }
226}
227
228pub trait KeyValueKeyContentSource<Payload: KeyValueKeyPayload>: Sized {
237 fn into_content(self) -> Payload::Content;
238
239 fn into_key(self) -> Payload {
240 Payload::from_content_source(self)
241 }
242}
243
244pub trait IndexKeyPayload:
247 Sized + AsRef<Self::Content> + AsMut<Self::Content> + From<Self::Content>
248{
249 type Content: IndexKeyContentSource<Self>;
250
251 fn into_content(self) -> Self::Content;
252 fn from_content(content: Self::Content) -> Self {
253 Self::from(content)
254 }
255
256 fn from_content_source<T: IndexKeyContentSource<Self>>(content: T) -> Self {
257 Self::from_content(content.into_content())
258 }
259}
260
261pub trait IndexKeyContentSource<Payload: IndexKeyPayload>: Sized {
270 fn into_content(self) -> Payload::Content;
271
272 fn into_key(self) -> Payload {
273 Payload::from_content_source(self)
274 }
275}
276
277pub trait SortedIndexKeyPayload: Sized + AsRef<Self::Content> + AsMut<Self::Content> {
280 type Content;
281 type FullContent: SortedIndexKeyFullContent<Self>;
282
283 fn from_sort_key_and_content(sort_key: u16, content: Self::Content) -> Self;
284 fn into_sort_key_and_content(self) -> (u16, Self::Content);
285 fn as_sort_key_and_content(&self) -> (u16, &Self::Content);
286
287 fn into_full_content(self) -> Self::FullContent {
288 let (sort_key, content) = self.into_sort_key_and_content();
289 Self::FullContent::from_sort_key_and_content(sort_key, content)
290 }
291
292 fn from_content_source<T: SortedIndexKeyContentSource<Self>>(content: T) -> Self {
293 let (sort_key, content) = content.into_sort_key_and_content();
294 Self::from_sort_key_and_content(sort_key, content)
295 }
296}
297
298pub trait SortedIndexKeyContentSource<Payload: SortedIndexKeyPayload>: Sized {
307 fn sort_key(&self) -> u16;
308 fn into_content(self) -> Payload::Content;
309
310 fn into_sort_key_and_content(self) -> (u16, Payload::Content) {
311 (self.sort_key(), self.into_content())
312 }
313
314 fn into_key(self) -> Payload {
315 Payload::from_content_source(self)
316 }
317}
318
319pub trait SortedIndexKeyFullContent<Payload: SortedIndexKeyPayload>:
322 SortedIndexKeyContentSource<Payload>
323{
324 fn from_sort_key_and_content(sort_key: u16, content: Payload::Content) -> Self;
325 fn as_content(&self) -> &Payload::Content;
326
327 fn as_sort_key_and_content(&self) -> (u16, &Payload::Content) {
328 (self.sort_key(), self.as_content())
329 }
330}