1use crate::coreobj::CoreObjectType;
2use cyfs_base::*;
3use serde::Serialize;
4
5#[derive(Debug, Clone, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)]
6#[cyfs_protobuf_type(crate::codec::protos::TextDescContent)]
7pub struct TextDescContent {
8 id: String,
9 header: String,
10}
11impl TextDescContent {
12 pub fn id(&self) -> &str {
13 &self.id
14 }
15
16 pub fn header(&self) -> &str {
17 &self.header
18 }
19
20 pub fn header_mut(&mut self) -> &mut String {
21 &mut self.header
22 }
23}
24
25impl DescContent for TextDescContent {
26 fn obj_type() -> u16 {
27 CoreObjectType::Text as u16
28 }
29
30 fn format(&self) -> u8 {
31 OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF
32 }
33
34 type OwnerType = Option<ObjectId>;
35 type AreaType = SubDescNone;
36 type AuthorType = SubDescNone;
37 type PublicKeyType = SubDescNone;
38}
39
40#[derive(Clone, Debug, ProtobufEncode, ProtobufDecode, ProtobufTransform, Serialize)]
41#[cyfs_protobuf_type(crate::codec::protos::TextContent)]
42pub struct TextContent {
43 value: String,
44}
45
46impl BodyContent for TextContent {
47 fn format(&self) -> u8 {
48 OBJECT_CONTENT_CODEC_FORMAT_PROTOBUF
49 }
50}
51
52impl TextContent {
53 pub fn value(&self) -> &str {
54 &self.value
55 }
56
57 pub fn value_mut(&mut self) -> &mut String {
58 &mut self.value
59 }
60}
61
62type TextType = NamedObjType<TextDescContent, TextContent>;
63type TextBuilder = NamedObjectBuilder<TextDescContent, TextContent>;
64type TextDesc = NamedObjectDesc<TextDescContent>;
65
66pub type TextId = NamedObjectId<TextType>;
67pub type Text = NamedObjectBase<TextType>;
68
69pub trait TextObj {
70 fn build(id: &str, header: impl Into<String>, value: impl Into<String>) -> TextBuilder;
71 fn create(id: &str, header: impl Into<String>, value: impl Into<String>) -> Self;
72
73 fn id(&self) -> &str;
74
75 fn header(&self) -> &str;
76 fn header_mut(&mut self) -> &mut String;
77
78 fn value(&self) -> &str;
79 fn value_mut(&mut self) -> &mut String;
80
81 fn into_header(self) -> String;
82 fn into_value(self) -> String;
83
84 fn text_id(&self) -> TextId;
85}
86
87impl TextObj for Text {
88 fn create(id: &str, header: impl Into<String>, value: impl Into<String>) -> Self {
89 Self::build(id, header, value).no_create_time().build()
90 }
91
92 fn build(id: &str, header: impl Into<String>, value: impl Into<String>) -> TextBuilder {
93 let desc = TextDescContent {
94 id: id.to_owned(),
95 header: header.into(),
96 };
97 let body = TextContent {
98 value: value.into(),
99 };
100 TextBuilder::new(desc, body)
101 }
102
103 fn id(&self) -> &str {
104 &self.desc().content().id
105 }
106
107 fn header(&self) -> &str {
108 &self.desc().content().header
109 }
110
111 fn header_mut(&mut self) -> &mut String {
112 self.desc_mut().content_mut().header_mut()
113 }
114
115 fn value(&self) -> &str {
116 self.body().as_ref().unwrap().content().value()
117 }
118
119 fn value_mut(&mut self) -> &mut String {
120 self.body_mut().as_mut().unwrap().content_mut().value_mut()
121 }
122
123 fn into_header(self) -> String {
124 self.into_desc().into_content().header
125 }
126
127 fn into_value(self) -> String {
128 self.into_body().unwrap().into_content().value.to_string()
129 }
130
131 fn text_id(&self) -> TextId {
132 self.desc().calculate_id().try_into().unwrap()
133 }
134}
135
136#[cfg(test)]
137mod test {
138 use crate::*;
139 use cyfs_base::*;
140
141 #[test]
142 fn test() {
143 let header = "cyfs system";
144 let value = "xxxxx";
145 let obj = Text::create("cyfs", header, value);
146 assert!(obj.desc().content().id() == "cyfs");
147
148 let obj2 = obj.clone();
149 let header2 = obj2.into_header();
150 assert_eq!(header2, header);
151
152 let obj2 = obj.clone();
153 let value2 = obj2.into_value();
154 assert_eq!(value2, value);
155
156 let value = "yyyyyyy";
157 let mut obj2 = obj.clone();
158 *obj2.value_mut() = value.to_owned();
159 let value2 = obj2.into_value();
160 assert_eq!(value2, value);
161 }
162
163 #[test]
164 fn test_empty() {
165 let text_obj = Text::create("", "", "");
166 let buf = text_obj.to_vec().unwrap();
167
168 println!("empty text_id: {}", text_obj.text_id());
169 let path = cyfs_util::get_app_data_dir("tests");
170 std::fs::create_dir_all(&path).unwrap();
171 let name = path.join("text_empty.desc");
172 std::fs::write(&name, buf).unwrap();
173 }
174
175 #[test]
176 fn test_codec() {
177 let id = "test_text";
178 let header = "test_header";
179 let value = "test_value";
180 let text_obj = Text::create(id, header, value);
181 let text_id = text_obj.desc().calculate_id();
182 let buf = text_obj.to_vec().unwrap();
183
184 let text_obj2 = Text::clone_from_slice(&buf).unwrap();
185 assert_eq!(text_id, text_obj2.desc().calculate_id());
186 assert_eq!(text_obj.id(), text_obj2.id());
187 assert_eq!(text_obj.header(), text_obj2.header());
188 assert_eq!(text_obj.value(), text_obj2.value());
189
190 let (any, left_buf) = AnyNamedObject::raw_decode(&buf).unwrap();
191 assert_eq!(left_buf.len(), 0);
192 info!("any id={}", any.calculate_id());
193 assert_eq!(text_id, any.calculate_id());
194
195 let buf2 = any.to_vec().unwrap();
196 assert_eq!(buf.len(), buf2.len());
197 assert_eq!(buf, buf2);
198
199 let path = cyfs_util::get_app_data_dir("tests");
201 std::fs::create_dir_all(&path).unwrap();
202 let name = path.join("text.desc");
203 std::fs::write(&name, buf2).unwrap();
204 }
205}