strop_core/buffer/
seed.rs1use serde::{Deserialize, Serialize};
6
7use super::Buffer;
8use crate::history::History;
9use crate::id::BufferRevision;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct BufferSeed {
16 pub text: String,
17 pub revision: BufferRevision,
18 pub history: History,
19 #[serde(with = "crate::path_serde::option")]
20 pub path: Option<std::path::PathBuf>,
21 pub name: Option<String>,
22 pub dirty: bool,
23 pub readonly: bool,
24 pub disk_stamp: Option<std::time::SystemTime>,
25 #[serde(with = "crate::path_serde::option")]
26 pub file_identity: Option<std::path::PathBuf>,
27}
28
29impl Buffer {
30 pub fn seed(&self) -> BufferSeed {
31 BufferSeed {
32 text: self.rope.to_string(),
33 revision: self.revision(),
34 history: self.history.clone(),
35 path: self.path.clone(),
36 name: self.name.clone(),
37 dirty: self.dirty,
38 readonly: self.readonly,
39 disk_stamp: self.disk_stamp,
40 file_identity: self.file_identity.clone(),
41 }
42 }
43}
44
45impl BufferSeed {
46 pub fn into_buffer(self) -> Result<Buffer, crate::history::HistoryError> {
49 let mut buffer = Buffer::from_text(&self.text);
50 buffer.restore_history(self.history)?;
51 buffer.epoch = self.revision.get();
52 buffer.path = self.path;
53 buffer.name = self.name;
54 buffer.dirty = self.dirty;
55 buffer.readonly = self.readonly;
56 buffer.disk_stamp = self.disk_stamp;
57 buffer.file_identity = self.file_identity;
58 Ok(buffer)
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn seed_round_trips_content_history_and_disk_baseline() {
68 let mut buffer = Buffer::from_text("line\nline two\n");
69 buffer.begin_undo_group();
70 buffer
71 .edit()
72 .replace(crate::Range::charwise(5, 8), "XY")
73 .unwrap();
74 buffer.commit_undo_group();
75 buffer.dirty = true;
76 buffer.disk_stamp = Some(std::time::UNIX_EPOCH);
77 let seed = buffer.seed();
78 let mut restored = seed.into_buffer().unwrap();
79 assert_eq!(restored.text().to_string(), "line\nXYe two\n");
80 restored.undo().unwrap();
82 assert_eq!(restored.text().to_string(), "line\nline two\n");
83 }
84
85 #[test]
86 fn history_that_disagrees_with_text_is_rejected() {
87 let mut buffer = Buffer::from_text("abc\n");
88 buffer.begin_undo_group();
89 buffer
90 .edit()
91 .replace(crate::Range::charwise(0, 1), "z")
92 .unwrap();
93 buffer.commit_undo_group();
94 let mut seed = buffer.seed();
95 seed.text = "different bytes\n".into();
96 assert!(seed.into_buffer().is_err());
97 }
98}