Mountain/ApplicationState/DTO/
CustomDocumentStateDTO.rs1use std::collections::HashMap;
17
18use serde::{Deserialize, Serialize};
19use url::Url;
20use CommonLibrary::Utility::Serialization::URLSerializationHelper;
21
22const MAX_VIEW_TYPE_LENGTH:usize = 256;
24
25const MAX_SIDECAR_IDENTIFIER_LENGTH:usize = 128;
27
28const MAX_EDITS_PER_DOCUMENT:usize = 1000;
30
31#[derive(Serialize, Deserialize, Debug, Clone)]
35#[serde(rename_all = "PascalCase")]
36pub struct CustomDocumentStateDTO {
37 #[serde(with = "URLSerializationHelper")]
39 pub URI:Url,
40
41 #[serde(skip_serializing_if = "String::is_empty")]
43 pub ViewType:String,
44
45 #[serde(skip_serializing_if = "String::is_empty")]
48 pub SideCarIdentifier:String,
49
50 pub IsEditable:bool,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub BackupIdentifier:Option<String>,
56
57 #[serde(skip_serializing_if = "HashMap::is_empty")]
60 pub Edits:HashMap<u32, serde_json::Value>,
61}
62
63impl CustomDocumentStateDTO {
64 pub fn New(URI:Url, ViewType:String, SideCarIdentifier:String, IsEditable:bool) -> Result<Self, String> {
75 if ViewType.len() > MAX_VIEW_TYPE_LENGTH {
77 return Err(format!("ViewType exceeds maximum length of {} bytes", MAX_VIEW_TYPE_LENGTH));
78 }
79
80 if SideCarIdentifier.len() > MAX_SIDECAR_IDENTIFIER_LENGTH {
82 return Err(format!(
83 "SideCarIdentifier exceeds maximum length of {} bytes",
84 MAX_SIDECAR_IDENTIFIER_LENGTH
85 ));
86 }
87
88 if URI.as_str().is_empty() {
90 return Err("URI cannot be empty".to_string());
91 }
92
93 Ok(Self {
94 URI,
95 ViewType,
96 SideCarIdentifier,
97 IsEditable,
98 BackupIdentifier:None,
99 Edits:HashMap::new(),
100 })
101 }
102
103 pub fn AddEdit(&mut self, EditID:u32, EditData:serde_json::Value) -> Result<(), String> {
112 if self.Edits.len() >= MAX_EDITS_PER_DOCUMENT {
113 return Err(format!("Maximum edit limit of {} reached for document", MAX_EDITS_PER_DOCUMENT));
114 }
115
116 self.Edits.insert(EditID, EditData);
117 Ok(())
118 }
119
120 pub fn ClearEdits(&mut self) { self.Edits.clear(); }
122
123 pub fn GetEditCount(&self) -> usize { self.Edits.len() }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn test_creation_success() {
133 let URI = Url::parse("file:///test/document.md").unwrap();
134 let dto =
135 CustomDocumentStateDTO::New(URI.clone(), "markdown.editor".to_string(), "sidecar-123".to_string(), true);
136 assert!(dto.is_ok());
137 assert_eq!(dto.unwrap().ViewType, "markdown.editor");
138 }
139
140 #[test]
141 fn test_invalid_view_type_length() {
142 let URI = Url::parse("file:///test/document.md").unwrap();
143 let LongViewType = "a".repeat(257);
144 let dto = CustomDocumentStateDTO::New(URI, LongViewType, "sidecar-123".to_string(), true);
145 assert!(dto.is_err());
146 }
147}