Skip to main content

reda_gds/io/read/
mod.rs

1mod error;
2
3pub use error::*;
4use std::collections::HashMap;
5use std::fs::File;
6use std::io::{BufRead, BufReader, Read, Seek, SeekFrom};
7use std::path::Path;
8use std::sync::{Arc, RwLock};
9
10use crate::{
11    GdsAref, GdsArefBuilder, GdsArefBuilderError, GdsBoundary, GdsBoundaryBuilder, GdsBoundaryBuilderError, GdsBox, GdsBoxBuilder, GdsBoxBuilderError, GdsDateTime, GdsCoord, GdsFormat, GdsLibrary, GdsLibraryBuilder, GdsNode, GdsNodeBuilder, GdsNodeBuilderError, GdsPath, GdsPathBuilder, GdsPathBuilderError, GdsPathType, GdsPresentation, GdsSref, GdsSrefBuilder, GdsSrefBuilderError, GdsStructure, GdsText, GdsTextBuilder, GdsTextBuilderError, GdsTransform
12};
13use super::record::GdsRecordType;
14use super::utils;
15
16pub struct GdsReader<R> {
17    reader: BufReader<R>,
18}
19
20impl GdsReader<File> {
21    pub fn open<P: AsRef<Path>>(path: P) -> GdsReadResult<Self> {
22        let reader = BufReader::new(File::open(path)?);
23        Ok(Self { reader })
24    }
25}
26
27impl<R: Read + Seek> GdsReader<R> {
28    pub fn new(reader: R) -> GdsReadResult<Self> {
29        Ok(Self { reader: BufReader::new(reader) })
30    }
31}
32
33impl<R: Read + Seek> GdsReader<R> {
34    pub fn read(&mut self) -> GdsReadResult<GdsLibrary> {
35        match self.read_impl() {
36            Ok(gds) => Ok(gds),
37            Err(e) => {
38                let context = match self.reader.stream_position() {
39                    Ok(pos) => format!("read until {pos} bytes"),
40                    Err(e) => format!("error to get bytes bias for '{e}'"),
41                };
42                Err(e.wrap(context)) 
43            }
44        }
45    }
46
47    fn read_impl(&mut self) -> GdsReadResult<GdsLibrary> {
48        let mut builder = GdsLibraryBuilder::default();
49        self.read_header(&mut builder).map_err(|e| e.wrap("read header"))?;
50        self.read_library(&mut builder).map_err(|e| e.wrap("read Library"))?;
51        Ok(builder.build().unwrap())
52    }
53}
54
55impl<R: Read + Seek> GdsReader<R> {
56    fn read_header(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
57        self.ensure_record(6, GdsRecordType::Header)?;
58        builder.version(self.take_i16_record()?);
59        Ok(())
60    }
61}
62
63impl<R: Read + Seek> GdsReader<R> {
64    fn read_library(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
65        self.read_library_begin(builder).map_err(|e| e.wrap("read library begin"))?;
66
67        self.read_library_name(builder).map_err(|e| e.wrap("read library name"))?;
68        self.read_library_options(builder).map_err(|e| e.wrap(""))?;
69        self.read_units(builder).map_err(|e| e.wrap("read units"))?;
70
71        let structures = self.read_structures().map_err(|e| e.wrap("read structures"))?;
72        builder.structures(structures);
73        
74        self.read_library_end(builder).map_err(|e| e.wrap("read library end"))?;
75        Ok(())
76    }
77
78    fn read_library_begin(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
79        self.ensure_record(28, GdsRecordType::BgnLib)?;
80        self.jump_bytes(4)?;
81
82        builder.create_date(self.take_datetime()?);
83        builder.modify_date(self.take_datetime()?);
84
85        Ok(())   
86    }
87
88    fn read_library_name(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
89        self.ensure_record_type(GdsRecordType::LibName)?;
90        builder.name(self.take_string_record()?);
91        Ok(())
92    }
93
94    fn read_units(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
95        self.ensure_record(20, GdsRecordType::Uints)?;
96        self.jump_bytes(4)?;
97
98        builder.usrunits_per_dbunit(self.take_f64()?);
99        builder.meters_per_dbunit(self.take_f64()?);
100
101        Ok(())
102    }
103
104    fn read_library_end(&mut self, _builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
105        self.ensure_record(4, GdsRecordType::EndLib)?;
106        self.jump_bytes(4)?;
107        Ok(())
108    }
109}
110
111impl<R: Read + Seek> GdsReader<R> {
112    fn read_library_options(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
113        loop {
114            let tp = self.peek_record_type()?;
115            match tp {
116                GdsRecordType::RefLibs => self.read_reflibs(builder).map_err(|e| e.wrap("read reflibs"))?,
117                GdsRecordType::Fonts => self.read_fonts(builder).map_err(|e| e.wrap("read reflibs"))?,
118                GdsRecordType::AttrTable => self.read_attrtable(builder).map_err(|e| e.wrap("read attrtable"))?,
119                GdsRecordType::Generations => self.read_generations(builder).map_err(|e| e.wrap("read generations"))?,
120                GdsRecordType::Format => self.read_format(builder).map_err(|e| e.wrap("read format"))?,
121                _ => return Ok(())
122            }
123        }
124    }
125
126    pub fn read_reflibs(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
127        self.ensure_record(94, GdsRecordType::RefLibs)?;
128        self.jump_bytes(4)?;
129        builder.reflibs([
130            self.take_string(45)?,
131            self.take_string(45)?,
132        ]);
133        Ok(())
134    }
135
136    pub fn read_fonts(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
137        self.ensure_record_size(4 * 44 + 4)?;
138        self.jump_bytes(4)?;
139        builder.fonts([
140            self.take_string(44)?,
141            self.take_string(44)?,
142            self.take_string(44)?,
143            self.take_string(44)?,
144        ]);
145        Ok(())
146    }
147
148    pub fn read_attrtable(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
149        self.ensure_record_size(48)?;
150        self.jump_bytes(4)?;
151        builder.attrtable(self.take_string(44)?);
152        Ok(())
153    }
154
155    pub fn read_generations(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
156        builder.generations(self.take_i16_record()?);
157        Ok(())
158    }
159
160    pub fn read_format(&mut self, builder: &mut GdsLibraryBuilder) -> GdsReadResult<()> {
161        let value = self.take_u16_record()?;
162        let fmt = GdsFormat::from_u16(value)
163            .ok_or_else(|| GdsReadError::InvalidFormat(value))?;
164        builder.format(fmt);
165        Ok(())
166    }
167}
168
169macro_rules! read_optional_field {
170    ($builder:ident.$field:ident <- $this:ident.$method:ident if $record_type:ident) => {
171        if $this.peek_record_type()? == GdsRecordType::$record_type {
172            $builder.$field($this.$method()?);
173        }
174    };
175}
176
177
178macro_rules! read_required_field {
179    (
180        $builder:ident.$field:ident <- $this:ident.$method:ident if $variant:ident =>
181        $read_error_variant:ident ( $builder_error_ty:ty )
182    ) => {
183        if $this.peek_record_type()? == GdsRecordType::$variant {
184            $builder.$field($this.$method()?);
185        } else {
186            return Err(GdsReadError::$read_error_variant(
187                <$builder_error_ty>::UninitializedField(stringify!($field))
188            ));
189        }
190    };
191}
192
193impl<R: Read + Seek> GdsReader<R> {
194    fn read_structures(&mut self) -> GdsReadResult<HashMap<String, Arc<RwLock<GdsStructure>>>> {
195        let mut structures = HashMap::new();
196        let mut size = 0;
197        while self.check_record_type(GdsRecordType::BgnStr)? {
198            let structure = self.read_structure().map_err(|e| e.wrap(format!("read {size} structure")))?;
199            let name = structure.name.clone();
200            structures.insert(name, Arc::new(RwLock::new(structure)));
201            size += 1;
202        }
203        Ok(structures)
204    }
205
206    fn read_structure(&mut self) -> GdsReadResult<GdsStructure> {
207        let mut s = GdsStructure::default();
208
209        self.read_structure_begin(&mut s).map_err(|e| e.wrap("read structure begin"))?;
210        self.read_structure_name(&mut s).map_err(|e| e.wrap("read structure name"))?;
211
212        self.read_structure_elements(&mut s).map_err(|e| e.wrap("read structure elements"))?;
213        self.read_structure_end().map_err(|e| e.wrap("read structure end"))?;
214
215        Ok(s)
216    }
217
218    fn read_structure_begin(&mut self, structure: &mut GdsStructure) -> GdsReadResult<()> {
219        self.ensure_record(28, GdsRecordType::BgnStr)?;
220        self.jump_bytes(4)?;
221        structure.modify_date = self.take_datetime()?;
222        structure.create_date = self.take_datetime()?;
223        Ok(())
224    }
225
226    fn read_structure_name(&mut self, structure: &mut GdsStructure) -> GdsReadResult<()> {
227        self.ensure_record_type(GdsRecordType::StrName)?;
228        structure.name = self.take_string_record()?;
229        Ok(())
230    }
231
232    fn read_structure_end(&mut self) -> GdsReadResult<()> {
233        self.ensure_record(4, GdsRecordType::EndStr)?;
234        self.jump_bytes(4)?;
235        Ok(())
236    }
237
238    fn read_structure_elements(&mut self, s: &mut GdsStructure) -> GdsReadResult<()> {
239        loop {
240            match self.peek_record_type()? {
241                GdsRecordType::Boundary => 
242                    s.boundarys.push(self.read_element_boundary().map_err(|e| e.wrap("read boundary"))?),
243                GdsRecordType::Path => 
244                    s.paths.push(self.read_element_path().map_err(|e| e.wrap("read path"))?),
245                GdsRecordType::Text => 
246                    s.texts.push(self.read_element_text().map_err(|e| e.wrap("read text"))?),
247                GdsRecordType::ARef => 
248                    s.arefs.push(self.read_element_aref().map_err(|e| e.wrap("read aref"))?),
249                GdsRecordType::SRef => 
250                    s.srefs.push(self.read_element_sref().map_err(|e| e.wrap("read sref"))?),
251                GdsRecordType::Node => 
252                    s.nodes.push(self.read_element_node().map_err(|e| e.wrap("read node"))?),
253                GdsRecordType::Box => 
254                    s.boxes.push(self.read_element_box().map_err(|e| e.wrap("read box"))?),
255                _ => break
256            }
257        }
258        Ok(())
259    }
260
261    fn read_element_boundary(&mut self) -> GdsReadResult<GdsBoundary> {
262        self.read_element_header()?;
263        let mut builder = GdsBoundaryBuilder::default();
264
265        read_optional_field!(builder.elf_flags <- self.take_i16_record if ElFlags);
266        read_optional_field!(builder.plex      <- self.take_i32_record if Plex);
267        read_required_field!(builder.layer     <- self.take_i16_record     if Layer     => BuildBoundary(GdsBoundaryBuilderError));
268        read_required_field!(builder.data_type <- self.take_i16_record if DataType  => BuildBoundary(GdsBoundaryBuilderError));
269        read_required_field!(builder.xy        <- self.read_xy        if Xy        => BuildBoundary(GdsBoundaryBuilderError));
270    
271        self.read_element_end()?;
272        Ok(builder.build()?)
273    }
274
275    pub fn read_element_path(&mut self) -> GdsReadResult<GdsPath> {
276        self.read_element_header()?;
277        let mut builder = GdsPathBuilder::default();
278
279        read_optional_field!(builder.elf_flags      <- self.take_i16_record    if ElFlags);
280        read_optional_field!(builder.plex           <- self.take_i32_record    if Plex);
281        read_required_field!(builder.layer          <- self.take_i16_record    if Layer     => BuildPath(GdsPathBuilderError));
282        read_required_field!(builder.data_type      <- self.take_i16_record    if DataType  => BuildPath(GdsPathBuilderError));
283        read_optional_field!(builder.path_type      <- self.read_path_type     if PathType);
284        read_optional_field!(builder.width          <- self.take_i32_record    if Width);
285        read_required_field!(builder.xy             <- self.read_xy            if Xy        => BuildPath(GdsPathBuilderError));
286        read_optional_field!(builder.purpose_layer  <- self.take_i16_record    if TextType);
287
288        if self.peek_record_type()? == GdsRecordType::BgnExtn {
289            self.take_i32_record()?;
290        }
291        if self.peek_record_type()? == GdsRecordType::EndExtn {
292            self.take_i32_record()?;
293        }
294
295        self.read_element_end()?;
296        Ok(builder.build()?)
297    }
298
299    pub fn read_element_sref(&mut self) -> GdsReadResult<GdsSref> {
300        self.read_element_header()?;
301        let mut builder = GdsSrefBuilder::default();
302
303        read_optional_field!(builder.elf_flags <- self.take_i16_record      if ElFlags);
304        read_optional_field!(builder.plex      <- self.take_i32_record      if Plex);
305        read_required_field!(builder.s_name    <- self.take_string_record   if SName     => BuildSref(GdsSrefBuilderError));
306        read_optional_field!(builder.transform <- self.read_transform       if STrans);
307        read_required_field!(builder.position  <- self.read_position        if Xy        => BuildSref(GdsSrefBuilderError));
308
309        self.read_element_end()?;
310        Ok(builder.build()?)
311    }
312
313    pub fn read_element_aref(&mut self) -> GdsReadResult<GdsAref> {
314        self.read_element_header()?;
315        let mut builder = GdsArefBuilder::default();
316
317        read_optional_field!(builder.elf_flags <- self.take_i16_record      if ElFlags);
318        read_optional_field!(builder.plex      <- self.take_i32_record      if Plex);
319        read_required_field!(builder.s_name    <- self.take_string_record   if SName     => BuildAref(GdsArefBuilderError));
320        read_optional_field!(builder.transform <- self.read_transform       if STrans);
321
322        if self.peek_record_type()? == GdsRecordType::ColRow {
323            let (col, row) = self.read_col_row()?;
324            builder.col(col);
325            builder.row(row);
326        }
327        read_required_field!(builder.position  <- self.read_position        if Xy        => BuildSref(GdsSrefBuilderError));
328
329        self.read_element_end()?;
330        Ok(builder.build()?)
331    }
332
333    pub fn read_element_text(&mut self) -> GdsReadResult<GdsText> {
334        self.read_element_header()?;
335        let mut builder = GdsTextBuilder::default();
336
337        read_optional_field!(builder.plex          <- self.take_i32_record     if Plex);
338        read_optional_field!(builder.elf_flags     <- self.take_i16_record     if ElFlags);
339        read_required_field!(builder.layer         <- self.take_i16_record     if Layer     => BuildText(GdsTextBuilderError));
340        read_required_field!(builder.text_type     <- self.take_i16_record     if TextType  => BuildText(GdsTextBuilderError));
341        read_optional_field!(builder.presentation  <- self.read_presentation   if Presentation);
342        read_optional_field!(builder.path_type     <- self.read_path_type      if PathType);
343        read_optional_field!(builder.width         <- self.take_i32_record     if Width);
344        read_optional_field!(builder.transform     <- self.read_transform      if STrans);
345        read_required_field!(builder.position      <- self.read_position       if Xy        => BuildSref(GdsSrefBuilderError));
346        read_required_field!(builder.string        <- self.take_string_record  if String    => BuildText(GdsTextBuilderError));
347
348        self.read_element_end()?;
349        Ok(builder.build()?)
350    }
351
352    pub fn read_element_node(&mut self) -> GdsReadResult<GdsNode> {
353        self.read_element_header()?;
354        let mut builder = GdsNodeBuilder::default();
355
356        read_optional_field!(builder.elf_flags     <- self.take_i16_record     if ElFlags);
357        read_optional_field!(builder.plex          <- self.take_i32_record     if Plex);
358        read_required_field!(builder.layer         <- self.take_i16_record     if Layer     => BuildNode(GdsNodeBuilderError));
359        read_required_field!(builder.node_type     <- self.take_i16_record     if Layer     => BuildNode(GdsNodeBuilderError));
360        read_required_field!(builder.xy            <- self.read_xy             if Layer     => BuildNode(GdsNodeBuilderError));
361
362        self.read_element_end()?;
363        Ok(builder.build()?)
364    }
365
366    pub fn read_element_box(&mut self) -> GdsReadResult<GdsBox> {
367        self.read_element_header()?;
368        let mut builder = GdsBoxBuilder::default();
369
370        read_optional_field!(builder.elf_flags     <- self.take_i16_record     if ElFlags);
371        read_optional_field!(builder.plex          <- self.take_i32_record     if Plex);
372        read_required_field!(builder.layer         <- self.take_i16_record     if Layer     => BuildBox(GdsBoxBuilderError));
373        read_required_field!(builder.box_type      <- self.take_i16_record     if Layer     => BuildBox(GdsBoxBuilderError));
374        read_required_field!(builder.xy            <- self.read_xy             if Layer     => BuildBox(GdsBoxBuilderError));
375
376        self.read_element_end()?;
377        Ok(builder.build()?)
378    }
379
380    fn read_element_header(&mut self) -> GdsReadResult<()> {
381        self.ensure_record_size(4)?;
382        self.jump_bytes(4)?;
383        Ok(())
384    }
385
386    fn read_element_end(&mut self) -> GdsReadResult<()> {
387        self.ensure_record(4, GdsRecordType::EndEle)?;
388        self.jump_bytes(4)?;
389        Ok(())
390    }
391
392    pub fn read_col_row(&mut self) -> GdsReadResult<(i16, i16)> {
393        self.ensure_record_size(8)?;
394        self.jump_bytes(4)?;
395        let col = self.take_i16()?;
396        let row = self.take_i16()?;
397        Ok((col, row))
398    }
399
400    pub fn read_xy(&mut self) -> GdsReadResult<Vec<GdsCoord>> {
401        let mut header = [0u8; 4];
402        self.reader.read_exact(&mut header)?;
403        let record_size = u16::from_be_bytes([header[0], header[1]]) as usize;
404        let record_type = u16::from_be_bytes([header[2], header[3]]);
405        let rec_type = GdsRecordType::from_u16(record_type)
406            .ok_or(GdsReadError::UnsupportRecordType(record_type))?;
407
408        if rec_type != GdsRecordType::Xy {
409            return Err(GdsReadError::UnexpectRecordType(GdsRecordType::Xy, rec_type));
410        }
411
412        if record_size < 4 || (record_size - 4) % 8 != 0 {
413            return Err(GdsReadError::InvalidRecordSize(record_size));
414        }
415
416        let position_count = (record_size - 4) / 8;
417        let mut coords = Vec::with_capacity(position_count);
418        for _ in 0..position_count {
419            let x = self.take_i32()?;
420            let y = self.take_i32()?;
421            coords.push(GdsCoord::new( x, y ));
422        }
423        Ok(coords)
424    }
425
426    pub fn read_position(&mut self) -> GdsReadResult<GdsCoord> {
427        let mut header = [0u8; 4];
428        self.reader.read_exact(&mut header)?;
429        let record_size = u16::from_be_bytes([header[0], header[1]]) as usize;
430        let record_type = u16::from_be_bytes([header[2], header[3]]);
431        let rec_type = GdsRecordType::from_u16(record_type)
432            .ok_or(GdsReadError::UnsupportRecordType(record_type))?;
433
434        if rec_type != GdsRecordType::Xy {
435            return Err(GdsReadError::UnexpectRecordType(GdsRecordType::Xy, rec_type));
436        }
437
438        if record_size < 4 || (record_size - 4) % 8 != 0 {
439            return Err(GdsReadError::InvalidRecordSize(record_size));
440        }
441
442        let position_count = (record_size - 4) / 8;
443        if position_count != 1 {
444            return Err(GdsReadError::ExecptPosition(position_count));
445        }
446
447        let x = self.take_i32()?;
448        let y = self.take_i32()?;
449
450        Ok((x, y).into())
451    }
452
453    pub fn read_transform(&mut self) -> GdsReadResult<GdsTransform> {
454        // Take the u16 value as flag
455        let value = self.take_u16_record()? as u16;
456        let mut transform = GdsTransform::with_flag(value);
457
458        // Is mag?
459        if self.peek_record_type()? == GdsRecordType::Mag {
460            transform.magnification = Some(self.take_f64_record()?);
461        }
462
463        // If angle
464        if self.peek_record_type()? == GdsRecordType::Angle {
465            transform.angle = Some(self.take_f64_record()?);
466        }
467
468        Ok(transform)
469    }   
470
471    pub fn read_path_type(&mut self) -> GdsReadResult<GdsPathType> {
472        let value = self.take_u16_record()?;
473        GdsPathType::from_u16(value)
474            .ok_or_else(|| GdsReadError::BuildText(GdsTextBuilderError::ValidationError(format!("'{value}' is not an valid path type"))))
475    }
476
477    pub fn read_presentation(&mut self) -> GdsReadResult<GdsPresentation> {
478        let value = self.take_u16_record()?;
479        GdsPresentation::from_u16(value)
480            .map_err(|e| GdsReadError::BuildText(GdsTextBuilderError::ValidationError(e)))
481    }
482}
483
484/// These method do not check record type, please ensure it correct!
485/// And will take all record!
486impl<R: Read + Seek> GdsReader<R> {
487    fn take_u16_record(&mut self) -> GdsReadResult<u16> {
488        self.ensure_record_size(6)?;
489        self.jump_bytes(4)?; // Jump record header
490        self.take_u16()
491    }
492
493    fn take_i16_record(&mut self) -> GdsReadResult<i16> {
494        self.ensure_record_size(6)?;
495        self.jump_bytes(4)?; // Jump record header
496        self.take_i16()
497    }
498
499    fn take_i32_record(&mut self) -> GdsReadResult<i32> {
500        self.ensure_record_size(6)?;
501        self.jump_bytes(4)?;
502        self.take_i32()
503    }
504
505    fn take_string_record(&mut self) -> GdsReadResult<String> {
506        let size = self.take_record_size()?;
507        self.jump_bytes(2)?;
508        self.take_string(size - 4)
509    }
510
511    fn take_f64_record(&mut self) -> GdsReadResult<f64> {
512        self.ensure_record_size(12)?;
513        self.jump_bytes(4)?;
514        self.take_f64()
515    }
516}
517
518/// Methods for take value from `reader`
519impl<R: Read + Seek> GdsReader<R> {
520    fn take_record_size(&mut self) -> GdsReadResult<usize> {
521        let mut buf = [0u8; 2];
522        self.reader.read_exact(&mut buf)?;
523        let size = u16::from_be_bytes(buf) as usize;
524        if size < 4 {
525            return Err(GdsReadError::InvalidRecordSize(size));
526        }
527        Ok(size)
528    }
529
530    fn take_u16(&mut self) -> GdsReadResult<u16> {
531        let mut buf = [0u8; 2];
532        self.reader.read_exact(&mut buf)?;
533        Ok(u16::from_be_bytes(buf))
534    }
535
536    fn take_i16(&mut self) -> GdsReadResult<i16> {
537        let mut buf = [0u8; 2];
538        self.reader.read_exact(&mut buf)?;
539        Ok(i16::from_be_bytes(buf))
540    }
541
542    fn take_i32(&mut self) -> GdsReadResult<i32> {
543        let mut buf = [0u8; 4];
544        self.reader.read_exact(&mut buf)?;
545        Ok(i32::from_be_bytes(buf))
546    }
547
548    fn take_string(&mut self, len: usize) -> GdsReadResult<String> {
549        let mut buf = vec![0u8; len];
550        self.reader.read_exact(&mut buf)?;
551        while buf.last() == Some(&0) {
552            buf.pop();
553        }
554        let s = String::from_utf8(buf)?;
555        Ok(s)
556    }
557
558    fn take_f64(&mut self) -> GdsReadResult<f64> {
559        let mut buf = [0u8; 8];
560        self.reader.read_exact(&mut buf)?;
561        Ok(utils::bytes_to_f64(buf))
562    }
563
564    fn take_datetime(&mut self) -> GdsReadResult<GdsDateTime> {
565        let year = self.take_i16()?;
566        let month = self.take_i16()?;
567        let day = self.take_i16()?;
568        let hour = self.take_i16()?;
569        let minute = self.take_i16()?;
570        let second = self.take_i16()?;
571
572        Ok(GdsDateTime {
573            year,
574            month,
575            day,
576            hour,
577            minute,
578            second
579        })
580    }
581}
582
583impl<R: Read + Seek> GdsReader<R> {
584    fn check_record_type(&mut self, tp: GdsRecordType) -> GdsReadResult<bool> {
585        let real_tp = self.peek_record_type()?;
586        Ok(real_tp == tp)
587    }
588
589    fn ensure_record(&mut self, size: usize, tp: GdsRecordType) -> GdsReadResult<()> {
590        self.ensure_record_size(size)?;
591        self.ensure_record_type(tp)?;
592        Ok(())
593    }
594
595    fn ensure_record_type(&mut self, tp: GdsRecordType) -> GdsReadResult<()> { 
596        let real_tp = self.peek_record_type()?;
597        if real_tp == tp {
598            Ok(())
599        } else {
600            Err(GdsReadError::UnexpectRecordType(tp, real_tp))
601        }
602    }
603
604    fn ensure_record_size(&mut self, size: usize) -> GdsReadResult<()> { 
605        let real_size = self.peek_record_size()?;
606        if real_size == size {
607            Ok(())
608        } else {
609            Err(GdsReadError::UnexpectRecordSize(size, real_size))
610        }
611    }
612
613    fn peek_record_size(&mut self) -> GdsReadResult<usize> {
614        let bytes = self.peek_bytes::<2>()?;
615        Ok(u16::from_be_bytes(bytes) as usize)
616    }
617
618    fn peek_record_type(&mut self) -> GdsReadResult<GdsRecordType> {
619        let bytes = self.peek_bytes::<4>()?;
620        let bytes = [bytes[2], bytes[3]];
621        let value = u16::from_be_bytes(bytes);
622        match GdsRecordType::from_u16(value) {
623            Some(t) => Ok(t),
624            None => Err(GdsReadError::UnsupportRecordType(value))
625        }
626    }
627
628    fn peek_bytes<const L: usize>(&mut self) -> GdsReadResult<[u8; L]> {
629        let mut bytes = [0u8; L];
630        let buf = self.reader.fill_buf()?;
631        if buf.len() < L {
632            return Err(GdsReadError::Io(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "Not enough bytes to peek")));
633        }
634
635        for i in 0..L {
636            bytes[i] = buf[i];
637        }
638
639        Ok(bytes)
640    }
641
642    fn jump_bytes(&mut self, size: i64) -> GdsReadResult<()> {
643        self.reader.seek(SeekFrom::Current(size))?;
644        Ok(())
645    }
646}