use serde::ser::Serialize;
use std::fs::File;
use std::ffi::OsStr;
use std::io::Write;
use std::path::Path;
use backend::*;
use format::{guess_format, Format};
use error::Error;
#[allow(unused_mut)]
pub fn to_string<T>(value: &T, format: Format) -> Result<String, Error>
where
T: Serialize,
{
#[allow(unreachable_patterns)]
match format {
#[cfg(feature = "yaml")]
Format::Yaml => Ok(serde_yaml::to_string(value)?),
#[cfg(feature = "json")]
Format::Json => Ok(serde_json::to_string(value)?),
#[cfg(feature = "toml")]
Format::Toml => Ok(toml::to_string(value)?),
#[cfg(feature = "ron")]
Format::Ron => Ok(ron::ser::to_string(value)?),
#[cfg(feature = "xml")]
Format::Xml => Ok(xml::to_string(value)?),
#[cfg(feature = "url")]
Format::Url => Ok(url::to_string(value)?),
_ => Err(Error::UnsupportedFormat(format)),
}
}
#[allow(unused_mut)]
pub fn to_string_pretty<T>(value: &T, format: Format) -> Result<String, Error>
where
T: Serialize,
{
#[allow(unreachable_patterns)]
match format {
#[cfg(feature = "yaml")]
Format::Yaml => Ok(serde_yaml::to_string(value)?),
#[cfg(feature = "json")]
Format::Json => Ok(serde_json::to_string_pretty(value)?),
#[cfg(feature = "toml")]
Format::Toml => Ok(toml::to_string_pretty(value)?),
#[cfg(feature = "ron")]
Format::Ron => Ok(ron::ser::to_string_pretty(
value,
ron::ser::PrettyConfig::default(),
)?),
#[cfg(feature = "xml")]
Format::Xml => Ok(xml::to_string(value)?),
#[cfg(feature = "url")]
Format::Url => Ok(url::to_string(value)?),
_ => Err(Error::UnsupportedFormat(format)),
}
}
pub fn to_vec<T>(value: &T, format: Format) -> Result<Vec<u8>, Error>
where
T: Serialize,
{
#[allow(unreachable_patterns)]
match format {
#[cfg(feature = "yaml")]
Format::Yaml => Ok(serde_yaml::to_vec(value)?),
#[cfg(feature = "json")]
Format::Json => Ok(serde_json::to_vec(value)?),
#[cfg(feature = "toml")]
Format::Toml => Ok(toml::to_vec(value)?),
#[cfg(feature = "ron")]
Format::Ron => Ok(ron::ser::to_string(value)?.into_bytes()),
#[cfg(feature = "xml")]
Format::Xml => Ok(xml::to_string(value)?.into_bytes()),
#[cfg(feature = "url")]
Format::Url => Ok(url::to_string(value)?.into_bytes()),
_ => Err(Error::UnsupportedFormat(format)),
}
}
pub fn to_vec_pretty<T>(value: &T, format: Format) -> Result<Vec<u8>, Error>
where
T: Serialize,
{
#[allow(unreachable_patterns)]
match format {
#[cfg(feature = "yaml")]
Format::Yaml => Ok(serde_yaml::to_vec(value)?),
#[cfg(feature = "json")]
Format::Json => Ok(serde_json::to_vec_pretty(value)?),
#[cfg(feature = "toml")]
Format::Toml => Ok(toml::ser::to_string_pretty(value)?.into_bytes()),
#[cfg(feature = "ron")]
Format::Ron => Ok(ron::ser::to_string_pretty(value, ron::ser::PrettyConfig::default())?.into_bytes()),
#[cfg(feature = "xml")]
Format::Xml => Ok(xml::to_string(value)?.into_bytes()),
#[cfg(feature = "url")]
Format::Url => Ok(url::to_string(value)?.into_bytes()),
_ => Err(Error::UnsupportedFormat(format)),
}
}
#[allow(unused_mut)]
pub fn to_writer<W, T>(mut writer: W, value: &T, format: Format) -> Result<(), Error>
where
W: Write,
T: Serialize,
{
#[allow(unreachable_patterns)]
match format {
#[cfg(feature = "yaml")]
Format::Yaml => Ok(serde_yaml::to_writer(writer, value)?),
#[cfg(feature = "json")]
Format::Json => Ok(serde_json::to_writer(writer, value)?),
#[cfg(feature = "toml")]
Format::Toml => {
let s = toml::to_vec(value)?;
writer.write(&s)?;
Ok(())
}
#[cfg(feature = "ron")]
Format::Ron => {
let s = ron::ser::to_string(value)?;
write!(&mut writer, "{}", s)?;
Ok(())
}
#[cfg(feature = "xml")]
Format::Xml => Ok(xml::to_writer(writer, value)?),
#[cfg(feature = "url")]
Format::Url => {
let s = url::to_string(value)?;
write!(&mut writer, "{}", s)?;
Ok(())
}
_ => Err(Error::UnsupportedFormat(format)),
}
}
#[allow(unused_mut)]
pub fn to_writer_pretty<W, T>(mut writer: W, value: &T, format: Format) -> Result<(), Error>
where
W: Write,
T: Serialize,
{
#[allow(unreachable_patterns)]
match format {
#[cfg(feature = "yaml")]
Format::Yaml => Ok(serde_yaml::to_writer(writer, value)?),
#[cfg(feature = "json")]
Format::Json => Ok(serde_json::to_writer_pretty(writer, value)?),
#[cfg(feature = "toml")]
Format::Toml => {
let s = toml::to_string_pretty(value)?;
write!(&mut writer, "{}", s)?;
Ok(())
}
#[cfg(feature = "ron")]
Format::Ron => {
let s = ron::ser::to_string_pretty(value, ron::ser::PrettyConfig::default())?;
write!(&mut writer, "{}", s)?;
Ok(())
}
#[cfg(feature = "xml")]
Format::Xml => Ok(xml::to_writer(writer, value)?),
#[cfg(feature = "url")]
Format::Url => {
let s = url::to_string(value)?;
write!(&mut writer, "{}", s)?;
Ok(())
}
_ => Err(Error::UnsupportedFormat(format)),
}
}
pub fn to_file<T, P>(path: P, value: &T) -> Result<(), Error>
where
T: Serialize,
P: AsRef<Path>,
{
let format = guess_format(&path);
match format {
Some(format) => to_writer(File::create(path)?, value, format),
None => {
let ext = path.as_ref()
.extension()
.and_then(OsStr::to_str)
.map(String::from)
.unwrap_or(String::new());
Err(Error::UnsupportedFileExtension(ext))
}
}
}
pub fn to_file_pretty<T, P>(path: P, value: &T) -> Result<(), Error>
where
T: Serialize,
P: AsRef<Path>,
{
let format = guess_format(&path);
match format {
Some(format) => to_writer_pretty(File::create(path)?, value, format),
None => {
let ext = path.as_ref()
.extension()
.and_then(OsStr::to_str)
.map(String::from)
.unwrap_or(String::new());
Err(Error::UnsupportedFileExtension(ext))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::remove_file;
#[derive(Serialize, PartialEq, Debug)]
struct Foo {
size: usize,
bar: Vec<f32>,
}
#[test]
fn unknown_extension_write() {
let foo = Foo {
size: 10,
bar: vec![1.0, 2.0, 4.0, 8.0],
};
let file_name = "ser_foo.dat";
assert_matches!(
to_file(file_name, &foo),
Err(Error::UnsupportedFileExtension(_))
);
assert_matches!(
to_file_pretty(file_name, &foo),
Err(Error::UnsupportedFileExtension(_))
);
remove_file(file_name).ok();
}
}