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