dangerous 0.10.0

Safely and explicitly parse untrusted / dangerous data
Documentation
use core::convert::TryFrom;

use dangerous::{error, BytesReader, Error, Expected, Input};

fn main() {
    println!("=== VALID PARSE ===");
    let input = dangerous::input(b"foo");
    let result: Result<_, Expected<'_>> = input.read_all(read_custom);
    println!("{:?}", result.unwrap());

    println!("\n=== INVALID PARSE ===");
    let input = dangerous::input(b"bar");
    let error: Expected<'_> = input.read_all(read_custom).unwrap_err();
    println!("{:#}", error);
}

#[derive(Debug)]
pub struct Custom<'i>(&'i str);

impl<'i> TryFrom<dangerous::String<'i>> for Custom<'i> {
    type Error = ParseCustomError;

    fn try_from(s: dangerous::String<'i>) -> Result<Self, Self::Error> {
        if s.as_dangerous() == "foo" {
            Ok(Self(s.as_dangerous()))
        } else {
            Err(ParseCustomError)
        }
    }
}

pub struct ParseCustomError;

impl<'i> error::External<'i> for ParseCustomError {
    fn push_backtrace<E>(self, error: E) -> E
    where
        E: error::WithContext<'i>,
    {
        error.with_context(error::ExternalContext {
            operation: Some("read my custom type"),
            expected: Some("my custom type"),
        })
    }
}

fn read_custom<'i, E>(r: &mut BytesReader<'i, E>) -> Result<Custom<'i>, E>
where
    E: Error<'i>,
{
    r.take_remaining_str()?
        .into_external("my custom type", Custom::try_from)
}