multidict/
lib.rs

1//! # multidict
2//!
3//! The `multidict` crate was inspired by Python `MultiDict` library
4//! `multidict` is useful for working with HTTP headers, URL query, form-data args etc
5//! HTTP Headers and URL query string require specific data structure: `multidict`.
6//! It behaves mostly like a regular map but it may have several values for the same key
7//! and preserves insertion ordering
8//!
9//! ## Examples
10//!
11//! Basic `MultiDict` creation and filling with data
12//! ```
13//! use multidict::{MultiDict, MultiElement};
14//!
15//! let mut map = MultiDict::new();
16//! map.add(MultiElement {
17//!             key: "some_key".to_string(),
18//!             value: "some_value_1".to_string(),
19//!         });
20//! println!("{map}"); // MultiDict < "some_key":"some_value_1" >
21//! map.add(MultiElement {
22//!             key: "some_key".to_string(),
23//!             value: "some_value_2".to_string(),
24//!         });
25//! println!("{map}");
26//! // MultiDict < "some_key":"some_value_1", "some_key":"some_value_2" >
27//! ```
28//!
29//! Get **all** key-values pairs for key
30//! ```
31//! use multidict::{MultiDict, MultiElement};
32//!
33//! let mut map = MultiDict::new();
34//! map.add(MultiElement {
35//!             key: "some_key".to_string(),
36//!             value: "some_value_1".to_string(),
37//!         });
38//! map.add(MultiElement {
39//!             key: "some_key".to_string(),
40//!             value: "some_value_2".to_string(),
41//!         });
42//! map.add(MultiElement {
43//!             key: "some_other_key".to_string(),
44//!             value: "some_value_3".to_string(),
45//!         });
46//! println!("{}", map.getall("some_key").unwrap());
47//! // MultiDict < "some_key":"some_value_1", "some_key":"some_value_2" >
48//! ```
49//!
50//! `MultiDict` debug output
51//! ```
52//! use multidict::{MultiDict, MultiElement};
53//!
54//! let mut map = MultiDict::new();
55//! map.add(MultiElement {
56//!             key: "some_key".to_string(),
57//!             value: "some_value_1".to_string(),
58//!         });
59//! map.add(MultiElement {
60//!             key: "some_key".to_string(),
61//!             value: "some_value_2".to_string(),
62//!         });
63//! map.add(MultiElement {
64//!             key: "some_other_key".to_string(),
65//!             value: "some_value_3".to_string(),
66//!         });
67//! println!("{map:?}");
68//! // MultiDict { elements: [
69//! //  MultiElement { key: "some_key", value: "some_value_1" },
70//! //  MultiElement { key: "some_key", value: "some_value_2" },
71//! //  MultiElement { key: "some_other_key", value: "some_value_3" }
72//! // ] }
73//! ```
74use core::slice::Iter;
75use std::fmt;
76
77/// `MultiElement` - element of `MultiDict` structure Vec.
78#[derive(Debug, Clone, Eq, PartialEq)]
79pub struct MultiElement {
80    pub key: String,
81    pub value: String,
82}
83impl fmt::Display for MultiElement {
84    /// `MultiElement` instance formatter
85    ///
86    /// # Examples
87    /// ```
88    /// use multidict::MultiElement;
89    ///
90    /// let element: MultiElement = MultiElement::new(["some_key".to_string(),
91    ///                                                 "some_value".to_string()
92    ///                                             ]);
93    /// println!("{element}")
94    /// // MultiElement < "some_key":"some_value_2" >
95    /// ```
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        write!(f, r#"MultiElement < "{}":"{}" >"#, self.key, self.value)
98    }
99}
100impl MultiElement {
101    /// Return new MultiElement instance
102    ///
103    /// # Examples
104    /// ```
105    /// use multidict::MultiElement;
106    ///
107    /// let element: MultiElement = MultiElement::new(["some_key".to_string(),
108    ///                                                 "some_value".to_string()
109    ///                                             ]);
110    /// ```
111    pub fn new(new_element: [String; 2]) -> Self {
112        MultiElement {
113            key: new_element[0].clone(),
114            value: new_element[1].clone(),
115        }
116    }
117}
118
119/// `MultiDict` - structure which enable to user store multiple
120/// similar keys with different values in map-like structure.
121///
122/// Was inspired by Python `MultiDict` library
123#[derive(Default, Debug, Clone)]
124pub struct MultiDict {
125    pub elements: Vec<MultiElement>,
126}
127impl fmt::Display for MultiDict {
128    /// `MultiDict` instance formatter
129    ///
130    /// # Examples
131    /// ```
132    /// use multidict::{MultiDict, MultiElement};
133    ///
134    /// let mut map: MultiDict = MultiDict::new();
135    /// map.add(MultiElement {
136    ///             key: "some_key".to_string(),
137    ///             value: "some_value_1".to_string(),
138    ///         });
139    /// map.add(MultiElement {
140    ///             key: "some_key".to_string(),
141    ///             value: "some_value_2".to_string(),
142    ///         });
143    /// println!("{}", map);
144    /// // MultiDict < "some_key":"some_value_1", "some_key":"some_value_2" >
145    /// ```
146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147        write!(
148            f,
149            "MultiDict < {} >",
150            self.elements
151                .iter()
152                .map(|item| format!(r#""{}":"{}""#, item.key, item.value))
153                .collect::<Vec<_>>()
154                .join(", ")
155        )
156    }
157}
158impl MultiDict {
159    /// Return new MultiDict instance
160    ///
161    /// # Examples
162    /// ```
163    /// use multidict::MultiDict;
164    ///
165    /// let mut map: MultiDict = MultiDict::new();
166    /// ```
167    pub fn new() -> Self {
168        MultiDict {
169            elements: Vec::new(),
170        }
171    }
172
173    /// Return new MultiDict instance with preset capacity
174    ///
175    /// # Examples
176    ///
177    /// Capacity will only prepare Vector with element for future elements,
178    /// but it can expand
179    /// ```
180    /// use multidict::{MultiDict, MultiElement};
181    ///
182    /// let mut map: MultiDict = MultiDict::new_capacity(&2);
183    /// map.add(MultiElement {
184    ///             key: "some_key".to_string(),
185    ///             value: "some_value_1".to_string(),
186    ///         });
187    /// map.add(MultiElement {
188    ///             key: "some_key".to_string(),
189    ///             value: "some_value_2".to_string(),
190    ///         });
191    /// println!("{}", map.len());
192    /// // 2
193    /// ```
194    /// ```
195    /// use multidict::{MultiDict, MultiElement};
196    ///
197    /// let mut map: MultiDict = MultiDict::new_capacity(&2);
198    /// map.add(MultiElement {
199    ///             key: "some_key".to_string(),
200    ///             value: "some_value_1".to_string(),
201    ///         });
202    /// map.add(MultiElement {
203    ///             key: "some_key".to_string(),
204    ///             value: "some_value_2".to_string(),
205    ///         });
206    /// map.add(MultiElement {
207    ///             key: "some_other_key".to_string(),
208    ///             value: "some_value_3".to_string(),
209    ///         });
210    /// println!("{}", map.len());
211    /// // 3
212    /// ```
213    pub fn new_capacity(capacity: &usize) -> Self {
214        MultiDict {
215            elements: Vec::with_capacity(*capacity),
216        }
217    }
218
219    /// Return the number of items in MultiDict
220    ///
221    /// # Examples
222    /// ```
223    /// use multidict::{MultiDict, MultiElement};
224    ///
225    /// let mut map = MultiDict::new();
226    /// map.add(MultiElement {
227    ///             key: "some_key".to_string(),
228    ///             value: "some_value_1".to_string(),
229    ///         });
230    /// map.add(MultiElement {
231    ///             key: "some_key".to_string(),
232    ///             value: "some_value_2".to_string(),
233    ///         });
234    /// println!("{}", map.len());
235    /// // 2
236    /// ```
237    pub fn len(&self) -> usize {
238        self.elements.len()
239    }
240
241    /// Return an iterator over the element.
242    ///
243    /// The iterator yields all items from start to end.
244    ///
245    /// # Examples
246    /// ```
247    /// use multidict::{MultiDict, MultiElement};
248    ///
249    /// let mut map = MultiDict::new();
250    /// map.add(MultiElement {
251    ///             key: "some_key".to_string(),
252    ///             value: "some_value_1".to_string(),
253    ///         });
254    /// map.add(MultiElement {
255    ///             key: "some_key".to_string(),
256    ///             value: "some_value_2".to_string(),
257    ///         });
258    /// for el in map.iter(){
259    ///     println!("{el}")
260    /// }
261    /// // MultiElement < "some_key":"some_value_1" >
262    /// // MultiElement < "some_key":"some_value_2" >
263    /// ```
264    ///
265    /// ```
266    /// use multidict::{MultiDict, MultiElement};
267    ///
268    /// let mut map = MultiDict::new();
269    /// map.add(MultiElement {
270    ///             key: "some_key".to_string(),
271    ///             value: "some_value_1".to_string(),
272    ///         });
273    /// map.add(MultiElement {
274    ///             key: "some_key".to_string(),
275    ///             value: "some_value_2".to_string(),
276    ///         });
277    /// let mut iterator = map.iter();
278    /// assert_eq!(iterator.next(), Some(map.elements.iter().nth(0).unwrap()));
279    /// assert_eq!(iterator.next(), Some(&MultiElement {
280    ///                                     key: "some_key".to_string(),
281    ///                                     value: "some_value_2".to_string(),
282    ///                                 })
283    ///         );
284    /// ```
285    pub fn iter(&self) -> Iter<MultiElement> {
286        self.elements.iter()
287    }
288
289    /// Return true if `MultiDict` has **no** elements,
290    /// else false
291    ///
292    /// # Examples
293    ///
294    /// When some elements is added
295    /// ```
296    /// use multidict::{MultiDict, MultiElement};
297    ///
298    /// let mut map = MultiDict::new();
299    /// map.add(MultiElement {
300    ///             key: "some_key".to_string(),
301    ///             value: "some_value_1".to_string(),
302    ///         });
303    /// map.add(MultiElement {
304    ///             key: "some_key".to_string(),
305    ///             value: "some_value_2".to_string(),
306    ///         });
307    /// println!("{}", map.is_empty());
308    /// // false
309    /// ```
310    /// ```
311    /// use multidict::{MultiDict, MultiElement};
312    ///
313    /// let mut map = MultiDict::new();
314    /// println!("{}", map.is_empty());
315    /// // true
316    /// ```
317    pub fn is_empty(&self) -> bool {
318        self.elements.is_empty()
319    }
320
321    /// Append (key, value) pair to the MultiDict.
322    ///
323    /// # Examples
324    /// ```
325    /// use multidict::{MultiDict, MultiElement};
326    ///
327    /// let mut map = MultiDict::new();
328    /// map.add(MultiElement {
329    ///             key: "some_key".to_string(),
330    ///             value: "some_value_1".to_string(),
331    ///         });
332    /// println!("{map}");
333    /// // MultiDict < "some_key":"some_value_1" >
334    /// map.add(MultiElement {
335    ///             key: "some_key".to_string(),
336    ///             value: "some_value_2".to_string(),
337    ///         });
338    /// println!("{map}");
339    /// // MultiDict < "some_key":"some_value_1", "some_key":"some_value_2" >
340    /// ```
341    pub fn add(&mut self, new_item: MultiElement) {
342        self.elements.push(new_item);
343    }
344
345    /// Return the **first** key-value pair for key if key is in the MultiDict
346    ///
347    /// # Examples
348    ///
349    /// If key exists
350    /// ```
351    /// use multidict::{MultiDict, MultiElement};
352    ///
353    /// let mut map = MultiDict::new();
354    /// map.add(MultiElement {
355    ///             key: "some_key".to_string(),
356    ///             value: "some_value_1".to_string(),
357    ///         });
358    /// map.add(MultiElement {
359    ///             key: "some_key".to_string(),
360    ///             value: "some_value_2".to_string(),
361    ///         });
362    /// println!("{}", map.get("some_key").unwrap());
363    /// // MultiElement < "some_key":"some_value_1" >
364    /// ```
365    ///
366    /// If key not exists
367    /// ```
368    /// use multidict::{MultiDict, MultiElement};
369    ///
370    /// let mut map = MultiDict::new();
371    /// map.add(MultiElement {
372    ///             key: "some_key".to_string(),
373    ///             value: "some_value_1".to_string(),
374    ///         });
375    /// map.add(MultiElement {
376    ///             key: "some_key".to_string(),
377    ///             value: "some_value_2".to_string(),
378    ///         });
379    /// println!("{:?}", map.get("some_other_key"));
380    /// // Err("No matching key found")
381    /// ```
382    pub fn get(&self, key: &str) -> Result<&MultiElement, &str> {
383        for item in &self.elements {
384            if item.key.eq(key) {
385                return Ok(item);
386            }
387        }
388        Err("No matching key found")
389    }
390
391    /// If key is in the MultiDict, remove it and return its the **first** value,
392    /// else return error text
393    ///
394    /// # Examples
395    ///
396    /// If key exists
397    /// ```
398    /// use multidict::{MultiDict, MultiElement};
399    ///
400    /// let mut map = MultiDict::new();
401    /// map.add(MultiElement {
402    ///             key: "some_key".to_string(),
403    ///             value: "some_value_1".to_string(),
404    ///         });
405    /// map.add(MultiElement {
406    ///             key: "some_key".to_string(),
407    ///             value: "some_value_2".to_string(),
408    ///         });
409    /// println!("{}", map);
410    /// // MultiDict < "some_key":"some_value_1", "some_key":"some_value_2" >
411    /// println!("{}", map.popone("some_key").unwrap());
412    /// // MultiElement < "some_key":"some_value_1" >
413    /// println!("{}", map);
414    /// // MultiDict < "some_key":"some_value_2" >
415    /// ```
416    ///
417    /// If key not exists
418    /// ```
419    /// use multidict::{MultiDict, MultiElement};
420    ///
421    /// let mut map = MultiDict::new();
422    /// map.add(MultiElement {
423    ///             key: "some_key".to_string(),
424    ///             value: "some_value_1".to_string(),
425    ///         });
426    /// map.add(MultiElement {
427    ///             key: "some_key".to_string(),
428    ///             value: "some_value_2".to_string(),
429    ///         });
430    /// println!("{:?}", map.popone("some_other_key"));
431    /// // Err("No matching key found")
432    /// println!("{}", map);
433    /// // MultiDict < "some_key":"some_value_1", "some_key":"some_value_2" >
434    /// ```
435    ///
436    pub fn popone(&mut self, key: &str) -> Result<MultiElement, &str> {
437        for (idx, item) in self.elements.iter().enumerate() {
438            if item.key.eq(key) {
439                return Ok(self.elements.remove(idx));
440            }
441        }
442        Err("No matching key found")
443    }
444
445    /// Return a list of all key-values for key if key is in the MultiDict
446    /// else - return error
447    ///
448    /// # Examples
449    ///
450    /// If key exists
451    /// ```
452    /// use multidict::{MultiDict, MultiElement};
453    ///
454    /// let mut map = MultiDict::new();
455    /// map.add(MultiElement {
456    ///             key: "some_key".to_string(),
457    ///             value: "some_value_1".to_string(),
458    ///         });
459    /// map.add(MultiElement {
460    ///             key: "some_key".to_string(),
461    ///             value: "some_value_2".to_string(),
462    ///         });
463    /// println!("{}", map.getall("some_key").unwrap());
464    /// // MultiDict < "some_key":"some_value_1", "some_key":"some_value_2" >
465    /// ```
466    ///
467    /// If key not exists
468    /// ```
469    /// use multidict::{MultiDict, MultiElement};
470    ///
471    /// let mut map = MultiDict::new();
472    /// map.add(MultiElement {
473    ///             key: "some_key".to_string(),
474    ///             value: "some_value_1".to_string(),
475    ///         });
476    /// map.add(MultiElement {
477    ///             key: "some_key".to_string(),
478    ///             value: "some_value_2".to_string(),
479    ///         });
480    /// println!("{:?}", map.getall("some_other_key")); // Err("No matching key found")
481    /// ```
482    pub fn getall(&self, key: &str) -> Result<MultiDict, &str> {
483        let mut results = MultiDict::new();
484        for item in &self.elements {
485            if item.key.eq(key) {
486                results.add(item.clone());
487            }
488        }
489        if !results.is_empty() {
490            Ok(results)
491        } else {
492            Err("No matching key found")
493        }
494    }
495
496    /// Return True if MultiDict has a key, else False.
497    ///
498    /// # Examples
499    ///
500    /// If key exists
501    /// ```
502    /// use multidict::{MultiDict, MultiElement};
503    ///
504    /// let mut map = MultiDict::new();
505    /// map.add(MultiElement {
506    ///             key: "some_key".to_string(),
507    ///             value: "some_value_1".to_string(),
508    ///         });
509    /// map.add(MultiElement {
510    ///             key: "some_key".to_string(),
511    ///             value: "some_value_2".to_string(),
512    ///         });
513    /// println!("{}", map.contains("some_key"));
514    /// // true
515    /// ```
516    ///
517    /// If key not exists
518    /// ```
519    /// use multidict::{MultiDict, MultiElement};
520    ///
521    /// let mut map = MultiDict::new();
522    /// map.add(MultiElement {
523    ///             key: "some_key".to_string(),
524    ///             value: "some_value_1".to_string(),
525    ///         });
526    /// map.add(MultiElement {
527    ///             key: "some_key".to_string(),
528    ///             value: "some_value_2".to_string(),
529    ///         });
530    /// println!("{}", map.contains("some_other_key"));
531    /// // false
532    /// ```
533    pub fn contains(&self, key: &str) -> bool {
534        for item in &self.elements {
535            if item.key.eq(key) {
536                return true;
537            }
538        }
539        false
540    }
541
542    /// Return Vec of all keys form MultiDict.
543    /// View contains all keys, possibly with duplicates.
544    ///
545    /// # Examples
546    ///
547    /// ```
548    /// use multidict::{MultiDict, MultiElement};
549    ///
550    /// let mut map = MultiDict::new();
551    /// map.add(MultiElement {
552    ///             key: "some_key".to_string(),
553    ///             value: "some_value_1".to_string(),
554    ///         });
555    /// map.add(MultiElement {
556    ///             key: "some_key".to_string(),
557    ///             value: "some_value_2".to_string(),
558    ///         });
559    /// map.add(MultiElement {
560    ///             key: "some_other_key".to_string(),
561    ///             value: "some_value_3".to_string(),
562    ///         });
563    /// println!("{:?}", map.keys());
564    /// // ["some_key", "some_key", "some_other_key"]
565    /// ```
566    pub fn keys(&self) -> Vec<&String> {
567        let mut results: Vec<&String> = Vec::with_capacity(self.elements.len());
568        for item in &self.elements {
569            results.push(&item.key);
570        }
571        results
572    }
573
574    /// Return Vec of all values form MultiDict.
575    ///
576    /// # Examples
577    ///
578    /// ```
579    /// use multidict::{MultiDict, MultiElement};
580    ///
581    /// let mut map = MultiDict::new();
582    /// map.add(MultiElement {
583    ///             key: "some_key".to_string(),
584    ///             value: "some_value_1".to_string(),
585    ///         });
586    /// map.add(MultiElement {
587    ///             key: "some_key".to_string(),
588    ///             value: "some_value_2".to_string(),
589    ///         });
590    /// map.add(MultiElement {
591    ///             key: "some_other_key".to_string(),
592    ///             value: "some_value_3".to_string(),
593    ///         });
594    /// println!("{:?}", map.values());
595    /// // ["some_value_1", "some_value_2", "some_value_3"]
596    /// ```
597    pub fn values(&self) -> Vec<&String> {
598        let mut results: Vec<&String> = Vec::with_capacity(self.elements.len());
599        for item in &self.elements {
600            results.push(&item.value);
601        }
602        results
603    }
604
605    /// Update the MultiDict with the key/value pairs,
606    /// overwriting existing keys/values
607    ///
608    /// # Examples
609    ///
610    /// This function update values **only** for already exists keys
611    /// ```
612    /// use multidict::{MultiDict, MultiElement};
613    ///
614    /// let mut map = MultiDict::new();
615    /// map.add(MultiElement {
616    ///             key: "some_key".to_string(),
617    ///             value: "some_value_1".to_string(),
618    ///         });
619    /// map.add(MultiElement {
620    ///             key: "some_other_key".to_string(),
621    ///             value: "some_value_2".to_string(),
622    ///         });
623    /// println!("{map}");
624    /// // MultiDict < "some_key":"some_value_1", "some_other_key":"some_value_2" >
625    /// map.update(MultiElement {
626    ///             key: "some_other_key".to_string(),
627    ///             value: "some_value_3".to_string(),
628    ///         });
629    /// println!("{map}");
630    /// // MultiDict < "some_key":"some_value_1", "some_other_key":"some_value_3" >
631    /// ```
632    ///
633    /// And it's update all equal keys values
634    /// ```
635    /// use multidict::{MultiDict, MultiElement};
636    ///
637    /// let mut map = MultiDict::new();
638    /// map.add(MultiElement {
639    ///             key: "some_key".to_string(),
640    ///             value: "some_value_1".to_string(),
641    ///         });
642    /// map.add(MultiElement {
643    ///             key: "some_key".to_string(),
644    ///             value: "some_value_2".to_string(),
645    ///         });
646    /// println!("{map}");
647    /// // MultiDict < "some_key":"some_value_1", "some_key":"some_value_2" >
648    /// map.update(MultiElement {
649    ///             key: "some_key".to_string(),
650    ///             value: "some_value_3".to_string(),
651    ///         });
652    /// println!("{map}");
653    /// // MultiDict < "some_key":"some_value_3", "some_key":"some_value_3" >
654    /// ```
655    pub fn update(&mut self, new_item: MultiElement) {
656        let new_item_key = &new_item.key;
657        let mut ids_for_replace = Vec::new();
658
659        for (idx, item) in self.elements.iter().enumerate() {
660            if item.key.eq(new_item_key) {
661                ids_for_replace.push(idx);
662            }
663        }
664        for idx in ids_for_replace {
665            self.elements.remove(idx);
666            self.elements.insert(idx, new_item.clone());
667        }
668    }
669}