use crate::parser::Stream;
use crate::parser::parts::txn_meta_location::parse_meta_location;
use crate::parser::parts::txn_meta_tags::parse_meta_tags;
use crate::parser::parts::txn_meta_uuid::parse_meta_uuid;
use tackler_api::location::GeoPoint;
use tackler_api::txn_header::Tags;
use uuid::Uuid;
use winnow::combinator::{alt, opt};
use winnow::{ModalResult, Parser, seq};
pub(crate) struct TxnMeta {
pub(crate) uuid: Option<Uuid>,
pub(crate) tags: Option<Tags>,
pub(crate) location: Option<GeoPoint>,
}
fn permutation_uuid(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = parse_meta_uuid.parse_next(is)?;
Ok(TxnMeta {
uuid: Some(m),
tags: None,
location: None,
})
}
fn permutation_uuid_tags_o_location(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = seq!(parse_meta_uuid, parse_meta_tags, opt(parse_meta_location)).parse_next(is)?;
Ok(TxnMeta {
uuid: Some(m.0),
tags: Some(m.1),
location: m.2,
})
}
fn permutation_uuid_location_o_tags(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = seq!(parse_meta_uuid, parse_meta_location, opt(parse_meta_tags),).parse_next(is)?;
Ok(TxnMeta {
uuid: Some(m.0),
tags: m.2,
location: Some(m.1),
})
}
fn permutation_tags(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = parse_meta_tags.parse_next(is)?;
Ok(TxnMeta {
uuid: None,
tags: Some(m),
location: None,
})
}
fn permutation_tags_uuid_o_location(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = seq!(parse_meta_tags, parse_meta_uuid, opt(parse_meta_location)).parse_next(is)?;
Ok(TxnMeta {
uuid: Some(m.1),
tags: Some(m.0),
location: m.2,
})
}
fn permutation_tags_location_o_uuid(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = seq!(parse_meta_tags, parse_meta_location, opt(parse_meta_uuid),).parse_next(is)?;
Ok(TxnMeta {
uuid: m.2,
tags: Some(m.0),
location: Some(m.1),
})
}
fn permutation_location(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = parse_meta_location.parse_next(is)?;
Ok(TxnMeta {
uuid: None,
tags: None,
location: Some(m),
})
}
fn permutation_location_uuid_o_tags(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = seq!(parse_meta_location, parse_meta_uuid, opt(parse_meta_tags)).parse_next(is)?;
Ok(TxnMeta {
uuid: Some(m.1),
tags: m.2,
location: Some(m.0),
})
}
fn permutation_location_tags_o_uuid(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let m = seq!(parse_meta_location, parse_meta_tags, opt(parse_meta_uuid),).parse_next(is)?;
Ok(TxnMeta {
uuid: m.2,
tags: Some(m.1),
location: Some(m.0),
})
}
pub(crate) fn parse_txn_meta(is: &mut Stream<'_>) -> ModalResult<TxnMeta> {
let meta = alt((
permutation_uuid_tags_o_location,
permutation_uuid_location_o_tags,
permutation_uuid,
permutation_tags_uuid_o_location,
permutation_tags_location_o_uuid,
permutation_tags,
permutation_location_uuid_o_tags,
permutation_location_tags_o_uuid,
permutation_location,
))
.parse_next(is)?;
Ok(meta)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::kernel::Settings;
use indoc::indoc;
use tackler_rs::IndocUtils;
struct MetaResult {
uuid: bool,
geo: bool,
tags: bool,
}
#[test]
fn test_parse_txn_meta() {
#[rustfmt::skip]
let pok_meta = vec![
(indoc!(
"| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
|"
).strip_margin(),
MetaResult { uuid: true, geo: false, tags: false,}),
(indoc!(
"| # location: geo:1.111,2.222,3.333
|"
).strip_margin(),
MetaResult { uuid: false, geo: true, tags: false,}),
(indoc!(
"| # tags: cef, first, second
|"
).strip_margin(),
MetaResult { uuid: false, geo: false, tags: true,}),
(indoc!(
"| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
| # location: geo:1.111,2.222,3.333
|"
).strip_margin(),
MetaResult { uuid: true, geo: true, tags: false,}),
(indoc!(
"| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
| # tags: cef, first, second
|"
).strip_margin(),
MetaResult { uuid: true, geo: false, tags: true,}),
(indoc!(
"| # location: geo:1.111,2.222,3.333
| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
|"
).strip_margin(),
MetaResult { uuid: true, geo: true, tags: false,}),
(indoc!(
"| # location: geo:1.111,2.222,3.333
| # tags: cef, first, second
|"
).strip_margin(),
MetaResult { uuid: false, geo: true, tags: true,}),
(indoc!(
"| # tags: cef, first, second
| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
|"
).strip_margin(),
MetaResult { uuid: true, geo: false, tags: true,}),
(indoc!(
"| # tags: cef, first, second
| # location: geo:1.111,2.222,3.333
|"
).strip_margin(),
MetaResult { uuid: false, geo: true, tags: true,}),
(indoc!(
"| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
| # location: geo:1.111,2.222,3.333
| # tags: cef, first, second
|"
).strip_margin(),
MetaResult { uuid: true, geo: true, tags: true,}),
(indoc!(
"| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
| # tags: cef, first, second
| # location: geo:1.111,2.222,3.333
|"
).strip_margin(),
MetaResult { uuid: true, geo: true, tags: true,}),
(indoc!(
"| # location: geo:1.111,2.222,3.333
| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
| # tags: cef, first, second
|"
).strip_margin(),
MetaResult { uuid: true, geo: true, tags: true,}),
(indoc!(
"| # location: geo:1.111,2.222,3.333
| # tags: cef, first, second
| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
|"
).strip_margin(),
MetaResult { uuid: true, geo: true, tags: true,}),
(indoc!(
"| # tags: cef, first, second
| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
| # location: geo:1.111,2.222,3.333
|"
).strip_margin(),
MetaResult { uuid: true, geo: true, tags: true,}),
(indoc!(
"| # tags: cef, first, second
| # location: geo:1.111,2.222,3.333
| # uuid: 506a2d55-2375-4d51-af3a-cf5021f04de9
|"
).strip_margin(),
MetaResult { uuid: true, geo: true, tags: true,}),
];
let mut count = 0;
for t in pok_meta {
let mut settings = Settings::default();
let mut is = Stream {
input: t.0.as_str(),
state: &mut settings,
};
let res = parse_txn_meta(&mut is);
assert!(
res.is_ok(),
"\nPOK is error: Offending test vector item: {}\n",
count + 1
);
let meta = res.unwrap();
assert_eq!(
meta.uuid.is_some(),
t.1.uuid,
"\nUUID: Offending test vector item: {}",
count + 1
);
assert_eq!(
meta.location.is_some(),
t.1.geo,
"\nGEO: Offending test vector item: {}",
count + 1
);
assert_eq!(
meta.tags.is_some(),
t.1.tags,
"\nTAGS: Offending test vector item: {}",
count + 1
);
count += 1;
}
assert_eq!(count, 15);
}
}