1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! # (`0001`) The header of a document.

use std::fmt;

use nom::{
    bytes::streaming::take,
    combinator::{map, rest},
    number::complete::be_u16,
    sequence::tuple,
    IResult,
};

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
/// A GEMDOS date
pub struct Date(pub u16);

impl fmt::Display for Date {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let year = (self.0 >> 9) + 1980;
        let month = (self.0 >> 5) & 0b1111;
        let day = self.0 & 0b11111;
        write!(f, "{:02}.{:02}.{:04}", day, month, year)
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
/// A GEMDOS time
pub struct Time(pub u16);

impl fmt::Display for Time {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let hours = self.0 >> 11;
        let minutes = (self.0 >> 5) & 0b111111;
        let seconds = (self.0 & 0b11111) << 1;
        write!(f, "{:02}:{:02}:{:02}", hours, minutes, seconds)
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
/// A GEMDOS date and time
pub struct DateTime {
    /// The date part
    pub date: Date,
    /// The time part
    pub time: Time,
}

impl fmt::Display for DateTime {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} {}", self.date, self.time)
    }
}

#[derive(Debug)]
/// The header of a signum file
pub struct Header<'a> {
    /// Leading bytes, usually all zero
    pub lead: &'a [u8],
    /// The created time
    pub ctime: DateTime,
    /// The last modified time
    pub mtime: DateTime,
    /// Trailing bytes, usually all zero
    pub trail: &'a [u8],
}

/// Parse the time as a 16 bit integer
pub fn p_time(input: &[u8]) -> IResult<&[u8], Time> {
    map(be_u16, Time)(input)
}

/// Parse the time as a 16 bit integer
pub fn p_date(input: &[u8]) -> IResult<&[u8], Date> {
    map(be_u16, Date)(input)
}

/// Parse the time as a 16 bit integer
pub fn p_datetime(input: &[u8]) -> IResult<&[u8], DateTime> {
    //map(be_u32, DateTime)(input)
    map(tuple((p_date, p_time)), |(date, time)| DateTime {
        date,
        time,
    })(input)
}

/// Parse the header (`0001`) chunk
pub fn parse_header(input: &[u8]) -> IResult<&[u8], Header> {
    let (rest, (lead, ctime, mtime, trail)) =
        tuple((take(0x48usize), p_datetime, p_datetime, rest))(input)?;
    Ok((
        rest,
        Header {
            lead,
            ctime,
            mtime,
            trail,
        },
    ))
}