#![feature(const_trait_impl)]
#![feature(const_default)]
mod item;
mod problem;
#[cfg(test)]
mod tests;
use std::{
env::args,
io::{
Write,
stdout
},
sync::LazyLock,
fs::read_to_string,
path::PathBuf
};
use core::fmt::Display;
use libutils_cage::Cage;
use libutils_threat::Threat;
use libutils_diff::Diff;
use libutils_issue::{
Issue,
Severity
};
use libutils_console::{
Console,
Argument
};
use item::Item;
pub static TERMINAL: Terminal = Terminal {
arguments: LazyLock::new(|| args().map(Argument::from).collect()),
layout: Cage::default(),
output: Cage::default()
};
pub struct Terminal {
arguments: LazyLock<Vec<Argument>>,
layout: Cage<Vec<Item>>,
output: Cage<String>
}
impl Console for Terminal {
#[inline]
fn arguments<'valid>(&'valid self) -> &'valid [Argument] {return self.arguments.as_slice()}
#[inline]
fn read(&self, filename: &str) -> Result<String, Issue> {return read_to_string(PathBuf::from(filename)).map_err(|error| Issue {
name: "Failed to read file",
description: Some(error.to_string()),
severity: Severity::Error
})}
#[inline]
fn sync(&self) -> () {
let content = self.layout.read(|layout| layout.iter().map(ToString::to_string).collect::<Vec<String>>()).join("\n\n");
self.output.write(|output| {
let mut lock = stdout().lock();
lock.write(<Diff as Into<Vec<u8>>>::into(Diff::new(
output.as_bytes(),
content.as_bytes()
)).as_ref()).unwrap();
lock.flush().unwrap();
*output = content;
});
}
#[inline]
fn problem(&self, threat: Threat) -> () {return self.layout.write(|layout| layout.push(Item::Problem(threat.into())))}
#[inline]
fn print<Type: Display>(&self, value: &Type) -> () {return self.layout.write(|layout| layout.push(Item::String(value.to_string())))}
}