1#![allow(non_camel_case_types)]
2use core::ffi::{c_char, c_uint};
3
4#[cfg(feature = "std")]
5extern crate std;
6
7#[cfg(feature = "std")]
8use std::fmt::Display;
9
10#[repr(C)]
11pub struct ada_url {
12 _unused: [u8; 0],
13 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
14}
15
16#[repr(C)]
17pub struct ada_url_search_params {
18 _unused: [u8; 0],
19 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
20}
21
22#[repr(C)]
23pub struct ada_string {
24 pub data: *const c_char,
25 pub length: usize,
26}
27
28impl ada_string {
29 #[must_use]
30 pub const fn as_str(&self) -> &'static str {
31 if self.length == 0 {
35 return "";
36 }
37 unsafe {
38 let slice = core::slice::from_raw_parts(self.data.cast(), self.length);
39 core::str::from_utf8_unchecked(slice)
40 }
41 }
42}
43
44#[repr(C)]
45pub struct ada_owned_string {
46 pub data: *const c_char,
47 pub length: usize,
48}
49
50impl AsRef<str> for ada_owned_string {
51 fn as_ref(&self) -> &str {
52 if self.length == 0 {
56 return "";
57 }
58 unsafe {
59 let slice = core::slice::from_raw_parts(self.data.cast(), self.length);
60 core::str::from_utf8_unchecked(slice)
61 }
62 }
63}
64
65#[cfg(feature = "std")]
66impl Display for ada_owned_string {
67 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
68 write!(f, "{}", self.as_ref().to_owned())
69 }
70}
71
72impl Drop for ada_owned_string {
73 fn drop(&mut self) {
74 let copy = ada_owned_string {
76 data: self.data,
77 length: self.length,
78 };
79 unsafe {
80 ada_free_owned_string(copy);
81 };
82 }
83}
84
85#[repr(C)]
87pub struct ada_strings {
88 _unused: [u8; 0],
89 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
90}
91
92#[repr(C)]
93pub struct ada_url_search_params_keys_iter {
94 _unused: [u8; 0],
95 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
96}
97
98#[repr(C)]
99pub struct ada_url_search_params_values_iter {
100 _unused: [u8; 0],
101 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
102}
103
104#[repr(C)]
105pub struct ada_url_search_params_entries_iter {
106 _unused: [u8; 0],
107 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
108}
109
110#[repr(C)]
112pub struct ada_string_pair {
113 pub key: ada_string,
114 pub value: ada_string,
115}
116
117#[repr(C)]
118pub struct ada_url_components {
119 pub protocol_end: u32,
120 pub username_end: u32,
121 pub host_start: u32,
122 pub host_end: u32,
123 pub port: u32,
124 pub pathname_start: u32,
125 pub search_start: u32,
126 pub hash_start: u32,
127}
128
129unsafe extern "C" {
130 pub fn ada_parse(input: *const c_char, length: usize) -> *mut ada_url;
131 pub fn ada_parse_with_base(
132 input: *const c_char,
133 input_length: usize,
134 base: *const c_char,
135 base_length: usize,
136 ) -> *mut ada_url;
137 pub fn ada_free(url: *mut ada_url);
138 pub fn ada_free_owned_string(url: ada_owned_string);
139 pub fn ada_copy(url: *mut ada_url) -> *mut ada_url;
140 pub fn ada_is_valid(url: *mut ada_url) -> bool;
141 pub fn ada_can_parse(url: *const c_char, length: usize) -> bool;
142 pub fn ada_can_parse_with_base(
143 input: *const c_char,
144 input_length: usize,
145 base: *const c_char,
146 base_length: usize,
147 ) -> bool;
148 pub fn ada_get_components(url: *mut ada_url) -> *mut ada_url_components;
149
150 pub fn ada_get_origin(url: *mut ada_url) -> ada_owned_string;
152 pub fn ada_get_href(url: *mut ada_url) -> ada_string;
153 pub fn ada_get_username(url: *mut ada_url) -> ada_string;
154 pub fn ada_get_password(url: *mut ada_url) -> ada_string;
155 pub fn ada_get_port(url: *mut ada_url) -> ada_string;
156 pub fn ada_get_hash(url: *mut ada_url) -> ada_string;
157 pub fn ada_get_host(url: *mut ada_url) -> ada_string;
158 pub fn ada_get_hostname(url: *mut ada_url) -> ada_string;
159 pub fn ada_get_pathname(url: *mut ada_url) -> ada_string;
160 pub fn ada_get_search(url: *mut ada_url) -> ada_string;
161 pub fn ada_get_protocol(url: *mut ada_url) -> ada_string;
162 pub fn ada_get_host_type(url: *mut ada_url) -> c_uint;
163 pub fn ada_get_scheme_type(url: *mut ada_url) -> c_uint;
164
165 pub fn ada_set_href(url: *mut ada_url, input: *const c_char, length: usize) -> bool;
167 pub fn ada_set_username(url: *mut ada_url, input: *const c_char, length: usize) -> bool;
168 pub fn ada_set_password(url: *mut ada_url, input: *const c_char, length: usize) -> bool;
169 pub fn ada_set_port(url: *mut ada_url, input: *const c_char, length: usize) -> bool;
170 pub fn ada_set_hash(url: *mut ada_url, input: *const c_char, length: usize);
171 pub fn ada_set_host(url: *mut ada_url, input: *const c_char, length: usize) -> bool;
172 pub fn ada_set_hostname(url: *mut ada_url, input: *const c_char, length: usize) -> bool;
173 pub fn ada_set_pathname(url: *mut ada_url, input: *const c_char, length: usize) -> bool;
174 pub fn ada_set_search(url: *mut ada_url, input: *const c_char, length: usize);
175 pub fn ada_set_protocol(url: *mut ada_url, input: *const c_char, length: usize) -> bool;
176
177 pub fn ada_clear_search(url: *mut ada_url);
179 pub fn ada_clear_hash(url: *mut ada_url);
180 pub fn ada_clear_port(url: *mut ada_url);
181
182 pub fn ada_has_credentials(url: *mut ada_url) -> bool;
184 pub fn ada_has_empty_hostname(url: *mut ada_url) -> bool;
185 pub fn ada_has_hostname(url: *mut ada_url) -> bool;
186 pub fn ada_has_non_empty_username(url: *mut ada_url) -> bool;
187 pub fn ada_has_non_empty_password(url: *mut ada_url) -> bool;
188 pub fn ada_has_port(url: *mut ada_url) -> bool;
189 pub fn ada_has_password(url: *mut ada_url) -> bool;
190 pub fn ada_has_hash(url: *mut ada_url) -> bool;
191 pub fn ada_has_search(url: *mut ada_url) -> bool;
192
193 pub fn ada_idna_to_unicode(input: *const c_char, length: usize) -> ada_owned_string;
195 pub fn ada_idna_to_ascii(input: *const c_char, length: usize) -> ada_owned_string;
196
197 pub fn ada_parse_search_params(
199 input: *const c_char,
200 length: usize,
201 ) -> *mut ada_url_search_params;
202 pub fn ada_free_search_params(search_params: *mut ada_url_search_params);
203 pub fn ada_search_params_size(search_params: *mut ada_url_search_params) -> usize;
204 pub fn ada_search_params_sort(search_params: *mut ada_url_search_params);
205 pub fn ada_search_params_to_string(
206 search_params: *mut ada_url_search_params,
207 ) -> ada_owned_string;
208 pub fn ada_search_params_append(
209 search_params: *mut ada_url_search_params,
210 name: *const c_char,
211 name_length: usize,
212 value: *const c_char,
213 value_length: usize,
214 );
215 pub fn ada_search_params_set(
216 search_params: *mut ada_url_search_params,
217 name: *const c_char,
218 name_length: usize,
219 value: *const c_char,
220 value_length: usize,
221 );
222 pub fn ada_search_params_remove(
223 search_params: *mut ada_url_search_params,
224 name: *const c_char,
225 name_length: usize,
226 );
227 pub fn ada_search_params_remove_value(
228 search_params: *mut ada_url_search_params,
229 name: *const c_char,
230 name_length: usize,
231 value: *const c_char,
232 value_length: usize,
233 );
234 pub fn ada_search_params_has(
235 search_params: *mut ada_url_search_params,
236 name: *const c_char,
237 name_length: usize,
238 ) -> bool;
239 pub fn ada_search_params_has_value(
240 search_params: *mut ada_url_search_params,
241 name: *const c_char,
242 name_length: usize,
243 value: *const c_char,
244 value_length: usize,
245 ) -> bool;
246 pub fn ada_search_params_get(
247 search_params: *mut ada_url_search_params,
248 key: *const c_char,
249 key_length: usize,
250 ) -> ada_string;
251 pub fn ada_search_params_get_all(
252 search_params: *mut ada_url_search_params,
254 key: *const c_char,
255 key_length: usize,
256 ) -> *mut ada_strings;
257 pub fn ada_search_params_get_keys(
258 search_params: *mut ada_url_search_params,
259 ) -> *mut ada_url_search_params_keys_iter;
260 pub fn ada_search_params_get_values(
261 search_params: *mut ada_url_search_params,
262 ) -> *mut ada_url_search_params_values_iter;
263 pub fn ada_search_params_get_entries(
264 search_params: *mut ada_url_search_params,
265 ) -> *mut ada_url_search_params_entries_iter;
266
267 pub fn ada_free_strings(strings: *mut ada_strings);
268 pub fn ada_strings_size(strings: *mut ada_strings) -> usize;
269 pub fn ada_strings_get(strings: *mut ada_strings, index: usize) -> ada_string;
270 pub fn ada_free_search_params_keys_iter(iter: *mut ada_url_search_params_keys_iter);
271 pub fn ada_search_params_keys_iter_next(
272 iter: *mut ada_url_search_params_keys_iter,
273 ) -> ada_string;
274 pub fn ada_search_params_keys_iter_has_next(iter: *mut ada_url_search_params_keys_iter)
275 -> bool;
276
277 pub fn ada_free_search_params_values_iter(iter: *mut ada_url_search_params_values_iter);
278 pub fn ada_search_params_values_iter_next(
279 iter: *mut ada_url_search_params_values_iter,
280 ) -> ada_string;
281 pub fn ada_search_params_values_iter_has_next(
282 iter: *mut ada_url_search_params_values_iter,
283 ) -> bool;
284
285 pub fn ada_free_search_params_entries_iter(iter: *mut ada_url_search_params_entries_iter);
286 pub fn ada_search_params_entries_iter_next(
287 iter: *mut ada_url_search_params_entries_iter,
288 ) -> ada_string_pair;
289 pub fn ada_search_params_entries_iter_has_next(
290 iter: *mut ada_url_search_params_entries_iter,
291 ) -> bool;
292}
293
294#[cfg(test)]
295mod tests {
296 use crate::ffi;
297
298 #[test]
299 fn ada_free_owned_string_works() {
300 let str = "meßagefactory.ca";
301 let result = unsafe { ffi::ada_idna_to_ascii(str.as_ptr().cast(), str.len()) };
302 assert_eq!(result.as_ref(), "xn--meagefactory-m9a.ca");
303 unsafe { ffi::ada_free_owned_string(result) };
304 }
305}