use crate::parse::sub_pattern::SubPatternDefinition;
use proc_macro2::Span;
use syn::{Pat, Result, spanned::Spanned};
#[derive(Clone)]
pub struct PatternDefinition {
pub sub_patterns: Vec<SubPatternDefinition>,
pub span: Span,
}
impl PatternDefinition {
pub fn parse(input: Pat) -> Result<Self> {
let span = input.span();
match input.clone() {
Pat::Tuple(tuple) => {
let sub_patterns = tuple
.elems
.into_iter()
.map(|p| SubPatternDefinition::parse(p))
.collect::<Result<Vec<SubPatternDefinition>>>()?;
if sub_patterns.len() > 0 {
Ok(PatternDefinition { sub_patterns, span })
} else {
Err(syn::Error::new_spanned(
input,
"Empty pattern is not allowed",
))
}
}
singleton => Ok(PatternDefinition {
sub_patterns: vec![SubPatternDefinition::parse(singleton)?],
span,
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use syn::{Pat, parse_quote};
#[test]
fn test_parse_single() {
let input: Pat = parse_quote!(MyStruct);
assert!(PatternDefinition::parse(input).is_ok());
}
#[test]
fn test_parse_tuple() {
let input: Pat = parse_quote!((MyStruct, MyStruct, MyStruct));
assert!(PatternDefinition::parse(input).is_ok());
}
#[test]
fn test_parse_invalid_tuple_fails() {
let input: Pat = parse_quote!((MyStruct, 42, MyStruct));
assert!(PatternDefinition::parse(input).is_err());
}
#[test]
fn test_parse_empty_tuple_fails() {
let input: Pat = parse_quote!(());
assert!(PatternDefinition::parse(input).is_err());
}
#[test]
fn test_parse_wildcard_fails() {
let input: Pat = parse_quote!(_);
assert!(PatternDefinition::parse(input).is_err());
}
#[test]
fn test_parse_slice_fails() {
let input: Pat = parse_quote!([a, b, c]);
assert!(PatternDefinition::parse(input).is_err());
}
}