Skip to main content

nix_compat/derivation/
parse_error.rs

1//! This contains error and result types that can happen while parsing
2//! Derivations from ATerm.
3use nom::IResult;
4
5use crate::{
6    derivation::{OutputName, ParseOutputNameError, outputs::OutputsError},
7    nixhash,
8    store_path::{self, StorePath},
9};
10
11pub type NomResult<I, O> = IResult<I, O, NomError<I>>;
12
13#[derive(Debug, thiserror::Error, PartialEq)]
14pub enum ErrorKind {
15    /// duplicate key in map
16    #[error("duplicate map key: {0}")]
17    DuplicateMapKey(String),
18
19    /// Input derivation has two outputs with the same name
20    #[error("duplicate output name {0} for input derivation {1}")]
21    DuplicateInputDerivationOutputName(OutputName, String),
22
23    #[error("duplicate input source: {0}")]
24    DuplicateInputSource(StorePath),
25
26    #[error("invalind output name")]
27    InvalidOutputName(#[from] ParseOutputNameError),
28
29    #[error("invalid outputs")]
30    InvalidOutputs(#[from] OutputsError),
31
32    #[error("nix hash error: {0}")]
33    NixHashError(nixhash::Error),
34
35    #[error("store path error: {0}")]
36    StorePathError(#[from] store_path::ParseStorePathError),
37
38    #[error("nom error: {0:?}")]
39    Nom(nom::error::ErrorKind),
40}
41
42/// Our own error type to pass along parser-related errors.
43#[derive(Debug, PartialEq)]
44pub struct NomError<I> {
45    /// position of the error in the input data
46    pub input: I,
47    /// error code
48    pub code: ErrorKind,
49}
50
51impl<I, E> nom::error::FromExternalError<I, E> for NomError<I> {
52    fn from_external_error(input: I, kind: nom::error::ErrorKind, _e: E) -> Self {
53        Self {
54            input,
55            code: ErrorKind::Nom(kind),
56        }
57    }
58}
59
60impl<I> nom::error::ParseError<I> for NomError<I> {
61    fn from_error_kind(input: I, kind: nom::error::ErrorKind) -> Self {
62        Self {
63            input,
64            code: ErrorKind::Nom(kind),
65        }
66    }
67
68    // FUTUREWORK: implement, so we have support for backtracking through the
69    // parse tree?
70    fn append(_input: I, _kind: nom::error::ErrorKind, other: Self) -> Self {
71        other
72    }
73}
74
75/// This wraps a [nom::error::Error] into our error.
76impl<I> From<nom::error::Error<I>> for NomError<I> {
77    fn from(value: nom::error::Error<I>) -> Self {
78        Self {
79            input: value.input,
80            code: ErrorKind::Nom(value.code),
81        }
82    }
83}
84
85/// This essentially implements
86/// `From<nom::Err<nom::error::Error<I>>>` for `nom::Err<NomError<I>>`,
87/// which we can't because `nom::Err<_>` is a foreign type.
88pub(crate) fn into_nomerror<I>(e: nom::Err<nom::error::Error<I>>) -> nom::Err<NomError<I>> {
89    match e {
90        nom::Err::Incomplete(n) => nom::Err::Incomplete(n),
91        nom::Err::Error(e) => nom::Err::Error(e.into()),
92        nom::Err::Failure(e) => nom::Err::Failure(e.into()),
93    }
94}