ddcore_rs/
utils.rs

1//
2// utils
3//
4
5use 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
41/// # Safety
42/// Utility function, shouldn't be considered always safe
43pub 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
50/// # Safety
51/// Utility function, shouldn't be considered always safe
52pub unsafe fn align_bytes<T>(slice: &[u8]) -> &[T] {
53    let (_head, body, _tail) = slice.align_to::<T>();
54    body
55}
56
57/// # Safety
58/// Utility function, shouldn't be considered always safe
59pub 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
83////////////////////////////////// C# Version String
84//////////////////////////////////
85
86pub 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