1// Copyright (C) 2019 Maxime “pep” Buquet <pep@bouah.net>
2// This Source Code Form is subject to the terms of the Mozilla Public
3// License, v. 2.0. If a copy of the MPL was not distributed with this
4// file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6use crate::data_forms::{DataForm, DataFormType, Field, FieldType};
7use crate::ns;
8use crate::util::error::Error;
9use std::convert::TryFrom;
10
11/// Structure representing a `http://jabber.org/network/serverinfo` form type.
12#[derive(Debug, Clone, PartialEq, Default)]
13pub struct ServerInfo {
14 /// Abuse addresses
15 pub abuse: Vec<String>,
16
17 /// Admin addresses
18 pub admin: Vec<String>,
19
20 /// Feedback addresses
21 pub feedback: Vec<String>,
22
23 /// Sales addresses
24 pub sales: Vec<String>,
25
26 /// Security addresses
27 pub security: Vec<String>,
28
29 /// Support addresses
30 pub support: Vec<String>,
31}
32
33impl TryFrom<DataForm> for ServerInfo {
34 type Error = Error;
35
36 fn try_from(form: DataForm) -> Result<ServerInfo, Error> {
37 if form.type_ != DataFormType::Result_ {
38 return Err(Error::ParseError("Wrong type of form."));
39 }
40 if form.form_type != Some(String::from(ns::SERVER_INFO)) {
41 return Err(Error::ParseError("Wrong FORM_TYPE for form."));
42 }
43 let mut server_info = ServerInfo::default();
44 for field in form.fields {
45 if field.type_ != FieldType::ListMulti {
46 return Err(Error::ParseError("Field is not of the required type."));
47 }
48 if field.var == "abuse-addresses" {
49 server_info.abuse = field.values;
50 } else if field.var == "admin-addresses" {
51 server_info.admin = field.values;
52 } else if field.var == "feedback-addresses" {
53 server_info.feedback = field.values;
54 } else if field.var == "sales-addresses" {
55 server_info.sales = field.values;
56 } else if field.var == "security-addresses" {
57 server_info.security = field.values;
58 } else if field.var == "support-addresses" {
59 server_info.support = field.values;
60 } else {
61 return Err(Error::ParseError("Unknown form field var."));
62 }
63 }
64
65 Ok(server_info)
66 }
67}
68
69impl From<ServerInfo> for DataForm {
70 fn from(server_info: ServerInfo) -> DataForm {
71 DataForm {
72 type_: DataFormType::Result_,
73 form_type: Some(String::from(ns::SERVER_INFO)),
74 title: None,
75 instructions: None,
76 fields: vec![
77 generate_address_field("abuse-addresses", server_info.abuse),
78 generate_address_field("admin-addresses", server_info.admin),
79 generate_address_field("feedback-addresses", server_info.feedback),
80 generate_address_field("sales-addresses", server_info.sales),
81 generate_address_field("security-addresses", server_info.security),
82 generate_address_field("support-addresses", server_info.support),
83 ],
84 }
85 }
86}
87
88/// Generate `Field` for addresses
89pub fn generate_address_field<S: Into<String>>(var: S, values: Vec<String>) -> Field {
90 Field {
91 var: var.into(),
92 type_: FieldType::ListMulti,
93 label: None,
94 required: false,
95 options: vec![],
96 values,
97 media: vec![],
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::data_forms::{DataForm, DataFormType, Field, FieldType};
105
106 #[cfg(target_pointer_width = "32")]
107 #[test]
108 fn test_size() {
109 assert_size!(ServerInfo, 72);
110 }
111
112 #[cfg(target_pointer_width = "64")]
113 #[test]
114 fn test_size() {
115 assert_size!(ServerInfo, 144);
116 }
117
118 #[test]
119 fn test_simple() {
120 let form = DataForm {
121 type_: DataFormType::Result_,
122 form_type: Some(String::from(ns::SERVER_INFO)),
123 title: None,
124 instructions: None,
125 fields: vec![
126 Field {
127 var: String::from("abuse-addresses"),
128 type_: FieldType::ListMulti,
129 label: None,
130 required: false,
131 options: vec![],
132 values: vec![],
133 media: vec![],
134 },
135 Field {
136 var: String::from("admin-addresses"),
137 type_: FieldType::ListMulti,
138 label: None,
139 required: false,
140 options: vec![],
141 values: vec![
142 String::from("xmpp:admin@foo.bar"),
143 String::from("https://foo.bar/chat/"),
144 String::from("mailto:admin@foo.bar"),
145 ],
146 media: vec![],
147 },
148 Field {
149 var: String::from("feedback-addresses"),
150 type_: FieldType::ListMulti,
151 label: None,
152 required: false,
153 options: vec![],
154 values: vec![],
155 media: vec![],
156 },
157 Field {
158 var: String::from("sales-addresses"),
159 type_: FieldType::ListMulti,
160 label: None,
161 required: false,
162 options: vec![],
163 values: vec![],
164 media: vec![],
165 },
166 Field {
167 var: String::from("security-addresses"),
168 type_: FieldType::ListMulti,
169 label: None,
170 required: false,
171 options: vec![],
172 values: vec![
173 String::from("xmpp:security@foo.bar"),
174 String::from("mailto:security@foo.bar"),
175 ],
176 media: vec![],
177 },
178 Field {
179 var: String::from("support-addresses"),
180 type_: FieldType::ListMulti,
181 label: None,
182 required: false,
183 options: vec![],
184 values: vec![String::from("mailto:support@foo.bar")],
185 media: vec![],
186 },
187 ],
188 };
189
190 let server_info = ServerInfo {
191 abuse: vec![],
192 admin: vec![
193 String::from("xmpp:admin@foo.bar"),
194 String::from("https://foo.bar/chat/"),
195 String::from("mailto:admin@foo.bar"),
196 ],
197 feedback: vec![],
198 sales: vec![],
199 security: vec![
200 String::from("xmpp:security@foo.bar"),
201 String::from("mailto:security@foo.bar"),
202 ],
203 support: vec![String::from("mailto:support@foo.bar")],
204 };
205
206 // assert_eq!(DataForm::from(server_info), form);
207 assert_eq!(ServerInfo::try_from(form).unwrap(), server_info);
208 }
209}