use syn::{Pat, PatIdent, PatPath, PatStruct, PatTupleStruct, Result};
#[derive(Clone)]
pub enum SubPatternDefinition {
Ident(PatIdent),
Path(PatPath),
TupleStruct(PatTupleStruct),
Struct(PatStruct),
}
impl SubPatternDefinition {
pub fn parse(input: Pat) -> Result<Self> {
match input {
Pat::Ident(ident) => Ok(SubPatternDefinition::Ident(ident)),
Pat::Path(path) => Ok(SubPatternDefinition::Path(path)),
Pat::TupleStruct(tuple_struct) => Ok(SubPatternDefinition::TupleStruct(tuple_struct)),
Pat::Struct(struct_pat) => Ok(SubPatternDefinition::Struct(struct_pat)),
_ => Err(syn::Error::new_spanned(
input,
"Invalid construct in pattern",
)),
}
}
pub fn to_syn_pattern(&self) -> Pat {
match self {
SubPatternDefinition::Ident(ident) => Pat::Ident(ident.clone()),
SubPatternDefinition::Path(path) => Pat::Path(path.clone()),
SubPatternDefinition::TupleStruct(tuple_struct) => {
Pat::TupleStruct(tuple_struct.clone())
}
SubPatternDefinition::Struct(struct_pat) => Pat::Struct(struct_pat.clone()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::traits::SubPattern;
use syn::{Pat, parse_quote};
#[test]
fn test_parse_ident() {
let pat: Pat = parse_quote!(SomeIdent);
let result = SubPatternDefinition::parse(pat).unwrap();
assert!(matches!(result, SubPatternDefinition::Ident(_)));
}
#[test]
fn test_parse_path_simple() {
let pat: Pat = parse_quote!(some::SomeVariant);
let result = SubPatternDefinition::parse(pat).unwrap();
assert!(matches!(result, SubPatternDefinition::Path(_)));
}
#[test]
fn test_parse_tuple_struct() {
let pat: Pat = parse_quote!(SomeTuple(x, y));
let result = SubPatternDefinition::parse(pat).unwrap();
assert!(matches!(result, SubPatternDefinition::TupleStruct(_)));
}
#[test]
fn test_parse_struct() {
let pat: Pat = parse_quote!(SomeStruct { x, y });
let result = SubPatternDefinition::parse(pat).unwrap();
assert!(matches!(result, SubPatternDefinition::Struct(_)));
}
#[test]
fn test_parse_invalid() {
let pat: Pat = parse_quote!((a, b));
let result = SubPatternDefinition::parse(pat);
assert!(result.is_err());
}
fn parse_to_identifier(pat: Pat) -> String {
SubPatternDefinition::parse(pat)
.unwrap()
.get_identifier()
.to_string()
}
#[test]
fn test_identifier_equality_across_paths() {
let pat1: Pat = parse_quote!(Variant);
let pat2: Pat = parse_quote!(MyEnum::Variant);
let pat3: Pat = parse_quote!(path::to::MyEnum::Variant);
assert_eq!("Variant", parse_to_identifier(pat1));
assert_eq!("Variant", parse_to_identifier(pat2));
assert_eq!("Variant", parse_to_identifier(pat3));
}
#[test]
fn test_identifier_equality_across_tuple_struct_paths() {
let pat1: Pat = parse_quote!(TupleVariant(_, _));
let pat2: Pat = parse_quote!(MyEnum::TupleVariant(_, _));
let pat3: Pat = parse_quote!(path::to::MyEnum::TupleVariant(_, _));
assert_eq!("TupleVariant", parse_to_identifier(pat1));
assert_eq!("TupleVariant", parse_to_identifier(pat2));
assert_eq!("TupleVariant", parse_to_identifier(pat3));
}
}