markdown_ppp/ast_specialized/
utilities.rs1use super::element_id::IdGenerator;
28use super::type_aliases::with_ids;
29use super::ElementId;
30
31pub mod id_utils {
33 use super::*;
34 use crate::ast::convert::WithData;
35 use crate::ast::generic;
36 use crate::ast::map_data_visitor::{map_user_data, MapDataVisitor};
37
38 pub fn add_ids_to_document(doc: crate::ast::Document) -> with_ids::Document {
40 let doc_with_unit: generic::Document<()> = doc.with_default_data();
41 let mut id_gen = IdGenerator::new();
42 map_user_data(doc_with_unit, |_| id_gen.generate())
43 }
44
45 pub fn add_ids_from(doc: crate::ast::Document, start_id: u64) -> with_ids::Document {
47 let doc_with_unit: generic::Document<()> = doc.with_default_data();
48 let mut id_gen = IdGenerator::starting_from(start_id);
49 map_user_data(doc_with_unit, |_| id_gen.generate())
50 }
51
52 pub struct IdAssignmentVisitor {
54 id_gen: IdGenerator,
55 }
56
57 impl IdAssignmentVisitor {
58 pub fn new() -> Self {
59 Self {
60 id_gen: IdGenerator::new(),
61 }
62 }
63
64 pub fn starting_from(start_id: u64) -> Self {
65 Self {
66 id_gen: IdGenerator::starting_from(start_id),
67 }
68 }
69 }
70
71 impl Default for IdAssignmentVisitor {
72 fn default() -> Self {
73 Self::new()
74 }
75 }
76
77 impl<T> MapDataVisitor<T, ElementId> for IdAssignmentVisitor {
78 fn map_data(&mut self, _data: T) -> ElementId {
79 self.id_gen.generate()
80 }
81 }
82
83 pub fn add_ids_to_generic_document<T>(doc: generic::Document<T>) -> with_ids::Document {
85 let mut visitor = IdAssignmentVisitor::new();
86 visitor.visit_document(doc)
87 }
88
89 #[cfg(test)]
90 mod tests {
91 use super::*;
92 use crate::ast::{Block, Heading, HeadingKind, Inline};
93
94 #[test]
95 fn test_add_ids_to_document() {
96 let doc = crate::ast::Document {
97 blocks: vec![Block::Heading(Heading {
98 kind: HeadingKind::Atx(1),
99 content: vec![Inline::Text("Test".to_string())],
100 })],
101 };
102
103 let doc_with_ids = add_ids_to_document(doc);
104
105 assert!(doc_with_ids.user_data.id() > 0);
107
108 assert_eq!(doc_with_ids.blocks.len(), 1);
110 match &doc_with_ids.blocks[0] {
111 generic::Block::Heading(h) => {
112 assert!(h.user_data.id() > 0);
113 assert_eq!(h.content.len(), 1);
114 match &h.content[0] {
115 generic::Inline::Text { user_data, .. } => {
116 assert!(user_data.id() > 0);
117 }
118 _ => panic!("Expected text inline"),
119 }
120 }
121 _ => panic!("Expected heading"),
122 }
123 }
124
125 #[test]
126 fn test_add_ids_from() {
127 let doc = crate::ast::Document {
128 blocks: vec![Block::Heading(Heading {
129 kind: HeadingKind::Atx(1),
130 content: vec![Inline::Text("Test".to_string())],
131 })],
132 };
133
134 let doc_with_ids = add_ids_from(doc, 100);
135
136 assert!(doc_with_ids.user_data.id() >= 100);
138 }
139
140 #[test]
141 fn test_id_assignment_visitor() {
142 let mut visitor = IdAssignmentVisitor::starting_from(50);
143 let id1 = visitor.map_data(());
144 let id2 = visitor.map_data(());
145
146 assert_eq!(id1.id(), 50);
147 assert_eq!(id2.id(), 51);
148 }
149 }
150}