drt_sc/types/managed/wrapped/
token_identifier.rs

1use alloc::string::ToString;
2
3use crate::{
4    abi::{TypeAbi, TypeAbiFrom, TypeName},
5    api::{ErrorApi, ErrorApiImpl, HandleConstraints, ManagedTypeApi, ManagedTypeApiImpl},
6    codec::*,
7    err_msg,
8    formatter::{FormatByteReceiver, SCDisplay, SCLowerHex},
9    types::{ManagedBuffer, ManagedType},
10};
11
12use super::RewaOrDcdtTokenIdentifier;
13
14/// Specialized type for handling token identifiers.
15/// It wraps a BoxedBytes with the full ASCII name of the token.
16/// REWA is stored as an empty name.
17///
18/// Not yet implemented, but we might add additional restrictions when deserializing as argument.
19#[repr(transparent)]
20#[derive(Clone)]
21pub struct TokenIdentifier<M: ErrorApi + ManagedTypeApi> {
22    buffer: ManagedBuffer<M>,
23}
24
25impl<M: ManagedTypeApi> ManagedType<M> for TokenIdentifier<M> {
26    type OwnHandle = M::ManagedBufferHandle;
27
28    #[inline]
29    fn from_handle(handle: M::ManagedBufferHandle) -> Self {
30        TokenIdentifier {
31            buffer: ManagedBuffer::from_handle(handle),
32        }
33    }
34
35    fn get_handle(&self) -> M::ManagedBufferHandle {
36        self.buffer.get_handle()
37    }
38
39    fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
40        unsafe { core::mem::transmute(handle_ref) }
41    }
42}
43
44impl<M: ManagedTypeApi> TokenIdentifier<M> {
45    #[inline]
46    pub fn from_dcdt_bytes<B: Into<ManagedBuffer<M>>>(bytes: B) -> Self {
47        TokenIdentifier {
48            buffer: bytes.into(),
49        }
50    }
51
52    #[inline]
53    pub fn into_managed_buffer(self) -> ManagedBuffer<M> {
54        self.buffer
55    }
56
57    #[inline]
58    pub fn as_managed_buffer(&self) -> &ManagedBuffer<M> {
59        &self.buffer
60    }
61
62    #[inline]
63    pub fn to_boxed_bytes(&self) -> crate::types::heap::BoxedBytes {
64        self.buffer.to_boxed_bytes()
65    }
66
67    pub fn is_valid_dcdt_identifier(&self) -> bool {
68        M::managed_type_impl().validate_token_identifier(self.buffer.handle.clone())
69    }
70
71    pub fn ticker(&self) -> ManagedBuffer<M> {
72        let token_id_len = self.buffer.len();
73        let ticker_len = M::managed_type_impl().get_token_ticker_len(token_id_len);
74        self.buffer.copy_slice(0, ticker_len).unwrap_or_else(|| {
75            M::error_api_impl().signal_error(err_msg::BAD_TOKEN_TICKER_FORMAT.as_bytes())
76        })
77    }
78}
79
80impl<M: ManagedTypeApi> From<ManagedBuffer<M>> for TokenIdentifier<M> {
81    #[inline]
82    fn from(buffer: ManagedBuffer<M>) -> Self {
83        TokenIdentifier { buffer }
84    }
85}
86
87impl<M: ManagedTypeApi> From<&[u8]> for TokenIdentifier<M> {
88    fn from(bytes: &[u8]) -> Self {
89        TokenIdentifier {
90            buffer: ManagedBuffer::new_from_bytes(bytes),
91        }
92    }
93}
94
95impl<M: ManagedTypeApi> From<&str> for TokenIdentifier<M> {
96    fn from(s: &str) -> Self {
97        TokenIdentifier::from(s.as_bytes())
98    }
99}
100
101impl<M: ManagedTypeApi> From<&crate::types::heap::String> for TokenIdentifier<M> {
102    fn from(s: &crate::types::heap::String) -> Self {
103        TokenIdentifier::from(s.as_bytes())
104    }
105}
106
107impl<M: ManagedTypeApi> PartialEq for TokenIdentifier<M> {
108    #[inline]
109    fn eq(&self, other: &Self) -> bool {
110        self.buffer == other.buffer
111    }
112}
113
114impl<M: ManagedTypeApi> Eq for TokenIdentifier<M> {}
115
116impl<M: ManagedTypeApi> PartialEq<RewaOrDcdtTokenIdentifier<M>> for TokenIdentifier<M> {
117    #[inline]
118    fn eq(&self, other: &RewaOrDcdtTokenIdentifier<M>) -> bool {
119        other.map_ref_or_else(
120            (),
121            |()| false,
122            |(), dcdt_token_identifier| dcdt_token_identifier == self,
123        )
124    }
125}
126
127impl<M: ManagedTypeApi> NestedEncode for TokenIdentifier<M> {
128    #[inline]
129    fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
130    where
131        O: NestedEncodeOutput,
132        H: EncodeErrorHandler,
133    {
134        self.buffer.dep_encode_or_handle_err(dest, h)
135    }
136}
137
138impl<M: ManagedTypeApi> TopEncode for TokenIdentifier<M> {
139    #[inline]
140    fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
141    where
142        O: TopEncodeOutput,
143        H: EncodeErrorHandler,
144    {
145        self.buffer.top_encode_or_handle_err(output, h)
146    }
147}
148
149impl<M: ManagedTypeApi> NestedDecode for TokenIdentifier<M> {
150    fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
151    where
152        I: NestedDecodeInput,
153        H: DecodeErrorHandler,
154    {
155        Ok(TokenIdentifier::from(
156            ManagedBuffer::dep_decode_or_handle_err(input, h)?,
157        ))
158    }
159}
160
161impl<M: ManagedTypeApi> TopDecode for TokenIdentifier<M> {
162    fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
163    where
164        I: TopDecodeInput,
165        H: DecodeErrorHandler,
166    {
167        Ok(TokenIdentifier::from(
168            ManagedBuffer::top_decode_or_handle_err(input, h)?,
169        ))
170    }
171}
172
173impl<M> TypeAbiFrom<&[u8]> for TokenIdentifier<M> where M: ManagedTypeApi {}
174impl<M> TypeAbiFrom<Vec<u8>> for TokenIdentifier<M> where M: ManagedTypeApi {}
175
176impl<M: ManagedTypeApi> TypeAbiFrom<Self> for TokenIdentifier<M> {}
177impl<M: ManagedTypeApi> TypeAbiFrom<&Self> for TokenIdentifier<M> {}
178
179impl<M: ManagedTypeApi> TypeAbi for TokenIdentifier<M> {
180    type Unmanaged = Self;
181
182    fn type_name() -> TypeName {
183        "TokenIdentifier".into()
184    }
185
186    fn type_name_rust() -> TypeName {
187        "TokenIdentifier<$API>".into()
188    }
189}
190
191impl<M: ManagedTypeApi> SCDisplay for TokenIdentifier<M> {
192    fn fmt<F: FormatByteReceiver>(&self, f: &mut F) {
193        f.append_managed_buffer(&ManagedBuffer::from_handle(
194            self.buffer.get_handle().cast_or_signal_error::<M, _>(),
195        ));
196    }
197}
198
199impl<M: ManagedTypeApi> SCLowerHex for TokenIdentifier<M> {
200    fn fmt<F: FormatByteReceiver>(&self, f: &mut F) {
201        f.append_managed_buffer_lower_hex(&ManagedBuffer::from_handle(
202            self.buffer.get_handle().cast_or_signal_error::<M, _>(),
203        ));
204    }
205}
206
207impl<M: ManagedTypeApi> core::fmt::Display for TokenIdentifier<M> {
208    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
209        let bytes = self.buffer.to_boxed_bytes();
210        let s = alloc::string::String::from_utf8_lossy(bytes.as_slice());
211        s.fmt(f)
212    }
213}
214
215impl<M: ManagedTypeApi> core::fmt::Debug for TokenIdentifier<M> {
216    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
217        f.debug_tuple("TokenIdentifier")
218            .field(&self.to_string())
219            .finish()
220    }
221}