From 41aa0349a07e63540bd50bcaf1c5731e123d809c Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 8 Oct 2023 16:06:52 -0400 Subject: [PATCH] Add tests for coalesce_whitespace_escaped. --- src/types/util.rs | 122 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 101 insertions(+), 21 deletions(-) diff --git a/src/types/util.rs b/src/types/util.rs index e8980ea..7eab912 100644 --- a/src/types/util.rs +++ b/src/types/util.rs @@ -314,9 +314,10 @@ fn impl_coalesce_whitespace_escaped<'s, C: Fn(char) -> bool>( ret, }, c, - ) if c == escape_character => { - CoalesceWhitespaceEscaped::RequiresMutationEscaping { ret } - } + ) if c == escape_character => CoalesceWhitespaceEscaped::RequiresMutationEscaping { + ret, + matched_escape_character: c, + }, ( CoalesceWhitespaceEscaped::RequiresMutation { mut in_whitespace, @@ -332,7 +333,7 @@ fn impl_coalesce_whitespace_escaped<'s, C: Fn(char) -> bool>( } ( CoalesceWhitespaceEscaped::RequiresMutation { - in_whitespace, + in_whitespace: _, mut ret, }, _, @@ -343,9 +344,13 @@ fn impl_coalesce_whitespace_escaped<'s, C: Fn(char) -> bool>( ret, } } - (CoalesceWhitespaceEscaped::RequiresMutationEscaping { mut ret }, c) - if escapable_characters(c) => - { + ( + CoalesceWhitespaceEscaped::RequiresMutationEscaping { + mut ret, + matched_escape_character: _, + }, + c, + ) if escapable_characters(c) => { ret.push(c); CoalesceWhitespaceEscaped::RequiresMutation { in_whitespace: false, @@ -353,7 +358,10 @@ fn impl_coalesce_whitespace_escaped<'s, C: Fn(char) -> bool>( } } ( - CoalesceWhitespaceEscaped::RequiresMutationEscaping { mut ret }, + CoalesceWhitespaceEscaped::RequiresMutationEscaping { + mut ret, + matched_escape_character: _, + }, ' ' | '\t' | '\r' | '\n', ) => { ret.push(' '); @@ -362,8 +370,14 @@ fn impl_coalesce_whitespace_escaped<'s, C: Fn(char) -> bool>( ret, } } - (CoalesceWhitespaceEscaped::RequiresMutationEscaping { mut ret }, c) => { - ret.push(escape_character); + ( + CoalesceWhitespaceEscaped::RequiresMutationEscaping { + mut ret, + matched_escape_character, + }, + c, + ) => { + ret.push(matched_escape_character); ret.push(c); // TODO CoalesceWhitespaceEscaped::RequiresMutation { @@ -373,19 +387,85 @@ fn impl_coalesce_whitespace_escaped<'s, C: Fn(char) -> bool>( } } } - // match state { - // CoalesceWhitespaceEscaped::Normal => Cow::Borrowed(input), - // CoalesceWhitespaceEscaped::RequiresMutation { - // in_whitespace: _, - // ret, - // } => Cow::Owned(ret), - // } - todo!() + match state { + CoalesceWhitespaceEscaped::Normal => Cow::Borrowed(input), + CoalesceWhitespaceEscaped::NormalEscaping { escape_offset: _ } => Cow::Borrowed(input), + CoalesceWhitespaceEscaped::RequiresMutation { + in_whitespace: _, + ret, + } => Cow::Owned(ret), + CoalesceWhitespaceEscaped::RequiresMutationEscaping { + mut ret, + matched_escape_character, + } => { + ret.push(matched_escape_character); + Cow::Owned(ret) + } + } } enum CoalesceWhitespaceEscaped { Normal, - NormalEscaping { escape_offset: usize }, - RequiresMutation { in_whitespace: bool, ret: String }, - RequiresMutationEscaping { ret: String }, + NormalEscaping { + escape_offset: usize, + }, + RequiresMutation { + in_whitespace: bool, + ret: String, + }, + RequiresMutationEscaping { + ret: String, + matched_escape_character: char, + }, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn coalesce_whitespace_escaped_default() -> Result<(), Box> { + let input = "foobarbaz"; + let output = coalesce_whitespace_escaped('&', |c| "".contains(c))(input); + assert_eq!(output, "foobarbaz"); + assert!(matches!(output, Cow::Borrowed(_))); + Ok(()) + } + + #[test] + fn coalesce_whitespace_escaped_whitespace_single() -> Result<(), Box> { + let input = "foo bar baz"; + let output = coalesce_whitespace_escaped('&', |c| "".contains(c))(input); + assert_eq!(output, "foo bar baz"); + // TODO: Technically this should be a Borrowed but to keep the code simple for now we are treating all whitespace as causing ownership. + assert!(matches!(output, Cow::Owned(_))); + Ok(()) + } + + #[test] + fn coalesce_whitespace_escaped_whitespace_double() -> Result<(), Box> { + let input = "foo bar baz"; + let output = coalesce_whitespace_escaped('&', |c| "".contains(c))(input); + assert_eq!(output, "foo bar baz"); + assert!(matches!(output, Cow::Owned(_))); + Ok(()) + } + + #[test] + fn coalesce_whitespace_escaped_escape_match() -> Result<(), Box> { + let input = "foo &bar baz"; + let output = coalesce_whitespace_escaped('&', |c| "b".contains(c))(input); + assert_eq!(output, "foo bar baz"); + assert!(matches!(output, Cow::Owned(_))); + Ok(()) + } + + #[test] + fn coalesce_whitespace_escaped_escape_mismatch() -> Result<(), Box> { + let input = "foo b&ar baz"; + let output = coalesce_whitespace_escaped('&', |c| "b".contains(c))(input); + assert_eq!(output, "foo b&ar baz"); + assert!(matches!(output, Cow::Owned(_))); + Ok(()) + } }