ftth_rsip/message/
response.rs1#[doc(hidden)]
2pub use tokenizer::Tokenizer;
3
4use crate::{
5 common::{
6 status_code::{self, StatusCode},
7 version::{self, Version},
8 },
9 headers::{header, Headers},
10 Error, SipMessage,
11};
12use std::convert::{TryFrom, TryInto};
13
14#[derive(Debug, PartialEq, Eq, Clone, Default)]
27pub struct Response {
28 pub status_code: StatusCode,
29 pub version: Version,
30 pub headers: Headers,
31 pub body: Vec<u8>,
32}
33
34impl Response {
35 pub fn status_code(&self) -> &StatusCode {
36 &self.status_code
37 }
38
39 pub fn version(&self) -> &Version {
40 &self.version
41 }
42
43 pub fn body(&self) -> &Vec<u8> {
44 &self.body
45 }
46
47 pub fn body_mut(&mut self) -> &mut Vec<u8> {
48 &mut self.body
49 }
50}
51
52impl super::HasHeaders for Response {
53 fn headers(&self) -> &Headers {
54 &self.headers
55 }
56
57 fn headers_mut(&mut self) -> &mut Headers {
58 &mut self.headers
59 }
60}
61
62impl std::fmt::Display for Response {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 write!(
65 f,
66 "{} {}\r\n{}\r\n{}",
67 self.version,
68 self.status_code,
69 self.headers,
70 String::from_utf8_lossy(&self.body)
71 )
72 }
73}
74
75impl TryFrom<SipMessage> for Response {
76 type Error = crate::Error;
77
78 fn try_from(sip_message: crate::SipMessage) -> Result<Self, Self::Error> {
79 match sip_message {
80 crate::SipMessage::Request(_) => Err(crate::Error::Unexpected(
81 "Can't convert a models::SipMessage::Response into Request !".into(),
82 )),
83 crate::SipMessage::Response(response) => Ok(response),
84 }
85 }
86}
87
88impl TryFrom<&[u8]> for Response {
89 type Error = Error;
90
91 fn try_from(from: &[u8]) -> Result<Self, Self::Error> {
92 Tokenizer::tokenize(from)?.1.try_into()
93 }
94}
95
96impl TryFrom<Vec<u8>> for Response {
97 type Error = Error;
98
99 fn try_from(from: Vec<u8>) -> Result<Self, Self::Error> {
100 Tokenizer::tokenize(&from)?.1.try_into()
101 }
102}
103
104impl TryFrom<&str> for Response {
105 type Error = Error;
106
107 fn try_from(from: &str) -> Result<Self, Self::Error> {
108 Tokenizer::tokenize(from.as_bytes())?.1.try_into()
109 }
110}
111
112impl TryFrom<String> for Response {
113 type Error = Error;
114
115 fn try_from(from: String) -> Result<Self, Self::Error> {
116 Tokenizer::tokenize(from.as_bytes())?.1.try_into()
117 }
118}
119
120impl TryFrom<bytes::Bytes> for Response {
121 type Error = Error;
122
123 fn try_from(from: bytes::Bytes) -> Result<Self, Self::Error> {
124 Tokenizer::tokenize(&from)?.1.try_into()
125 }
126}
127
128impl From<Response> for String {
129 fn from(res: Response) -> Self {
130 res.to_string()
131 }
132}
133
134impl From<Response> for Vec<u8> {
135 fn from(res: Response) -> Self {
136 res.to_string().into_bytes()
137 }
138}
139
140impl From<Response> for bytes::Bytes {
141 fn from(res: Response) -> Self {
142 bytes::Bytes::from(res.to_string())
143 }
144}
145
146#[doc(hidden)]
147pub mod tokenizer {
148 use super::{header, status_code, version, Response};
149 use crate::{Error, IResult, NomError, TokenizerError};
150 use std::convert::TryInto;
151
152 impl<'a> TryInto<Response> for Tokenizer<'a> {
153 type Error = Error;
154
155 fn try_into(self) -> Result<Response, Error> {
156 Ok(Response {
157 version: self.version.try_into()?,
158 status_code: self.status_code.try_into()?,
159 headers: self
160 .headers
161 .into_iter()
162 .map(TryInto::try_into)
163 .collect::<Result<Vec<_>, Error>>()?
164 .into(),
165 body: self.body.into(),
166 })
167 }
168 }
169
170 #[derive(Debug, PartialEq, Eq)]
171 pub struct Tokenizer<'a> {
172 pub version: version::Tokenizer<'a, &'a [u8], u8>,
173 pub status_code: status_code::Tokenizer<'a, &'a [u8], u8>,
174 pub headers: Vec<header::Tokenizer<'a>>,
175 pub body: &'a [u8],
176 }
177
178 impl<'a> Tokenizer<'a> {
179 pub fn tokenize(part: &'a [u8]) -> IResult<Self> {
180 use crate::parser_utils::is_empty_or_fail_with;
181 use nom::{
182 branch::alt,
183 bytes::complete::{tag, take_until},
184 character::complete::space1,
185 multi::many0,
186 sequence::tuple,
187 };
188
189 let (rem, (version, _, status_code, _)) = tuple((
190 version::Tokenizer::tokenize,
191 space1,
192 status_code::Tokenizer::tokenize,
193 tag("\r\n"),
194 ))(part)?;
195
196 let (body, (raw_headers, _)) = alt((
197 tuple((take_until("\r\n\r\n"), tag("\r\n\r\n"))),
198 tuple((take_until("\r\n"), tag("\r\n"))),
199 ))(rem)
200 .map_err(|_: NomError<'a>| TokenizerError::from(("headers", rem)).into())?;
201 let (rem, headers) = many0(header::Tokenizer::tokenize)(raw_headers)?;
202 is_empty_or_fail_with(rem, ("headers", rem))?;
203
204 Ok((
205 &[],
206 Self {
207 version,
208 status_code,
209 headers,
210 body,
211 },
212 ))
213 }
214 }
215}