use std::{
ops::BitXor,
time::SystemTime,
};
use base64::{engine::general_purpose, Engine};
pub struct UUID {}
impl UUID {
pub fn new() -> Self {
Self {}
}
fn time_calculation() -> (u32, u16) {
match SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
Ok(d) => (
(d.as_secs() & 0xffff_ffff) as u32,
(d.subsec_millis() & 0x3ff) as u16,
),
Err(_) => (0, 0),
}
}
pub fn uuid(custom: u32) -> (u64, u32) {
let rand = rand::random::<u16>();
let (secs, mils) = UUID::time_calculation();
let p1 = (secs as u64) << 32 | (rand as u64) << 16 | (mils as u64);
let custom_xor = custom.bitxor(((mils as u32) << 16 | rand as u32) as u32);
(p1, custom_xor)
}
pub fn uuid_u128(custom: u32) -> u128 {
let (p1, custom_xor) = UUID::uuid(custom);
((p1 as u128) << 32) | (custom_xor as u128)
}
pub fn uuid_string(custom: u32) -> String {
let (p1, custom_xor) = UUID::uuid(custom);
let mut byts = p1.to_be_bytes().to_vec();
byts.append(&mut custom_xor.to_be_bytes().to_vec());
general_purpose::URL_SAFE_NO_PAD.encode(byts)
}
pub fn decode(encode: String) -> u32 {
let b = general_purpose::URL_SAFE_NO_PAD.decode(encode).unwrap();
let mils = ((b[6] as u16) << 8) | b[7] as u16;
let rand = ((b[4] as u16) << 8) | b[5] as u16;
let custom_xor =
((b[8] as u32) << 24) | ((b[9] as u32) << 16) | ((b[10] as u32) << 8) | b[11] as u32;
custom_xor.bitxor(((mils as u32) << 16 | rand as u32) as u32)
}
pub fn decode_full(encode: String) -> (u32, u32, u16, u16) {
let b = general_purpose::URL_SAFE_NO_PAD.decode(encode).unwrap();
let mils = ((b[6] as u16) << 8) | b[7] as u16;
let rand = ((b[4] as u16) << 8) | b[5] as u16;
let secs =
((b[0] as u32) << 24) | ((b[1] as u32) << 16) | ((b[2] as u32) << 8) | b[3] as u32;
let custom_xor =
((b[8] as u32) << 24) | ((b[9] as u32) << 16) | ((b[10] as u32) << 8) | b[11] as u32;
let cus = custom_xor.bitxor(((mils as u32) << 16 | rand as u32) as u32);
(cus, secs, mils, rand)
}
pub fn decode_int(encode: (u64, u32)) -> u32 {
let rand = ((encode.0 & 0x00000000ffff0000) >> 16) as u16;
let mils = (encode.0 & 0x000000000000ffff) as u16;
encode.1.bitxor(((mils as u32) << 16 | rand as u32) as u32)
}
}
#[test]
fn test() {
for i in 23424..23524 {
let encode = UUID::uuid_string(i);
let cus = UUID::decode(encode.clone());
println!("自定义数字:{} - uuid:{} - 解码:{}", i, encode, cus);
}
}