Use custom Arc backed input

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-06 12:40:02 +01:00
parent 1ea15f0e49
commit 1ee7611981
6 changed files with 283 additions and 77 deletions

View file

@ -31,9 +31,10 @@ use winnow::token::take_until;
use winnow::token::take_while;
use crate::SourceSpan;
use crate::input::TempleInput;
use crate::resume_after_cut;
type Input<'input> = Recoverable<LocatingSlice<&'input str>, ParseError>;
type Input<'input> = Recoverable<LocatingSlice<TempleInput>, ParseError>;
type PResult<'input, T> = Result<T, ParseError>;
#[derive(Debug)]
@ -177,12 +178,12 @@ impl<'input> ParserError<Input<'input>> for ParseError {
}
#[derive(Debug)]
pub struct ParsedTemplate<'input> {
tokens: Vec<TemplateToken<'input>>,
pub struct ParsedTemplate {
tokens: Vec<TemplateToken>,
}
impl<'input> ParsedTemplate<'input> {
pub fn tokens(&self) -> &[TemplateToken<'input>] {
impl ParsedTemplate {
pub fn tokens(&self) -> &[TemplateToken] {
&self.tokens
}
}
@ -198,88 +199,86 @@ pub enum TokenKind {
Invalid,
}
impl PartialEq<TokenKind> for TemplateToken<'_> {
impl PartialEq<TokenKind> for TemplateToken {
fn eq(&self, other: &TokenKind) -> bool {
self.kind == *other
}
}
impl winnow::stream::ContainsToken<&'_ TemplateToken<'_>> for TokenKind {
fn contains_token(&self, token: &'_ TemplateToken<'_>) -> bool {
impl winnow::stream::ContainsToken<&'_ TemplateToken> for TokenKind {
fn contains_token(&self, token: &'_ TemplateToken) -> bool {
*self == token.kind
}
}
impl winnow::stream::ContainsToken<&'_ TemplateToken<'_>> for &'_ [TokenKind] {
fn contains_token(&self, token: &'_ TemplateToken<'_>) -> bool {
impl winnow::stream::ContainsToken<&'_ TemplateToken> for &'_ [TokenKind] {
fn contains_token(&self, token: &'_ TemplateToken) -> bool {
self.contains(&token.kind)
}
}
impl<const LEN: usize> winnow::stream::ContainsToken<&'_ TemplateToken<'_>>
for &'_ [TokenKind; LEN]
{
fn contains_token(&self, token: &'_ TemplateToken<'_>) -> bool {
impl<const LEN: usize> winnow::stream::ContainsToken<&'_ TemplateToken> for &'_ [TokenKind; LEN] {
fn contains_token(&self, token: &'_ TemplateToken) -> bool {
self.contains(&token.kind)
}
}
impl<const LEN: usize> winnow::stream::ContainsToken<&'_ TemplateToken<'_>> for [TokenKind; LEN] {
fn contains_token(&self, token: &'_ TemplateToken<'_>) -> bool {
impl<const LEN: usize> winnow::stream::ContainsToken<&'_ TemplateToken> for [TokenKind; LEN] {
fn contains_token(&self, token: &'_ TemplateToken) -> bool {
self.contains(&token.kind)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TemplateToken<'input> {
pub struct TemplateToken {
kind: TokenKind,
source: &'input str,
source: TempleInput,
}
impl<'input> TemplateToken<'input> {
fn content(source: &'input str) -> Self {
impl TemplateToken {
fn content(source: TempleInput) -> Self {
TemplateToken {
kind: TokenKind::Content,
source,
}
}
fn left_delim(source: &'input str) -> Self {
fn left_delim(source: TempleInput) -> Self {
TemplateToken {
kind: TokenKind::LeftDelim,
source,
}
}
fn right_delim(source: &'input str) -> Self {
fn right_delim(source: TempleInput) -> Self {
TemplateToken {
kind: TokenKind::RightDelim,
source,
}
}
fn wants_output(source: &'input str) -> Self {
fn wants_output(source: TempleInput) -> Self {
TemplateToken {
kind: TokenKind::WantsOutput,
source,
}
}
fn ident(source: &'input str) -> Self {
fn ident(source: TempleInput) -> Self {
TemplateToken {
kind: TokenKind::Ident,
source,
}
}
fn whitespace(source: &'input str) -> Self {
fn whitespace(source: TempleInput) -> Self {
TemplateToken {
kind: TokenKind::Whitespace,
source,
}
}
fn invalid(source: &'input str) -> Self {
fn invalid(source: TempleInput) -> Self {
TemplateToken {
kind: TokenKind::Invalid,
source,
@ -290,13 +289,14 @@ impl<'input> TemplateToken<'input> {
self.kind
}
pub fn source(&self) -> &'input str {
self.source
pub fn source(&self) -> TempleInput {
self.source.clone()
}
}
pub fn parse(input: &str) -> Result<ParsedTemplate<'_>, ParseFailure> {
let (_remaining, val, errors) = parse_tokens.recoverable_parse(LocatingSlice::new(input));
pub fn parse(input: &str) -> Result<ParsedTemplate, ParseFailure> {
let (_remaining, val, errors) =
parse_tokens.recoverable_parse(LocatingSlice::new(TempleInput::from(input)));
if errors.is_empty()
&& let Some(val) = val
@ -307,13 +307,13 @@ pub fn parse(input: &str) -> Result<ParsedTemplate<'_>, ParseFailure> {
}
}
fn parse_tokens<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken<'input>>> {
fn parse_tokens<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken>> {
repeat_till(0.., alt((parse_interpolate, parse_content)), eof)
.map(|(v, _): (Vec<_>, _)| v.into_iter().flatten().collect())
.parse_next(input)
}
fn parse_content<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken<'input>>> {
fn parse_content<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken>> {
alt((
repeat_till(1.., any, peek((multispace0, "{{"))).map(|((), _)| ()),
rest.void(),
@ -324,9 +324,7 @@ fn parse_content<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<Templ
.parse_next(input)
}
fn parse_interpolate<'input>(
input: &mut Input<'input>,
) -> PResult<'input, Vec<TemplateToken<'input>>> {
fn parse_interpolate<'input>(input: &mut Input<'input>) -> PResult<'input, Vec<TemplateToken>> {
let prev_whitespace = opt(parse_whitespace).parse_next(input)?;
let left_delim = "{{".map(TemplateToken::left_delim).parse_next(input)?;
let wants_output = opt("=".map(TemplateToken::wants_output)).parse_next(input)?;
@ -337,7 +335,9 @@ fn parse_interpolate<'input>(
let (inside_tokens, _): (Vec<_>, _) = get_tokens
.resume_after(recover)
.with_taken()
.map(|(val, taken)| val.unwrap_or_else(|| (vec![TemplateToken::invalid(taken)], "")))
.map(|(val, taken)| {
val.unwrap_or_else(|| (vec![TemplateToken::invalid(taken)], TempleInput::from("")))
})
.parse_next(input)?;
let right_delim = "}}".map(TemplateToken::right_delim).parse_next(input)?;
@ -354,9 +354,7 @@ fn parse_interpolate<'input>(
Ok(tokens)
}
fn parse_interpolate_token<'input>(
input: &mut Input<'input>,
) -> PResult<'input, TemplateToken<'input>> {
fn parse_interpolate_token<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace(
"parse_interpolate_token",
alt((parse_ident, parse_whitespace)),
@ -364,7 +362,7 @@ fn parse_interpolate_token<'input>(
.parse_next(input)
}
fn parse_whitespace<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken<'input>> {
fn parse_whitespace<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
trace(
"parse_whitespace",
multispace1.map(TemplateToken::whitespace),
@ -372,7 +370,7 @@ fn parse_whitespace<'input>(input: &mut Input<'input>) -> PResult<'input, Templa
.parse_next(input)
}
fn parse_ident<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken<'input>> {
fn parse_ident<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateToken> {
resume_after_cut(
terminated(
ident.map(TemplateToken::ident),
@ -390,7 +388,7 @@ fn parse_ident<'input>(input: &mut Input<'input>) -> PResult<'input, TemplateTok
.parse_next(input)
}
fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, &'input str> {
fn ident<'input>(input: &mut Input<'input>) -> PResult<'input, TempleInput> {
take_while(1.., char::is_alphanumeric).parse_next(input)
}