use serde_yaml::Value;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChildrenNorm {
pub children: bool,
pub source: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SeriesNorm {
pub series: bool,
pub order: Option<Vec<String>>,
}
pub fn normalize_children(v: &Value) -> ChildrenNorm {
match v {
Value::Bool(b) => ChildrenNorm { children: *b, source: None },
Value::String(s) => {
let t = s.trim();
match t {
"true" => ChildrenNorm { children: true, source: None },
"false" | "" => ChildrenNorm { children: false, source: None },
_ => ChildrenNorm { children: true, source: Some(s.clone()) },
}
}
_ => ChildrenNorm { children: false, source: None },
}
}
pub fn normalize_series(v: &Value) -> SeriesNorm {
match v {
Value::Bool(b) => SeriesNorm { series: *b, order: None },
Value::String(s) => match s.trim() {
"true" => SeriesNorm { series: true, order: None },
_ => SeriesNorm { series: false, order: None },
},
Value::Sequence(items) => {
if items.is_empty() {
return SeriesNorm { series: true, order: None };
}
let mut order = Vec::with_capacity(items.len());
for it in items {
match it {
Value::String(s) => order.push(s.clone()),
_ => return SeriesNorm { series: false, order: None },
}
}
SeriesNorm { series: true, order: Some(order) }
}
_ => SeriesNorm { series: false, order: None },
}
}
#[cfg(test)]
mod tests {
use super::*;
fn s(v: &str) -> Value {
Value::String(v.to_string())
}
#[test]
fn children_bool_true() {
assert_eq!(
normalize_children(&Value::Bool(true)),
ChildrenNorm { children: true, source: None }
);
}
#[test]
fn children_bool_false() {
assert_eq!(
normalize_children(&Value::Bool(false)),
ChildrenNorm { children: false, source: None }
);
}
#[test]
fn children_string_true_false() {
assert_eq!(
normalize_children(&s("true")),
ChildrenNorm { children: true, source: None }
);
assert_eq!(
normalize_children(&s("false")),
ChildrenNorm { children: false, source: None }
);
}
#[test]
fn children_empty_string_is_off() {
assert_eq!(
normalize_children(&s("")),
ChildrenNorm { children: false, source: None }
);
}
#[test]
fn children_wikilink() {
assert_eq!(
normalize_children(&s("[[News]]")),
ChildrenNorm { children: true, source: Some("[[News]]".to_string()) }
);
}
#[test]
fn children_bare_path() {
assert_eq!(
normalize_children(&s("news/index.md")),
ChildrenNorm { children: true, source: Some("news/index.md".to_string()) }
);
}
#[test]
fn children_other_types_off() {
assert_eq!(
normalize_children(&Value::Null),
ChildrenNorm { children: false, source: None }
);
assert_eq!(
normalize_children(&Value::Number(3.into())),
ChildrenNorm { children: false, source: None }
);
}
#[test]
fn series_bool() {
assert_eq!(
normalize_series(&Value::Bool(true)),
SeriesNorm { series: true, order: None }
);
assert_eq!(
normalize_series(&Value::Bool(false)),
SeriesNorm { series: false, order: None }
);
}
#[test]
fn series_list_of_strings() {
let seq = Value::Sequence(vec![s("[[Ch 1]]"), s("[[Ch 2]]")]);
assert_eq!(
normalize_series(&seq),
SeriesNorm {
series: true,
order: Some(vec!["[[Ch 1]]".to_string(), "[[Ch 2]]".to_string()])
}
);
}
#[test]
fn series_malformed_list_off() {
let seq = Value::Sequence(vec![s("[[Ch 1]]"), Value::Bool(true)]);
assert_eq!(
normalize_series(&seq),
SeriesNorm { series: false, order: None }
);
}
#[test]
fn series_empty_list_is_flag() {
assert_eq!(
normalize_series(&Value::Sequence(vec![])),
SeriesNorm { series: true, order: None }
);
}
#[test]
fn series_other_off() {
assert_eq!(
normalize_series(&Value::Null),
SeriesNorm { series: false, order: None }
);
}
#[test]
fn children_roundtrip_via_to_value() {
let raw = s("[[News]]");
let reexpressed = serde_yaml::to_value("[[News]]").unwrap();
assert_eq!(normalize_children(&raw), normalize_children(&reexpressed));
}
}