use serde::Serialize;
#[derive(PartialEq)]
pub enum PrinterType {
Stderr,
Json,
}
#[derive(Serialize)]
pub struct Message {
r#type: String,
body: String,
}
impl Message {
pub fn new(r#type: &str, body: &str) -> Self {
Self {
r#type: r#type.to_string(),
body: body.to_string(),
}
}
fn intersperse(&self, delim: &str) -> String {
format!("{}{}{}", self.r#type, delim, self.body)
}
}
pub struct Printer {
printer_type: PrinterType,
messages: Vec<Message>,
}
impl Printer {
pub fn new(printer_type: PrinterType) -> Self {
Self {
printer_type,
messages: vec![],
}
}
pub fn print(&mut self, message: Message, only: Option<PrinterType>) {
let allowed = match only {
Some(ptype) => self.printer_type == ptype,
None => true,
};
if allowed {
match self.printer_type {
PrinterType::Stderr => eprintln!("{}", message.intersperse(":")),
PrinterType::Json => self.messages.push(message),
}
}
}
pub fn echo(&mut self, r#type: &str, body: &str) {
self.print(Message::new(r#type, body), None)
}
fn serialize(&self) -> String {
serde_json::to_string(&self.messages).unwrap()
}
pub fn flush(&self) {
if self.printer_type == PrinterType::Json {
println!("{}", self.serialize())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_json_serialize() {
let mut p = Printer::new(PrinterType::Json);
p.print(Message::new("data dir", "~/.local/share/evry/data"), None);
p.print(
Message::new("tag name", "this is tag name"),
Some(PrinterType::Json),
);
p.print(
Message::new("status", "something bad happened"),
Some(PrinterType::Json),
);
p.print(
Message::new("status", "this shouldnt be in the output"),
Some(PrinterType::Stderr),
);
assert_eq!(p.serialize(), "[{\"type\":\"data dir\",\"body\":\"~/.local/share/evry/data\"},{\"type\":\"tag name\",\"body\":\"this is tag name\"},{\"type\":\"status\",\"body\":\"something bad happened\"}]");
}
}