use tyrx::{TyRx, RegexPattern, FromMatch, ErasedLifetime, Result};
use tyrx::{builder, util::Spanned};
#[test]
fn complex_nested_types_and_attributes() -> Result<()> {
#[derive(Clone, Debug, PartialEq, Eq, RegexPattern, FromMatch, ErasedLifetime)]
struct Foo<'lt> {
#[tyrx(pattern = r"(?<Foo.bar>[a-zA-Z_]+)\s+")]
bar: &'lt str,
#[tyrx(rename = qux, pattern = format_args!(r"(?<Foo.qux>[{}\.]+)", builder::CharRange::<'0', '9'>::pattern_display()))]
baz: String,
}
#[derive(Clone, Debug, PartialEq, RegexPattern, FromMatch, ErasedLifetime)]
#[tyrx(lifetime = 'x)]
enum Choices<'x> {
First,
Second(Foo<'x>),
Third {
#[tyrx(pattern = format_args!("(?<Choices.Third.field>{}+)", builder::CharClass::<builder::AsciiAlpha>::pattern_display()))]
field: Spanned<String>,
#[tyrx(pattern = format_args!("(?<Choices.Third.space>{}+)", builder::CharClass::<builder::AsciiBlank>::pattern_display()))]
space: builder::Ignore<f64>, #[tyrx(rename = r#impl)]
other_field: i64,
},
}
let s = String::from(r#"
First
abdefxqz -876
__ 137.036
"#);
let results: Vec<_> = Spanned::<Choices<'_>>::iter_from_str(s.as_str()).collect::<Result<_>>()?;
assert_eq!(results, [
Spanned::new(Choices::First, 9..14),
Spanned::new(Choices::Third {
field: Spanned::new(String::from("abdefxqz"), 23..31),
space: Default::default(),
other_field: -876,
}, 23..36),
Spanned::new(Choices::Second(Foo {
bar: "__",
baz: String::from("137.036"),
}), 45..55),
]);
Ok(())
}
#[test]
fn option_from_match() -> Result<()> {
#[derive(Clone, PartialEq, Debug, RegexPattern, FromMatch, ErasedLifetime)]
struct Compound {
begin: builder::LineStart,
id: builder::Any1<builder::CharClass<builder::AsciiAlnum>, String>,
sep: builder::Char<':'>,
value: Option<f32>,
end: builder::LineEnd,
}
let opt_no_match: Option<i16> = TyRx::from_str("nope")?;
assert_eq!(opt_no_match, None);
let opt_empty: Option<i16> = TyRx::from_str("")?;
assert_eq!(opt_empty, None);
let opt_some: Option<i16> = TyRx::from_str("+3907")?;
assert_eq!(opt_some, Some(3907));
let compound_some = Compound::from_str("someident98:496.875")?;
assert_eq!(compound_some.id.value(), "someident98");
assert_eq!(compound_some.value, Some(496.875));
let compound_none = Compound::from_str("123otherident:")?;
assert_eq!(compound_none.id.value(), "123otherident");
assert_eq!(compound_none.value, None);
Ok(())
}
#[test]
fn derive_regex_pattern_flags() {
#[derive(Clone, Debug, RegexPattern)]
struct NoFlags;
#[derive(Clone, Debug, RegexPattern)]
#[tyrx(flag(case_insensitive))]
struct CaseInsensitive;
#[derive(Clone, Debug, RegexPattern)]
#[tyrx(flag(unicode = false))]
struct NoUnicode;
#[derive(Clone, Debug, RegexPattern)]
#[tyrx(flag(ignore_whitespace = true, dot_matches_new_line = false, unicode, crlf = true, swap_greed = false))]
struct ManyFlags;
#[derive(Clone, Copy, PartialEq, Eq, Debug, RegexPattern, FromMatch, ErasedLifetime)]
#[tyrx(flag(multi_line, case_insensitive = true))]
enum ManyVariants {
NoFlags,
#[tyrx(flag(swap_greed))]
SwapGreed,
#[tyrx(flag(ignore_whitespace = false))]
NoIgnoreWhitespace,
#[tyrx(flag(ignore_whitespace = false, swap_greed = true, crlf, unicode = false))]
ManyFlags,
}
assert_eq!(NoFlags::pattern_display().to_string(), "");
assert_eq!(CaseInsensitive::pattern_display().to_string(), "(?i:)");
assert_eq!(NoUnicode::pattern_display().to_string(), "(?-u:)");
assert_eq!(ManyFlags::pattern_display().to_string(), "(?Rux-sU:)");
assert_eq!(
ManyVariants::pattern_display().to_string(),
"(?im:(?<ManyVariants.NoFlags>NoFlags)|(?U:(?<ManyVariants.SwapGreed>SwapGreed))|(?-x:(?<ManyVariants.NoIgnoreWhitespace>NoIgnoreWhitespace))|(?RU-ux:(?<ManyVariants.ManyFlags>ManyFlags)))",
);
let enums: Vec<_> = ManyVariants::iter_from_str("SwapGreed NoIgnoreWhitespace manyflags noFlAGs")
.collect::<Result<_>>()
.unwrap();
assert_eq!(enums, [
ManyVariants::SwapGreed,
ManyVariants::NoIgnoreWhitespace,
ManyVariants::ManyFlags,
ManyVariants::NoFlags,
]);
}
#[test]
fn top_level_type_renaming() -> Result<()> {
#[derive(Clone, PartialEq, Eq, Debug, RegexPattern, FromMatch, ErasedLifetime)]
#[tyrx(rename = ChangedTheName)]
struct Renamed {
field: u16,
#[tyrx(rename = not_that_field)]
other: String,
}
#[derive(Clone, PartialEq, Debug, RegexPattern, FromMatch, ErasedLifetime)]
#[tyrx(rename = AlternateTy)]
enum FewVariants {
Var {
one: i32,
#[tyrx(rename = sep)]
comma: builder::Char<','>,
two: u64
},
#[tyrx(rename = Second)]
Renamed(bool),
}
assert_eq!(
Renamed::pattern_display().to_string(),
r"(?<ChangedTheName.field>\+?[0-9]+)(?<ChangedTheName.not_that_field>.*)",
);
assert_eq!(
Renamed::from_str("01683 other stuff")?,
Renamed {
field: 1683,
other: String::from(" other stuff"),
},
);
assert_eq!(
FewVariants::pattern_display().to_string(),
r"(?<AlternateTy.Var>(?<AlternateTy.Var.one>[-\+]?[0-9]+)(?<AlternateTy.Var.sep>,)(?<AlternateTy.Var.two>\+?[0-9]+))|(?<AlternateTy.Second>(?<AlternateTy.Second.0>false|true))",
);
assert_eq!(
FewVariants::from_str("-47,+19919911")?,
FewVariants::Var {
one: -47,
comma: Default::default(),
two: 19919911,
},
);
assert_eq!(
Spanned::<FewVariants>::iter_from_str("a true statement, a false impression").collect::<Result<Vec<_>>>()?,
[
Spanned::new(FewVariants::Renamed(true), 2..6),
Spanned::new(FewVariants::Renamed(false), 20..25),
],
);
Ok(())
}