neo3/neo_types/
numeric.rs

1use num_bigint::BigInt;
2
3/// Trait to convert types to padded byte vectors.
4pub trait ToBytesPadded {
5	/// Converts the type to a byte vector padded to the given length.
6	///
7	/// # Arguments
8	///
9	/// * `length` - The desired length of the resulting byte vector.
10	fn to_bytes_padded(&self, length: usize) -> Vec<u8>;
11}
12
13impl ToBytesPadded for BigInt {
14	fn to_bytes_padded(&self, length: usize) -> Vec<u8> {
15		let bytes = self.to_signed_bytes_be();
16		if bytes.len() < length {
17			let mut padded = vec![0u8; length];
18			padded[length - bytes.len()..].copy_from_slice(&bytes);
19			padded
20		} else {
21			bytes
22		}
23	}
24}
25
26/// Returns the result of raising the base to the power of the exponent.
27///
28/// # Arguments
29///
30/// * `base` - The base number.
31/// * `exp` - The exponent to which the base is raised.
32fn power_of(base: i32, exp: i32) -> i32 {
33	base.pow(exp as u32)
34}
35
36/// Determines the size of a variable based on its value.
37///
38/// # Arguments
39///
40/// * `n` - The value to determine the size for.
41fn var_size(n: i128) -> usize {
42	match n {
43		n if n < 0xfd => 1,
44		n if n <= 0xffff => 3,
45		n if n <= 0xffffffff => 5,
46		_ => 9,
47	}
48}
49
50/// Converts an i32 to its unsigned counterpart.
51///
52/// # Arguments
53///
54/// * `n` - The signed integer to convert.
55fn to_unsigned(n: i32) -> u32 {
56	n as u32
57}
58
59/// Trait to convert types to byte vectors.
60pub trait ToBytes {
61	/// Converts the type to a byte vector.
62	fn to_bytes(&self) -> Vec<u8>;
63}
64
65impl ToBytes for i32 {
66	fn to_bytes(&self) -> Vec<u8> {
67		self.to_be_bytes().to_vec()
68	}
69}
70
71impl ToBytes for i64 {
72	fn to_bytes(&self) -> Vec<u8> {
73		self.to_be_bytes().to_vec()
74	}
75}
76
77impl ToBytes for f32 {
78	fn to_bytes(&self) -> Vec<u8> {
79		self.to_be_bytes().to_vec()
80	}
81}
82
83impl ToBytes for f64 {
84	fn to_bytes(&self) -> Vec<u8> {
85		self.to_be_bytes().to_vec()
86	}
87}
88
89/// Converts a DateTime object to milliseconds since the Unix epoch.
90///
91/// # Arguments
92///
93/// * `datetime` - The DateTime object to convert.
94fn to_milliseconds(datetime: chrono::DateTime<chrono::Utc>) -> i64 {
95	datetime.timestamp_millis()
96}
97
98#[cfg(test)]
99mod tests {
100	use super::*;
101
102	#[test]
103	fn test_to_bytes_padded() {
104		let n = BigInt::from(1234);
105		let bytes = n.to_bytes_padded(8);
106
107		assert_eq!(bytes, vec![0, 0, 0, 0, 0, 0, 4, 210]);
108	}
109
110	#[test]
111	fn test_power() {
112		assert_eq!(power_of(2, 3), 8);
113		assert_eq!(power_of(5, 2), 25);
114	}
115
116	#[test]
117	fn test_var_size() {
118		assert_eq!(var_size(100), 1);
119		assert_eq!(var_size(1000), 3);
120		assert_eq!(var_size(1000000), 5);
121		assert_eq!(var_size(10000000000), 9);
122	}
123
124	#[test]
125	fn test_to_unsigned() {
126		assert_eq!(to_unsigned(-1), 4294967295);
127		assert_eq!(to_unsigned(10), 10);
128	}
129
130	#[test]
131	fn test_i32_to_bytes() {
132		let n = 256;
133		assert_eq!(n.to_bytes(), vec![0, 0, 1, 0]);
134	}
135
136	#[test]
137	fn test_i64_to_bytes() {
138		let n = 123456;
139		assert_eq!(n.to_bytes(), vec![0, 1, 226, 64]);
140	}
141
142	#[test]
143	fn test_f32_to_bytes() {
144		let n = 1.5f32;
145		assert_eq!(n.to_bytes(), vec![63, 192, 0, 0]);
146	}
147
148	#[test]
149	fn test_datetime_to_ms() {
150		let dt = chrono::Utc::now();
151		let ms = to_milliseconds(dt);
152
153		assert!(ms > 0);
154	}
155}