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