use std::io::{self, Read, Write};
use std::path::Path;
pub fn to_bincode<T: serde::Serialize>(value: &T) -> io::Result<Vec<u8>> {
bincode::serialize(value).map_err(io::Error::other)
}
pub fn from_bincode<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> io::Result<T> {
bincode::deserialize(bytes).map_err(io::Error::other)
}
pub fn to_json_pretty<T: serde::Serialize>(value: &T) -> io::Result<String> {
serde_json::to_string_pretty(value).map_err(io::Error::other)
}
pub fn to_json<T: serde::Serialize>(value: &T) -> io::Result<String> {
serde_json::to_string(value).map_err(io::Error::other)
}
pub fn from_json<T: serde::de::DeserializeOwned>(json: &str) -> io::Result<T> {
serde_json::from_str(json).map_err(io::Error::other)
}
pub fn write_bincode_file<P: AsRef<Path>, T: serde::Serialize>(
path: P,
value: &T,
) -> io::Result<()> {
let bytes = to_bincode(value)?;
std::fs::write(path, bytes)
}
pub fn read_bincode_file<P: AsRef<Path>, T: serde::de::DeserializeOwned>(path: P) -> io::Result<T> {
let bytes = std::fs::read(path)?;
from_bincode(&bytes)
}
pub fn write_json_file<P: AsRef<Path>, T: serde::Serialize>(path: P, value: &T) -> io::Result<()> {
let file = std::fs::File::create(path)?;
serde_json::to_writer_pretty(file, value).map_err(io::Error::other)
}
pub fn read_json_file<P: AsRef<Path>, T: serde::de::DeserializeOwned>(path: P) -> io::Result<T> {
let file = std::fs::File::open(path)?;
serde_json::from_reader(file).map_err(io::Error::other)
}
pub fn write_bincode<W: Write, T: serde::Serialize>(writer: &mut W, value: &T) -> io::Result<()> {
let bytes = to_bincode(value)?;
writer.write_all(&bytes)
}
pub fn read_bincode<R: Read, T: serde::de::DeserializeOwned>(reader: &mut R) -> io::Result<T> {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes)?;
from_bincode(&bytes)
}
pub fn write_json_pretty<W: Write, T: serde::Serialize>(
writer: &mut W,
value: &T,
) -> io::Result<()> {
serde_json::to_writer_pretty(writer, value).map_err(io::Error::other)
}
pub fn write_json_compact<W: Write, T: serde::Serialize>(
writer: &mut W,
value: &T,
) -> io::Result<()> {
serde_json::to_writer(writer, value).map_err(io::Error::other)
}
pub fn read_json<R: Read, T: serde::de::DeserializeOwned>(reader: &mut R) -> io::Result<T> {
serde_json::from_reader(reader).map_err(io::Error::other)
}
#[cfg(feature = "async")]
pub mod async_serialize {
use std::io;
use std::path::Path;
use tokio::io::AsyncWriteExt;
pub async fn write_bincode_file<P: AsRef<Path>, T: serde::Serialize>(
path: P,
value: &T,
) -> io::Result<()> {
let bytes = super::to_bincode(value)?;
tokio::fs::write(path, bytes).await
}
pub async fn read_bincode_file<P: AsRef<Path>, T: serde::de::DeserializeOwned>(
path: P,
) -> io::Result<T> {
let bytes = tokio::fs::read(path).await?;
super::from_bincode(&bytes)
}
pub async fn write_json_file<P: AsRef<Path>, T: serde::Serialize>(
path: P,
value: &T,
) -> io::Result<()> {
let json = super::to_json_pretty(value)?;
tokio::fs::write(path, json.as_bytes()).await
}
pub async fn read_json_file<P: AsRef<Path>, T: serde::de::DeserializeOwned>(
path: P,
) -> io::Result<T> {
let bytes = tokio::fs::read(path).await?;
let json = String::from_utf8(bytes).map_err(io::Error::other)?;
super::from_json(&json)
}
pub async fn write_bincode<W: AsyncWriteExt + Unpin, T: serde::Serialize>(
writer: &mut W,
value: &T,
) -> io::Result<()> {
let bytes = super::to_bincode(value)?;
writer.write_all(&bytes).await
}
pub async fn write_json_pretty<W: AsyncWriteExt + Unpin, T: serde::Serialize>(
writer: &mut W,
value: &T,
) -> io::Result<()> {
let json = super::to_json_pretty(value)?;
writer.write_all(json.as_bytes()).await
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct TestData {
id: u32,
name: String,
values: Vec<i32>,
}
impl TestData {
fn sample() -> Self {
TestData {
id: 42,
name: "test".to_string(),
values: vec![1, 2, 3],
}
}
}
#[test]
fn test_bincode_roundtrip() {
let data = TestData::sample();
let bytes = to_bincode(&data).unwrap();
let decoded: TestData = from_bincode(&bytes).unwrap();
assert_eq!(data, decoded);
}
#[test]
fn test_json_roundtrip() {
let data = TestData::sample();
let json = to_json(&data).unwrap();
let decoded: TestData = from_json(&json).unwrap();
assert_eq!(data, decoded);
}
#[test]
fn test_json_pretty() {
let data = TestData::sample();
let json = to_json_pretty(&data).unwrap();
assert!(json.contains('\n')); assert!(json.contains(" ")); }
}