1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use elrond_codec::TryStaticCast;
use crate::api::ErrorApi;
use super::{BigIntApi, EllipticCurveApi, ManagedBufferApi, StaticBufferApi};
pub type Handle = i32;
pub trait ManagedTypeApi:
TryStaticCast
+ BigIntApi
+ EllipticCurveApi
+ ManagedBufferApi
+ StaticBufferApi
+ ErrorApi
+ Clone
+ 'static
{
const TICKER_MIN_LENGTH: usize = 3;
const TICKER_MAX_LENGTH: usize = 10;
const ADDITIONAL_RANDOM_CHARS_LENGTH: usize = 6;
const IDENTIFIER_MIN_LENGTH: usize =
Self::TICKER_MIN_LENGTH + Self::ADDITIONAL_RANDOM_CHARS_LENGTH + 1;
const IDENTIFIER_MAX_LENGTH: usize =
Self::TICKER_MAX_LENGTH + Self::ADDITIONAL_RANDOM_CHARS_LENGTH + 1;
const DASH_CHARACTER: u8 = b'-';
fn instance() -> Self;
fn mb_to_big_int_unsigned(&self, buffer_handle: Handle) -> Handle;
fn mb_to_big_int_signed(&self, buffer_handle: Handle) -> Handle;
fn mb_from_big_int_unsigned(&self, big_int_handle: Handle) -> Handle;
fn mb_from_big_int_signed(&self, big_int_handle: Handle) -> Handle;
fn mb_overwrite_static_buffer(&self, buffer_handle: Handle) -> bool {
self.with_lockable_static_buffer(|lsb| {
let len = self.mb_len(buffer_handle);
lsb.try_lock_with_copy_bytes(len, |dest| {
let _ = self.mb_load_slice(buffer_handle, 0, dest);
})
})
}
fn append_mb_to_static_buffer(&self, buffer_handle: Handle) -> bool {
self.with_lockable_static_buffer(|lsb| {
let len = self.mb_len(buffer_handle);
lsb.try_extend_from_copy_bytes(len, |dest| {
let _ = self.mb_load_slice(buffer_handle, 0, dest);
})
})
}
fn append_static_buffer_to_mb(&self, buffer_handle: Handle) {
self.with_lockable_static_buffer(|lsb| {
self.mb_append_bytes(buffer_handle, lsb.as_slice());
});
}
fn validate_token_identifier(&self, token_id_handle: Handle) -> bool {
let token_id_bytes = self.mb_to_boxed_bytes(token_id_handle);
let id_len = token_id_bytes.len();
#[allow(clippy::manual_range_contains)]
if id_len < Self::IDENTIFIER_MIN_LENGTH || id_len > Self::IDENTIFIER_MAX_LENGTH {
return false;
}
let token_id_slice = token_id_bytes.as_slice();
let lowercase_letter_range = &b'a'..=&b'z';
let uppercase_letter_range = &b'A'..=&b'Z';
let number_range = &b'0'..=&b'9';
let ticker_len = id_len - Self::ADDITIONAL_RANDOM_CHARS_LENGTH - 1;
let ticker = &token_id_slice[..ticker_len];
for ticker_char in ticker {
let is_uppercase_letter = uppercase_letter_range.contains(&ticker_char);
let is_number = number_range.contains(&ticker_char);
if !is_uppercase_letter && !is_number {
return false;
}
}
let dash_position = ticker_len;
if token_id_slice[dash_position] != Self::DASH_CHARACTER {
return false;
}
let random_chars = &token_id_slice[(id_len - Self::ADDITIONAL_RANDOM_CHARS_LENGTH)..];
for rand_char in random_chars {
let is_lowercase_letter = lowercase_letter_range.contains(&rand_char);
let is_number = number_range.contains(&rand_char);
if !is_lowercase_letter && !is_number {
return false;
}
}
true
}
}