use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use super::SerializationFormat;
use crate::error::{MetricsError, Result};
#[allow(dead_code)]
pub fn convert_format<T>(
data: &T,
from_format: SerializationFormat,
to_format: SerializationFormat,
) -> Result<Vec<u8>>
where
T: Serialize + for<'de> Deserialize<'de>,
{
if from_format == to_format {
return serialize(data, to_format);
}
let json_value = match from_format {
SerializationFormat::Json => {
serde_json::to_value(data)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?
}
SerializationFormat::Yaml => {
let yaml_str = serde_yaml::to_string(data)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
let yaml_value = serde_yaml::from_str::<serde_yaml::Value>(&yaml_str)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
serde_json::to_value(&yaml_value)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?
}
SerializationFormat::Toml => {
let toml_str = toml::to_string(data)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
let toml_value = toml::from_str::<toml::Value>(&toml_str)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
serde_json::to_value(&toml_value)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?
}
SerializationFormat::Cbor => {
let mut serialized = Vec::new();
ciborium::ser::into_writer(data, &mut serialized)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
let value: ciborium::Value = ciborium::de::from_reader(&serialized[..])
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
serde_json::to_value(value)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?
}
};
match to_format {
SerializationFormat::Json => serde_json::to_vec_pretty(&json_value)
.map_err(|e| MetricsError::SerializationError(e.to_string())),
SerializationFormat::Yaml => {
let yaml = serde_yaml::to_string(&json_value)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
Ok(yaml.into_bytes())
}
SerializationFormat::Toml => {
let json = serde_json::to_string(&json_value)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
let toml_value: toml::Value = serde_json::from_str(&json)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
let toml_str = toml::to_string_pretty(&toml_value)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
Ok(toml_str.into_bytes())
}
SerializationFormat::Cbor => {
let mut bytes = Vec::new();
ciborium::ser::into_writer(&json_value, &mut bytes)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
Ok(bytes)
}
}
}
#[allow(dead_code)]
pub fn convert_file<T, P1, P2>(
input_path: P1,
output_path: P2,
from_format: SerializationFormat,
to_format: SerializationFormat,
) -> Result<()>
where
T: Serialize + for<'de> Deserialize<'de>,
P1: AsRef<Path>,
P2: AsRef<Path>,
{
let data = deserialize_from_file::<T, P1>(input_path, from_format)?;
serialize_to_file(&data, output_path, to_format)
}
#[allow(dead_code)]
pub fn serialize<T>(data: &T, format: SerializationFormat) -> Result<Vec<u8>>
where
T: Serialize,
{
match format {
SerializationFormat::Json => serde_json::to_vec_pretty(data)
.map_err(|e| MetricsError::SerializationError(e.to_string())),
SerializationFormat::Yaml => {
let yaml = serde_yaml::to_string(data)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
Ok(yaml.into_bytes())
}
SerializationFormat::Toml => {
let toml = toml::to_string_pretty(data)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
Ok(toml.into_bytes())
}
SerializationFormat::Cbor => {
let mut bytes = Vec::new();
ciborium::ser::into_writer(data, &mut bytes)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
Ok(bytes)
}
}
}
#[allow(dead_code)]
pub fn deserialize<T>(data: &[u8], format: SerializationFormat) -> Result<T>
where
T: for<'de> Deserialize<'de>,
{
match format {
SerializationFormat::Json => serde_json::from_slice(data)
.map_err(|e| MetricsError::SerializationError(e.to_string())),
SerializationFormat::Yaml => {
let yaml_str = std::str::from_utf8(data)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
serde_yaml::from_str(yaml_str)
.map_err(|e| MetricsError::SerializationError(e.to_string()))
}
SerializationFormat::Toml => {
let toml_str = std::str::from_utf8(data)
.map_err(|e| MetricsError::SerializationError(e.to_string()))?;
toml::from_str(toml_str).map_err(|e| MetricsError::SerializationError(e.to_string()))
}
SerializationFormat::Cbor => ciborium::de::from_reader(data)
.map_err(|e| MetricsError::SerializationError(e.to_string())),
}
}
#[allow(dead_code)]
pub fn serialize_to_file<T, P>(data: &T, path: P, format: SerializationFormat) -> Result<()>
where
T: Serialize,
P: AsRef<Path>,
{
let serialized = serialize(data, format)?;
let mut file = File::create(path).map_err(|e| MetricsError::IOError(e.to_string()))?;
file.write_all(&serialized)
.map_err(|e| MetricsError::IOError(e.to_string()))?;
Ok(())
}
#[allow(dead_code)]
pub fn deserialize_from_file<T, P>(path: P, format: SerializationFormat) -> Result<T>
where
T: for<'de> Deserialize<'de>,
P: AsRef<Path>,
{
let mut file = File::open(path).map_err(|e| MetricsError::IOError(e.to_string()))?;
let mut data = Vec::new();
file.read_to_end(&mut data)
.map_err(|e| MetricsError::IOError(e.to_string()))?;
deserialize(&data, format)
}