1use std::mem::size_of;
6use std::{num::ParseIntError, string::FromUtf8Error};
7use std::fmt::Write;
8
9pub fn byte_array_to_string(bytes: &[u8]) -> Result<String, FromUtf8Error> {
10 for (i, b) in bytes.iter().enumerate() {
11 if *b == 0u8 {
12 return String::from_utf8(bytes[..i].to_vec());
13 }
14 }
15 String::from_utf8(bytes[..].to_vec())
16}
17
18pub fn decode_hex(s: &str) -> Result<Vec<u8>, ParseIntError> {
19 (0..s.len())
20 .step_by(2)
21 .map(|i| u8::from_str_radix(&s[i..i + 2], 16))
22 .collect()
23}
24
25pub fn md5_to_string(digest: &[u8]) -> String {
26 let mut s = String::with_capacity(2* digest.len());
27 for byte in digest {
28 write!(s, "{:02X}", byte).expect("Couldn't decode hash byte");
29 }
30 s
31}
32
33pub fn md5_to_string_lower(digest: &[u8]) -> String {
34 let mut s = String::with_capacity(2* digest.len());
35 for byte in digest {
36 write!(s, "{:02x}", byte).expect("Couldn't decode hash byte");
37 }
38 s
39}
40
41pub unsafe fn as_bytes<T: Sized>(p: &T) -> &[u8] {
44 ::std::slice::from_raw_parts(
45 (p as *const T) as *const u8,
46 ::std::mem::size_of::<T>(),
47 )
48}
49
50pub unsafe fn align_bytes<T>(slice: &[u8]) -> &[T] {
53 let (_head, body, _tail) = slice.align_to::<T>();
54 body
55}
56
57pub unsafe fn writer_buf<'a, T: Sized>(source: &mut T) -> &'a mut [u8] {
60 std::slice::from_raw_parts_mut(source as *mut _ as *mut u8, size_of::<T>())
61}
62
63#[macro_export]
64macro_rules! client_https {
65 () => {
66 {
67 use hyper_rustls::ConfigBuilderExt;
68 let tls = rustls::ClientConfig::builder()
69 .with_safe_defaults()
70 .with_native_roots()
71 .with_no_client_auth();
72 let https = hyper_rustls::HttpsConnectorBuilder::new()
73 .with_tls_config(tls)
74 .https_or_http()
75 .enable_http1()
76 .build();
77 let client: Client<_, hyper::Body> = Client::builder().build(https);
78 client
79 }
80 };
81}
82
83pub struct Version {
87 pub s: String,
88}
89
90impl Version {
91 pub fn new<T: ToString>(s: T) -> Self {
92 Self {
93 s: s.to_string()
94 }
95 }
96}
97
98impl PartialEq for Version {
99 fn eq(&self, other: &Self) -> bool {
100 self.s.eq(&other.s)
101 }
102}
103
104impl PartialOrd for Version {
105 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
106 let mut self_split = self.s.split('.').map(|x| x.parse::<i32>().unwrap());
107 let mut other_split = other.s.split('.').map(|x| x.parse::<i32>().unwrap());
108 let (major,minor,build,rev) = (self_split.next()?, self_split.next()?, self_split.next()?, self_split.next()?);
109 let (omajor,ominor,obuild,orev) = (other_split.next()?, other_split.next()?, other_split.next()?, other_split.next()?);
110
111 let mut is_greater = rev > orev;
112
113 if build > obuild {
114 is_greater = true;
115 }
116
117 if build < obuild {
118 is_greater = false;
119 }
120
121 if minor > ominor {
122 is_greater = true;
123 }
124
125 if minor < ominor {
126 is_greater = false;
127 }
128
129 if major > omajor {
130 is_greater = true;
131 }
132
133 if major < omajor {
134 is_greater = false;
135 }
136
137 if self == other {
138 return Some(std::cmp::Ordering::Equal);
139 }
140
141 if is_greater {
142 return Some(std::cmp::Ordering::Greater);
143 }
144
145 Some(std::cmp::Ordering::Less)
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 #[test]
152 fn version() {
153 use crate::utils::Version;
154
155 let a = Version::new("0.6.9.1");
156 let b = Version::new("0.6.8.1");
157 let c = Version::new("0.6.9.1");
158 let d = Version::new("0.7.1.1");
159
160 assert!(a > b);
161 assert!(a != b);
162 assert!(b < a);
163 assert!(a == c);
164 assert!(a < d);
165 assert!(d >= a);
166 }
167}
168