rust_rcs_core/internet/
uri.rs1use super::parameter::ParameterParser;
16
17pub enum URIPath<'a> {
19 AbEmpty(&'a [u8], Option<&'a [u8]>), Absolute(&'a [u8]), Rootless(&'a [u8]), NoScheme(&'a [u8]), Empty(),
24}
25
26pub enum URI<'a> {
27 Standard(&'a [u8], URIPath<'a>, Option<&'a [u8]>, Option<&'a [u8]>),
33 Relative(URIPath<'a>, Option<&'a [u8]>, Option<&'a [u8]>),
39}
40
41impl URI<'_> {
42 pub fn is_absolute(&self) -> bool {
43 match self {
44 URI::Standard(_, _, _, fragment) => match fragment {
45 Some(_) => false,
46 None => true,
47 },
48 _ => false,
49 }
50 }
51
52 pub fn get_query_value<'b>(&self, query_name: &'b [u8]) -> Option<&[u8]> {
53 if let Some(query_part) = match self {
54 URI::Standard(_, _, query, _) => *query,
55 URI::Relative(_, query, _) => *query,
56 } {
57 for query_parameter in ParameterParser::new(query_part, b'&', false) {
58 if query_parameter.name.eq_ignore_ascii_case(query_name) {
59 if query_parameter.value.is_none() {
60 return Some(&[]);
61 } else {
62 return query_parameter.value;
63 }
64 }
65 }
66 }
67
68 None
69 }
70
71 pub fn string_representation_without_query_and_fragment(&self) -> Vec<u8> {
72 match self {
73 URI::Standard(scheme, hier_part, _, _) => {
74 let mut uri_string = Vec::new();
75 uri_string.extend_from_slice(scheme);
76 uri_string.extend(b":");
77 match hier_part {
78 URIPath::AbEmpty(authority, path) => {
79 uri_string.extend(b"//");
80 uri_string.extend_from_slice(authority);
81 if let Some(path) = path {
82 uri_string.extend(b"/");
83 uri_string.extend_from_slice(path);
84 }
85 uri_string
86 }
87 URIPath::Absolute(path) => {
88 uri_string.extend(b"/");
89 uri_string.extend_from_slice(path);
90 uri_string
91 }
92 URIPath::Rootless(path) => {
93 uri_string.extend_from_slice(path);
94 uri_string
95 }
96 _ => uri_string,
97 }
98 }
99
100 URI::Relative(path, _, _) => {
101 let mut uri_string = Vec::new();
102 match path {
103 URIPath::AbEmpty(authority, path) => {
104 uri_string.extend(b"//");
105 uri_string.extend_from_slice(authority);
106 if let Some(path) = path {
107 uri_string.extend(b"/");
108 uri_string.extend_from_slice(path);
109 }
110 uri_string
111 }
112 URIPath::Absolute(path) => {
113 uri_string.extend(b"/");
114 uri_string.extend_from_slice(path);
115 uri_string
116 }
117 URIPath::NoScheme(path) => {
118 uri_string.extend_from_slice(path);
119 uri_string
120 }
121 _ => uri_string,
122 }
123 }
124 }
125 }
126}
127
128pub trait AsURI<'a> {
129 type Target;
130 fn as_standard_uri(&'a self) -> Option<Self::Target>;
131}
132
133impl<'a> AsURI<'a> for [u8] {
134 type Target = URI<'a>;
135 fn as_standard_uri(&'a self) -> Option<URI<'a>> {
136 if let Some(position) = self.iter().position(|c| *c == b':') {
137 let scheme = &self[..position];
138
139 let mut query: Option<&'a [u8]> = None;
140 let mut fragment: Option<&'a [u8]> = None;
141
142 let hierarchical_part_and_query_and_fragment = &self[position + 1..];
143
144 let hierarchical_part_and_query: &'a [u8];
145
146 if let Some(begin_of_fragment) = hierarchical_part_and_query_and_fragment
147 .iter()
148 .position(|c| *c == b'#')
149 {
150 hierarchical_part_and_query =
151 &hierarchical_part_and_query_and_fragment[..begin_of_fragment];
152 fragment = Some(&hierarchical_part_and_query_and_fragment[begin_of_fragment + 1..]);
153 } else {
154 hierarchical_part_and_query = hierarchical_part_and_query_and_fragment;
155 }
156
157 let hierarchical_part: &'a [u8];
158
159 if let Some(begin_of_query) =
160 hierarchical_part_and_query.iter().position(|c| *c == b'?')
161 {
162 hierarchical_part = &hierarchical_part_and_query[..begin_of_query];
163 query = Some(&hierarchical_part_and_query[begin_of_query + 1..]);
164 } else {
165 hierarchical_part = hierarchical_part_and_query
166 }
167
168 if hierarchical_part.starts_with(b"//") {
169 let part = &hierarchical_part[2..];
170 if let Some(begin_of_path) = part.iter().position(|c| *c == b'/') {
171 let authority = &part[..begin_of_path];
172 let path = Some(&part[begin_of_path + 1..]);
173 return Some(URI::Standard(
174 scheme,
175 URIPath::AbEmpty(authority, path),
176 query,
177 fragment,
178 ));
179 } else {
180 return Some(URI::Standard(
181 scheme,
182 URIPath::AbEmpty(part, None),
183 query,
184 fragment,
185 ));
186 }
187 } else if hierarchical_part.starts_with(b"/") {
188 let segments = &hierarchical_part[1..];
189 return Some(URI::Standard(
190 scheme,
191 URIPath::Absolute(segments),
192 query,
193 fragment,
194 ));
195 } else if hierarchical_part.len() > 0 {
196 return Some(URI::Standard(
197 scheme,
198 URIPath::Rootless(hierarchical_part),
199 query,
200 fragment,
201 ));
202 } else if hierarchical_part.len() == 0 {
203 return Some(URI::Standard(scheme, URIPath::Empty(), query, fragment));
204 }
205 }
206
207 None
208 }
209}