1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
use indexmap::IndexMap; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] #[serde(untagged)] enum Itch { Obj(IndexMap<String, Itch>), Array(Vec<Itch>), Bool(bool), Int(i64), Float(f64), Text(String), } pub enum FromType { Json, Toml, Url, Yaml, Xml, } impl std::str::FromStr for FromType { type Err = String; fn from_str(s: &str) -> Result<Self, Self::Err> { match s { "json" => Ok(Self::Json), "qs" => Ok(Self::Url), "toml" => Ok(Self::Toml), "url" => Ok(Self::Url), "xml" => Ok(Self::Xml), "yaml" => Ok(Self::Yaml), _ => Err(format!("could not parse `{}` as an input type", s)), } } } pub enum ToType { Json, Toml, Url, Yaml, Xml, } impl std::str::FromStr for ToType { type Err = String; fn from_str(s: &str) -> Result<Self, Self::Err> { match s { "json" => Ok(Self::Json), "qs" => Ok(Self::Url), "toml" => Ok(Self::Toml), "url" => Ok(Self::Url), "xml" => Ok(Self::Xml), "yaml" => Ok(Self::Yaml), _ => Err(format!("could not parse `{}` as an output type", s)), } } } pub fn convert<From: std::io::Read, To: std::io::Write>( from_type: &FromType, to_type: &ToType, mut input: From, mut output: To, ) -> Result<(), String> { let itch: Itch = match from_type { FromType::Json => serde_json::from_reader(input) .map_err(|e| format!("error parsing json: `{}`", e))?, FromType::Xml => serde_xml_rs::from_reader(input) .map_err(|e| format!("error parsing xml: `{}`", e))?, FromType::Yaml => serde_yaml::from_reader(input) .map_err(|e| format!("error parsing yaml: `{}`", e))?, FromType::Toml => { let mut s = String::new(); input .read_to_string(&mut s) .map_err(|e| format!("error parsing toml: `{}`", e))?; toml::from_str(&s).map_err(|e| format!("error parsing toml: `{}`", e))? } FromType::Url => { let mut s = String::new(); input .read_to_string(&mut s) .map_err(|e| format!("error parsing url query string: `{}`", e))?; serde_qs::from_str(&s) .map_err(|e| format!("error parsing url query string: `{}`", e))? } }; match to_type { ToType::Json => serde_json::to_writer(output, &itch).map_err(|e| { dbg!(&e); format!("error outputting json: `{}`", e) })?, ToType::Url => serde_qs::to_writer(&itch, &mut output) .map_err(|e| format!("error outputting url query string: `{}`", e))?, ToType::Xml => serde_xml_rs::to_writer(output, &itch) .map_err(|e| format!("error outputting xml: `{}`", e))?, ToType::Yaml => serde_yaml::to_writer(output, &itch) .map_err(|e| format!("error outputting yaml: `{}`", e))?, ToType::Toml => { let s = toml::to_string_pretty(&itch) .map_err(|e| format!("error outputting toml: `{}`", e))?; output .write(s.as_bytes()) .map(|_| ()) .map_err(|e| format!("error outputting toml: `{}`", e))? } }; Ok(()) }