/* * examples/validate_json.rs * * ftml - Library to parse Wikidot text * Copyright (C) 2019-2024 Wikijump Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ extern crate ftml; extern crate serde_json; #[macro_use] extern crate str_macro; extern crate termcolor; use std::env; use std::ffi::OsString; use std::fs::File; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::process; use termcolor::{Buffer, BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; fn main() { let json_paths = { let mut arguments: Vec = env::args_os().collect(); arguments.remove(0); arguments }; if json_paths.is_empty() { println!("No files listed."); process::exit(0); } // Read files let mut results: Vec<(PathBuf, Outcome)> = Vec::new(); for json_path in json_paths { let path = PathBuf::from(json_path); let mut file = match File::open(&path) { Ok(file) => file, Err(error) => { let outcome = Outcome::Error(str!(error)); results.push((path, outcome)); continue; } }; let syntax_tree = match serde_json::from_reader(&mut file) { Ok(tree) => tree, Err(error) => { let outcome = Outcome::Failure(str!(error)); results.push((path, outcome)); continue; } }; let outcome = Outcome::Success(syntax_tree); results.push((path, outcome)); } // Output results let mut buf_writer = BufferWriter::stdout(ColorChoice::Auto); let mut success = true; println!(); for (path, outcome) in results { write_result(&mut buf_writer, &path, &outcome).expect("Unable to write"); success &= matches!(outcome, Outcome::Success(_)); } // Exit if !success { process::exit(1); } } fn write_result( buf_writer: &mut BufferWriter, path: &Path, outcome: &Outcome, ) -> io::Result<()> { let mut buffer = buf_writer.buffer(); outcome.write(&mut buffer, path)?; buf_writer.print(&buffer)?; Ok(()) } #[derive(Debug)] enum Outcome { Success(ftml::tree::SyntaxTree<'static>), Failure(String), Error(String), } impl Outcome { fn write(&self, buffer: &mut Buffer, path: &Path) -> io::Result<()> { buffer.set_color(&ColorSpec::new().set_bold(true).set_fg(Some(self.color())))?; match self { Outcome::Success(_) => write!(buffer, " pass")?, Outcome::Failure(_) => write!(buffer, " fail")?, Outcome::Error(_) => write!(buffer, "error")?, } buffer.set_color(&ColorSpec::new())?; write!(buffer, ": {}: ", path.display())?; match self { Outcome::Success(tree) => writeln!(buffer, "\n\n{:#?}\n", tree)?, Outcome::Failure(message) | Outcome::Error(message) => { writeln!(buffer, "{}", message)? } } Ok(()) } fn color(&self) -> Color { match self { Outcome::Success(_) => Color::Green, Outcome::Failure(_) => Color::Red, Outcome::Error(_) => Color::Yellow, } } }