1#[macro_use]
88extern crate bitflags;
89
90use std::{
91 io::{self, Read},
92 mem,
93 path::Path,
94};
95
96pub mod layout;
97
98pub trait LayoutBuffer: zerocopy::FromBytes {
100 type Buffer;
101 fn empty() -> Self::Buffer;
102 fn slice(buffer: &Self::Buffer) -> &[u8];
103 fn slice_mut(buffer: &mut Self::Buffer) -> &mut [u8];
104}
105
106pub struct SectionReader<R> {
110 reader: R,
111 buffer: [u8; mem::size_of::<layout::Header>()],
112}
113
114pub struct Section<'a, R>
116where
117 R: Read,
118{
119 pub header: &'a layout::Header,
120 pub reader: SubsectionReaderKind<R>,
121}
122
123pub struct SubsectionReader<R, T>
125where
126 R: Read,
127 T: LayoutBuffer,
128{
129 reader: R,
130 len: u16,
131 buffer: T::Buffer,
132 subsection_layout: std::marker::PhantomData<T>,
133}
134
135pub type Coords3dIndexedColorReader<R> = SubsectionReader<R, layout::Coords3dIndexedColor>;
136pub type Coords2dIndexedColorReader<R> = SubsectionReader<R, layout::Coords2dIndexedColor>;
137pub type ColorPaletteReader<R> = SubsectionReader<R, layout::ColorPalette>;
138pub type Coords3dTrueColorReader<R> = SubsectionReader<R, layout::Coords3dTrueColor>;
139pub type Coords2dTrueColorReader<R> = SubsectionReader<R, layout::Coords2dTrueColor>;
140
141pub enum SubsectionReaderKind<R>
143where
144 R: Read,
145{
146 Coords3dIndexedColor(Coords3dIndexedColorReader<R>),
147 Coords2dIndexedColor(Coords2dIndexedColorReader<R>),
148 ColorPalette(ColorPaletteReader<R>),
149 Coords3dTrueColor(Coords3dTrueColorReader<R>),
150 Coords2dTrueColor(Coords2dTrueColorReader<R>),
151}
152
153impl<R> SectionReader<R>
154where
155 R: Read,
156{
157 pub fn new(reader: R) -> Self {
159 let buffer = [0u8; mem::size_of::<layout::Header>()];
160 SectionReader { reader, buffer }
161 }
162
163 pub fn read_next(&mut self) -> io::Result<Option<Section<&mut R>>> {
168 let SectionReader {
169 ref mut buffer,
170 ref mut reader,
171 } = *self;
172
173 if let Err(err) = reader.read_exact(buffer) {
175 if let io::ErrorKind::UnexpectedEof = err.kind() {
176 return Ok(None);
177 }
178 }
179
180 let header: &layout::Header = zerocopy::LayoutVerified::new(&buffer[..])
182 .map(zerocopy::LayoutVerified::into_ref)
183 .ok_or_else(|| {
184 let err_msg = "could not verify the layout of `Header`";
185 io::Error::new(io::ErrorKind::InvalidData, err_msg)
186 })?;
187
188 if header.ilda != layout::Header::ILDA {
190 let err_msg = "could not verify `Header` due to invalid ILDA ascii";
191 return Err(io::Error::new(io::ErrorKind::InvalidData, err_msg));
192 }
193
194 let len = header.num_records.get();
196 let reader = match header.format {
197 layout::Format::COORDS_3D_INDEXED_COLOR => {
198 Coords3dIndexedColorReader::new(reader, len).into()
199 }
200 layout::Format::COORDS_2D_INDEXED_COLOR => {
201 Coords2dIndexedColorReader::new(reader, len).into()
202 }
203 layout::Format::COLOR_PALETTE => ColorPaletteReader::new(reader, len).into(),
204 layout::Format::COORDS_3D_TRUE_COLOR => {
205 Coords3dTrueColorReader::new(reader, len).into()
206 }
207 layout::Format::COORDS_2D_TRUE_COLOR => {
208 Coords2dTrueColorReader::new(reader, len).into()
209 }
210 _ => {
211 let err_msg = "could not verify the layout of `Header`";
212 return Err(io::Error::new(io::ErrorKind::InvalidData, err_msg));
213 }
214 };
215
216 Ok(Some(Section { header, reader }))
217 }
218}
219
220impl<R, T> SubsectionReader<R, T>
221where
222 R: Read,
223 T: LayoutBuffer,
224{
225 fn new(reader: R, len: u16) -> Self {
226 let buffer = T::empty();
227 let subsection_layout = std::marker::PhantomData;
228 Self {
229 reader,
230 len,
231 buffer,
232 subsection_layout,
233 }
234 }
235
236 pub fn len(&self) -> u16 {
238 self.len
239 }
240
241 pub fn read_next(&mut self) -> io::Result<Option<&T>> {
243 match self.len {
244 0 => return Ok(None),
245 ref mut n => *n -= 1,
246 }
247 self.reader.read_exact(T::slice_mut(&mut self.buffer))?;
248 let subsection = zerocopy::LayoutVerified::new(T::slice(&self.buffer))
249 .map(zerocopy::LayoutVerified::into_ref)
250 .ok_or_else(|| {
251 let err_msg = "could not verify the layout of `Header`";
252 io::Error::new(io::ErrorKind::InvalidData, err_msg)
253 })?;
254 Ok(Some(subsection))
255 }
256}
257
258impl<R, T> Drop for SubsectionReader<R, T>
259where
260 R: Read,
261 T: LayoutBuffer,
262{
263 fn drop(&mut self) {
264 while let Ok(Some(_)) = self.read_next() {}
265 }
266}
267
268impl LayoutBuffer for layout::Coords3dIndexedColor {
269 type Buffer = [u8; mem::size_of::<Self>()];
270 fn empty() -> Self::Buffer {
271 [0u8; mem::size_of::<Self>()]
272 }
273 fn slice(buffer: &Self::Buffer) -> &[u8] {
274 &buffer[..]
275 }
276 fn slice_mut(buffer: &mut Self::Buffer) -> &mut [u8] {
277 &mut buffer[..]
278 }
279}
280
281impl LayoutBuffer for layout::Coords2dIndexedColor {
282 type Buffer = [u8; mem::size_of::<Self>()];
283 fn empty() -> Self::Buffer {
284 [0u8; mem::size_of::<Self>()]
285 }
286 fn slice(buffer: &Self::Buffer) -> &[u8] {
287 &buffer[..]
288 }
289 fn slice_mut(buffer: &mut Self::Buffer) -> &mut [u8] {
290 &mut buffer[..]
291 }
292}
293
294impl LayoutBuffer for layout::ColorPalette {
295 type Buffer = [u8; mem::size_of::<Self>()];
296 fn empty() -> Self::Buffer {
297 [0u8; mem::size_of::<Self>()]
298 }
299 fn slice(buffer: &Self::Buffer) -> &[u8] {
300 &buffer[..]
301 }
302 fn slice_mut(buffer: &mut Self::Buffer) -> &mut [u8] {
303 &mut buffer[..]
304 }
305}
306
307impl LayoutBuffer for layout::Coords3dTrueColor {
308 type Buffer = [u8; mem::size_of::<Self>()];
309 fn empty() -> Self::Buffer {
310 [0u8; mem::size_of::<Self>()]
311 }
312 fn slice(buffer: &Self::Buffer) -> &[u8] {
313 &buffer[..]
314 }
315 fn slice_mut(buffer: &mut Self::Buffer) -> &mut [u8] {
316 &mut buffer[..]
317 }
318}
319
320impl LayoutBuffer for layout::Coords2dTrueColor {
321 type Buffer = [u8; mem::size_of::<Self>()];
322 fn empty() -> Self::Buffer {
323 [0u8; mem::size_of::<Self>()]
324 }
325 fn slice(buffer: &Self::Buffer) -> &[u8] {
326 &buffer[..]
327 }
328 fn slice_mut(buffer: &mut Self::Buffer) -> &mut [u8] {
329 &mut buffer[..]
330 }
331}
332
333impl<R> From<Coords3dIndexedColorReader<R>> for SubsectionReaderKind<R>
334where
335 R: Read,
336{
337 fn from(r: Coords3dIndexedColorReader<R>) -> Self {
338 Self::Coords3dIndexedColor(r)
339 }
340}
341
342impl<R> From<Coords2dIndexedColorReader<R>> for SubsectionReaderKind<R>
343where
344 R: Read,
345{
346 fn from(r: Coords2dIndexedColorReader<R>) -> Self {
347 Self::Coords2dIndexedColor(r)
348 }
349}
350
351impl<R> From<ColorPaletteReader<R>> for SubsectionReaderKind<R>
352where
353 R: Read,
354{
355 fn from(r: ColorPaletteReader<R>) -> Self {
356 Self::ColorPalette(r)
357 }
358}
359
360impl<R> From<Coords3dTrueColorReader<R>> for SubsectionReaderKind<R>
361where
362 R: Read,
363{
364 fn from(r: Coords3dTrueColorReader<R>) -> Self {
365 Self::Coords3dTrueColor(r)
366 }
367}
368
369impl<R> From<Coords2dTrueColorReader<R>> for SubsectionReaderKind<R>
370where
371 R: Read,
372{
373 fn from(r: Coords2dTrueColorReader<R>) -> Self {
374 Self::Coords2dTrueColor(r)
375 }
376}
377
378pub type BufFileSectionReader = SectionReader<io::BufReader<std::fs::File>>;
380
381pub fn open<P>(path: P) -> io::Result<BufFileSectionReader>
385where
386 P: AsRef<Path>,
387{
388 open_path(path.as_ref())
389}
390
391fn open_path(path: &Path) -> io::Result<BufFileSectionReader> {
392 let file = std::fs::File::open(path).unwrap();
393 let buf_reader = std::io::BufReader::new(file);
394 Ok(SectionReader::new(buf_reader))
395}
396
397pub const DEFAULT_PALETTE: [layout::Color; 64] = [
399 layout::Color {
400 red: 255,
401 green: 0,
402 blue: 0,
403 },
404 layout::Color {
405 red: 255,
406 green: 16,
407 blue: 0,
408 },
409 layout::Color {
410 red: 255,
411 green: 32,
412 blue: 0,
413 },
414 layout::Color {
415 red: 255,
416 green: 48,
417 blue: 0,
418 },
419 layout::Color {
420 red: 255,
421 green: 64,
422 blue: 0,
423 },
424 layout::Color {
425 red: 255,
426 green: 80,
427 blue: 0,
428 },
429 layout::Color {
430 red: 255,
431 green: 96,
432 blue: 0,
433 },
434 layout::Color {
435 red: 255,
436 green: 112,
437 blue: 0,
438 },
439 layout::Color {
440 red: 255,
441 green: 128,
442 blue: 0,
443 },
444 layout::Color {
445 red: 255,
446 green: 144,
447 blue: 0,
448 },
449 layout::Color {
450 red: 255,
451 green: 160,
452 blue: 0,
453 },
454 layout::Color {
455 red: 255,
456 green: 176,
457 blue: 0,
458 },
459 layout::Color {
460 red: 255,
461 green: 192,
462 blue: 0,
463 },
464 layout::Color {
465 red: 255,
466 green: 208,
467 blue: 0,
468 },
469 layout::Color {
470 red: 255,
471 green: 224,
472 blue: 0,
473 },
474 layout::Color {
475 red: 255,
476 green: 240,
477 blue: 0,
478 },
479 layout::Color {
480 red: 255,
481 green: 255,
482 blue: 0,
483 },
484 layout::Color {
485 red: 224,
486 green: 255,
487 blue: 0,
488 },
489 layout::Color {
490 red: 192,
491 green: 255,
492 blue: 0,
493 },
494 layout::Color {
495 red: 160,
496 green: 255,
497 blue: 0,
498 },
499 layout::Color {
500 red: 128,
501 green: 255,
502 blue: 0,
503 },
504 layout::Color {
505 red: 96,
506 green: 255,
507 blue: 0,
508 },
509 layout::Color {
510 red: 64,
511 green: 255,
512 blue: 0,
513 },
514 layout::Color {
515 red: 32,
516 green: 255,
517 blue: 0,
518 },
519 layout::Color {
520 red: 0,
521 green: 255,
522 blue: 0,
523 },
524 layout::Color {
525 red: 0,
526 green: 255,
527 blue: 36,
528 },
529 layout::Color {
530 red: 0,
531 green: 255,
532 blue: 73,
533 },
534 layout::Color {
535 red: 0,
536 green: 255,
537 blue: 109,
538 },
539 layout::Color {
540 red: 0,
541 green: 255,
542 blue: 146,
543 },
544 layout::Color {
545 red: 0,
546 green: 255,
547 blue: 182,
548 },
549 layout::Color {
550 red: 0,
551 green: 255,
552 blue: 219,
553 },
554 layout::Color {
555 red: 0,
556 green: 255,
557 blue: 255,
558 },
559 layout::Color {
560 red: 0,
561 green: 227,
562 blue: 255,
563 },
564 layout::Color {
565 red: 0,
566 green: 198,
567 blue: 255,
568 },
569 layout::Color {
570 red: 0,
571 green: 170,
572 blue: 255,
573 },
574 layout::Color {
575 red: 0,
576 green: 142,
577 blue: 255,
578 },
579 layout::Color {
580 red: 0,
581 green: 113,
582 blue: 255,
583 },
584 layout::Color {
585 red: 0,
586 green: 85,
587 blue: 255,
588 },
589 layout::Color {
590 red: 0,
591 green: 56,
592 blue: 255,
593 },
594 layout::Color {
595 red: 0,
596 green: 28,
597 blue: 255,
598 },
599 layout::Color {
600 red: 0,
601 green: 0,
602 blue: 255,
603 },
604 layout::Color {
605 red: 32,
606 green: 0,
607 blue: 255,
608 },
609 layout::Color {
610 red: 64,
611 green: 0,
612 blue: 255,
613 },
614 layout::Color {
615 red: 96,
616 green: 0,
617 blue: 255,
618 },
619 layout::Color {
620 red: 128,
621 green: 0,
622 blue: 255,
623 },
624 layout::Color {
625 red: 160,
626 green: 0,
627 blue: 255,
628 },
629 layout::Color {
630 red: 192,
631 green: 0,
632 blue: 255,
633 },
634 layout::Color {
635 red: 224,
636 green: 0,
637 blue: 255,
638 },
639 layout::Color {
640 red: 255,
641 green: 0,
642 blue: 255,
643 },
644 layout::Color {
645 red: 255,
646 green: 32,
647 blue: 255,
648 },
649 layout::Color {
650 red: 255,
651 green: 64,
652 blue: 255,
653 },
654 layout::Color {
655 red: 255,
656 green: 96,
657 blue: 255,
658 },
659 layout::Color {
660 red: 255,
661 green: 128,
662 blue: 255,
663 },
664 layout::Color {
665 red: 255,
666 green: 160,
667 blue: 255,
668 },
669 layout::Color {
670 red: 255,
671 green: 192,
672 blue: 255,
673 },
674 layout::Color {
675 red: 255,
676 green: 224,
677 blue: 255,
678 },
679 layout::Color {
680 red: 255,
681 green: 255,
682 blue: 255,
683 },
684 layout::Color {
685 red: 255,
686 green: 224,
687 blue: 224,
688 },
689 layout::Color {
690 red: 255,
691 green: 192,
692 blue: 192,
693 },
694 layout::Color {
695 red: 255,
696 green: 160,
697 blue: 160,
698 },
699 layout::Color {
700 red: 255,
701 green: 128,
702 blue: 128,
703 },
704 layout::Color {
705 red: 255,
706 green: 96,
707 blue: 96,
708 },
709 layout::Color {
710 red: 255,
711 green: 64,
712 blue: 64,
713 },
714 layout::Color {
715 red: 255,
716 green: 32,
717 blue: 32,
718 },
719];