1use std::collections::BTreeMap;
2use std::fmt;
3use std::str::FromStr;
4
5use super::{parse::Parse, serialize::Serialize, Error};
6
7pub use bytes::Bytes;
8pub use http::uri::Uri;
9
10pub trait Message: Serialize + fmt::Display {
11 type Metadata: Parse;
12
13 fn new(metadata: Self::Metadata, headers: Headers, body: Option<Bytes>) -> Self;
14}
15
16pub type Headers = BTreeMap<String, String>;
17
18#[derive(Clone, PartialEq, Debug)]
19pub enum Method {
20 Describe,
21 Announce,
22 Setup,
23 Play,
24 Pause,
25 Record,
26 Options,
27 Redirect,
28 Teardown,
29 GetParameter,
30 SetParameter,
31}
32
33impl fmt::Display for Method {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 match self {
36 Method::Describe => write!(f, "DESCRIBE"),
37 Method::Announce => write!(f, "ANNOUNCE"),
38 Method::Setup => write!(f, "SETUP"),
39 Method::Play => write!(f, "PLAY"),
40 Method::Pause => write!(f, "PAUSE"),
41 Method::Record => write!(f, "RECORD"),
42 Method::Options => write!(f, "OPTIONS"),
43 Method::Redirect => write!(f, "REDIRECT"),
44 Method::Teardown => write!(f, "TEARDOWN"),
45 Method::GetParameter => write!(f, "GET_PARAMETER"),
46 Method::SetParameter => write!(f, "SET_PARAMETER"),
47 }
48 }
49}
50
51impl FromStr for Method {
52 type Err = Error;
53
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 match s {
56 "DESCRIBE" => Ok(Method::Describe),
57 "ANNOUNCE" => Ok(Method::Announce),
58 "SETUP" => Ok(Method::Setup),
59 "PLAY" => Ok(Method::Play),
60 "PAUSE" => Ok(Method::Pause),
61 "RECORD" => Ok(Method::Record),
62 "OPTIONS" => Ok(Method::Options),
63 "REDIRECT" => Ok(Method::Redirect),
64 "TEARDOWN" => Ok(Method::Teardown),
65 "GET_PARAMETER" => Ok(Method::GetParameter),
66 "SET_PARAMETER" => Ok(Method::SetParameter),
67 _ => Err(Error::MethodUnknown {
68 method: s.to_string(),
69 }),
70 }
71 }
72}
73
74#[derive(Copy, Clone, PartialEq, Debug)]
75pub enum Version {
76 V1,
77 V2,
78 Unknown,
79}
80
81impl Default for Version {
82 #[inline]
83 fn default() -> Version {
84 Version::V1
85 }
86}
87
88impl fmt::Display for Version {
89 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 match self {
91 Version::V1 => write!(f, "1.0"),
92 Version::V2 => write!(f, "2.0"),
93 Version::Unknown => write!(f, "?"),
94 }
95 }
96}
97
98pub type StatusCode = usize;
99
100#[derive(Clone, PartialEq, Debug)]
101pub enum StatusCategory {
102 Informational,
103 Success,
104 Redirection,
105 ClientError,
106 ServerError,
107 Unknown,
108}
109
110#[derive(Clone, Copy, PartialEq, Debug)]
111pub enum Status {
112 Continue,
113 Ok,
114 Created,
115 LowonStorageSpace,
116 MultipleChoices,
117 MovedPermanently,
118 MovedTemporarily,
119 SeeOther,
120 UseProxy,
121 BadRequest,
122 Unauthorized,
123 PaymentRequired,
124 Forbidden,
125 NotFound,
126 MethodNotAllowed,
127 NotAcceptable,
128 ProxyAuthenticationRequired,
129 RequestTimeout,
130 Gone,
131 LengthRequired,
132 PreconditionFailed,
133 RequestEntityTooLarge,
134 RequestUriTooLong,
135 UnsupportedMediaType,
136 InvalidParameter,
137 IllegalConferenceIdentifier,
138 NotEnoughBandwidth,
139 SessionNotFound,
140 MethodNotValidInThisState,
141 HeaderFieldNotValid,
142 InvalidRange,
143 ParameterIsReadOnly,
144 AggregateOperationNotAllowed,
145 OnlyAggregateOperationAllowed,
146 UnsupportedTransport,
147 DestinationUnreachable,
148 InternalServerError,
149 NotImplemented,
150 BadGateway,
151 ServiceUnavailable,
152 GatewayTimeout,
153 RTSPVersionNotSupported,
154 OptionNotSupported,
155}
156
157pub(crate) fn status_to_code(status: Status) -> StatusCode {
158 match status {
159 Status::Continue => 100,
160 Status::Ok => 200,
161 Status::Created => 201,
162 Status::LowonStorageSpace => 250,
163 Status::MultipleChoices => 300,
164 Status::MovedPermanently => 301,
165 Status::MovedTemporarily => 302,
166 Status::SeeOther => 303,
167 Status::UseProxy => 305,
168 Status::BadRequest => 400,
169 Status::Unauthorized => 401,
170 Status::PaymentRequired => 402,
171 Status::Forbidden => 403,
172 Status::NotFound => 404,
173 Status::MethodNotAllowed => 405,
174 Status::NotAcceptable => 406,
175 Status::ProxyAuthenticationRequired => 407,
176 Status::RequestTimeout => 408,
177 Status::Gone => 410,
178 Status::LengthRequired => 411,
179 Status::PreconditionFailed => 412,
180 Status::RequestEntityTooLarge => 413,
181 Status::RequestUriTooLong => 414,
182 Status::UnsupportedMediaType => 415,
183 Status::InvalidParameter => 451,
184 Status::IllegalConferenceIdentifier => 452,
185 Status::NotEnoughBandwidth => 453,
186 Status::SessionNotFound => 454,
187 Status::MethodNotValidInThisState => 455,
188 Status::HeaderFieldNotValid => 456,
189 Status::InvalidRange => 457,
190 Status::ParameterIsReadOnly => 458,
191 Status::AggregateOperationNotAllowed => 459,
192 Status::OnlyAggregateOperationAllowed => 460,
193 Status::UnsupportedTransport => 461,
194 Status::DestinationUnreachable => 462,
195 Status::InternalServerError => 500,
196 Status::NotImplemented => 501,
197 Status::BadGateway => 502,
198 Status::ServiceUnavailable => 503,
199 Status::GatewayTimeout => 504,
200 Status::RTSPVersionNotSupported => 505,
201 Status::OptionNotSupported => 551,
202 }
203}
204
205pub(crate) fn status_to_reason(status: Status) -> &'static str {
206 match status {
207 Status::Continue => "Continue",
208 Status::Ok => "OK",
209 Status::Created => "Created",
210 Status::LowonStorageSpace => "Low on Storage Space",
211 Status::MultipleChoices => "Multiple Choices",
212 Status::MovedPermanently => "Moved Permanently",
213 Status::MovedTemporarily => "Moved Temporarily",
214 Status::SeeOther => "See Other",
215 Status::UseProxy => "Use Proxy",
216 Status::BadRequest => "Bad Request",
217 Status::Unauthorized => "Unauthorized",
218 Status::PaymentRequired => "Payment Required",
219 Status::Forbidden => "Forbidden",
220 Status::NotFound => "Not Found",
221 Status::MethodNotAllowed => "Method Not Allowed",
222 Status::NotAcceptable => "Not Acceptable",
223 Status::ProxyAuthenticationRequired => "Proxy Authentication Required",
224 Status::RequestTimeout => "Request Timeout",
225 Status::Gone => "Gone",
226 Status::LengthRequired => "Length Required",
227 Status::PreconditionFailed => "Precondition Failed",
228 Status::RequestEntityTooLarge => "Request Entity Too Large",
229 Status::RequestUriTooLong => "Request-URI Too Long",
230 Status::UnsupportedMediaType => "Unsupported Media Type",
231 Status::InvalidParameter => "Invalid parameter",
232 Status::IllegalConferenceIdentifier => "Illegal Conference Identifier",
233 Status::NotEnoughBandwidth => "Not Enough Bandwidth",
234 Status::SessionNotFound => "Session Not Found",
235 Status::MethodNotValidInThisState => "Method Not Valid In This State",
236 Status::HeaderFieldNotValid => "Header Field Not Valid",
237 Status::InvalidRange => "Invalid Range",
238 Status::ParameterIsReadOnly => "Parameter Is Read-Only",
239 Status::AggregateOperationNotAllowed => "Aggregate Operation Not Allowed",
240 Status::OnlyAggregateOperationAllowed => "Only Aggregate Operation Allowed",
241 Status::UnsupportedTransport => "Unsupported Transport",
242 Status::DestinationUnreachable => "Destination Unreachable",
243 Status::InternalServerError => "Internal Server Error",
244 Status::NotImplemented => "Not Implemented",
245 Status::BadGateway => "Bad Gateway",
246 Status::ServiceUnavailable => "Service Unavailable",
247 Status::GatewayTimeout => "Gateway Timeout",
248 Status::RTSPVersionNotSupported => "RTSP Version Not Supported",
249 Status::OptionNotSupported => "Option Not Supported",
250 }
251}