1use chrono::{NaiveDate, NaiveDateTime};
2
3use error::*;
4
5pub(crate) fn read_stringz(data: &[u8]) -> String {
6 let zestr: Vec<u8> = data.into_iter().cloned().take_while(|&b| b != 0).collect();
7 String::from_utf8_lossy(&zestr).into_owned()
8}
9
10pub(crate) fn read_datetime(data: &[u8]) -> Result<NaiveDateTime> {
12 let year = 2000 + (i32::from(data[0]) & 0x3F);
13 let month = (u32::from(data[0]) >> 6) | ((u32::from(data[1]) & 0x03) << 2);
14 let day = u32::from(data[1] >> 2) & 0x1F;
15
16 let hour = (u32::from(data[1]) >> 7) | ((u32::from(data[2]) & 0x0F) << 1);
17 let minute = (u32::from(data[2]) >> 4) | ((u32::from(data[3]) & 0x03) << 4);
18 let second = u32::from(data[3]) >> 2;
19
20 match NaiveDate::from_ymd_opt(year, month, day) {
21 None => Err(ErrorKind::InvalidDateTime(year, month, day, hour, minute, second).into()),
22 Some(date) => match date.and_hms_opt(hour, minute, second) {
23 None => Err(ErrorKind::InvalidDateTime(year, month, day, hour, minute, second).into()),
24 Some(datetime) => Ok(datetime),
25 },
26 }
27}
28
29pub(crate) fn allowed_char(c: char) -> bool {
30 (c as u32) >= 0x20 && (c as u32) <= 0x7E
31}