ftth_rsip/message/
response.rs

1#[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/// Response reprsents a SIP response message, which contains a [StatusCode](crate::StatusCode),
15/// a [Version](crate::Version), [Headers](crate::Headers) and a
16/// body, represented as a `Vec<u8>`, thus not checked for UTF-8 compliance.
17///
18/// A Response can easily be transformed to a [SipMessage](crate::SipMessage).
19/// Also it can be converted to a `String`, `&str`, or `Bytes`, all using the underlying `Debug`
20/// trait.
21///
22/// In order to access specific [headers](crate::headers::untyped), you should take a look on the
23/// [HeadersExt](crate::message::HeadersExt) trait that is automatically implemented for any type
24/// that has implemented the [HasHeaders](crate::message::HasHeaders) trait, which Response
25/// implements it.
26#[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}