1use anyhow::{Context, Result};
9use std::collections::HashSet;
10use std::fs::OpenOptions;
11use std::io::{BufWriter, Write};
12use std::path::Path;
13
14use crate::error::LinkError;
15use crate::link::Link;
16use crate::link_storage::{ChangeObserver, LinkStorage};
17use crate::named_types::{NamedTypes, NamedTypesDecorator};
18
19pub trait NamedTypeLinks {
20 fn create(&mut self, source: u32, target: u32) -> u32;
21 fn ensure_created(&mut self, id: u32) -> u32;
22 fn try_ensure_created(&mut self, id: u32) -> Result<u32> {
23 if id == 0 || id == u32::MAX {
24 return Err(LinkError::InvalidFormat(format!(
25 "Cannot ensure unsupported link address {id}"
26 ))
27 .into());
28 }
29
30 Ok(self.ensure_created(id))
31 }
32 fn get_link(&mut self, id: u32) -> Option<Link>;
33 fn exists(&mut self, id: u32) -> bool;
34 fn update(&mut self, id: u32, source: u32, target: u32) -> Result<Link>;
35 fn delete(&mut self, id: u32) -> Result<Link>;
36 fn delete_observed(&mut self, id: u32, observer: ChangeObserver<'_>) -> Result<Link> {
52 let before = self.delete(id)?;
53 observer(before, Link::null());
54 Ok(before)
55 }
56 fn all_links(&mut self) -> Vec<Link>;
57 fn search(&mut self, source: u32, target: u32) -> Option<u32>;
58 fn get_or_create(&mut self, source: u32, target: u32) -> u32;
59 fn get_name(&mut self, id: u32) -> Result<Option<String>>;
60 fn set_name(&mut self, id: u32, name: &str) -> Result<u32>;
61 fn get_by_name(&mut self, name: &str) -> Result<Option<u32>>;
62 fn remove_name(&mut self, id: u32) -> Result<()>;
63 fn save(&mut self) -> Result<()>;
64
65 fn get_or_create_named(&mut self, name: &str) -> Result<u32> {
66 if let Some(id) = self.get_by_name(name)? {
67 return Ok(id);
68 }
69
70 let id = self.create(0, 0);
71 self.set_name(id, name)?;
72 self.update(id, id, id)?;
73 Ok(id)
74 }
75
76 fn format_reference(&mut self, id: u32) -> Result<String> {
77 Ok(self
78 .get_name(id)?
79 .map(|name| escape_lino_reference(&name))
80 .unwrap_or_else(|| id.to_string()))
81 }
82
83 fn format_lino(&mut self, link: &Link) -> Result<String> {
84 Ok(format!(
85 "({}: {} {})",
86 self.format_reference(link.index)?,
87 self.format_reference(link.source)?,
88 self.format_reference(link.target)?
89 ))
90 }
91
92 fn lino_lines(&mut self) -> Result<Vec<String>> {
93 let mut links = self.all_links();
94 links.sort_by_key(|link| link.index);
95
96 links
97 .iter()
98 .map(|link| self.format_lino(link))
99 .collect::<Result<Vec<_>>>()
100 }
101
102 fn write_lino_output<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
103 let path = path.as_ref();
104 let file = OpenOptions::new()
105 .write(true)
106 .create(true)
107 .truncate(true)
108 .open(path)
109 .with_context(|| format!("Failed to create LiNo output: {}", path.display()))?;
110
111 let mut writer = BufWriter::new(file);
112 for line in self.lino_lines()? {
113 writeln!(writer, "{line}")?;
114 }
115 writer.flush()?;
116 Ok(())
117 }
118
119 fn print_all_lino(&mut self) -> Result<()> {
120 for line in self.lino_lines()? {
121 println!("{line}");
122 }
123 Ok(())
124 }
125
126 fn print_change_lino(&mut self, before: &Option<Link>, after: &Option<Link>) -> Result<()> {
127 let before_text = before
128 .map(|link| self.format_lino(&link))
129 .transpose()?
130 .unwrap_or_default();
131 let after_text = after
132 .map(|link| self.format_lino(&link))
133 .transpose()?
134 .unwrap_or_default();
135 println!("({before_text}) ({after_text})");
136 Ok(())
137 }
138
139 fn format_structure(&mut self, id: u32) -> Result<String> {
140 let mut visited = HashSet::new();
141 self.format_structure_recursive(id, &mut visited)
142 }
143
144 fn format_structure_recursive(
145 &mut self,
146 id: u32,
147 visited: &mut HashSet<u32>,
148 ) -> Result<String> {
149 let link = self.get_link(id).ok_or(LinkError::not_found(id))?;
150 if !visited.insert(id) {
151 return self.format_reference(id);
152 }
153
154 let source = if self.exists(link.source) && !visited.contains(&link.source) {
155 self.format_structure_recursive(link.source, visited)?
156 } else {
157 self.format_reference(link.source)?
158 };
159 let target = self.format_reference(link.target)?;
160 let index = self.format_reference(link.index)?;
161 visited.remove(&id);
162
163 Ok(format!("({index}: {source} {target})"))
164 }
165}
166
167impl NamedTypeLinks for LinkStorage {
168 fn create(&mut self, source: u32, target: u32) -> u32 {
169 LinkStorage::create(self, source, target)
170 }
171
172 fn ensure_created(&mut self, id: u32) -> u32 {
173 LinkStorage::ensure_created(self, id)
174 }
175
176 fn get_link(&mut self, id: u32) -> Option<Link> {
177 self.get(id).copied()
178 }
179
180 fn exists(&mut self, id: u32) -> bool {
181 LinkStorage::exists(self, id)
182 }
183
184 fn update(&mut self, id: u32, source: u32, target: u32) -> Result<Link> {
185 LinkStorage::update(self, id, source, target)
186 }
187
188 fn delete(&mut self, id: u32) -> Result<Link> {
189 LinkStorage::delete(self, id)
190 }
191
192 fn delete_observed(&mut self, id: u32, observer: ChangeObserver<'_>) -> Result<Link> {
193 LinkStorage::delete_observed(self, id, observer)
194 }
195
196 fn all_links(&mut self) -> Vec<Link> {
197 self.all().into_iter().copied().collect()
198 }
199
200 fn search(&mut self, source: u32, target: u32) -> Option<u32> {
201 LinkStorage::search(self, source, target)
202 }
203
204 fn get_or_create(&mut self, source: u32, target: u32) -> u32 {
205 LinkStorage::get_or_create(self, source, target)
206 }
207
208 fn get_name(&mut self, id: u32) -> Result<Option<String>> {
209 Ok(LinkStorage::get_name(self, id).cloned())
210 }
211
212 fn set_name(&mut self, id: u32, name: &str) -> Result<u32> {
213 LinkStorage::set_name(self, id, name);
214 Ok(id)
215 }
216
217 fn get_by_name(&mut self, name: &str) -> Result<Option<u32>> {
218 Ok(LinkStorage::get_by_name(self, name))
219 }
220
221 fn remove_name(&mut self, id: u32) -> Result<()> {
222 LinkStorage::remove_name(self, id);
223 Ok(())
224 }
225
226 fn save(&mut self) -> Result<()> {
227 LinkStorage::save(self)
228 }
229
230 fn get_or_create_named(&mut self, name: &str) -> Result<u32> {
231 Ok(LinkStorage::get_or_create_named(self, name))
232 }
233}
234
235impl NamedTypeLinks for NamedTypesDecorator {
236 fn create(&mut self, source: u32, target: u32) -> u32 {
237 NamedTypesDecorator::create(self, source, target)
238 }
239
240 fn ensure_created(&mut self, id: u32) -> u32 {
241 NamedTypesDecorator::ensure_created(self, id)
242 }
243
244 fn get_link(&mut self, id: u32) -> Option<Link> {
245 self.get(id).copied()
246 }
247
248 fn exists(&mut self, id: u32) -> bool {
249 NamedTypesDecorator::exists(self, id)
250 }
251
252 fn update(&mut self, id: u32, source: u32, target: u32) -> Result<Link> {
253 NamedTypesDecorator::update(self, id, source, target)
254 }
255
256 fn delete(&mut self, id: u32) -> Result<Link> {
257 NamedTypesDecorator::delete(self, id)
258 }
259
260 fn delete_observed(&mut self, id: u32, observer: ChangeObserver<'_>) -> Result<Link> {
261 NamedTypesDecorator::delete_observed(self, id, observer)
262 }
263
264 fn all_links(&mut self) -> Vec<Link> {
265 self.all().into_iter().copied().collect()
266 }
267
268 fn search(&mut self, source: u32, target: u32) -> Option<u32> {
269 NamedTypesDecorator::search(self, source, target)
270 }
271
272 fn get_or_create(&mut self, source: u32, target: u32) -> u32 {
273 NamedTypesDecorator::get_or_create(self, source, target)
274 }
275
276 fn get_name(&mut self, id: u32) -> Result<Option<String>> {
277 NamedTypes::get_name(self, id)
278 }
279
280 fn set_name(&mut self, id: u32, name: &str) -> Result<u32> {
281 NamedTypes::set_name(self, id, name)
282 }
283
284 fn get_by_name(&mut self, name: &str) -> Result<Option<u32>> {
285 NamedTypes::get_by_name(self, name)
286 }
287
288 fn remove_name(&mut self, id: u32) -> Result<()> {
289 NamedTypes::remove_name(self, id)
290 }
291
292 fn save(&mut self) -> Result<()> {
293 NamedTypesDecorator::save(self)
294 }
295}
296
297impl NamedTypeLinks for crate::transactions::TransactionsDecorator {
298 fn create(&mut self, source: u32, target: u32) -> u32 {
299 crate::transactions::TransactionsDecorator::create(self, source, target)
300 .expect("TransactionsDecorator::create failed in NamedTypeLinks bridge")
301 }
302
303 fn ensure_created(&mut self, id: u32) -> u32 {
304 crate::transactions::TransactionsDecorator::ensure_created(self, id)
305 .expect("TransactionsDecorator::ensure_created failed in NamedTypeLinks bridge")
306 }
307
308 fn get_link(&mut self, id: u32) -> Option<Link> {
309 self.get(id).copied()
310 }
311
312 fn exists(&mut self, id: u32) -> bool {
313 crate::transactions::TransactionsDecorator::exists(self, id)
314 }
315
316 fn update(&mut self, id: u32, source: u32, target: u32) -> Result<Link> {
317 Ok(crate::transactions::TransactionsDecorator::update(
318 self, id, source, target,
319 )?)
320 }
321
322 fn delete(&mut self, id: u32) -> Result<Link> {
323 Ok(crate::transactions::TransactionsDecorator::delete(
324 self, id,
325 )?)
326 }
327
328 fn delete_observed(&mut self, id: u32, observer: ChangeObserver<'_>) -> Result<Link> {
329 Ok(crate::transactions::TransactionsDecorator::delete_observed(
330 self, id, observer,
331 )?)
332 }
333
334 fn all_links(&mut self) -> Vec<Link> {
335 self.all().into_iter().copied().collect()
336 }
337
338 fn search(&mut self, source: u32, target: u32) -> Option<u32> {
339 crate::transactions::TransactionsDecorator::search(self, source, target)
340 }
341
342 fn get_or_create(&mut self, source: u32, target: u32) -> u32 {
343 crate::transactions::TransactionsDecorator::get_or_create(self, source, target)
344 .expect("TransactionsDecorator::get_or_create failed in NamedTypeLinks bridge")
345 }
346
347 fn get_name(&mut self, id: u32) -> Result<Option<String>> {
348 NamedTypes::get_name(self.inner_mut(), id)
349 }
350
351 fn set_name(&mut self, id: u32, name: &str) -> Result<u32> {
352 NamedTypes::set_name(self.inner_mut(), id, name)
353 }
354
355 fn get_by_name(&mut self, name: &str) -> Result<Option<u32>> {
356 NamedTypes::get_by_name(self.inner_mut(), name)
357 }
358
359 fn remove_name(&mut self, id: u32) -> Result<()> {
360 NamedTypes::remove_name(self.inner_mut(), id)
361 }
362
363 fn save(&mut self) -> Result<()> {
364 Ok(crate::transactions::TransactionsDecorator::save(self)?)
365 }
366}
367
368impl NamedTypeLinks for crate::version_control::VersionControlDecorator {
369 fn create(&mut self, source: u32, target: u32) -> u32 {
370 crate::version_control::VersionControlDecorator::create(self, source, target)
371 .expect("VersionControlDecorator::create failed in NamedTypeLinks bridge")
372 }
373
374 fn ensure_created(&mut self, id: u32) -> u32 {
375 crate::version_control::VersionControlDecorator::ensure_created(self, id)
376 }
377
378 fn get_link(&mut self, id: u32) -> Option<Link> {
379 self.get(id).copied()
380 }
381
382 fn exists(&mut self, id: u32) -> bool {
383 crate::version_control::VersionControlDecorator::exists(self, id)
384 }
385
386 fn update(&mut self, id: u32, source: u32, target: u32) -> Result<Link> {
387 crate::version_control::VersionControlDecorator::update(self, id, source, target)
388 }
389
390 fn delete(&mut self, id: u32) -> Result<Link> {
391 crate::version_control::VersionControlDecorator::delete(self, id)
392 }
393
394 fn delete_observed(&mut self, id: u32, observer: ChangeObserver<'_>) -> Result<Link> {
395 crate::version_control::VersionControlDecorator::delete_observed(self, id, observer)
396 }
397
398 fn all_links(&mut self) -> Vec<Link> {
399 self.all().into_iter().copied().collect()
400 }
401
402 fn search(&mut self, source: u32, target: u32) -> Option<u32> {
403 crate::version_control::VersionControlDecorator::search(self, source, target)
404 }
405
406 fn get_or_create(&mut self, source: u32, target: u32) -> u32 {
407 crate::version_control::VersionControlDecorator::get_or_create(self, source, target)
408 .expect("VersionControlDecorator::get_or_create failed in NamedTypeLinks bridge")
409 }
410
411 fn get_name(&mut self, id: u32) -> Result<Option<String>> {
412 NamedTypes::get_name(self.transactions_mut().inner_mut(), id)
413 }
414
415 fn set_name(&mut self, id: u32, name: &str) -> Result<u32> {
416 NamedTypes::set_name(self.transactions_mut().inner_mut(), id, name)
417 }
418
419 fn get_by_name(&mut self, name: &str) -> Result<Option<u32>> {
420 NamedTypes::get_by_name(self.transactions_mut().inner_mut(), name)
421 }
422
423 fn remove_name(&mut self, id: u32) -> Result<()> {
424 NamedTypes::remove_name(self.transactions_mut().inner_mut(), id)
425 }
426
427 fn save(&mut self) -> Result<()> {
428 crate::version_control::VersionControlDecorator::save(self)
429 }
430}
431
432pub fn escape_lino_reference(reference: &str) -> String {
433 if reference.is_empty() || reference.trim().is_empty() {
434 return String::new();
435 }
436
437 let has_single_quote = reference.contains('\'');
438 let has_double_quote = reference.contains('"');
439 let needs_quoting = reference.contains(':')
440 || reference.contains('(')
441 || reference.contains(')')
442 || reference.contains(' ')
443 || reference.contains('\t')
444 || reference.contains('\n')
445 || reference.contains('\r')
446 || has_single_quote
447 || has_double_quote;
448
449 if has_single_quote && has_double_quote {
450 return format!("'{}'", reference.replace('\'', "\\'"));
451 }
452
453 if has_double_quote {
454 return format!("'{reference}'");
455 }
456
457 if has_single_quote {
458 return format!("\"{reference}\"");
459 }
460
461 if needs_quoting {
462 return format!("'{reference}'");
463 }
464
465 reference.to_string()
466}