multiversx_chain_core/types/flags/
code_metadata.rs1#![allow(clippy::bad_bit_mask)]
2
3use crate::codec::*;
4use bitflags::bitflags;
5
6const UPGRADEABLE_STRING: &str = "Upgradeable";
7const READABLE_STRING: &str = "Readable";
8const PAYABLE_STRING: &str = "Payable";
9const PAYABLE_BY_SC_STRING: &str = "PayableBySC";
10const DEFAULT_STRING: &str = "Default";
11
12bitflags! {
13 #[derive(Default, PartialEq, Debug, Clone, Copy)]
14 pub struct CodeMetadata: u16 {
15 const DEFAULT = 0;
16 const UPGRADEABLE = 0b0000_0001_0000_0000; const READABLE = 0b0000_0100_0000_0000; const PAYABLE = 0b0000_0000_0000_0010; const PAYABLE_BY_SC = 0b0000_0000_0000_0100; }
21}
22
23impl CodeMetadata {
24 pub fn is_upgradeable(&self) -> bool {
25 *self & CodeMetadata::UPGRADEABLE != CodeMetadata::DEFAULT
26 }
27
28 pub fn is_payable(&self) -> bool {
29 *self & CodeMetadata::PAYABLE != CodeMetadata::DEFAULT
30 }
31
32 pub fn is_payable_by_sc(&self) -> bool {
33 *self & CodeMetadata::PAYABLE_BY_SC != CodeMetadata::DEFAULT
34 }
35
36 pub fn is_readable(&self) -> bool {
37 *self & CodeMetadata::READABLE != CodeMetadata::DEFAULT
38 }
39
40 #[inline]
41 pub fn to_byte_array(&self) -> [u8; 2] {
42 self.bits().to_be_bytes()
43 }
44
45 pub fn to_vec(&self) -> Vec<u8> {
46 self.to_byte_array().to_vec()
47 }
48
49 pub fn for_each_string_token<F: FnMut(&'static str)>(&self, mut f: F) {
50 let mut nothing_printed: bool = true;
51 if self.is_upgradeable() {
52 f(UPGRADEABLE_STRING);
53 nothing_printed = false;
54 }
55 if self.is_readable() {
56 if !nothing_printed {
57 f("|");
58 }
59 f(READABLE_STRING);
60 nothing_printed = false;
61 }
62 if self.is_payable() {
63 if !nothing_printed {
64 f("|");
65 }
66 f(PAYABLE_STRING);
67 nothing_printed = false;
68 }
69 if self.is_payable_by_sc() {
70 if !nothing_printed {
71 f("|");
72 }
73 f(PAYABLE_BY_SC_STRING);
74 nothing_printed = false;
75 }
76
77 if nothing_printed {
78 f(DEFAULT_STRING);
79 }
80 }
81}
82
83impl From<[u8; 2]> for CodeMetadata {
84 #[inline]
85 fn from(arr: [u8; 2]) -> Self {
86 CodeMetadata::from(u16::from_be_bytes(arr))
87 }
88}
89
90impl From<u16> for CodeMetadata {
91 #[inline]
92 fn from(value: u16) -> Self {
93 CodeMetadata::from_bits_truncate(value)
94 }
95}
96
97impl From<&[u8]> for CodeMetadata {
98 fn from(slice: &[u8]) -> Self {
99 let arr: [u8; 2] = slice.try_into().unwrap_or_default();
100 CodeMetadata::from(arr)
101 }
102}
103
104impl From<&Vec<u8>> for CodeMetadata {
105 fn from(v: &Vec<u8>) -> Self {
106 CodeMetadata::from(v.as_slice())
107 }
108}
109
110impl NestedEncode for CodeMetadata {
111 fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
112 where
113 O: NestedEncodeOutput,
114 H: EncodeErrorHandler,
115 {
116 self.bits().dep_encode_or_handle_err(dest, h)?;
117 Ok(())
118 }
119}
120
121impl TopEncode for CodeMetadata {
122 #[inline]
123 fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
124 where
125 O: TopEncodeOutput,
126 H: EncodeErrorHandler,
127 {
128 top_encode_from_nested(self, output, h)
129 }
130}
131
132impl NestedDecode for CodeMetadata {
133 fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
134 where
135 I: NestedDecodeInput,
136 H: DecodeErrorHandler,
137 {
138 Ok(CodeMetadata::from(u16::dep_decode_or_handle_err(input, h)?))
139 }
140}
141
142impl TopDecode for CodeMetadata {
143 fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
144 where
145 I: TopDecodeInput,
146 H: DecodeErrorHandler,
147 {
148 top_decode_from_nested_or_handle_err(input, h)
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155
156 #[test]
157 fn test_default() {
158 assert!(!CodeMetadata::DEFAULT.is_upgradeable());
159 assert!(!CodeMetadata::DEFAULT.is_payable());
160 assert!(!CodeMetadata::DEFAULT.is_readable());
161 }
162
163 #[test]
164 fn test_all() {
165 let all = CodeMetadata::UPGRADEABLE
166 | CodeMetadata::PAYABLE
167 | CodeMetadata::PAYABLE_BY_SC
168 | CodeMetadata::READABLE;
169 assert!(all.is_upgradeable());
170 assert!(all.is_payable());
171 assert!(all.is_payable_by_sc());
172 assert!(all.is_readable());
173
174 assert_eq!(all.bits(), 0x0506);
175
176 assert_eq!(CodeMetadata::from_bits_truncate(0xffff), all);
177 }
178
179 #[test]
180 fn test_each() {
181 assert!(CodeMetadata::UPGRADEABLE.is_upgradeable());
182 assert!(!CodeMetadata::PAYABLE.is_upgradeable());
183 assert!(!CodeMetadata::PAYABLE_BY_SC.is_upgradeable());
184 assert!(!CodeMetadata::READABLE.is_upgradeable());
185
186 assert!(!CodeMetadata::UPGRADEABLE.is_payable());
187 assert!(CodeMetadata::PAYABLE.is_payable());
188 assert!(!CodeMetadata::PAYABLE_BY_SC.is_payable());
189 assert!(!CodeMetadata::READABLE.is_payable());
190
191 assert!(!CodeMetadata::UPGRADEABLE.is_payable_by_sc());
192 assert!(!CodeMetadata::PAYABLE.is_payable_by_sc());
193 assert!(CodeMetadata::PAYABLE_BY_SC.is_payable_by_sc());
194 assert!(!CodeMetadata::READABLE.is_payable_by_sc());
195
196 assert!(!CodeMetadata::UPGRADEABLE.is_readable());
197 assert!(!CodeMetadata::PAYABLE.is_readable());
198 assert!(!CodeMetadata::PAYABLE_BY_SC.is_readable());
199 assert!(CodeMetadata::READABLE.is_readable());
200 }
201
202 #[test]
204 fn test_from_array() {
205 assert!(CodeMetadata::from([1, 0]).is_upgradeable());
206 assert!(!CodeMetadata::from([1, 0]).is_readable());
207 assert!(CodeMetadata::from([0, 2]).is_payable());
208 assert!(CodeMetadata::from([4, 0]).is_readable());
209 assert!(!CodeMetadata::from([4, 0]).is_upgradeable());
210 assert!(!CodeMetadata::from([0, 0]).is_upgradeable());
211 assert!(!CodeMetadata::from([0, 0]).is_payable());
212 assert!(!CodeMetadata::from([0, 0]).is_readable());
213 }
214}