wireman_core/descriptor/
message.rs1mod template;
2
3use self::template::apply_template_for_message;
4use crate::{
5 error::{Error, FROM_UTF8},
6 Result,
7};
8use prost_reflect::{
9 DeserializeOptions, DynamicMessage as DynMessage, MessageDescriptor, ReflectMessage,
10 SerializeOptions,
11};
12use serde::{Serialize, Serializer};
13use std::ops::{Deref, DerefMut};
14
15#[derive(Debug, Clone)]
18pub struct DynamicMessage {
19 inner: DynMessage,
20}
21
22impl Deref for DynamicMessage {
23 type Target = DynMessage;
24
25 fn deref(&self) -> &DynMessage {
26 &self.inner
27 }
28}
29
30impl DerefMut for DynamicMessage {
31 fn deref_mut(&mut self) -> &mut Self::Target {
32 &mut self.inner
33 }
34}
35
36type JsonSerializer = serde_json::Serializer<Vec<u8>>;
37
38impl DynamicMessage {
39 #[must_use]
41 pub fn new(message_desc: MessageDescriptor) -> Self {
42 let message = DynMessage::new(message_desc);
43 Self { inner: message }
44 }
45
46 #[must_use]
48 pub fn message_name(&self) -> String {
49 self.descriptor().name().to_string()
50 }
51
52 #[must_use]
54 pub fn descriptor(&self) -> MessageDescriptor {
55 self.inner.descriptor()
56 }
57
58 pub fn from_json(&mut self, json: &str) -> Result<()> {
64 let mut de = serde_json::Deserializer::from_str(json);
65 let msg = DynMessage::deserialize_with_options(
66 self.descriptor(),
67 &mut de,
68 &DeserializeOptions::new(),
69 )
70 .map_err(Error::DeserializeMessage)?;
71 de.end().map_err(Error::DeserializeMessage)?;
72 self.inner = msg;
73 Ok(())
74 }
75
76 pub fn to_json(&self) -> Result<String> {
83 let mut s = serde_json::Serializer::new(Vec::new());
84 self.serialize(&mut s).map_err(Error::SerializeJsonError)?;
85 String::from_utf8(s.into_inner()).map_err(|_| Error::Internal(FROM_UTF8.to_string()))
86 }
87
88 pub fn apply_template(&mut self) {
90 apply_template_for_message(self, 0);
91 }
92}
93
94impl Serialize for DynamicMessage {
95 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
96 where
97 S: Serializer,
98 {
99 self.inner.serialize_with_options(
100 serializer,
101 &SerializeOptions::new()
102 .stringify_64_bit_integers(false)
103 .skip_default_fields(false),
104 )
105 }
106}
107
108#[cfg(test)]
109mod test {
110 use crate::ProtoDescriptor;
111
112 use super::*;
113
114 #[test]
115 fn test_template_nested() {
116 let mut given_message = load_test_message("Nested");
118 let expected_json = "{\"items\":[{\"number\":0,\"text\":\"\"}]}";
119
120 given_message.apply_template();
122 let json = given_message.to_json().unwrap();
123
124 assert_eq!(json, expected_json);
126 }
127
128 #[test]
129 fn test_template_repeated() {
130 let mut given_message = load_test_message("Repeated");
132 let expected_json = "{\"number\":[0]}";
133
134 given_message.apply_template();
136 let json = given_message.to_json().unwrap();
137
138 assert_eq!(json, expected_json);
140 }
141
142 #[test]
143 fn test_template_enum() {
144 let mut given_message = load_test_message("Enum");
146 let expected_json = "{\"color\":\"NONE\"}";
147
148 given_message.apply_template();
150 let json = given_message.to_json().unwrap();
151
152 assert_eq!(json, expected_json);
154 }
155
156 fn load_test_message(method: &str) -> DynamicMessage {
157 let files = vec!["test_files/test.proto"];
158 let includes = vec!["."];
159
160 let desc = ProtoDescriptor::new(includes, files).unwrap();
161
162 let method = desc
163 .get_method_by_name("proto.TestService", method)
164 .unwrap();
165 let request = method.input();
166 DynamicMessage::new(request)
167 }
168
169 #[test]
170 fn test_to_json() {
171 let given_message = load_test_message("Simple");
173
174 let json = given_message.to_json().unwrap();
176
177 let expected_json = "{\"number\":0}";
179 assert_eq!(json, expected_json);
180 }
181
182 #[test]
183 fn test_from_json() {
184 let mut given_message = load_test_message("Multiple");
186 let given_json = "{\"number\":1}";
187 given_message.from_json(given_json).unwrap();
188
189 let json = given_message.to_json().unwrap();
191
192 let expected_json = "{\"id\":\"\",\"number\":1}";
194 assert_eq!(json, expected_json);
195 }
196}