unmp_id/
unique.rs

1//! 全球唯一ID
2
3use crate::{Id, IdKind, ID_LEN};
4#[cfg(feature = "wasm")]
5use wasm_bindgen::prelude::*;
6
7#[cfg_attr(feature = "wasm", wasm_bindgen)]
8#[derive(Debug, PartialEq)]
9pub struct UniqueId {
10    product: u64,
11    sn: u64,
12}
13#[cfg_attr(feature = "wasm", wasm_bindgen)]
14impl UniqueId {
15    pub const fn new(product: u64, sn: u64) -> Self {
16        return UniqueId { product, sn };
17    }
18    pub const fn product(&self) -> u64 {
19        self.product
20    }
21    pub const fn sn(&self) -> u64 {
22        self.sn
23    }
24    pub const fn id(&self) -> Id {
25        let product = self.product.to_be_bytes();
26        let sn = self.sn.to_be_bytes();
27        let mut i_p = 0;
28        while i_p < product.len() && product[i_p] == 0 {
29            i_p += 1;
30        }
31        let product_len = product.len() - i_p;
32        let mut i_s = 0;
33        while i_s < sn.len() && sn[i_s] == 0 {
34            i_s += 1;
35        }
36        let sn_len = sn.len() - i_s;
37
38        let mut buf: [u8; ID_LEN] = [0; ID_LEN];
39        buf[0] = 0x80 | (product_len + sn_len) as u8;
40        buf[1] = ((sn_len << 4) | product_len) as u8;
41        let mut i = 0;
42        while i < product_len {
43            buf[i + 2] = product[i_p + i];
44            i += 1;
45        }
46        let mut i = 0;
47        while i < sn_len {
48            buf[i + 2 + product_len] = sn[i_s + i];
49            i += 1;
50        }
51        Id {
52            len: 2 + product_len + sn_len,
53            buf: buf,
54        }
55    }
56    pub fn try_from(id: &Id) -> Option<UniqueId> {
57        if id.kind() != IdKind::Unique {
58            return None;
59        }
60        let product_len = id.buf[1] & 0x0F;
61        let sn_len = (id.buf[1] & 0xF0) >> 4;
62        if id.len() as u8 != 2 + product_len + sn_len || sn_len > 7 {
63            return None;
64        }
65        let mut product: [u8; 8] = [0; 8];
66        let mut sn: [u8; 8] = [0; 8];
67        product[8 - product_len as usize..].copy_from_slice(&id.buf[2..2 + product_len as usize]);
68        sn[8 - sn_len as usize..].copy_from_slice(&id.buf[2 + product_len as usize..id.len()]);
69        return Some(UniqueId::new(
70            u64::from_be_bytes(product),
71            u64::from_be_bytes(sn),
72        ));
73    }
74}