use crate::protocol::{u16_le, u32_le, wr};
use std::fmt;
pub const USER_DEFAULT: u8 = 0;
pub const USER_ADMIN: u8 = 14;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct User {
pub uid: u16,
pub name: String,
pub privilege: u8,
pub password: String,
pub group_id: String,
pub user_id: String,
pub card: u32,
}
impl User {
pub fn new(
uid: u16,
name: impl Into<String>,
privilege: u8,
password: impl Into<String>,
group_id: impl Into<String>,
user_id: impl Into<String>,
card: u32,
) -> Self {
User {
uid,
name: name.into(),
privilege,
password: password.into(),
group_id: group_id.into(),
user_id: user_id.into(),
card,
}
}
pub fn is_disabled(&self) -> bool {
self.privilege & 1 != 0
}
pub fn is_enabled(&self) -> bool {
!self.is_disabled()
}
pub fn usertype(&self) -> u8 {
self.privilege & 0xE
}
pub(crate) fn repack29(&self) -> Vec<u8> {
let group = self.group_id.parse::<u8>().unwrap_or(0);
let user_id = self.user_id.parse::<u32>().unwrap_or(0);
wr(|w| {
w.u8(2) .u16(self.uid)
.u8(self.privilege)
.fixed(self.password.as_bytes(), 5)
.fixed(self.name.as_bytes(), 8)
.u32(self.card)
.pad(1) .u8(group)
.u16(0) .u32(user_id);
})
}
pub(crate) fn repack73(&self) -> Vec<u8> {
wr(|w| {
w.u8(2) .u16(self.uid)
.u8(self.privilege)
.fixed(self.password.as_bytes(), 8)
.fixed(self.name.as_bytes(), 24)
.u32(self.card)
.u8(1)
.fixed(self.group_id.as_bytes(), 7)
.pad(1) .fixed(self.user_id.as_bytes(), 24);
})
}
pub(crate) fn parse_zk6(rec: &[u8; 28]) -> User {
let uid = u16_le(&rec[0..2]);
let privilege = rec[2];
let password = decode_cstr(&rec[3..8]);
let name = decode_cstr(&rec[8..16]).trim().to_string();
let card = u32_le(&rec[16..20]);
let group_id = rec[21].to_string();
let user_id_num = u32_le(&rec[24..28]);
let user_id = user_id_num.to_string();
let name = if name.is_empty() {
format!("NN-{user_id}")
} else {
name
};
User::new(uid, name, privilege, password, group_id, user_id, card)
}
pub(crate) fn parse_zk8(rec: &[u8; 72]) -> User {
let uid = u16_le(&rec[0..2]);
let privilege = rec[2];
let password = decode_cstr(&rec[3..11]);
let name = decode_cstr(&rec[11..35]).trim().to_string();
let card = u32_le(&rec[35..39]);
let group_id = decode_cstr(&rec[40..47]).trim().to_string();
let user_id = decode_cstr(&rec[48..72]);
let name = if name.is_empty() {
format!("NN-{user_id}")
} else {
name
};
User::new(uid, name, privilege, password, group_id, user_id, card)
}
}
impl fmt::Display for User {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"<User>: [uid:{}, name:{} user_id:{}]",
self.uid, self.name, self.user_id
)
}
}
fn decode_cstr(field: &[u8]) -> String {
let end = field.iter().position(|&b| b == 0).unwrap_or(field.len());
String::from_utf8_lossy(&field[..end]).into_owned()
}