Outil CLI en Rust pour formater, valider et convertir fichiers JSON, YAML, TOML avec gestion robuste des erreurs et sortie lisible.
use clap::{Arg, Command};
use serde_json::Value as JsonValue;
use std::fs;
use std::path::Path;
// Fonction principale
fn main() {
// Définition CLI avec clap
let matches = Command::new("formattatore")
.version("1.0")
.author("Senior Software Engineer")
.about("Formate et valide les fichiers JSON, YAML et TOML")
.arg(
Arg::new("input")
.help("Fichier d'entrée à traiter")
.required(true)
.index(1),
)
.arg(
Arg::new("output-format")
.help("Format de sortie : json, yaml, toml")
.short('o')
.long("output-format")
.takes_value(true)
.default_value("json"),
)
.get_matches();
// Lecture des arguments
let input_path = matches.get_one::<String>("input").unwrap();
let output_format = matches.get_one::<String>("output-format").unwrap().to_lowercase();
// Lecture du fichier
let content = match fs::read_to_string(input_path) {
Ok(c) => c,
Err(e) => {
eprintln!("Erreur lors de la lecture du fichier '{}': {}", input_path, e);
std::process::exit(1);
}
};
// Détermination du format d'entrée à partir de l'extension
let input_format = match Path::new(input_path).extension().and_then(|s| s.to_str()) {
Some(ext) => ext.to_lowercase(),
None => {
eprintln!("Impossible de déterminer le format à partir du fichier d'entrée");
std::process::exit(1);
}
};
// Analyse et sérialisation
let parsed = match input_format.as_str() {
"json" => parse_json(&content),
"yaml" | "yml" => parse_yaml(&content),
"toml" => parse_toml(&content),
_ => {
eprintln!("Format d'entrée non supporté : {}", input_format);
std::process::exit(1);
}
};
let data = match parsed {
Ok(d) => d,
Err(e) => {
eprintln!("Erreur lors de l'analyse du fichier : {}", e);
std::process::exit(1);
}
};
// Sérialisation dans le format de sortie choisi
let output = match output_format.as_str() {
"json" => serde_json::to_string_pretty(&data),
"yaml" => serde_yaml::to_string(&data),
"toml" => toml::to_string_pretty(&data),
_ => {
eprintln!("Format de sortie non supporté : {}", output_format);
std::process::exit(1);
}
};
match output {
Ok(s) => println!("{}", s),
Err(e) => {
eprintln!("Erreur lors de la sérialisation : {}", e);
std::process::exit(1);
}
}
}
// Fonction pour parser JSON
fn parse_json(input: &str) -> Result<JsonValue, serde_json::Error> {
serde_json::from_str(input)
}
// Fonction pour parser YAML
fn parse_yaml(input: &str) -> Result<JsonValue, serde_yaml::Error> {
serde_yaml::from_str(input)
}
// Fonction pour parser TOML
fn parse_toml(input: &str) -> Result<JsonValue, toml::de::Error> {
// toml::Value n'implémente pas directement Serialize/Deserialize compatible avec JsonValue,
// donc on convertit toml::Value en chaîne JSON puis en JsonValue
let toml_val: toml::Value = toml::from_str(input)?;
let json_str = serde_json::to_string(&toml_val).map_err(|e| toml::de::Error::custom(e.to_string()))?;
let json_val = serde_json::from_str(&json_str).map_err(|e| toml::de::Error::custom(e.to_string()))?;
Ok(json_val)
}CLI : utilise la crate 'clap' pour l'analyse des arguments en ligne de commande.
Parsing : utilise 'serde' avec 'serde_json', 'serde_yaml' et 'toml' pour l'analyse et la sérialisation des formats respectifs.
Sortie : affiche le contenu formaté ou des messages d'erreur détaillés à l'écran.
Dépendances Cargo.toml :Aucun branchement matériel ou câblage requis, étant une application CLI logicielle.
Configuration : aucune configuration externe requise, tout est géré via les arguments CLI.