multiversx_sc/types/managed/wrapped/
managed_byte_array.rs1use core::convert::TryFrom;
2
3use alloc::format;
4
5use crate::{
6 abi::{TypeAbi, TypeAbiFrom, TypeName},
7 api::ManagedTypeApi,
8 codec::{
9 DecodeError, DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput,
10 NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput,
11 TryStaticCast,
12 },
13 formatter::{hex_util::encode_bytes_as_hex, FormatByteReceiver, SCLowerHex},
14 types::{ManagedBuffer, ManagedType},
15};
16
17const DECODE_ERROR_BAD_LENGTH: &str = "bad array length";
18
19#[repr(transparent)]
23#[derive(Clone)]
24pub struct ManagedByteArray<M, const N: usize>
25where
26 M: ManagedTypeApi,
27{
28 pub(crate) buffer: ManagedBuffer<M>,
29}
30
31impl<M, const N: usize> ManagedType<M> for ManagedByteArray<M, N>
32where
33 M: ManagedTypeApi,
34{
35 type OwnHandle = M::ManagedBufferHandle;
36
37 #[inline]
38 unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self {
39 ManagedByteArray {
40 buffer: ManagedBuffer::from_handle(handle),
41 }
42 }
43
44 fn get_handle(&self) -> M::ManagedBufferHandle {
45 self.buffer.get_handle()
46 }
47
48 unsafe fn forget_into_handle(self) -> Self::OwnHandle {
49 self.buffer.forget_into_handle()
50 }
51
52 fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
53 unsafe { core::mem::transmute(handle_ref) }
54 }
55
56 fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self {
57 unsafe { core::mem::transmute(handle_ref) }
58 }
59}
60
61impl<M, const N: usize> Default for ManagedByteArray<M, N>
62where
63 M: ManagedTypeApi,
64{
65 #[inline]
66 fn default() -> Self {
67 Self::new_from_bytes(&[0u8; N])
68 }
69}
70
71impl<M, const N: usize> From<&[u8; N]> for ManagedByteArray<M, N>
72where
73 M: ManagedTypeApi,
74{
75 #[inline]
76 fn from(bytes: &[u8; N]) -> Self {
77 Self::new_from_bytes(bytes)
78 }
79}
80
81impl<M, const N: usize> ManagedByteArray<M, N>
82where
83 M: ManagedTypeApi,
84{
85 #[inline]
86 pub fn new_from_bytes(bytes: &[u8; N]) -> Self {
87 ManagedByteArray {
88 buffer: ManagedBuffer::new_from_bytes(&bytes[..]),
89 }
90 }
91
92 pub unsafe fn new_uninit() -> Self {
98 ManagedByteArray {
99 buffer: ManagedBuffer::new_uninit(),
100 }
101 }
102
103 #[inline]
105 pub fn len(&self) -> usize {
106 self.buffer.len()
107 }
108
109 #[inline]
110 pub fn is_empty(&self) -> bool {
111 self.len() == 0
112 }
113
114 #[inline]
115 pub fn as_managed_buffer(&self) -> &ManagedBuffer<M> {
116 &self.buffer
117 }
118
119 #[inline]
120 pub fn to_byte_array(&self) -> [u8; N] {
121 let mut result = [0u8; N];
122 self.buffer.load_slice(0, &mut result[..]);
123 result
124 }
125}
126
127impl<M, const N: usize> PartialEq for ManagedByteArray<M, N>
128where
129 M: ManagedTypeApi,
130{
131 #[inline]
132 fn eq(&self, other: &Self) -> bool {
133 self.buffer == other.buffer
134 }
135}
136
137impl<M, const N: usize> Eq for ManagedByteArray<M, N> where M: ManagedTypeApi {}
138
139impl<M, const N: usize> TryFrom<ManagedBuffer<M>> for ManagedByteArray<M, N>
140where
141 M: ManagedTypeApi,
142{
143 type Error = DecodeError;
144
145 fn try_from(value: ManagedBuffer<M>) -> Result<Self, Self::Error> {
146 if value.len() != N {
147 return Err(DecodeError::from(DECODE_ERROR_BAD_LENGTH));
148 }
149 Ok(ManagedByteArray { buffer: value })
150 }
151}
152
153impl<M, const N: usize> TopEncode for ManagedByteArray<M, N>
154where
155 M: ManagedTypeApi,
156{
157 #[inline]
158 fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
159 where
160 O: TopEncodeOutput,
161 H: EncodeErrorHandler,
162 {
163 self.buffer.top_encode_or_handle_err(output, h)
164 }
165}
166
167impl<M, const N: usize> TopDecode for ManagedByteArray<M, N>
168where
169 M: ManagedTypeApi,
170{
171 fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
172 where
173 I: TopDecodeInput,
174 H: DecodeErrorHandler,
175 {
176 let buffer = ManagedBuffer::top_decode_or_handle_err(input, h)?;
177 if buffer.len() != N {
178 return Err(h.handle_error(DecodeError::from(DECODE_ERROR_BAD_LENGTH)));
179 }
180 Ok(ManagedByteArray { buffer })
181 }
182}
183
184#[derive(Clone)]
185pub(crate) struct ManagedBufferSizeContext(pub usize);
186
187impl TryStaticCast for ManagedBufferSizeContext {}
188
189impl<M, const N: usize> NestedEncode for ManagedByteArray<M, N>
190where
191 M: ManagedTypeApi,
192{
193 #[inline]
194 fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
195 where
196 O: NestedEncodeOutput,
197 H: EncodeErrorHandler,
198 {
199 if O::supports_specialized_type::<ManagedBuffer<M>>() {
200 dest.push_specialized((), &self.buffer, h)
201 } else {
202 dest.write(self.buffer.to_boxed_bytes().as_slice());
203 Ok(())
204 }
205 }
206}
207
208impl<M, const N: usize> NestedDecode for ManagedByteArray<M, N>
209where
210 M: ManagedTypeApi,
211{
212 fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
213 where
214 I: NestedDecodeInput,
215 H: DecodeErrorHandler,
216 {
217 let buffer = if I::supports_specialized_type::<ManagedBuffer<M>>() {
218 input.read_specialized(ManagedBufferSizeContext(N), h)?
219 } else {
220 let byte_array = <[u8; N]>::dep_decode_or_handle_err(input, h)?;
221 byte_array.as_ref().into()
222 };
223 Ok(ManagedByteArray { buffer })
224 }
225}
226
227impl<M, const N: usize> TypeAbiFrom<ManagedByteArray<M, N>> for [u8; N] where M: ManagedTypeApi {}
228
229impl<M, const N: usize> TypeAbiFrom<Self> for ManagedByteArray<M, N> where M: ManagedTypeApi {}
230impl<M, const N: usize> TypeAbiFrom<&Self> for ManagedByteArray<M, N> where M: ManagedTypeApi {}
231
232impl<M, const N: usize> TypeAbi for ManagedByteArray<M, N>
233where
234 M: ManagedTypeApi,
235{
236 type Unmanaged = [u8; N];
237
238 fn type_name() -> TypeName {
240 <[u8; N] as TypeAbi>::type_name()
241 }
242
243 fn type_name_rust() -> TypeName {
244 format!("ManagedByteArray<$API, {N}usize>")
245 }
246}
247
248impl<M, const N: usize> SCLowerHex for ManagedByteArray<M, N>
249where
250 M: ManagedTypeApi,
251{
252 fn fmt<F: FormatByteReceiver>(&self, f: &mut F) {
253 SCLowerHex::fmt(&self.buffer, f)
254 }
255}
256
257impl<M, const N: usize> core::fmt::Debug for ManagedByteArray<M, N>
258where
259 M: ManagedTypeApi,
260{
261 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
262 f.debug_struct("ManagedByteArray")
263 .field("handle", &self.buffer.handle)
264 .field("size", &N)
265 .field("hex-value", &encode_bytes_as_hex(&self.to_byte_array()))
266 .finish()
267 }
268}