1use std::path::{Path, PathBuf};
4
5use crate::definition::Definition;
6
7use super::convert::slug_from_name;
8use super::types::{EditorError, EditorModel, EditorSource};
9
10impl EditorModel {
11 pub fn load(path: &Path) -> Result<Self, EditorError> {
13 if !path.exists() {
14 return Err(EditorError::NotFound(path.to_path_buf()));
15 }
16 let content = std::fs::read_to_string(path)?;
17 let def: Definition =
18 serde_json::from_str(&content).map_err(|e| EditorError::InvalidJson(e.to_string()))?;
19 Ok(Self::from_definition(
20 &def,
21 EditorSource::File(path.to_path_buf()),
22 ))
23 }
24
25 pub fn save_to(&self, path: &Path) -> Result<(), EditorError> {
28 let def = self.to_definition();
29 let json = serde_json::to_string_pretty(&def)
30 .map_err(|e| EditorError::InvalidJson(e.to_string()))?;
31
32 if let Some(parent) = path.parent() {
33 std::fs::create_dir_all(parent)?;
34 }
35
36 let temp_path = path.with_extension("bnto.json.tmp");
38 std::fs::write(&temp_path, &json)?;
39 std::fs::rename(&temp_path, path)?;
40
41 Ok(())
42 }
43
44 pub fn save_path(&self, recipes_dir: &Path) -> PathBuf {
49 match &self.source {
50 EditorSource::File(path) => path.clone(),
51 EditorSource::New | EditorSource::Predefined(_) => {
52 let slug = slug_from_name(&self.recipe_name);
53 let filename = if slug.is_empty() {
54 "untitled".to_string()
55 } else {
56 slug
57 };
58 recipes_dir.join(format!("{filename}.bnto.json"))
59 }
60 }
61 }
62}