udled 0.6.2

Tokenizer and parser
Documentation
use crate::Span;

mod sealed {

    pub trait Sealed {}

    impl<'a> Sealed for &'a str {}

    impl Sealed for char {}

    impl<'a> Sealed for &'a [u8] {}
}

pub trait StringExt: sealed::Sealed {
    fn is_ascii_alphanumeric(&self) -> bool;
    fn is_ascii_alphabetic(&self) -> bool;
    fn is_ascii_whitespace(&self) -> bool;
    fn is_ascii_punctuation(&self) -> bool;
    fn is_whitespace(&self) -> bool;
    fn is_linebreak(&self) -> bool;

    fn is_ascii_digit(&self) -> bool;
    fn is_digit(&self, radix: u32) -> bool;

    fn is_alphanumeric(&self) -> bool;
    fn is_alphabetic(&self) -> bool;
}

impl<'a> StringExt for &'a str {
    fn is_ascii_alphanumeric(&self) -> bool {
        self.chars().all(|m| m.is_ascii_alphanumeric())
    }

    fn is_ascii_punctuation(&self) -> bool {
        self.chars().all(|m| m.is_ascii_punctuation())
    }

    fn is_ascii_alphabetic(&self) -> bool {
        self.chars().all(|m| m.is_ascii_alphabetic())
    }

    fn is_ascii_whitespace(&self) -> bool {
        self.chars().all(|m| m.is_ascii_whitespace())
    }

    fn is_whitespace(&self) -> bool {
        self.chars().all(|m| m.is_whitespace())
    }

    fn is_ascii_digit(&self) -> bool {
        self.chars().all(|m| m.is_ascii_digit())
    }

    fn is_digit(&self, radix: u32) -> bool {
        self.chars().all(|m| m.is_digit(radix))
    }

    fn is_linebreak(&self) -> bool {
        self.chars().all(|m| m.is_linebreak())
    }

    fn is_alphanumeric(&self) -> bool {
        self.chars().all(|m| m.is_alphanumeric())
    }
    fn is_alphabetic(&self) -> bool {
        self.chars().all(|m| m.is_alphabetic())
    }
}

impl StringExt for char {
    fn is_ascii_alphanumeric(&self) -> bool {
        (*self).is_ascii_alphanumeric()
    }

    fn is_digit(&self, radix: u32) -> bool {
        (*self).is_digit(radix)
    }

    fn is_ascii_alphabetic(&self) -> bool {
        (*self).is_ascii_alphabetic()
    }

    fn is_ascii_whitespace(&self) -> bool {
        (*self).is_ascii_whitespace()
    }

    fn is_ascii_punctuation(&self) -> bool {
        (*self).is_ascii_punctuation()
    }

    fn is_whitespace(&self) -> bool {
        (*self).is_whitespace()
    }

    fn is_ascii_digit(&self) -> bool {
        (*self).is_ascii_digit()
    }

    fn is_alphanumeric(&self) -> bool {
        (*self).is_alphanumeric()
    }
    fn is_alphabetic(&self) -> bool {
        (*self).is_alphabetic()
    }

    fn is_linebreak(&self) -> bool {
        *self == '\n' || *self == '\r' || *self == '\u{2028}' || *self == '\u{2029}'
    }
}

pub trait LineBreaks: sealed::Sealed {
    fn count_linebreak(&self) -> usize;
}

impl<'a> LineBreaks for &'a str {
    fn count_linebreak(&self) -> usize {
        self.chars()
            .fold(0, |p, c| p + if c.is_linebreak() { 1 } else { 0 })
    }
}

impl<'a> LineBreaks for &'a [u8] {
    fn count_linebreak(&self) -> usize {
        self.iter().fold(0, |p, c| {
            p + if (*c as char).is_linebreak() { 1 } else { 0 }
        })
    }
}

impl LineBreaks for char {
    fn count_linebreak(&self) -> usize {
        if self.is_linebreak() {
            1
        } else {
            0
        }
    }
}

pub trait AsChar {
    fn as_char(&self) -> Option<char>;
}

impl AsChar for char {
    fn as_char(&self) -> Option<char> {
        Some(*self)
    }
}

impl AsChar for u8 {
    fn as_char(&self) -> Option<char> {
        Some(*self as _)
    }
}

impl AsChar for u32 {
    fn as_char(&self) -> Option<char> {
        char::from_u32(*self)
    }
}

pub trait AsBytes<'a> {
    fn as_bytes(&self) -> &'a [u8];
}

impl<'a> AsBytes<'a> for &'a str {
    fn as_bytes(&self) -> &'a [u8] {
        (*self).as_bytes()
    }
}

impl<'a> AsBytes<'a> for &'a [u8] {
    fn as_bytes(&self) -> &'a [u8] {
        self
    }
}

pub trait AsStr<'a>: AsBytes<'a> {
    fn as_str(&self) -> &'a str;
}

impl<'a> AsStr<'a> for &'a str {
    fn as_str(&self) -> &'a str {
        self
    }
}

pub trait AsSlice<'a> {
    type Slice;
    fn sliced(&self, span: Span) -> Option<Self::Slice>;
}

impl<'a> AsSlice<'a> for &'a str {
    type Slice = &'a str;
    fn sliced(&self, span: Span) -> Option<Self::Slice> {
        span.slice(self)
    }
}

impl<'a> AsSlice<'a> for &'a [u8] {
    type Slice = &'a [u8];
    fn sliced(&self, span: Span) -> Option<Self::Slice> {
        if span.end > self.len() {
            return None;
        }

        Some(&self[span.start..span.end])
    }
}