1#![feature(const_trait_impl)]
7#![feature(const_default)]
8
9mod continuations;
11mod problem;
12mod section;
13#[cfg(test)]
14mod tests;
15
16use std::{
18 env::args,
19 sync::LazyLock,
20 fs::File,
21 path::PathBuf
22};
23
24use core::fmt::{
26 Display,
27 Debug
28};
29
30use libutils_cage::Cage;
32
33use libutils_threat::Threat;
35
36use continuations::{
38 ActionRequired,
39 FileDescriptor
40};
41
42use libutils_issue::{
44 Issue,
45 Severity
46};
47
48use libutils_console::{
50 Console,
51 Argument,
52 Synchronization,
53 Descriptor
54};
55
56use section::Section;
58
59
60pub static TERMINAL: Terminal = Terminal {
66 arguments: LazyLock::new(|| args().map(Argument::from).collect()),
67 layout: Cage::default(),
68 output: Cage::default()
69};
70
71pub struct Terminal {
73 arguments: LazyLock<Vec<Argument>>,
74 layout: Cage<Vec<Section>>,
75 output: Cage<String>
76}
77
78impl Console for Terminal {
80 #[inline]
81 fn arguments<'valid>(&'valid self) -> &'valid [Argument] {return self.arguments.as_slice()}
82 #[inline]
83 fn open(&self, filename: &str) -> Result<impl Descriptor, Issue> {match File::open(PathBuf::from(filename)) {
84 Ok(file) => Ok(FileDescriptor {
85 file: file
86 }),
87 Err(error) => Err(Issue {
88 name: "Failed to open file",
89 description: Some(error.to_string()),
90 severity: Severity::Error
91 })
92 }}
93 #[inline]
94 fn problem(&self, threat: Threat) -> impl Synchronization {
95 self.layout.write(|layout| layout.push(Section::Problem(threat.into())));
96 return ActionRequired;
97 }
98 #[inline]
99 fn print(&self, value: impl Display) -> impl Synchronization {
100 self.layout.write(|layout| layout.push(Section::Display(value.to_string())));
101 return ActionRequired;
102 }
103 #[inline]
104 fn debug(&self, value: impl Debug) -> impl Synchronization {
105 self.layout.write(|layout| layout.push(Section::Debug(format!("{value:#?}"))));
106 return ActionRequired;
107 }
108}