assembly_maps/luz/
io.rs

1use super::core::ZoneFile;
2use super::parser;
3use assembly_core::nom::{error::Error as NomError, error::ErrorKind, Err as NomErr};
4use displaydoc::Display;
5use std::convert::TryFrom;
6use std::io::Read;
7use std::{fs, io};
8use thiserror::Error;
9
10/// Error when loading a LUZ file
11#[derive(Debug, Error, Display)]
12pub enum LoadError {
13    /// Failed to open the file
14    FileOpen(io::Error),
15    /// Failed to read from the file
16    Read(io::Error),
17    /// Missing bytes
18    Incomplete,
19    /// Failed to parse (recoverable)
20    ParseError(ErrorKind),
21    /// Failed to parse (fatal)
22    ParseFailure(ErrorKind),
23}
24
25type LoadResult<T> = Result<T, LoadError>;
26
27// Generates a LoadError from a nom error
28impl From<NomErr<NomError<&[u8]>>> for LoadError {
29    fn from(e: NomErr<NomError<&[u8]>>) -> LoadError {
30        match e {
31            // Need to translate the error here, as this lives longer than the input
32            NomErr::Incomplete(_) => LoadError::Incomplete,
33            NomErr::Error(e) => LoadError::ParseError(e.code),
34            NomErr::Failure(e) => LoadError::ParseFailure(e.code),
35        }
36    }
37}
38
39pub trait TryFromLUZ<T>
40where
41    T: Read,
42    Self: Sized,
43{
44    type Error;
45
46    fn try_from_luz(buf: &mut T) -> Result<Self, Self::Error>;
47}
48
49impl TryFrom<&str> for ZoneFile<Vec<u8>> {
50    type Error = LoadError;
51
52    fn try_from(filename: &str) -> LoadResult<Self> {
53        fs::File::open(filename)
54            .map_err(LoadError::FileOpen)
55            .and_then(ZoneFile::try_from)
56    }
57}
58
59impl TryFrom<fs::File> for ZoneFile<Vec<u8>> {
60    type Error = LoadError;
61
62    fn try_from(file: fs::File) -> LoadResult<Self> {
63        ZoneFile::try_from_luz(&mut io::BufReader::new(file))
64    }
65}
66
67impl<T> TryFromLUZ<T> for ZoneFile<Vec<u8>>
68where
69    T: Read,
70{
71    type Error = LoadError;
72
73    fn try_from_luz(buf: &mut T) -> Result<Self, Self::Error> {
74        let mut bytes: Vec<u8> = Vec::new();
75        buf.read_to_end(&mut bytes)
76            .map_err(LoadError::Read)
77            .and_then(|_| {
78                parser::parse_zone_file(&bytes)
79                    .map_err(LoadError::from)
80                    .map(|r| r.1)
81            })
82    }
83}