1use core::fmt;
16
17use crate::{
18 class,
19 error::{ErrorKind, Result, err},
20 limits::{DuplicatePolicy, Limits},
21 scan::control_kind,
22 text::{Word, is_ows, parse_quoted, token_len, validated_word},
23};
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
37pub struct Param<'a> {
38 pub name: &'a [u8],
40 pub value: Word<'a>,
42}
43
44pub const MAX_CHECKED_PARAMS: usize = 64;
67
68const INLINE_NAMES: usize = 8;
71
72pub(crate) struct Names {
77 first: [usize; INLINE_NAMES],
78 rest: Option<[usize; MAX_CHECKED_PARAMS - INLINE_NAMES]>,
79 len: usize,
80 seen: u64,
81}
82
83impl Names {
84 #[inline]
85 pub(crate) const fn new() -> Self {
86 Self {
87 first: [0; INLINE_NAMES],
88 rest: None,
89 len: 0,
90 seen: 0,
91 }
92 }
93
94 #[inline]
98 pub(crate) fn repeats(
99 &mut self,
100 text: &[u8],
101 off: usize,
102 name: &[u8],
103 in_name: fn(u8) -> bool,
104 ) -> bool {
105 let bit = name_bit(name);
106 if self.seen & bit == 0 {
107 if let Some(slot) = self.first.get_mut(self.len) {
108 self.seen |= bit;
109 *slot = off;
110 self.len += 1;
111 return false;
112 }
113 }
114 self.repeats_slow(text, off, name, in_name, bit)
115 }
116
117 #[cold]
120 fn repeats_slow(
121 &mut self,
122 text: &[u8],
123 off: usize,
124 name: &[u8],
125 in_name: fn(u8) -> bool,
126 bit: u64,
127 ) -> bool {
128 if self.seen & bit != 0 {
129 let l = name.len();
130 let same = |&o: &usize| {
131 text.get(o + l).is_none_or(|&b| !in_name(b))
132 && text
133 .get(o..o + l)
134 .is_some_and(|e| e.eq_ignore_ascii_case(name))
135 };
136 let inline = self.first.get(..self.len.min(INLINE_NAMES));
137 let spilled = self.len.saturating_sub(INLINE_NAMES);
138 let rest = self.rest.as_ref().and_then(|r| r.get(..spilled));
139 if inline.unwrap_or(&[]).iter().any(same) || rest.unwrap_or(&[]).iter().any(same) {
140 return true;
141 }
142 }
143 self.seen |= bit;
144 let slot = match self.len.checked_sub(INLINE_NAMES) {
145 None => self.first.get_mut(self.len),
146 Some(i) => self
147 .rest
148 .get_or_insert([0; MAX_CHECKED_PARAMS - INLINE_NAMES])
149 .get_mut(i),
150 };
151 if let Some(slot) = slot {
152 *slot = off;
153 self.len += 1;
154 }
155 false
156 }
157}
158
159#[inline]
162fn name_bit(name: &[u8]) -> u64 {
163 let first = name.first().map_or(0, u8::to_ascii_lowercase);
164 let last = name.last().map_or(0, u8::to_ascii_lowercase);
165 let h = (name.len() as u64)
166 .wrapping_mul(31)
167 .wrapping_add(u64::from(first))
168 .wrapping_mul(31)
169 .wrapping_add(u64::from(last));
170 1u64 << (h & 63)
171}
172
173pub fn parse<'a>(s: &'a [u8], limits: &Limits) -> Result<(Params<'a>, usize)> {
200 let policy = limits.duplicate_params;
201 let refuse = policy == DuplicatePolicy::Refuse;
202 let max = if refuse {
203 usize::from(limits.params).min(MAX_CHECKED_PARAMS)
204 } else {
205 usize::from(limits.params)
206 };
207 let at = |rest: &[u8]| s.len() - rest.len();
210 let (mut done, mut count) = (s, 0usize);
211 let mut names = Names::new();
212 while let [b';', after @ ..] = skip_ws(done) {
213 let r = skip_ws(after);
214 let n = token_len(r);
215 if n == 0 {
216 match r.first() {
217 None | Some(b';') => {
218 done = r;
219 continue;
220 }
221 Some(b',') => {
224 done = after;
225 break;
226 }
227 Some(&b) => {
228 let kind = if crate::scan::is_control(b) {
229 control_kind(b)
230 } else {
231 ErrorKind::NotToken
232 };
233 return err(kind, at(r));
234 }
235 }
236 }
237 let name_at = at(r);
238 let (name, r) = r.split_at(n);
239 let value = match r {
240 [b'=', value @ ..] => value,
241 [b, ..] if is_ows(*b) => {
242 let kind = if skip_ws(r).first() == Some(&b'=') {
243 ErrorKind::InvalidByte
244 } else {
245 ErrorKind::MissingValue
246 };
247 return err(kind, at(r));
248 }
249 [b'"', ..] => return err(ErrorKind::MissingValue, at(r)),
250 [b, ..] if *b != b';' && *b != b',' && class::is_field_text(*b) => {
251 return err(ErrorKind::NotToken, at(r));
252 }
253 [b, ..] if !class::is_field_text(*b) => return err(control_kind(*b), at(r)),
254 _ => return err(ErrorKind::MissingValue, at(r)),
255 };
256 let used = match value {
257 [b, ..] if is_ows(*b) => return err(ErrorKind::InvalidByte, at(value)),
258 [] | [b';' | b',', ..] => return err(ErrorKind::MissingValue, at(value)),
259 [b'"', ..] => parse_quoted(value).map_err(|e| e.shifted(at(value)))?.1,
260 [b, ..] => match token_len(value) {
261 0 => return err(control_or_invalid(*b), at(value)),
262 n => n,
263 },
264 };
265 count += 1;
266 if count > max {
267 return err(ErrorKind::TooManyMembers, name_at);
268 }
269 if refuse && names.repeats(s, name_at, name, class::is_tchar) {
270 return err(ErrorKind::DuplicateParameter, name_at);
271 }
272 done = value.get(used..).unwrap_or(&[]);
273 }
274 let used = at(done);
275 Ok((
276 Params {
277 text: s.get(..used).unwrap_or(&[]),
278 count: u32::try_from(count).unwrap_or(u32::MAX),
279 policy,
280 },
281 used,
282 ))
283}
284
285#[inline]
287fn skip_ws(s: &[u8]) -> &[u8] {
288 match s {
289 [b' ' | b'\t', ..] => {
290 let n = s
291 .iter()
292 .position(|&b| b != b' ' && b != b'\t')
293 .unwrap_or(s.len());
294 s.get(n..).unwrap_or(&[])
295 }
296 _ => s,
297 }
298}
299
300#[inline]
301const fn control_or_invalid(b: u8) -> ErrorKind {
302 if crate::scan::is_control(b) {
303 control_kind(b)
304 } else {
305 ErrorKind::InvalidByte
306 }
307}
308
309#[derive(Clone, Copy, PartialEq, Eq, Hash)]
324pub struct Params<'a> {
325 pub(crate) text: &'a [u8],
326 pub(crate) count: u32,
327 pub(crate) policy: DuplicatePolicy,
328}
329
330impl<'a> Params<'a> {
331 #[must_use]
345 pub fn iter(&self) -> ParamIter<'a> {
346 ParamIter { rest: self.text }
347 }
348
349 #[must_use]
363 pub fn get(&self, name: &str) -> Option<Word<'a>> {
364 let name = name.as_bytes();
365 let last = self.policy == DuplicatePolicy::Last;
366 let mut found = None;
367 let mut rest = self.text;
373 while let [b';', after @ ..] = skip_ws(rest) {
374 let tail = skip_ws(after);
375 let value = match tail.split_at_checked(name.len()) {
376 Some((head, [b'=', value @ ..]))
379 if (head == name || head.eq_ignore_ascii_case(name))
380 && head.first().is_some_and(|&b| class::is_tchar(b))
381 && !name.contains(&b'=') =>
382 {
383 let (word, used) = validated_word(value);
384 if !last {
385 return Some(word);
386 }
387 found = Some(word);
388 rest = value.get(used..).unwrap_or(&[]);
389 continue;
390 }
391 _ => match token_len(tail) {
392 0 => {
393 rest = tail;
394 continue;
395 }
396 n => tail.get(n + 1..).unwrap_or(&[]),
397 },
398 };
399 rest = value.get(validated_word(value).1..).unwrap_or(&[]);
400 }
401 found
402 }
403
404 pub(crate) fn split_at_name(&self, name: &[u8]) -> (Params<'a>, Option<Param<'a>>) {
409 for (index, p) in self.iter().enumerate() {
410 if p.name.eq_ignore_ascii_case(name) {
411 let off = (p.name.as_ptr() as usize).saturating_sub(self.text.as_ptr() as usize);
413 let head = self.text.get(..off).unwrap_or(&[]);
414 let semi = head.iter().rposition(|&b| b == b';').unwrap_or(0);
415 let mut text = self.text.get(..semi).unwrap_or(&[]);
416 while let [rest @ .., b' ' | b'\t'] = text {
417 text = rest;
418 }
419 let before = Params {
420 text,
421 count: u32::try_from(index).unwrap_or(u32::MAX),
422 policy: self.policy,
423 };
424 return (before, Some(p));
425 }
426 }
427 (*self, None)
428 }
429
430 #[must_use]
441 pub const fn len(&self) -> usize {
442 self.count as usize
443 }
444
445 #[must_use]
457 pub const fn is_empty(&self) -> bool {
458 self.count == 0
459 }
460
461 #[must_use]
474 pub const fn raw(&self) -> &'a [u8] {
475 self.text
476 }
477}
478
479impl fmt::Debug for Params<'_> {
480 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481 f.write_str("Params(")?;
482 f.debug_list()
483 .entries(
484 self.iter()
485 .map(|p| core::str::from_utf8(p.name).unwrap_or("?")),
486 )
487 .finish()?;
488 f.write_str(")")
489 }
490}
491
492#[derive(Clone, Debug)]
507pub struct ParamIter<'a> {
508 rest: &'a [u8],
509}
510
511impl<'a> Iterator for ParamIter<'a> {
512 type Item = Param<'a>;
513
514 fn next(&mut self) -> Option<Param<'a>> {
515 loop {
516 let [b';', after @ ..] = skip_ws(self.rest) else {
518 self.rest = &[];
519 return None;
520 };
521 let tail = skip_ws(after);
522 let n = token_len(tail);
523 let Some((name, [_, value_text @ ..])) = (n > 0).then(|| tail.split_at(n)) else {
524 self.rest = tail;
525 continue;
526 };
527 let (value, used) = validated_word(value_text);
528 self.rest = value_text.get(used..).unwrap_or(&[]);
529 return Some(Param { name, value });
530 }
531 }
532}
533
534#[cfg(test)]
535mod tests {
536 use std::{format, string::String, vec, vec::Vec};
537
538 use proptest::prelude::{Just, Strategy, prop, prop_assert_eq, prop_oneof};
539
540 use super::*;
541
542 fn p(s: &[u8]) -> Result<(Params<'_>, usize)> {
543 parse(s, &Limits::DEFAULT)
544 }
545
546 fn names<'a>(ps: &Params<'a>) -> Vec<&'a [u8]> {
547 ps.iter().map(|x| x.name).collect()
548 }
549
550 #[test]
551 fn test_params_edge_cases() {
552 assert_eq!(p(b"").unwrap().1, 0);
553 assert!(p(b";").unwrap().0.is_empty());
554 assert_eq!(p(b";").unwrap().1, 1);
555 assert_eq!(p(b";;").unwrap().1, 2);
556 let (ps, used) = p(b"; a=b").unwrap();
557 assert_eq!((used, names(&ps)), (5, [&b"a"[..]].to_vec()));
558 assert_eq!(p(b";a=").unwrap_err().kind(), ErrorKind::MissingValue);
559 assert_eq!(p(b";a").unwrap_err().kind(), ErrorKind::MissingValue);
560 assert_eq!(p(b";a;b=c").unwrap_err().kind(), ErrorKind::MissingValue);
561 assert_eq!(p(b";a =b").unwrap_err().kind(), ErrorKind::InvalidByte);
562 assert_eq!(p(b";a= b").unwrap_err().kind(), ErrorKind::InvalidByte);
563 assert_eq!(p(b";@=b").unwrap_err().kind(), ErrorKind::NotToken);
564 assert_eq!(p(b";a@=b").unwrap_err().kind(), ErrorKind::NotToken);
565 assert_eq!(p(b";a=\"\"").unwrap().0.get("a").map(|w| w.len()), Some(0));
566 assert!(
567 p(b";a=\"x\\\"y\"")
568 .unwrap()
569 .0
570 .get("a")
571 .unwrap()
572 .eq_bytes(b"x\"y")
573 );
574 assert_eq!(
575 p(b";a=\"x").unwrap_err().kind(),
576 ErrorKind::UnterminatedQuote
577 );
578 assert_eq!(p(b";a=b\rc").unwrap().1, 4);
579 assert_eq!(p(b";a=\x01").unwrap_err().kind(), ErrorKind::Control);
580 }
581
582 #[test]
583 fn test_params_stop_at_list_separator_and_trailing_ows() {
584 let (ps, used) = p(b";a=1 , b").unwrap();
585 assert_eq!((used, ps.len()), (4, 1));
586 let (_, used) = p(b";a=1; ,b").unwrap();
587 assert_eq!(used, 5);
588 let (_, used) = p(b" ;a=1 x").unwrap();
589 assert_eq!(used, 5);
590 }
591
592 #[test]
593 fn test_params_duplicate_refused_case_insensitive() {
594 let e = p(b";A=b;a=c").unwrap_err();
595 assert_eq!((e.kind(), e.offset()), (ErrorKind::DuplicateParameter, 5));
596 assert!(p(b";ab=1;ba=2;aa=3;bb=4").is_ok());
597 }
598
599 #[test]
600 fn test_params_first_and_last_policies() {
601 let first = Limits::DEFAULT.duplicate_params(DuplicatePolicy::First);
602 let last = Limits::DEFAULT.duplicate_params(DuplicatePolicy::Last);
603 let (a, _) = parse(b";a=1;A=2", &first).unwrap();
604 let (b, _) = parse(b";a=1;A=2", &last).unwrap();
605 assert!(a.get("a").unwrap().eq_bytes(b"1"));
606 assert!(b.get("a").unwrap().eq_bytes(b"2"));
607 assert_eq!(a.len(), 2);
608 }
609
610 #[test]
611 fn test_params_count_limit() {
612 let mut v = Vec::new();
613 for i in 0..257 {
614 v.extend_from_slice(format!(";p{i}=v").as_bytes());
615 }
616 let cut = v.len() - format!(";p{}=v", 256).len();
617 for policy in [DuplicatePolicy::First, DuplicatePolicy::Last] {
619 let l = Limits::DEFAULT.duplicate_params(policy);
620 assert_eq!(parse(&v[..cut], &l).unwrap().0.len(), 256);
621 assert_eq!(parse(&v, &l).unwrap_err().kind(), ErrorKind::TooManyMembers);
622 }
623 let upto = |n: usize| {
625 (0..n)
626 .map(|i| format!(";p{i}=v"))
627 .collect::<Vec<_>>()
628 .concat()
629 };
630 assert_eq!(p(upto(MAX_CHECKED_PARAMS).as_bytes()).unwrap().0.len(), 64);
631 let over = upto(MAX_CHECKED_PARAMS + 1);
632 let e = p(over.as_bytes()).unwrap_err();
633 let last = over.rfind(';').unwrap() + 1;
634 assert_eq!((e.kind(), e.offset()), (ErrorKind::TooManyMembers, last));
635 let wide = Limits::DEFAULT.max_params(u16::MAX);
636 assert_eq!(
637 parse(over.as_bytes(), &wide).unwrap_err().kind(),
638 ErrorKind::TooManyMembers
639 );
640 assert_eq!(
641 parse(upto(3).as_bytes(), &Limits::DEFAULT.max_params(2))
642 .unwrap_err()
643 .kind(),
644 ErrorKind::TooManyMembers
645 );
646 }
647
648 #[test]
649 fn test_params_duplicate_found_in_every_table_slot() {
650 let base = (0..63)
654 .map(|i| format!(";p{i}=\"v;p{i}=w\""))
655 .collect::<Vec<_>>()
656 .concat();
657 for i in 0..63 {
658 let dup = format!("{base};P{i}=x");
659 let e = p(dup.as_bytes()).unwrap_err();
660 assert_eq!(
661 (e.kind(), e.offset()),
662 (ErrorKind::DuplicateParameter, base.len() + 1),
663 "{i}"
664 );
665 }
666 for other in ["p", "p1x", "xp1", "p100"] {
667 assert!(p(format!("{base};{other}=x").as_bytes()).is_ok(), "{other}");
668 }
669 }
670
671 #[test]
672 fn test_params_debug_prints_names_only() {
673 let (ps, _) = p(b";user=alice;token=\"s3cr3t\"").unwrap();
674 let d = format!("{ps:?}");
675 assert_eq!(d, "Params([\"user\", \"token\"])");
676 assert!(!d.contains("s3cr3t") && !d.contains("alice"));
677 }
678
679 #[test]
680 fn test_params_iter_skips_empty_parameters() {
681 let (ps, _) = p(b";; a=1 ;;b=\"x;y\";").unwrap();
682 assert_eq!(names(&ps), [&b"a"[..], b"b"]);
683 assert!(ps.get("b").unwrap().eq_bytes(b"x;y"));
684 assert_eq!(ps.raw(), b";; a=1 ;;b=\"x;y\";");
685 }
686
687 #[test]
688 fn test_params_get_matches_whole_names_only() {
689 let (ps, _) = p(b";;a=\"\"").unwrap();
692 assert!(ps.get(";a").is_none());
693 assert!(ps.get("a").is_some_and(|v| v.eq_bytes(b"")));
694 let (ps, _) = p(b";a=b;c=d").unwrap();
695 for name in ["a=b", "a=b;c", "", ";", "=", "a;", " a"] {
696 assert!(ps.get(name).is_none(), "{name}");
697 }
698 assert!(ps.get("C").is_some_and(|v| v.eq_bytes(b"d")));
699 }
700
701 mod reference {
704 use super::super::*;
705 use crate::text::{parse_word, skip_ows};
706
707 pub(super) fn parse<'a>(s: &'a [u8], limits: &Limits) -> Result<(Params<'a>, usize)> {
708 let policy = limits.duplicate_params;
709 let mut count: usize = 0;
710 let mut used = 0usize;
711 let mut seen: u64 = 0;
712 loop {
713 let ows = skip_ows(s.get(used..).unwrap_or(&[]));
714 let semi = used + ows;
715 if s.get(semi) != Some(&b';') {
716 break;
717 }
718 let mut i = semi + 1;
719 i += skip_ows(s.get(i..).unwrap_or(&[]));
720 match s.get(i) {
721 None | Some(b';') => {
722 used = i;
723 continue;
724 }
725 Some(&b) if !class::is_tchar(b) => {
726 if b == b',' {
729 used = semi + 1;
730 break;
731 }
732 return err(
733 if crate::scan::is_control(b) {
734 control_kind(b)
735 } else {
736 ErrorKind::NotToken
737 },
738 i,
739 );
740 }
741 Some(_) => {}
742 }
743 let name_start = i;
744 let name_len = s
745 .get(i..)
746 .unwrap_or(&[])
747 .iter()
748 .take_while(|&&b| class::is_tchar(b))
749 .count();
750 let name = s.get(name_start..name_start + name_len).unwrap_or(&[]);
751 i += name_len;
752 match s.get(i) {
753 Some(b'=') => i += 1,
754 Some(&b) if is_ows(b) => {
755 let after = i + skip_ows(s.get(i..).unwrap_or(&[]));
756 if s.get(after) == Some(&b'=') {
757 return err(ErrorKind::InvalidByte, i);
758 }
759 return err(ErrorKind::MissingValue, i);
760 }
761 Some(b'"') => return err(ErrorKind::MissingValue, i),
762 Some(&b) if b != b';' && b != b',' && class::is_field_text(b) => {
763 return err(ErrorKind::NotToken, i);
764 }
765 Some(&b) if !class::is_field_text(b) => return err(control_kind(b), i),
766 _ => return err(ErrorKind::MissingValue, i),
767 }
768 let value_start = i;
769 match s.get(i) {
770 Some(&b) if is_ows(b) => return err(ErrorKind::InvalidByte, i),
771 None | Some(b';' | b',') => return err(ErrorKind::MissingValue, i),
772 _ => {}
773 }
774 let rest = s.get(i..).unwrap_or(&[]);
775 let (_, n) = parse_word(rest).map_err(|e| match e.kind() {
776 ErrorKind::Empty => crate::error::ParseError::new(
777 control_or_invalid(rest.first().copied().unwrap_or(0)),
778 value_start,
779 ),
780 _ => e.shifted(value_start),
781 })?;
782 i += n;
783 count += 1;
784 if count > usize::from(limits.params) {
785 return err(ErrorKind::TooManyMembers, name_start);
786 }
787 if policy == DuplicatePolicy::Refuse {
788 let bit = name_bit(name);
789 if seen & bit != 0 {
790 let earlier = Params {
791 text: s.get(..used).unwrap_or(&[]),
792 count: 0,
793 policy,
794 };
795 if earlier.iter().any(|p| p.name.eq_ignore_ascii_case(name)) {
796 return err(ErrorKind::DuplicateParameter, name_start);
797 }
798 }
799 seen |= bit;
800 }
801 used = i;
802 }
803 Ok((
804 Params {
805 text: s.get(..used).unwrap_or(&[]),
806 count: u32::try_from(count).unwrap_or(u32::MAX),
807 policy,
808 },
809 used,
810 ))
811 }
812 }
813
814 fn param_text() -> impl Strategy<Value = Vec<u8>> {
816 let piece = prop_oneof![
817 Just(b";".to_vec()),
818 Just(b" ".to_vec()),
819 Just(b"\t".to_vec()),
820 Just(b"=".to_vec()),
821 Just(b",".to_vec()),
822 Just(b"\"a\\\"b;c=d\"".to_vec()),
823 Just(b"\"\\".to_vec()),
824 Just(b"\r".to_vec()),
825 Just(b"\x7f".to_vec()),
826 "[a-cA-C]{1,3}".prop_map(String::into_bytes),
827 "[0-9]{1,3}".prop_map(String::into_bytes),
828 "[(){}@/]".prop_map(String::into_bytes),
829 "; ?[a-cA-C]{1,2}=[0-9a-c]{1,2}".prop_map(String::into_bytes),
830 "; ?[a-c]=\"[a-c;,= ]{0,3}\"".prop_map(String::into_bytes),
831 ];
832 prop::collection::vec(piece, 0..16).prop_map(|v| v.concat())
833 }
834
835 fn outcome(
836 r: Result<(Params<'_>, usize)>,
837 ) -> core::result::Result<(Vec<u8>, usize, usize), (ErrorKind, usize)> {
838 r.map(|(p, used)| (p.raw().to_vec(), p.len(), used))
839 .map_err(|e| (e.kind(), e.offset()))
840 }
841
842 fn reference_iter(raw: &[u8]) -> Vec<Param<'_>> {
844 let mut out = Vec::new();
845 let mut i = 0;
846 loop {
847 i += crate::text::skip_ows(raw.get(i..).unwrap_or(&[]));
848 if raw.get(i) != Some(&b';') {
849 return out;
850 }
851 i += 1;
852 i += crate::text::skip_ows(raw.get(i..).unwrap_or(&[]));
853 let Ok((name, n)) = crate::text::parse_token(raw.get(i..).unwrap_or(&[])) else {
854 continue;
855 };
856 i += n + 1;
857 let (value, n) = crate::text::parse_word(raw.get(i..).unwrap_or(&[])).unwrap();
858 i += n;
859 out.push(Param { name, value });
860 }
861 }
862
863 proptest::proptest! {
864 #![proptest_config(proptest::prelude::ProptestConfig::with_cases(4096))]
865
866 #[test]
867 fn test_parse_agrees_with_reference(v in param_text()) {
868 for policy in [DuplicatePolicy::Refuse, DuplicatePolicy::First, DuplicatePolicy::Last] {
869 let limits = Limits::DEFAULT.duplicate_params(policy);
870 prop_assert_eq!(outcome(parse(&v, &limits)), outcome(reference::parse(&v, &limits)));
871 }
872 }
873
874 #[test]
875 fn test_iter_and_get_agree_with_checked_reads(v in param_text(), name in "[a-cA-C=; \"]{0,4}") {
876 for policy in [DuplicatePolicy::Refuse, DuplicatePolicy::First, DuplicatePolicy::Last] {
877 let limits = Limits::DEFAULT.duplicate_params(policy);
878 let Ok((p, _)) = parse(&v, &limits) else { continue };
879 let all: Vec<Param<'_>> = p.iter().collect();
880 prop_assert_eq!(&all, &reference_iter(p.raw()));
881 prop_assert_eq!(all.len(), p.len());
882 let mut matching = all.iter().filter(|x| x.name.eq_ignore_ascii_case(name.as_bytes()));
883 let expected = if policy == DuplicatePolicy::Last { matching.next_back() } else { matching.next() };
884 prop_assert_eq!(p.get(&name), expected.map(|x| x.value));
885 for x in &all {
886 let n = core::str::from_utf8(x.name).unwrap();
887 let mut same = all.iter().filter(|y| y.name.eq_ignore_ascii_case(x.name));
888 let expected = if policy == DuplicatePolicy::Last { same.next_back() } else { same.next() };
889 prop_assert_eq!(p.get(n), expected.map(|y| y.value));
890 }
891 }
892 }
893 }
894}