22//!
33//! Signum! 3/4 uses a completely different format from 1/2.
44
5+ use core:: fmt;
56use std:: { borrow:: Cow , num:: NonZeroU32 } ;
67
78use nom:: {
@@ -10,7 +11,7 @@ use nom::{
1011 error:: { context, ContextError , ParseError } ,
1112 multi:: { length_value, many0, many1} ,
1213 number:: complete:: { be_u16, be_u32} ,
13- sequence:: { preceded, terminated} ,
14+ sequence:: { pair , preceded, terminated, tuple } ,
1415 IResult , Parser ,
1516} ;
1617
@@ -28,7 +29,12 @@ pub const CHUNK_FOUSED01: &[u8; 12] = b"\0\0foused01\0\0";
2829#[ derive( Debug ) ]
2930#[ allow( dead_code) ]
3031pub struct Header < ' a > {
31- buf : Buf < ' a > ,
32+ lead : Buf < ' a > ,
33+ /// Create time
34+ pub ctime : DateTime ,
35+ /// Modified time
36+ pub mtime : DateTime ,
37+ tail : Buf < ' a > ,
3238}
3339
3440/// Document root
@@ -44,6 +50,11 @@ pub struct SDocV3<'a> {
4450}
4551
4652impl < ' a > SDocV3 < ' a > {
53+ /// Get the *file pointers* `flptrs01` chunk
54+ pub fn sdoc03 ( & self ) -> & Header {
55+ & self . header
56+ }
57+
4758 /// Get the *file pointers* `flptrs01` chunk
4859 pub fn flptrs01 ( & self ) -> & FilePointers {
4960 & self . file_pointers
@@ -75,9 +86,86 @@ pub struct FilePointers {
7586 pub ofs_chapters : Vec < u32 > ,
7687}
7788
89+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
90+ /// Full date
91+ pub struct Date {
92+ year : u16 ,
93+ month : u16 ,
94+ day : u16 ,
95+ }
96+
97+ impl fmt:: Display for Date {
98+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
99+ write ! ( f, "{:04}-{:02}-{:02}" , self . year, self . month, self . day)
100+ }
101+ }
102+
103+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
104+ /// Time of day
105+ pub struct Time {
106+ hour : u16 ,
107+ minute : u16 ,
108+ second : u16 ,
109+ }
110+
111+ impl fmt:: Display for Time {
112+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
113+ write ! ( f, "{:02}:{:02}:{:02}" , self . hour, self . minute, self . second)
114+ }
115+ }
116+
117+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
118+ /// [Date] and [Time]
119+ pub struct DateTime {
120+ date : Date ,
121+ time : Time ,
122+ }
123+
124+ impl fmt:: Display for DateTime {
125+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
126+ self . date . fmt ( f) ?;
127+ f. write_str ( "T" ) ?;
128+ self . time . fmt ( f) ?;
129+ Ok ( ( ) )
130+ }
131+ }
132+
133+ fn parse_date < ' a , E : ParseError < & ' a [ u8 ] > > ( input : & ' a [ u8 ] ) -> IResult < & ' a [ u8 ] , Date , E > {
134+ let ( input, ( year, month, day) ) = tuple ( ( be_u16, be_u16, be_u16) ) ( input) ?;
135+ Ok ( ( input, Date { year, month, day } ) )
136+ }
137+
138+ fn parse_time < ' a , E : ParseError < & ' a [ u8 ] > > ( input : & ' a [ u8 ] ) -> IResult < & ' a [ u8 ] , Time , E > {
139+ let ( input, ( hour, minute, second) ) = tuple ( ( be_u16, be_u16, be_u16) ) ( input) ?;
140+ Ok ( (
141+ input,
142+ Time {
143+ hour,
144+ minute,
145+ second,
146+ } ,
147+ ) )
148+ }
149+
150+ fn parse_datetime < ' a , E : ParseError < & ' a [ u8 ] > > ( input : & ' a [ u8 ] ) -> IResult < & ' a [ u8 ] , DateTime , E > {
151+ let ( input, ( date, time) ) = pair ( parse_date, parse_time) ( input) ?;
152+ Ok ( ( input, DateTime { date, time } ) )
153+ }
154+
78155fn parse_header < ' a , E : ParseError < & ' a [ u8 ] > > ( input : & ' a [ u8 ] ) -> IResult < & ' a [ u8 ] , Header < ' a > , E > {
79- let ( input, buf) = map ( rest, Buf ) ( input) ?;
80- Ok ( ( input, Header { buf } ) )
156+ let ( input, lead) = map ( take ( 40usize ) , Buf ) ( input) ?;
157+ let ( input, ctime) = parse_datetime ( input) ?;
158+ let ( input, mtime) = parse_datetime ( input) ?;
159+ let ( input, tail) = map ( rest, Buf ) ( input) ?;
160+ Ok ( (
161+ input,
162+ Header {
163+ lead,
164+ ctime,
165+ mtime,
166+ tail,
167+ } ,
168+ ) )
81169}
82170
83171fn opt_be_nonzero_u32 < ' a , E : ParseError < & ' a [ u8 ] > > (
0 commit comments