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
//! The implementation for Version 2 UUIDs which is based on Version 1 UUID.

use super::*;
use libc;

pub enum Domain {
    Person = 0,
    Group = 1,
    Org = 2,
}

impl Uuid {
    /// Creates a new Version 2 UUID based on a Version 1 UUID + domain name + id
    ///
    /// The domain may be either of Person, Group and Organization.
    ///
    /// The id may be PID, UID or GID.
    ///
    /// # Examples
    ///
    /// ```
    /// use yauuid::{Uuid, Node, Context};
    /// use yauuid::Domain;
    ///
    /// let mut ctx = Context::new();
    /// let node = Node::new("lo");
    ///
    /// let u1 = Uuid::new_v1(&mut ctx, node);
    ///
    /// let u = Uuid::new_v2(&u1, Domain::Person, 42);
    /// ```
    pub fn new_v2(uuid: &Uuid, domain: Domain, id: u32) -> Self {
        assert_eq!(uuid.version(), Version(1));

        let mut bs = uuid.as_bytes();
        bs[6] = (bs[6] & 0x0f) | (0x2 << 4); // version 2
        bs[9] = domain as u8;
        bs[0..4].copy_from_slice(&id.to_be_bytes());

        Uuid::from_bytes(bs)
    }

    /// Creates a Version 2 Person category UUID
    pub fn new_v2_person(uuid: &Uuid) -> Self {
        let uid = unsafe { libc::getuid() };
        Self::new_v2(uuid, Domain::Person, uid)
    }

    /// Creates a Version 2 Group category UUID
    pub fn new_v2_group(uuid: &Uuid) -> Self {
        let gid = unsafe { libc::getgid() };
        Self::new_v2(uuid, Domain::Group, gid)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_new() {
        let mut cntx = Context::new();
        let node = Node::new("lo");

        let u_v1 = Uuid::new_v1(&mut cntx, node);

        let u = Uuid::new_v2(&u_v1, Domain::Person, 12345678);
        assert_eq!(u.version(), Version(2));
        assert_eq!(u.as_bytes()[0..4], 12345678u32.to_be_bytes());
    }
}