radix_engine/blueprints/models/
payloads.rs

1use crate::internal_prelude::*;
2
3macro_rules! declare_payload_new_type {
4    (
5        content_trait: $content_trait:ident,
6        payload_trait: $payload_trait:ident,
7        ----
8        $(#[$attributes:meta])*
9        $vis:vis struct $payload_type_name:ident
10            $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? $( = $deflt:tt)? ),+ >)?
11            ($content_type:ty)$(;)?
12    ) => {
13        $(#[$attributes])*
14        #[sbor(transparent)]
15        /// This new type represents the payload of a particular field or collection.
16        /// It is unique to this particular field/collection.
17        ///
18        /// Therefore, it can be used to disambiguate if the same content type is used
19        /// by different blueprints (e.g. two different versions of the same blueprint)
20        $vis struct $payload_type_name
21        $(< $( $lt $( : $clt $(+ $dlt )* )? $( = $deflt)? ),+ >)?
22        {
23            content: $content_type
24        }
25
26        impl
27        $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
28        $payload_type_name $(< $( $lt ),+ >)?
29        {
30            pub fn of(content: $content_type) -> Self {
31                Self {
32                    content,
33                }
34            }
35        }
36
37
38        impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
39            core::convert::From<$content_type>
40            for $payload_type_name $(< $( $lt ),+ >)?
41        {
42            fn from(value: $content_type) -> Self {
43                Self {
44                    content: value,
45                }
46            }
47        }
48
49        impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
50            core::convert::AsRef<$content_type>
51            for $payload_type_name $(< $( $lt ),+ >)?
52        {
53            fn as_ref(&self) -> &$content_type {
54                &self.content
55            }
56        }
57
58        impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
59            core::ops::Deref
60            for $payload_type_name $(< $( $lt ),+ >)?
61        {
62            type Target = $content_type;
63
64            fn deref(&self) -> &Self::Target {
65                &self.content
66            }
67        }
68
69        impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
70            core::convert::AsMut<$content_type>
71            for $payload_type_name $(< $( $lt ),+ >)?
72        {
73            fn as_mut(&mut self) -> &mut $content_type {
74                &mut self.content
75            }
76        }
77
78        impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
79            core::ops::DerefMut
80            for $payload_type_name $(< $( $lt ),+ >)?
81        {
82            fn deref_mut(&mut self) -> &mut Self::Target {
83                &mut self.content
84            }
85        }
86
87        impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
88            $payload_trait
89            for $payload_type_name $(< $( $lt ),+ >)?
90        {
91            type Content = $content_type;
92
93            fn into_content(self) -> Self::Content {
94                self.content
95            }
96        }
97
98        impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
99            $content_trait<$payload_type_name$(< $( $lt ),+ >)?>
100            for $content_type
101        {
102            fn into_content(self) -> $content_type {
103                self
104            }
105        }
106    }
107}
108use crate::system::system_substates::FieldSubstate;
109#[allow(unused)]
110pub(crate) use declare_payload_new_type;
111
112/// This trait is intended to be implemented by an explicit new type for for the given
113/// `{ content: T }` payload of a particular field.
114pub trait FieldPayload:
115    Sized + AsRef<Self::Content> + AsMut<Self::Content> + From<Self::Content>
116{
117    type Content: FieldContentSource<Self>;
118
119    fn into_content(self) -> Self::Content;
120
121    fn from_content(content: Self::Content) -> Self {
122        Self::from(content)
123    }
124
125    fn from_content_source<T: FieldContentSource<Self>>(content: T) -> Self {
126        Self::from_content(content.into_content())
127    }
128
129    fn into_locked_substate(self) -> FieldSubstate<Self> {
130        FieldSubstate::new_locked_field(self)
131    }
132
133    fn into_unlocked_substate(self) -> FieldSubstate<Self> {
134        FieldSubstate::new_unlocked_field(self)
135    }
136}
137
138/// This trait is intended to be implemented by types which embody the content
139/// of a particular field payload.
140///
141/// Note:
142/// * Multiple types might be mappable into the payload, and so implement this trait
143/// * This trait is only one way - from value into content
144/// * This trait uses a generic, because the same type might be usable as a payload for multiple
145///   substates
146pub trait FieldContentSource<Payload: FieldPayload>: Sized {
147    fn into_content(self) -> Payload::Content;
148
149    fn into_payload(self) -> Payload {
150        Payload::from_content_source(self)
151    }
152
153    fn into_locked_substate(self) -> FieldSubstate<Payload> {
154        self.into_payload().into_locked_substate()
155    }
156
157    fn into_unlocked_substate(self) -> FieldSubstate<Payload> {
158        self.into_payload().into_unlocked_substate()
159    }
160}
161
162/// This trait is intended to be implemented by an explicit new type for for the given
163/// `{ content: T }` payload of a particular key value collection.
164pub trait KeyValueEntryPayload:
165    Sized + AsRef<Self::Content> + AsMut<Self::Content> + From<Self::Content>
166{
167    type Content: KeyValueEntryContentSource<Self>;
168
169    fn into_content(self) -> Self::Content;
170
171    fn from_content(inner_content: Self::Content) -> Self {
172        Self::from(inner_content)
173    }
174
175    fn from_content_source<T: KeyValueEntryContentSource<Self>>(content: T) -> Self {
176        Self::from_content(content.into_content())
177    }
178
179    fn into_locked_substate(self) -> KeyValueEntrySubstate<Self> {
180        KeyValueEntrySubstate::locked_entry(self)
181    }
182
183    fn into_unlocked_substate(self) -> KeyValueEntrySubstate<Self> {
184        KeyValueEntrySubstate::unlocked_entry(self)
185    }
186}
187
188/// This trait is intended to be implemented by types which embody the content
189/// of a particular key value entry payload.
190///
191/// Note:
192/// * Multiple types might be mappable into the payload, and so implement this trait
193/// * This trait is only one way - from value into content
194/// * This trait uses a generic, because the same type might be usable as a payload for multiple
195///   substates
196pub trait KeyValueEntryContentSource<Payload: KeyValueEntryPayload>: Sized {
197    fn into_content(self) -> Payload::Content;
198
199    fn into_payload(self) -> Payload {
200        Payload::from_content_source(self)
201    }
202
203    fn into_locked_substate(self) -> KeyValueEntrySubstate<Payload> {
204        self.into_payload().into_locked_substate()
205    }
206
207    fn into_unlocked_substate(self) -> KeyValueEntrySubstate<Payload> {
208        self.into_payload().into_unlocked_substate()
209    }
210}
211
212/// This trait is intended to be implemented by an explicit new type for for the given
213/// `{ content: T }` payload of a particular index collection.
214pub trait IndexEntryPayload:
215    Sized + AsRef<Self::Content> + AsMut<Self::Content> + From<Self::Content>
216{
217    type Content: IndexEntryContentSource<Self>;
218
219    fn into_content(self) -> Self::Content;
220    fn from_content(inner_content: Self::Content) -> Self {
221        Self::from(inner_content)
222    }
223
224    fn from_content_source<T: IndexEntryContentSource<Self>>(content: T) -> Self {
225        Self::from_content(content.into_content())
226    }
227
228    fn into_substate(self) -> IndexEntrySubstate<Self> {
229        IndexEntrySubstate::entry(self)
230    }
231}
232
233/// This trait is intended to be implemented by types which embody the content
234/// of a particular index entry payload.
235///
236/// Note:
237/// * Multiple types might be mappable into the payload, and so implement this trait
238/// * This trait is only one way - from value into content
239/// * This trait uses a generic, because the same type might be usable as a payload for multiple
240///   substates
241pub trait IndexEntryContentSource<Payload: IndexEntryPayload>: Sized {
242    fn into_content(self) -> Payload::Content;
243
244    fn into_payload(self) -> Payload {
245        Payload::from_content_source(self)
246    }
247
248    fn into_substate(self) -> IndexEntrySubstate<Payload> {
249        self.into_payload().into_substate()
250    }
251}
252
253/// This trait is intended to be implemented by an explicit new type for for the given
254/// `{ content: T }` payload of a particular sorted index collection.
255pub trait SortedIndexEntryPayload:
256    Sized + AsRef<Self::Content> + AsMut<Self::Content> + From<Self::Content>
257{
258    type Content: SortedIndexEntryContentSource<Self>;
259
260    fn into_content(self) -> Self::Content;
261
262    fn from_content(inner_content: Self::Content) -> Self {
263        Self::from(inner_content)
264    }
265
266    fn from_content_source<T: SortedIndexEntryContentSource<Self>>(content: T) -> Self {
267        Self::from_content(content.into_content())
268    }
269
270    fn into_substate(self) -> SortedIndexEntrySubstate<Self> {
271        SortedIndexEntrySubstate::entry(self)
272    }
273}
274
275/// This trait is intended to be implemented by types which embody the content
276/// of a particular sorted index entry payload.
277///
278/// Note:
279/// * Multiple types might be mappable into the payload, and so implement this trait
280/// * This trait is only one way - from value into content
281/// * This trait uses a generic, because the same type might be usable as a payload for multiple
282///   substates
283pub trait SortedIndexEntryContentSource<Payload: SortedIndexEntryPayload>: Sized {
284    fn into_content(self) -> Payload::Content;
285
286    fn into_payload(self) -> Payload {
287        Payload::from_content_source(self)
288    }
289
290    fn into_substate(self) -> SortedIndexEntrySubstate<Payload> {
291        self.into_payload().into_substate()
292    }
293}