@@ -147,38 +147,210 @@ impl URLSearchParams {
147147 /// let params = URLSearchParams::parse("a=1&b=2");
148148 /// assert_eq!(params.to_string(), "a=1&b=2");
149149 /// ```
150- pub fn to_string ( & self ) -> & str {
151- unsafe {
152- let out = ffi:: ada_search_params_to_string ( self . 0 ) ;
153- let slice = core:: slice:: from_raw_parts ( out. data . cast ( ) , out. length ) ;
154- core:: str:: from_utf8_unchecked ( slice)
155- }
150+ #[ cfg( feature = "std" ) ]
151+ #[ allow( clippy:: inherent_to_string) ]
152+ pub fn to_string ( & self ) -> String {
153+ unsafe { ffi:: ada_search_params_to_string ( self . 0 ) . to_string ( ) }
156154 }
157155
158156 /// Returns all values of the key.
159157 ///
160158 /// ```
161159 /// use ada_url::URLSearchParams;
162160 /// let params = URLSearchParams::parse("a=1&a=2");
163- /// assert_eq!(params.get_all("a"), vec!["1", "2"]);
161+ /// let pairs = params.get_all("a");
162+ /// assert_eq!(pairs.get_size(), 2);
164163 /// ```
165- pub fn get_all ( & self , key : & str ) -> Vec < & str > {
164+ pub fn get_all ( & self , key : & str ) -> URLSearchParamsEntry {
166165 unsafe {
167166 let strings = ffi:: ada_search_params_get_all ( self . 0 , key. as_ptr ( ) . cast ( ) , key. len ( ) ) ;
168167 let size = ffi:: ada_strings_size ( strings) ;
169- let mut out = Vec :: with_capacity ( size) ;
170168
171- if size == 0 {
172- return out;
173- }
169+ URLSearchParamsEntry :: new ( strings, size)
170+ }
171+ }
172+
173+ /// Returns all keys as an iterator
174+ ///
175+ /// ```
176+ /// use ada_url::URLSearchParams;
177+ /// let params = URLSearchParams::parse("a=1");
178+ /// let mut keys = params.get_keys();
179+ /// assert!(keys.has_next());
180+ pub fn get_keys ( & self ) -> URLSearchParamsKeysIterator {
181+ let iterator = unsafe { ffi:: ada_search_params_get_keys ( self . 0 ) } ;
182+ URLSearchParamsKeysIterator :: new ( iterator)
183+ }
184+
185+ /// Returns all keys as an iterator
186+ ///
187+ /// ```
188+ /// use ada_url::URLSearchParams;
189+ /// let params = URLSearchParams::parse("a=1");
190+ /// let mut values = params.get_values();
191+ /// assert!(values.has_next());
192+ pub fn get_values ( & self ) -> URLSearchParamsValuesIterator {
193+ let iterator = unsafe { ffi:: ada_search_params_get_values ( self . 0 ) } ;
194+ URLSearchParamsValuesIterator :: new ( iterator)
195+ }
196+ }
197+
198+ pub struct URLSearchParamsKeysIterator < ' a > {
199+ iterator : * mut ffi:: ada_url_search_params_keys_iter ,
200+ _phantom : core:: marker:: PhantomData < & ' a str > ,
201+ }
202+
203+ impl < ' a > Drop for URLSearchParamsKeysIterator < ' a > {
204+ fn drop ( & mut self ) {
205+ unsafe { ffi:: ada_free_search_params_keys_iter ( self . iterator ) }
206+ }
207+ }
208+
209+ impl < ' a > URLSearchParamsKeysIterator < ' a > {
210+ /// Returns true if iterator has a next value.
211+ pub fn has_next ( & self ) -> bool {
212+ unsafe { ffi:: ada_search_params_keys_iter_has_next ( self . iterator ) }
213+ }
214+
215+ /// Returns a new value if it's available
216+ pub fn get_next ( & self ) -> Option < & str > {
217+ if self . has_next ( ) {
218+ return None ;
219+ }
220+ let string = unsafe { ffi:: ada_search_params_keys_iter_next ( self . iterator ) } ;
221+ Some ( string. as_str ( ) )
222+ }
223+ }
224+
225+ pub struct URLSearchParamsValuesIterator < ' a > {
226+ iterator : * mut ffi:: ada_url_search_params_values_iter ,
227+ _phantom : core:: marker:: PhantomData < & ' a str > ,
228+ }
229+
230+ impl < ' a > URLSearchParamsKeysIterator < ' a > {
231+ fn new ( iterator : * mut ffi:: ada_url_search_params_keys_iter ) -> URLSearchParamsKeysIterator < ' a > {
232+ URLSearchParamsKeysIterator {
233+ iterator,
234+ _phantom : core:: marker:: PhantomData ,
235+ }
236+ }
237+ }
238+
239+ impl < ' a > Drop for URLSearchParamsValuesIterator < ' a > {
240+ fn drop ( & mut self ) {
241+ unsafe { ffi:: ada_free_search_params_values_iter ( self . iterator ) }
242+ }
243+ }
174244
175- for index in 0 ..size {
176- let string = ffi:: ada_strings_get ( strings, index) ;
245+ impl < ' a > URLSearchParamsValuesIterator < ' a > {
246+ fn new (
247+ iterator : * mut ffi:: ada_url_search_params_values_iter ,
248+ ) -> URLSearchParamsValuesIterator < ' a > {
249+ URLSearchParamsValuesIterator {
250+ iterator,
251+ _phantom : core:: marker:: PhantomData ,
252+ }
253+ }
254+ }
255+
256+ impl < ' a > URLSearchParamsValuesIterator < ' a > {
257+ /// Returns true if iterator has a next value.
258+ pub fn has_next ( & self ) -> bool {
259+ unsafe { ffi:: ada_search_params_values_iter_has_next ( self . iterator ) }
260+ }
261+
262+ /// Returns a new value if it's available
263+ pub fn get_next ( & self ) -> Option < & str > {
264+ if self . has_next ( ) {
265+ return None ;
266+ }
267+ let string = unsafe { ffi:: ada_search_params_values_iter_next ( self . iterator ) } ;
268+ Some ( string. as_str ( ) )
269+ }
270+ }
271+
272+ pub struct URLSearchParamsEntry < ' a > {
273+ strings : * mut ffi:: ada_strings ,
274+ size : usize ,
275+ _phantom : core:: marker:: PhantomData < & ' a str > ,
276+ }
277+
278+ impl < ' a > URLSearchParamsEntry < ' a > {
279+ fn new ( strings : * mut ffi:: ada_strings , size : usize ) -> URLSearchParamsEntry < ' a > {
280+ URLSearchParamsEntry {
281+ strings,
282+ size,
283+ _phantom : core:: marker:: PhantomData ,
284+ }
285+ }
286+
287+ /// Returns whether the key value pair is empty or not
288+ ///
289+ /// ```
290+ /// use ada_url::URLSearchParams;
291+ /// let params = URLSearchParams::parse("a=1&b=2");
292+ /// let pairs = params.get_all("a");
293+ /// assert_eq!(pairs.is_empty(), false);
294+ /// ```
295+ pub fn is_empty ( & self ) -> bool {
296+ self . size == 0
297+ }
298+
299+ /// Returns the size of the key value pairs
300+ ///
301+ /// ```
302+ /// use ada_url::URLSearchParams;
303+ /// let params = URLSearchParams::parse("a=1&b=2");
304+ /// let pairs = params.get_all("a");
305+ /// assert_eq!(pairs.get_size(), 1);
306+ /// ```
307+ pub fn get_size ( & self ) -> usize {
308+ self . size
309+ }
310+
311+ /// Get an entry by index
312+ ///
313+ /// ```
314+ /// use ada_url::URLSearchParams;
315+ /// let params = URLSearchParams::parse("a=1&a=2");
316+ /// let pairs = params.get_all("a");
317+ /// assert_eq!(pairs.get_size(), 2);
318+ /// assert_eq!(pairs.get(0), Some("1"));
319+ /// assert_eq!(pairs.get(1), Some("2"));
320+ /// assert_eq!(pairs.get(2), None);
321+ /// assert_eq!(pairs.get(55), None);
322+ /// ```
323+ pub fn get ( & self , index : usize ) -> Option < & str > {
324+ if self . size == 0 || index > self . size - 1 {
325+ return None ;
326+ }
327+
328+ unsafe {
329+ let string = ffi:: ada_strings_get ( self . strings , index) ;
330+ let slice = core:: slice:: from_raw_parts ( string. data . cast ( ) , string. length ) ;
331+ Some ( core:: str:: from_utf8_unchecked ( slice) )
332+ }
333+ }
334+ }
335+
336+ impl < ' a > Drop for URLSearchParamsEntry < ' a > {
337+ /// Automatically frees the underlying C pointer.
338+ fn drop ( & mut self ) {
339+ unsafe { ffi:: ada_free_strings ( self . strings ) }
340+ }
341+ }
342+
343+ #[ cfg( feature = "std" ) ]
344+ impl < ' a > From < URLSearchParamsEntry < ' a > > for Vec < & ' a str > {
345+ fn from ( val : URLSearchParamsEntry < ' a > ) -> Self {
346+ let mut vec = Vec :: with_capacity ( val. size ) ;
347+ unsafe {
348+ for index in 0 ..val. size {
349+ let string = ffi:: ada_strings_get ( val. strings , index) ;
177350 let slice = core:: slice:: from_raw_parts ( string. data . cast ( ) , string. length ) ;
178- out . push ( core:: str:: from_utf8_unchecked ( slice) ) ;
351+ vec . push ( core:: str:: from_utf8_unchecked ( slice) ) ;
179352 }
180-
181- out
182353 }
354+ vec
183355 }
184356}
0 commit comments