diff options
author | Florian Klink <flokli@flokli.de> | 2023-07-31T13·46+0200 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2023-10-16T12·23+0000 |
commit | 2410f2292f53a17242ed54b0af2d7b04ec3173f6 (patch) | |
tree | 476d93504a2c21d48011fce4f4afe79bfb0b0cca /tvix/nix-compat/src/derivation/parse_error.rs | |
parent | 8b09ae54b1d635e77c394dd965915479283489a2 (diff) |
feat(nix-compat/{aterm,derivation}): init parser r/6831
This provides a nom-based parser for Nix derivations in ATerm format, which can be reached via `Derivation::from_aterm_bytes`. Some of the lower-level ATerm primitives are moved into a (new) aterm module, and some more higher-level ones that construct derivation- specific types. Also, move the escape_bytes function into there, this is a generic ATerm thing. Change-Id: I2b03b8a1461c7ea2fcb8640c2fc3d1fa3ea719fb Reviewed-on: https://cl.tvl.fyi/c/depot/+/9730 Autosubmit: flokli <flokli@flokli.de> Reviewed-by: raitobezarius <tvl@lahfa.xyz> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/nix-compat/src/derivation/parse_error.rs')
-rw-r--r-- | tvix/nix-compat/src/derivation/parse_error.rs | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/tvix/nix-compat/src/derivation/parse_error.rs b/tvix/nix-compat/src/derivation/parse_error.rs new file mode 100644 index 000000000000..a064d4faba7b --- /dev/null +++ b/tvix/nix-compat/src/derivation/parse_error.rs @@ -0,0 +1,73 @@ +//! This contains error and result types that can happen while parsing +//! Derivations from ATerm. +use nom::IResult; + +use crate::nixhash; + +pub type NomResult<I, O> = IResult<I, O, NomError<I>>; + +#[derive(Debug, PartialEq)] +pub enum ErrorKind { + // duplicate key in map + DuplicateMapKey(String), + + // Digest parsing error + NixHashError(nixhash::Error), + + // error kind wrapped from native nom errors + Nom(nom::error::ErrorKind), +} + +/// Our own error type to pass along parser-related errors. +#[derive(Debug, PartialEq)] +pub struct NomError<I> { + /// position of the error in the input data + pub input: I, + /// error code + pub code: ErrorKind, +} + +impl<I, E> nom::error::FromExternalError<I, E> for NomError<I> { + fn from_external_error(input: I, kind: nom::error::ErrorKind, _e: E) -> Self { + Self { + input, + code: ErrorKind::Nom(kind), + } + } +} + +impl<I> nom::error::ParseError<I> for NomError<I> { + fn from_error_kind(input: I, kind: nom::error::ErrorKind) -> Self { + Self { + input, + code: ErrorKind::Nom(kind), + } + } + + // FUTUREWORK: implement, so we have support for backtracking through the + // parse tree? + fn append(_input: I, _kind: nom::error::ErrorKind, other: Self) -> Self { + other + } +} + +/// This wraps a [nom::error::Error] into our error. +impl<I> From<nom::error::Error<I>> for NomError<I> { + fn from(value: nom::error::Error<I>) -> Self { + Self { + input: value.input, + code: ErrorKind::Nom(value.code), + } + } +} + +/// This essentially implements +/// From<nom::Err<nom::error::Error<I>>> for nom::Err<NomError<I>>, +/// which we can't because nom::Err<_> is a foreign type. +pub(crate) fn into_nomerror<I>(e: nom::Err<nom::error::Error<I>>) -> nom::Err<NomError<I>> { + match e { + nom::Err::Incomplete(n) => nom::Err::Incomplete(n), + nom::Err::Error(e) => nom::Err::Error(e.into()), + nom::Err::Failure(e) => nom::Err::Failure(e.into()), + } +} |