1use 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}