1use crate::xml_escape::{escape_xml_attr, escape_xml_text};
23use crate::TwiML;
24
25#[derive(Debug, Clone, PartialEq)]
27pub enum ReceiveMediaType {
28 ApplicationPdf,
30 ImageTiff,
32}
33
34impl ReceiveMediaType {
35 fn as_str(&self) -> &str {
36 match self {
37 ReceiveMediaType::ApplicationPdf => "application/pdf",
38 ReceiveMediaType::ImageTiff => "image/tiff",
39 }
40 }
41}
42
43#[derive(Debug, Clone, PartialEq)]
45pub enum ReceivePageSize {
46 Letter,
48 Legal,
50 A4,
52}
53
54impl ReceivePageSize {
55 fn as_str(&self) -> &str {
56 match self {
57 ReceivePageSize::Letter => "letter",
58 ReceivePageSize::Legal => "legal",
59 ReceivePageSize::A4 => "a4",
60 }
61 }
62}
63
64#[derive(Debug, Clone, Default)]
66pub struct ReceiveAttributes {
67 pub action: Option<String>,
69 pub media_type: Option<ReceiveMediaType>,
71 pub method: Option<String>,
73 pub page_size: Option<ReceivePageSize>,
75 pub store_media: Option<bool>,
77}
78
79impl ReceiveAttributes {
80 pub fn new() -> Self {
82 Self::default()
83 }
84
85 pub fn action(mut self, action: impl Into<String>) -> Self {
87 self.action = Some(action.into());
88 self
89 }
90
91 pub fn media_type(mut self, media_type: ReceiveMediaType) -> Self {
93 self.media_type = Some(media_type);
94 self
95 }
96
97 pub fn method(mut self, method: impl Into<String>) -> Self {
99 self.method = Some(method.into());
100 self
101 }
102
103 pub fn page_size(mut self, page_size: ReceivePageSize) -> Self {
105 self.page_size = Some(page_size);
106 self
107 }
108
109 pub fn store_media(mut self, store_media: bool) -> Self {
111 self.store_media = Some(store_media);
112 self
113 }
114}
115
116#[derive(Debug, Clone)]
118pub struct Receive {
119 attributes: ReceiveAttributes,
120}
121
122impl Receive {
123 pub(crate) fn new(attributes: Option<ReceiveAttributes>) -> Self {
125 Self {
126 attributes: attributes.unwrap_or_default(),
127 }
128 }
129
130 fn to_xml(&self) -> String {
131 let mut attrs = Vec::new();
132
133 if let Some(ref action) = self.attributes.action {
134 attrs.push(format!(" action=\"{}\"", escape_xml_attr(action)));
135 }
136 if let Some(ref media_type) = self.attributes.media_type {
137 attrs.push(format!(" mediaType=\"{}\"", media_type.as_str()));
138 }
139 if let Some(ref method) = self.attributes.method {
140 attrs.push(format!(" method=\"{}\"", escape_xml_attr(method)));
141 }
142 if let Some(ref page_size) = self.attributes.page_size {
143 attrs.push(format!(" pageSize=\"{}\"", page_size.as_str()));
144 }
145 if let Some(store_media) = self.attributes.store_media {
146 attrs.push(format!(" storeMedia=\"{}\"", store_media));
147 }
148
149 format!("<Receive{}/>", attrs.join(""))
150 }
151}
152
153#[derive(Debug, Clone, Default)]
155pub struct FaxResponse {
156 receive: Option<Receive>,
157 comments_before: Vec<String>,
158 comments: Vec<String>,
159 comments_after: Vec<String>,
160}
161
162impl FaxResponse {
163 pub fn new() -> Self {
167 Self::default()
168 }
169
170 pub fn receive(mut self, attributes: Option<ReceiveAttributes>) -> Self {
178 self.receive = Some(Receive::new(attributes));
179 self
180 }
181
182 pub fn comment(mut self, comment: impl Into<String>) -> Self {
190 self.comments.push(comment.into());
191 self
192 }
193
194 pub fn comment_after(mut self, comment: impl Into<String>) -> Self {
202 self.comments_after.push(comment.into());
203 self
204 }
205
206 pub fn comment_before(mut self, comment: impl Into<String>) -> Self {
214 self.comments_before.push(comment.into());
215 self
216 }
217}
218
219impl TwiML for FaxResponse {
220 fn to_xml(&self) -> String {
221 let mut xml = String::from("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
222
223 for comment in &self.comments_before {
225 xml.push_str(&format!("<!-- {} -->\n", escape_xml_text(comment)));
226 }
227
228 xml.push_str("<Response>");
229
230 for comment in &self.comments {
232 xml.push_str(&format!("\n <!-- {} -->", escape_xml_text(comment)));
233 }
234
235 if let Some(ref receive) = self.receive {
236 xml.push_str(&receive.to_xml());
237 }
238
239 xml.push_str("</Response>");
240
241 for comment in &self.comments_after {
243 xml.push_str(&format!("\n<!-- {} -->", escape_xml_text(comment)));
244 }
245
246 xml
247 }
248}