aboutsummaryrefslogtreecommitdiff
path: root/src/uid.rs
blob: b15f65b898b72a630f6b8bba1e88cb9b35de2fbe (plain)
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
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
pub struct UID(u8, u8);
impl UID {
    fn to_hex(&self) -> String {
        hex::encode_upper(vec![self.0, self.1])
    }
    pub fn from(s: String) -> Result<Self, String> {
        if s.is_ascii() {
            if s.len() == 4 {
                match hex::decode(s) {
                    Ok(n) => Ok(UID(n[0], n[1])),
                    Err(_) => Err("Could not decode hex".into())
                }

            } else {
                Err("UID length is incorrect".into())
            }
        } else {
            Err("UID String is not valid".into())
        }
    }
}

#[derive(Serialize, Deserialize)]
pub struct Generator {
    used_uids: Vec<UID>
}
impl Generator {
    pub fn new() -> Generator {
        Generator { used_uids: vec![] }
    }

    pub fn is_taken(&self, uid: UID) -> bool {
        for u in self.used_uids.clone() {
            if u == uid {
                return true;
            }
        }

        false
    }

    pub fn add_uid(&mut self, u: UID) -> Result<UID, String> {
        if self.used_uids.contains(&u) {
            Err("UID Taken".into())
        } else {
            self.used_uids.push(u);
            Ok(u)
        }
    }

    pub fn new_uid(&mut self) -> Result<UID, String> {
        let mut count = 0;
        loop {
            let first = rand::random::<u8>();
            let second = rand::random::<u8>();
            let new = UID(first, second);

            if self.used_uids.contains(&new) {
                count += 1
            } else {
                self.used_uids.push(new);
                return Ok(new);
            }

            if count > 1000 {
                break
            }
        }

        // Random generation didn't work.  Try counting up throught all UID possibilities
        loop {
            for x in 0..=u8::MAX {
                for y in 0..=u8::MAX {
                    let new = UID(x, y);
                    if !(self.used_uids.contains(&new)) {
                        self.used_uids.push(new);
                        return Ok(new);
                    }
                }
            }

            break
        }

        Err("No available UID left".into())
    }
}