use crate::dat_key::Kid;
use crate::error::DatError;
use crate::util::now_unix_timestamp;
pub struct DatRecords<T: Kid> {
dat: String,
expire: u64,
kid: T,
plain_ptr: usize,
secure_ptr: usize,
sign_ptr: usize,
}
impl <T: Kid> DatRecords<T> {
pub fn from(dat: String) -> Result<Self, DatError> {
let dat_ptr = dat.as_ptr() as usize;
let mut dat_split = dat.split('.');
let expire = dat_split.next().ok_or_else(|| DatError::InvalidDatFormat)?;
let expire = expire.parse::<u64>().map_err(|_| DatError::InvalidDatFormat)?;
if expire < now_unix_timestamp() {
return Err(DatError::InvalidDat);
}
let kid = dat_split.next().ok_or_else(|| DatError::InvalidDatFormat)?;
let kid = T::from_str(kid).map_err(|_| DatError::InvalidDatKidFormat)?;
let plain = dat_split.next().ok_or_else(|| DatError::InvalidDatFormat)?;
let plain_ptr = plain.as_ptr() as usize - dat_ptr;
let secure = dat_split.next().ok_or_else(|| DatError::InvalidDatFormat)?;
let secure_ptr = secure.as_ptr() as usize - dat_ptr;
let sign = dat_split.next().filter(|e| !e.is_empty()).ok_or_else(|| DatError::InvalidDatFormat)?;
let sign_ptr = sign.as_ptr() as usize - dat_ptr;
if dat_split.next().is_some() {
return Err(DatError::InvalidDatFormat);
}
Ok(DatRecords {
dat,
expire,
kid,
plain_ptr,
secure_ptr,
sign_ptr,
})
}
pub fn kid(&self) -> &T {
&self.kid
}
pub fn expire(&self) -> u64 {
self.expire
}
pub fn plain_base64(&self) -> &str {
&self.dat[self.plain_ptr .. self.secure_ptr - 1]
}
pub fn secure_base64(&self) -> &str {
&self.dat[self.secure_ptr .. self.sign_ptr - 1]
}
pub fn sign_base64(&self) -> &str {
&self.dat[self.sign_ptr ..]
}
pub fn body_str(&self) -> &str {
&self.dat[0 .. self.sign_ptr - 1]
}
}