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 ptr = dat.as_ptr() as usize;
let mut parts = dat.split('.');
let expire = parts.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 = parts.next().ok_or_else(|| DatError::InvalidDatFormat)?;
let kid = T::from_str(kid).map_err(|_| DatError::InvalidDatKidFormat)?;
let plain = parts.next().ok_or_else(|| DatError::InvalidDatFormat)?;
let plain_ptr = plain.as_ptr() as usize - ptr;
let secure = parts.next().ok_or_else(|| DatError::InvalidDatFormat)?;
let secure_ptr = secure.as_ptr() as usize - ptr;
let sign = parts.next().filter(|e| !e.is_empty()).ok_or_else(|| DatError::InvalidDatFormat)?;
let sign_ptr = sign.as_ptr() as usize - ptr;
if parts.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]
}
}