sylvia_iot_corelib/
strings.rs1use chrono::{DateTime, SecondsFormat, Utc};
4use hex;
5use hmac::Hmac;
6use pbkdf2;
7use rand::{distributions::Alphanumeric, thread_rng, Rng};
8use regex::Regex;
9use sha2::{Digest, Sha256};
10use url::Url;
11
12const PASSWORD_ROUNDS: u32 = 10000;
13
14pub fn hex_addr_to_u128(addr: &str) -> Result<u128, &'static str> {
16 if addr.len() == 0 || addr.len() > 32 || addr.len() % 2 != 0 {
17 return Err("invalid address format");
18 }
19
20 match u128::from_str_radix(addr, 16) {
21 Err(_) => Err("invalid address format"),
22 Ok(value) => Ok(value),
23 }
24}
25
26pub fn is_account(account: &str) -> bool {
28 let name_regex = Regex::new(r"^[a-z0-9]{1}[a-z0-9_-]*$").unwrap();
29 let email_regex = Regex::new(
30 r"^([a-z0-9_+]([a-z0-9_+.]*[a-z0-9_+])?)@([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})$",
31 )
32 .unwrap();
33
34 name_regex.is_match(account) || email_regex.is_match(account)
35}
36
37pub fn is_code(code: &str) -> bool {
39 let regex = Regex::new(r"^[a-z0-9]{1}[a-z0-9_-]*$").unwrap();
40 regex.is_match(code)
41}
42
43pub fn is_scope(scope: &str) -> bool {
45 let regex = Regex::new(r"^[a-z0-9]+([\.]{1}[a-z0-9]+)*$").unwrap();
46 regex.is_match(scope)
47}
48
49pub fn is_uri(uri: &str) -> bool {
51 Url::parse(uri).is_ok()
52}
53
54pub fn password_hash(password: &str, salt: &str) -> String {
56 let mut res: [u8; 32] = [0; 32];
57 let _ = pbkdf2::pbkdf2::<Hmac<Sha256>>(
58 password.as_bytes(),
59 salt.as_bytes(),
60 PASSWORD_ROUNDS,
61 &mut res,
62 );
63 hex::encode(res)
64}
65
66pub fn random_id(time: &DateTime<Utc>, len: usize) -> String {
68 format!("{}-{}", time.timestamp_millis(), randomstring(len))
69}
70
71pub fn random_id_sha(time: &DateTime<Utc>, len: usize) -> String {
73 let str = random_id(time, len);
74 let mut hasher = Sha256::new();
75 hasher.update(str.as_bytes());
76 hex::encode(hasher.finalize())
77}
78
79pub fn randomstring(len: usize) -> String {
81 let mut rng = thread_rng();
82 std::iter::repeat(())
83 .map(|()| rng.sample(Alphanumeric))
84 .map(char::from)
85 .take(len)
86 .collect()
87}
88
89pub fn time_str(time: &DateTime<Utc>) -> String {
91 time.to_rfc3339_opts(SecondsFormat::Millis, true)
92}
93
94pub fn u128_to_addr(value: u128, len: usize) -> String {
96 match len {
97 0 | 1 | 2 => format!("{:02x}", value & 0xff),
98 3 | 4 => format!("{:04x}", value & 0xffff),
99 5 | 6 => format!("{:06x}", value & 0xff_ffff),
100 7 | 8 => format!("{:08x}", value & 0xffff_ffff),
101 9 | 10 => format!("{:010x}", value & 0xff_ffff_ffff),
102 11 | 12 => format!("{:012x}", value & 0xffff_ffff_ffff),
103 13 | 14 => format!("{:014x}", value & 0xff_ffff_ffff_ffff),
104 15 | 16 => format!("{:016x}", value & 0xffff_ffff_ffff_ffff),
105 17 | 18 => format!("{:018x}", value & 0xff_ffff_ffff_ffff_ffff),
106 19 | 20 => format!("{:020x}", value & 0xffff_ffff_ffff_ffff_ffff),
107 21 | 22 => format!("{:022x}", value & 0xff_ffff_ffff_ffff_ffff_ffff),
108 23 | 24 => format!("{:024x}", value & 0xffff_ffff_ffff_ffff_ffff_ffff),
109 25 | 26 => format!("{:026x}", value & 0xff_ffff_ffff_ffff_ffff_ffff_ffff),
110 27 | 28 => format!("{:028x}", value & 0xffff_ffff_ffff_ffff_ffff_ffff_ffff),
111 29 | 30 => format!("{:030x}", value & 0xff_ffff_ffff_ffff_ffff_ffff_ffff_ffff),
112 _ => format!("{:032x}", value),
113 }
114}