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#[derive(Debug, Error, Display)]
12pub enum LoadError {
13 FileOpen(io::Error),
15 Read(io::Error),
17 Incomplete,
19 ParseError(ErrorKind),
21 ParseFailure(ErrorKind),
23}
24
25type LoadResult<T> = Result<T, LoadError>;
26
27impl From<NomErr<NomError<&[u8]>>> for LoadError {
29 fn from(e: NomErr<NomError<&[u8]>>) -> LoadError {
30 match e {
31 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}