use crate::{
decoder::Decode,
errors::ParseResult,
numbers::NumberParser,
parse_from_string,
parsers::datetime::parse_date_time,
parsers::json::JSONParser,
parsers::{datetime::DateTime, json::JSON, keyword::KeywordParser},
strings::{StringEncoder, StringParser, StringStandard},
ParserCore,
};
pub struct Tools {
pub number_parser: NumberParser,
pub string_parser: StringParser,
pub string_encoder: StringEncoder,
pub keyword_parser: KeywordParser,
}
impl Tools {
pub fn new() -> Self {
Tools {
number_parser: NumberParser::new(),
string_parser: StringParser::new(),
string_encoder: StringEncoder::new(),
keyword_parser: KeywordParser::new(),
}
}
pub fn set_string_standard(&mut self, std: StringStandard) -> &mut Self {
self.string_parser.set(std);
self.string_encoder.set(std);
self
}
pub fn parse_string(&self, body: &str) -> ParseResult<String> {
self.string_parser.parse_string(body)
}
pub fn encode_string(&self, body: &str) -> String {
self.string_encoder.encode(body)
}
pub fn parse_i128(&self, body: &str) -> ParseResult<i128> {
let decoder = Decode::from_string(body);
let mut parser = ParserCore::new("", decoder);
self.number_parser.parse_i128(&mut parser)
}
pub fn parse_u128(&self, body: &str) -> ParseResult<u128> {
let decoder = Decode::from_string(body);
let mut parser = ParserCore::new("", decoder);
self.number_parser.parse_u128(&mut parser)
}
pub fn parse_f64(&self, body: &str) -> ParseResult<f64> {
let decoder = Decode::from_string(body);
let mut parser = ParserCore::new("", decoder);
self.number_parser.parse_f64(&mut parser)
}
pub fn parse_keyword(&self, body: &str) -> ParseResult<String> {
let decoder = Decode::from_string(body);
let mut parser = ParserCore::new("", decoder);
self.keyword_parser.parse(&mut parser)
}
pub fn parse_date_time(&self, body: &str) -> ParseResult<Option<DateTime>> {
let mut parser = parse_from_string(body);
parse_date_time(&mut parser)
}
pub fn parse_json(&self, body: &str) -> ParseResult<JSON> {
let mut parser = parse_from_string(body);
JSONParser::new().parse_value_ws(&mut parser)
}
}
impl Default for Tools {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use crate::strings::EncodingStandard;
use crate::strings::StringStandard;
use crate::Tools;
#[test]
fn set_string_standard_test() {
let mut tools = Tools::new();
tools.set_string_standard(StringStandard::C);
assert_eq!(
tools
.parse_string("V\\xf6llerei l\\xe4sst gr\\xfc\\xdfen.")
.unwrap(),
"Völlerei lässt grüßen."
);
assert_eq!(tools.parse_string("\\?").unwrap(), "?");
tools.set_string_standard(StringStandard::Python);
assert_eq!(tools.parse_string("\\?").unwrap(), "\\?");
tools.set_string_standard(StringStandard::JSON);
assert!(tools.parse_string("\\?").is_err());
tools.set_string_standard(StringStandard::JSON);
assert_eq!(tools.parse_string("\\u01da").unwrap(), "ǚ");
assert!(tools.parse_string("\\u{1da}").is_err());
tools.set_string_standard(StringStandard::Rust);
assert_eq!(tools.parse_string("\\u{1da}").unwrap(), "ǚ");
assert!(tools.parse_string("\\u01da").is_err());
}
#[test]
fn encode_decode_string_test() {
let mut tools = Tools::new();
let encodeme = "Völlerei lässt grüßen.\n\
床前明月光,\n\
疑是地上霜。\n\
举头望明月,\n\
低头思故乡。\n\
“Thoughts in the Silent Night”, by Li Bai\n\
﷽\n\
😃";
tools.set_string_standard(StringStandard::C);
tools.string_encoder.encoding_standard = EncodingStandard::ASCII;
let result = tools.encode_string(encodeme);
#[cfg(not(feature = "uppercase_hex"))]
assert_eq!(
&result,
"V\\u00f6llerei l\\u00e4sst gr\\u00fc\\u00dfen.\\n\
\\u5e8a\\u524d\\u660e\\u6708\\u5149\\uff0c\\n\
\\u7591\\u662f\\u5730\\u4e0a\\u971c\\u3002\\n\
\\u4e3e\\u5934\\u671b\\u660e\\u6708\\uff0c\\n\
\\u4f4e\\u5934\\u601d\\u6545\\u4e61\\u3002\\n\
\\u201cThoughts in the Silent Night\\u201d, by Li Bai\\n\
\\ufdfd\\n\
\\U0001f603"
);
#[cfg(feature = "uppercase_hex")]
assert_eq!(
&result,
&"V\\u00F6llerei l\\u00E4sst gr\\u00FC\\u00DFen.\\n\
\\u5E8A\\u524D\\u660E\\u6708\\u5149\\uFF0C\\n\
\\u7591\\u662F\\u5730\\u4E0A\\u971C\\u3002\\n\
\\u4E3E\\u5934\\u671B\\u660E\\u6708\\uFF0C\\n\
\\u4F4E\\u5934\\u601D\\u6545\\u4E61\\u3002\\n\
\\u201CThoughts in the Silent Night\\u201D, by Li Bai\\n\
\\uFDFD\\n\
\\U0001F603"
);
assert_eq!(tools.parse_string(&result).unwrap(), encodeme);
tools.set_string_standard(StringStandard::JSON);
tools.string_encoder.encoding_standard = EncodingStandard::ASCII;
let result = tools.encode_string(encodeme);
#[cfg(not(feature = "uppercase_hex"))]
assert_eq!(
&result,
"V\\u00f6llerei l\\u00e4sst gr\\u00fc\\u00dfen.\\n\
\\u5e8a\\u524d\\u660e\\u6708\\u5149\\uff0c\\n\
\\u7591\\u662f\\u5730\\u4e0a\\u971c\\u3002\\n\
\\u4e3e\\u5934\\u671b\\u660e\\u6708\\uff0c\\n\
\\u4f4e\\u5934\\u601d\\u6545\\u4e61\\u3002\\n\
\\u201cThoughts in the Silent Night\\u201d, by Li Bai\\n\
\\ufdfd\\n\
\\ud83d\\ude03"
);
#[cfg(feature = "uppercase_hex")]
assert_eq!(
&result,
"V\\u00F6llerei l\\u00E4sst gr\\u00FC\\u00DFen.\\n\
\\u5E8A\\u524D\\u660E\\u6708\\u5149\\uFF0C\\n\
\\u7591\\u662F\\u5730\\u4E0A\\u971C\\u3002\\n\
\\u4E3E\\u5934\\u671B\\u660E\\u6708\\uFF0C\\n\
\\u4F4E\\u5934\\u601D\\u6545\\u4E61\\u3002\\n\
\\u201CThoughts in the Silent Night\\u201D, by Li Bai\\n\
\\uFDFD\\n\
\\uD83D\\uDE03"
);
assert_eq!(tools.parse_string(&result).unwrap(), encodeme);
tools.set_string_standard(StringStandard::Rust);
tools.string_encoder.encoding_standard = EncodingStandard::ASCII;
let result = tools.encode_string(encodeme);
#[cfg(not(feature = "uppercase_hex"))]
assert_eq!(
&result,
"V\\u{0000f6}llerei l\\u{0000e4}sst gr\\u{0000fc}\\u{0000df}en.\\n\\u{005e8a}\
\\u{00524d}\\u{00660e}\\u{006708}\\u{005149}\\u{00ff0c}\\n\\u{007591}\
\\u{00662f}\\u{005730}\\u{004e0a}\\u{00971c}\\u{003002}\\n\\u{004e3e}\
\\u{005934}\\u{00671b}\\u{00660e}\\u{006708}\\u{00ff0c}\\n\\u{004f4e}\
\\u{005934}\\u{00601d}\\u{006545}\\u{004e61}\\u{003002}\\n\\u{00201c}\
Thoughts in the Silent Night\\u{00201d}, by Li Bai\\n\\u{00fdfd}\\n\\u{01f603}"
);
#[cfg(feature = "uppercase_hex")]
assert_eq!(
&result,
"V\\u{0000F6}llerei l\\u{0000E4}sst gr\\u{0000FC}\\u{0000DF}en.\\n\\u{005E8A}\
\\u{00524D}\\u{00660E}\\u{006708}\\u{005149}\\u{00FF0C}\\n\\u{007591}\
\\u{00662F}\\u{005730}\\u{004E0A}\\u{00971C}\\u{003002}\\n\\u{004E3E}\
\\u{005934}\\u{00671B}\\u{00660E}\\u{006708}\\u{00FF0C}\\n\\u{004F4E}\
\\u{005934}\\u{00601D}\\u{006545}\\u{004E61}\\u{003002}\\n\\u{00201C}\
Thoughts in the Silent Night\\u{00201D}, by Li Bai\\n\\u{00FDFD}\\n\\u{01F603}"
);
assert_eq!(tools.parse_string(&result).unwrap(), encodeme);
tools.set_string_standard(StringStandard::Python);
tools.string_encoder.encoding_standard = EncodingStandard::ASCII;
let result = tools.encode_string(encodeme);
#[cfg(not(feature = "uppercase_hex"))]
assert_eq!(
&result,
"V\\u00f6llerei l\\u00e4sst gr\\u00fc\\u00dfen.\\n\
\\u5e8a\\u524d\\u660e\\u6708\\u5149\\uff0c\\n\
\\u7591\\u662f\\u5730\\u4e0a\\u971c\\u3002\\n\
\\u4e3e\\u5934\\u671b\\u660e\\u6708\\uff0c\\n\
\\u4f4e\\u5934\\u601d\\u6545\\u4e61\\u3002\\n\
\\u201cThoughts in the Silent Night\\u201d, by Li Bai\\n\
\\ufdfd\\n\
\\U0001f603"
);
#[cfg(feature = "uppercase_hex")]
assert_eq!(
&result,
"V\\u00F6llerei l\\u00E4sst gr\\u00FC\\u00DFen.\\n\
\\u5E8A\\u524D\\u660E\\u6708\\u5149\\uFF0C\\n\
\\u7591\\u662F\\u5730\\u4E0A\\u971C\\u3002\\n\
\\u4E3E\\u5934\\u671B\\u660E\\u6708\\uFF0C\\n\
\\u4F4E\\u5934\\u601D\\u6545\\u4E61\\u3002\\n\
\\u201CThoughts in the Silent Night\\u201D, by Li Bai\\n\
\\uFDFD\\n\
\\U0001F603"
);
assert_eq!(tools.parse_string(&result).unwrap(), encodeme);
tools.set_string_standard(StringStandard::Trivet);
tools.string_encoder.encoding_standard = EncodingStandard::ASCII;
let result = tools.encode_string(encodeme);
#[cfg(not(feature = "uppercase_hex"))]
assert_eq!(
&result,
"V\\u{0000f6}llerei l\\u{0000e4}sst gr\\u{0000fc}\\u{0000df}en.\\n\\u{005e8a}\
\\u{00524d}\\u{00660e}\\u{006708}\\u{005149}\\u{00ff0c}\\n\\u{007591}\
\\u{00662f}\\u{005730}\\u{004e0a}\\u{00971c}\\u{003002}\\n\\u{004e3e}\
\\u{005934}\\u{00671b}\\u{00660e}\\u{006708}\\u{00ff0c}\\n\\u{004f4e}\
\\u{005934}\\u{00601d}\\u{006545}\\u{004e61}\\u{003002}\\n\\u{00201c}\
Thoughts in the Silent Night\\u{00201d}, by Li Bai\\n\\u{00fdfd}\\n\\u{01f603}"
);
#[cfg(feature = "uppercase_hex")]
assert_eq!(
&result,
"V\\u{0000F6}llerei l\\u{0000E4}sst gr\\u{0000FC}\\u{0000DF}en.\\n\\u{005E8A}\
\\u{00524D}\\u{00660E}\\u{006708}\\u{005149}\\u{00FF0C}\\n\\u{007591}\
\\u{00662F}\\u{005730}\\u{004E0A}\\u{00971C}\\u{003002}\\n\\u{004E3E}\
\\u{005934}\\u{00671B}\\u{00660E}\\u{006708}\\u{00FF0C}\\n\\u{004F4E}\
\\u{005934}\\u{00601D}\\u{006545}\\u{004E61}\\u{003002}\\n\\u{00201C}\
Thoughts in the Silent Night\\u{00201D}, by Li Bai\\n\\u{00FDFD}\\n\\u{01F603}"
);
assert_eq!(tools.parse_string(&result).unwrap(), encodeme);
}
#[test]
fn date_time_test() {
let tools = Tools::new();
let examples = [
(
"2014-02-26 14:21:04.001+01:00",
"2014-02-26T14:21:04.001+01:00",
),
(
"2014-02-26 14:21:04.000001+01:00",
"2014-02-26T14:21:04.000001+01:00",
),
(
"2014-02-26 14:21:04.000000001+01:00",
"2014-02-26T14:21:04.000000001+01:00",
),
(
"2014-02-26 14:21:04.0000000005+01:00",
"2014-02-26T14:21:04.000000001+01:00",
),
(
"2014-02-26 14:21:04.0000000004+01:00",
"2014-02-26T14:21:04.000000000+01:00",
),
(
"2014-02-26 14:21:04.001+01:30",
"2014-02-26T14:21:04.001+01:30",
),
("2014-02-26 14:21:04.001Z", "2014-02-26T14:21:04.001Z"),
("2014-02-26 14:21:04+01:00", "2014-02-26T14:21:04+01:00"),
("2014-02-26 14:21:04+01:30", "2014-02-26T14:21:04+01:30"),
("2014-02-26 14:21:04Z", "2014-02-26T14:21:04Z"),
("2014-02-26 14:21+01:00", "2014-02-26T14:21:00+01:00"),
("2014-02-26 14:21+01:30", "2014-02-26T14:21:00+01:30"),
("2014-02-26 14:21Z", "2014-02-26T14:21:00Z"),
("2014-02-26 14:21", "2014-02-26T14:21:00"),
("2014-02-26", "2014-02-26"),
("14:21:04.001+01:00", "14:21:04.001+01:00"),
("14:21:04.000001+01:00", "14:21:04.000001+01:00"),
("14:21:04.000000001+01:00", "14:21:04.000000001+01:00"),
("14:21:04.0000000005+01:00", "14:21:04.000000001+01:00"),
("14:21:04.0000000004+01:00", "14:21:04.000000000+01:00"),
("14:21:04.001+01:30", "14:21:04.001+01:30"),
("14:21:04.001Z", "14:21:04.001Z"),
("14:21:04+01:00", "14:21:04+01:00"),
("14:21:04+01:30", "14:21:04+01:30"),
("14:21:04Z", "14:21:04Z"),
("14:21+01:00", "14:21:00+01:00"),
("14:21+01:30", "14:21:00+01:30"),
("14:21Z", "14:21:00Z"),
("14:21", "14:21:00"),
];
for (in_str, out_str) in examples {
let when = tools.parse_date_time(in_str);
assert_eq!(when.unwrap().unwrap().to_string(), out_str);
}
}
#[test]
fn keywords_test() {
let tools = Tools::new();
assert_eq!(
tools.parse_keyword("__FIRST_Execution_Flag").unwrap(),
"__FIRST_Execution_Flag"
);
}
#[test]
fn json_test() {
let tools = Tools::new();
assert_eq!(
tools.parse_json(r#"
{ "keymaster" :
[
"Rick Moranis", "Mark Bryan Wilson", "Tim Lawrence", "Paul Rudd"
]
}
"#).unwrap().to_string(),
"{\n \"keymaster\": [\n \"Rick Moranis\",\n \"Mark Bryan Wilson\",\n \"Tim Lawrence\",\n \"Paul Rudd\"\n ]\n}"
);
}
}