toasty_cli/migration/
snapshot_file.rs1use anyhow::{Result, bail};
2use serde::{Deserialize, Serialize};
3use std::fmt;
4use std::path::Path;
5use std::str::FromStr;
6use toasty_core::schema::db::Schema;
7use toml_edit::{DocumentMut, Item};
8
9const SNAPSHOT_FILE_VERSION: u32 = 1;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct SnapshotFile {
14 version: u32,
16
17 pub schema: Schema,
19}
20
21impl SnapshotFile {
22 pub fn new(schema: Schema) -> Self {
24 Self {
25 version: SNAPSHOT_FILE_VERSION,
26 schema,
27 }
28 }
29
30 pub fn load(path: impl AsRef<Path>) -> Result<Self> {
32 let contents = std::fs::read_to_string(path.as_ref())?;
33 contents.parse()
34 }
35
36 pub fn save(&self, path: impl AsRef<Path>) -> Result<()> {
38 std::fs::write(path.as_ref(), self.to_string())?;
39 Ok(())
40 }
41}
42
43impl FromStr for SnapshotFile {
44 type Err = anyhow::Error;
45
46 fn from_str(s: &str) -> Result<Self> {
47 let file: SnapshotFile = toml::from_str(s)?;
48
49 if file.version != SNAPSHOT_FILE_VERSION {
51 bail!(
52 "Unsupported snapshot file version: {}. Expected version {}",
53 file.version,
54 SNAPSHOT_FILE_VERSION
55 );
56 }
57
58 Ok(file)
59 }
60}
61
62impl fmt::Display for SnapshotFile {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 let doc = self.to_toml_document().map_err(|_| fmt::Error)?;
65 write!(f, "{}", doc)
66 }
67}
68
69impl SnapshotFile {
70 fn to_toml_document(&self) -> Result<DocumentMut> {
71 let mut doc = toml_edit::ser::to_document(self)?;
72 for (_key, item) in doc.as_table_mut().iter_mut() {
73 if item.is_inline_table() {
74 let mut placeholder = Item::None;
75 std::mem::swap(item, &mut placeholder);
76 let mut table = placeholder.into_table().unwrap();
77
78 for (_key, item) in table.iter_mut() {
79 if item.is_array() {
80 let mut placeholder = Item::None;
81 std::mem::swap(item, &mut placeholder);
82 let mut array = placeholder.into_array_of_tables().unwrap();
83
84 for table in array.iter_mut() {
85 for (_key, item) in table.iter_mut() {
86 if item.is_array() {
87 let mut placeholder = Item::None;
88 std::mem::swap(item, &mut placeholder);
89 let array = placeholder.into_array_of_tables().unwrap();
90 *item = array.into();
91 }
92 }
93 }
94
95 *item = array.into();
96 }
97 }
98
99 *item = table.into();
100 }
101 }
102
103 Ok(doc)
104 }
105}