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)]
34pub struct SnapshotFile {
35 version: u32,
37
38 pub schema: Schema,
40}
41
42impl SnapshotFile {
43 pub fn new(schema: Schema) -> Self {
45 Self {
46 version: SNAPSHOT_FILE_VERSION,
47 schema,
48 }
49 }
50
51 pub fn load(path: impl AsRef<Path>) -> Result<Self> {
53 let contents = std::fs::read_to_string(path.as_ref())?;
54 contents.parse()
55 }
56
57 pub fn save(&self, path: impl AsRef<Path>) -> Result<()> {
59 std::fs::write(path.as_ref(), self.to_string())?;
60 Ok(())
61 }
62}
63
64impl FromStr for SnapshotFile {
65 type Err = anyhow::Error;
66
67 fn from_str(s: &str) -> Result<Self> {
68 let file: SnapshotFile = toml::from_str(s)?;
69
70 if file.version != SNAPSHOT_FILE_VERSION {
72 bail!(
73 "Unsupported snapshot file version: {}. Expected version {}",
74 file.version,
75 SNAPSHOT_FILE_VERSION
76 );
77 }
78
79 Ok(file)
80 }
81}
82
83impl fmt::Display for SnapshotFile {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 let doc = self.to_toml_document().map_err(|_| fmt::Error)?;
86 write!(f, "{}", doc)
87 }
88}
89
90impl SnapshotFile {
91 fn to_toml_document(&self) -> Result<DocumentMut> {
92 let mut doc = toml_edit::ser::to_document(self)?;
93 for (_key, item) in doc.as_table_mut().iter_mut() {
94 if item.is_inline_table() {
95 let mut placeholder = Item::None;
96 std::mem::swap(item, &mut placeholder);
97 let mut table = placeholder.into_table().unwrap();
98
99 for (_key, item) in table.iter_mut() {
100 if item.is_array() {
101 let mut placeholder = Item::None;
102 std::mem::swap(item, &mut placeholder);
103 let mut array = placeholder.into_array_of_tables().unwrap();
104
105 for table in array.iter_mut() {
106 for (_key, item) in table.iter_mut() {
107 if item.is_array() {
108 let mut placeholder = Item::None;
109 std::mem::swap(item, &mut placeholder);
110 let array = placeholder.into_array_of_tables().unwrap();
111 *item = array.into();
112 }
113 }
114 }
115
116 *item = array.into();
117 }
118 }
119
120 *item = table.into();
121 }
122 }
123
124 Ok(doc)
125 }
126}