1#![doc = include_str!("crate-doc.md")]
2
3use itertools::join;
4use linkme::distributed_slice;
5use std::cmp::Ordering;
6
7#[doc(hidden)]
8pub use linkme;
9
10pub use ffizz_macros::item;
11pub use ffizz_macros::snippet;
12
13#[doc(hidden)]
19#[derive(Clone)]
20pub struct HeaderItem {
21 pub order: usize,
22 pub name: &'static str,
23 pub content: &'static str,
24}
25
26#[doc(hidden)]
28#[distributed_slice]
29pub static FFIZZ_HEADER_ITEMS: [HeaderItem] = [..];
30
31pub fn generate() -> String {
36 generate_from_vec(FFIZZ_HEADER_ITEMS.iter().collect::<Vec<_>>())
37}
38
39fn generate_from_vec(mut items: Vec<&'static HeaderItem>) -> String {
41 items.sort_by(
42 |a: &&'static HeaderItem, b: &&'static HeaderItem| match a.order.cmp(&b.order) {
43 Ordering::Less => Ordering::Less,
44 Ordering::Equal => a.name.cmp(b.name),
45 Ordering::Greater => Ordering::Greater,
46 },
47 );
48
49 let mut result = join(items.iter().map(|hi| hi.content.trim()), "\n\n");
51 if !items.is_empty() {
53 result.push('\n');
54 }
55 result
56}
57
58#[cfg(test)]
59mod test {
60 #[test]
61 fn test_generate_order_by_order() {
62 assert_eq!(
63 super::generate_from_vec(vec![
64 &super::HeaderItem {
65 order: 1,
66 name: "foo",
67 content: "one"
68 },
69 &super::HeaderItem {
70 order: 3,
71 name: "foo",
72 content: "three"
73 },
74 &super::HeaderItem {
75 order: 2,
76 name: "foo",
77 content: "two"
78 },
79 ]),
80 String::from("one\n\ntwo\n\nthree\n")
81 );
82 }
83
84 #[test]
85 fn test_generate_order_by_name() {
86 assert_eq!(
87 super::generate_from_vec(vec![
88 &super::HeaderItem {
89 order: 3,
90 name: "bbb",
91 content: "two"
92 },
93 &super::HeaderItem {
94 order: 3,
95 name: "ccc",
96 content: "three"
97 },
98 &super::HeaderItem {
99 order: 3,
100 name: "aaa",
101 content: "one"
102 },
103 ]),
104 String::from("one\n\ntwo\n\nthree\n")
105 );
106 }
107
108 #[test]
109 fn test_empty() {
110 assert_eq!(super::generate(), String::new());
111 }
112}