hyperlit_runtime/
evaluate_directive.rs

1use hyperlit_base::result::HyperlitResult;
2use hyperlit_database::Database;
3use hyperlit_model::directive_evaluation::DirectiveEvaluation;
4use hyperlit_model::directives::parse_directive;
5use hyperlit_model::segment::segments_sort_by_title;
6
7pub fn evaluate_directive<'a>(
8    string: &str,
9    database: &'a dyn Database,
10) -> HyperlitResult<DirectiveEvaluation<'a>> {
11    let string = string.trim();
12    let prefix = "§{";
13    Ok(if string.starts_with(prefix) && string.ends_with("}") {
14        let directive = parse_directive(string)?;
15        match directive {
16            hyperlit_model::directives::Directive::IncludeByTag { tag } => {
17                let mut segments = database.get_segments_by_tag(&tag)?;
18                segments_sort_by_title(segments.as_mut_slice());
19                DirectiveEvaluation::Segments { segments }
20            }
21            hyperlit_model::directives::Directive::IncludeRest => {
22                let segments = database.get_all_segments()?;
23                let mut rest_segments: Vec<_> =
24                    segments.into_iter().filter(|s| !s.is_included).collect();
25                segments_sort_by_title(rest_segments.as_mut_slice());
26                DirectiveEvaluation::Segments {
27                    segments: rest_segments,
28                }
29            }
30        }
31    } else {
32        DirectiveEvaluation::NoDirective
33    })
34}
35
36#[cfg(test)]
37mod tests {
38    use crate::evaluate_directive::evaluate_directive;
39    use hyperlit_base::result::HyperlitResult;
40    use hyperlit_database::Database;
41    use hyperlit_database::in_memory_database::InMemoryDatabase;
42    use hyperlit_model::directive_evaluation::DirectiveEvaluation;
43    use hyperlit_model::location::Location;
44    use hyperlit_model::segment::Segment;
45
46    fn make_segments(how_many: usize) -> Vec<Segment> {
47        vec![Segment::new(0, "title", vec![], "text", Location::new("path", 1)); how_many]
48    }
49
50    #[test]
51    fn test_evaluate_include_rest_directive() -> HyperlitResult<()> {
52        let mut database = InMemoryDatabase::new();
53        database.add_segments(make_segments(3))?;
54        database.set_segment_included(1)?;
55        let evaluation = evaluate_directive("§{@include_rest}", &database)?;
56        match evaluation {
57            DirectiveEvaluation::Segments { segments } => {
58                assert_eq!(
59                    segments.iter().map(|s| s.id).collect::<Vec<_>>(),
60                    vec![0, 2]
61                );
62            }
63            _ => panic!("should be segments, instead got: {evaluation:?}"),
64        }
65        Ok(())
66    }
67
68    #[test]
69    fn test_evaluate_include_by_tag() -> HyperlitResult<()> {
70        let mut database = InMemoryDatabase::new();
71        database.add_segments(make_segments(3))?;
72        database.add_segments(vec![Segment::new(
73            0,
74            "title A",
75            vec!["the_tag".to_string()],
76            "text",
77            Location::new("path", 1),
78        )])?;
79        database.add_segments(make_segments(3))?;
80        database.add_segments(vec![Segment::new(
81            0,
82            "title B",
83            vec!["the_tag".to_string()],
84            "text",
85            Location::new("path", 1),
86        )])?;
87        let evaluation = evaluate_directive("§{@include_by_tag:#the_tag}", &database)?;
88        match evaluation {
89            DirectiveEvaluation::Segments { segments } => {
90                assert_eq!(
91                    segments.iter().map(|s| s.id).collect::<Vec<_>>(),
92                    vec![3, 7]
93                );
94            }
95            _ => panic!("should be segments, instead got: {evaluation:?}"),
96        }
97        Ok(())
98    }
99
100    #[test]
101    fn test_evaluate_no_directive() -> HyperlitResult<()> {
102        fn evaluate(string: &str) -> HyperlitResult<()> {
103            let database = InMemoryDatabase::new();
104            let evaluation = evaluate_directive(string, &database)?;
105            match evaluation {
106                DirectiveEvaluation::NoDirective => {
107                    // Ok
108                }
109                _ => panic!("should be no directive, instead got: {evaluation:?}"),
110            }
111            Ok(())
112        }
113        evaluate("")?;
114        evaluate("    ")?;
115        evaluate("§{    }x")?;
116        evaluate("§{    x")?;
117        evaluate("}")?;
118        evaluate("§ {  }")?;
119        Ok(())
120    }
121}