pomsky-syntax 0.12.0

Parser for pomsky, a new regular expression language
Documentation
use std::borrow::Cow;

use crate::error::{NumberError, ParseErrorKind};

pub(super) fn parse_quoted_text(input: &str) -> Result<Cow<'_, str>, ParseErrorKind> {
    Ok(match input.as_bytes()[0] {
        b'"' => {
            let mut s = strip_first_last(input);
            let mut buf = String::new();

            loop {
                let mut chars = s.chars();
                let char_len;
                match chars.next() {
                    Some('\\') => {
                        char_len = 1;
                        match chars.next() {
                            Some('\\') => {
                                buf.push('\\');
                                s = &s[1..];
                            }
                            Some('"') => {
                                buf.push('"');
                                s = &s[1..];
                            }
                            _ => {
                                return Err(ParseErrorKind::InvalidEscapeInStringAt(
                                    input.len() - s.len(),
                                ));
                            }
                        }
                    }
                    Some(c) => {
                        char_len = c.len_utf8();
                        buf.push(c);
                    }
                    None => break,
                }
                s = &s[char_len..];
            }
            Cow::Owned(buf)
        }
        _ => Cow::Borrowed(strip_first_last(input)),
    })
}

pub(super) fn strip_first_last(s: &str) -> &str {
    &s[1..s.len() - 1]
}

pub(super) fn parse_number(src: &str, radix: u8) -> Result<Vec<u8>, NumberError> {
    let mut digits = Vec::with_capacity(src.len());
    for c in src.bytes() {
        let n = match c {
            b'0'..=b'9' => c - b'0',
            b'a'..=b'z' => c - b'a' + 10,
            b'A'..=b'Z' => c - b'A' + 10,
            _ => return Err(NumberError::InvalidDigit),
        };
        if n >= radix {
            return Err(NumberError::InvalidDigit);
        }
        digits.push(n);
    }
    Ok(digits)
}

pub(super) fn has_leading_zero(s: &[u8]) -> bool {
    s.len() > 1 && matches!(s, [0, ..])
}