💾
Rustで簡単にstructを保存するtraitを作る
概要
- structをserdeを用いてjsonやtomlにシリアライズする
- シリアライズされた文字列をfsなどでファイルに保存する
- 保存されたファイルからデシアライズして、読み出す
Code
以下のコードはtoml用。<P: AsRef<Path>>
はtrait全体でまとめても良いかも。
Cargo.toml
[dependencies]
serde = {version = "1.0.219", features = ["derive"]}
toml = "0.9.5"
storable.rs
// serdeはシリアライズとデシアライズのため
use serde::{Serialize, de::DeserializeOwned};
// io関連
use std::{
fs::{self, OpenOptions},
io::{self, Write},
path::Path,
};
// tomlをパースするため
use toml::{from_str, to_string_pretty};
#[derive(Debug)]
pub enum Error {
IoE(io::Error),
ParTomlE(toml::ser::Error),
DesTomlE(toml::de::Error),
}
pub trait Storable {
/// pathは保存先
/// new_createは新規作成を許可するかどうか。OpenOptionsの.create()にそのまま渡される
fn save<P: AsRef<Path>>(&self, path: P, new_create: bool) -> Result<(), Error>
where
// Selfは`Serialize`と`Deserialize`をderiveなどで付与している必要がある
Self: Serialize + DeserializeOwned,
{
let s = to_string_pretty(self).map_err(Error::ParTomlE)?;
let mut f = OpenOptions::new()
.write(true)
.truncate(true)
.create(new_create)
.open(path)
.map_err(Error::IoE)?;
f.write_all(s.as_bytes()).map_err(Error::IoE)
}
// 戻り値はSelf
fn load<P: AsRef<Path>>(path: P) -> Result<Self, Error>
where
Self: Serialize + DeserializeOwned,
{
let file_content = fs::read_to_string(path).map_err(Error::IoE)?;
from_str::<Self>(&file_content).map_err(Error::DesTomlE)
}
}
Example
ex.rust
#[derive(Debug, Serialize, Deserialize)]
struct Person {
name: String,
age: u32,
os: Os,
}
impl Storable for Person {}
#[derive(Debug, Serialize, Deserialize)]
enum Os {
Mac,
Linux,
Windows,
}
fn main() {
let mike = Person {
name: "Mike".to_string(),
age: 20,
os: Os::Linux,
};
mike.save("./users/mike.toml", true).unwrap();
let loaded_mike = Person::load("./users/mike.toml").unwrap();
println!("{loaded_mike:?}");
}
Exampleのコードはunwrapしまくりなので注意。jsonの場合はserde_json
を使うとほぼ同じ手順で行ける。
Discussion