munyo 0.8.0

A data language which aims to be the most efficient way to handwrite data.
Documentation
use std::fmt::Display;

use anyhow::{anyhow, Error};
use pest::error::{Error as PestError, InputLocation};
use pest::RuleType;

use crate::lang::munyo_parser::Pair;

pub(crate) struct ParseFail {
    pub(crate) start_index: usize,
    pub(crate) message: anyhow::Error,
}

impl ParseFail {
    pub(crate) fn new(start_index: usize, message: anyhow::Error) -> Self {
        Self {
            start_index,
            message,
        }
    }

    pub(crate) fn msg(start_index: usize, message: String) -> Self {
        Self {
            start_index,
            message: anyhow!(message),
        }
    }

    pub(crate) fn from_pest_err<R: RuleType>(e: PestError<R>) -> Self {
        let start_index = match e.location {
            InputLocation::Pos(start) => start,
            InputLocation::Span((start, _end)) => start,
        };

        Self {
            start_index,
            message: anyhow!("{e}"),
        }
    }
}

pub(crate) fn parse_fail(pair: &Pair, s: &str) -> ParseFail {
    ParseFail::msg(pair.as_span().start(), s.to_string())
}

pub(crate) trait ParseFailHelper<T> {
    fn op(self, pair: &Pair) -> Result<T, ParseFail>;
    fn os(self, index: usize) -> Result<T, ParseFail>;
}

pub(crate) trait ParseFailHelper2<T> {
    fn oe(self, index: usize) -> Result<T, ParseFail>;
}

impl<T> ParseFailHelper2<T> for Result<T, Error> {
    fn oe(self, index: usize) -> Result<T, ParseFail> {
        match self {
            Ok(t) => Ok(t),
            Err(e) => Err(ParseFail::new(index, e)),
        }
    }
}

impl<T> ParseFailHelper<T> for Result<T, String> {
    fn op(self, pair: &Pair) -> Result<T, ParseFail> {
        match self {
            Ok(r) => Ok(r),
            Err(s) => Err(parse_fail(pair, &s)),
        }
    }

    fn os(self, index: usize) -> Result<T, ParseFail> {
        match self {
            Ok(r) => Ok(r),
            Err(s) => Err(ParseFail::msg(index, s)),
        }
    }
}

pub(crate) trait PairHelper {
    fn start_index(&self) -> usize;
}

impl<'a> PairHelper for Pair<'a> {
    fn start_index(&self) -> usize {
        self.as_span().start()
    }
}

impl std::error::Error for ParseFail {}

impl std::fmt::Display for ParseFail {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        Display::fmt(&self.message, f)
    }
}

impl std::fmt::Debug for ParseFail {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}\n{}", &self.message, self.message.backtrace())
    }
}