|
1 | 1 | use std::cell::Cell; |
2 | 2 | use std::cmp::Ordering::{self, Equal, Greater, Less}; |
3 | 3 | use std::convert::identity; |
| 4 | +use std::fmt; |
4 | 5 | use std::mem; |
5 | 6 | use std::panic; |
6 | 7 | use std::rc::Rc; |
@@ -995,75 +996,65 @@ fn test_rsplitnator() { |
995 | 996 |
|
996 | 997 | #[test] |
997 | 998 | fn test_split_iterators_size_hint() { |
998 | | - for len in 0..=2 { |
999 | | - let mut v: Vec<u8> = (0..len).collect(); |
1000 | | - fn verify_descending(sequence: &[usize], context: &str) { |
1001 | | - let len = sequence.len(); |
1002 | | - let target: Vec<usize> = (0..len).rev().collect(); |
1003 | | - assert_eq!(sequence, target, "while testing: {}", context); |
1004 | | - } |
1005 | | - |
1006 | | - macro_rules! test_size_hint { |
1007 | | - ($create_iterator:expr) => {{ |
1008 | | - // with a predicate always returning false, the split*-iterators |
1009 | | - // become maximally short, so the size_hint lower bounds are correct |
1010 | | - |
1011 | | - macro_rules! p { |
1012 | | - () => { |
1013 | | - |_| false |
1014 | | - }; |
1015 | | - } |
1016 | | - let mut short_iterator = $create_iterator; |
1017 | | - let mut lower_bounds = vec![short_iterator.size_hint().0]; |
1018 | | - while let Some(_) = short_iterator.next() { |
1019 | | - lower_bounds.push(short_iterator.size_hint().0); |
| 999 | + #[derive(Copy, Clone)] |
| 1000 | + enum Bounds { |
| 1001 | + Lower, |
| 1002 | + Upper, |
| 1003 | + } |
| 1004 | + fn assert_precise_size_hints<I: Iterator>( |
| 1005 | + mut it: I, |
| 1006 | + which: Bounds, |
| 1007 | + context: impl fmt::Display, |
| 1008 | + ) { |
| 1009 | + match which { |
| 1010 | + Bounds::Lower => { |
| 1011 | + let mut lower_bounds = vec![it.size_hint().0]; |
| 1012 | + while let Some(_) = it.next() { |
| 1013 | + lower_bounds.push(it.size_hint().0); |
1020 | 1014 | } |
1021 | | - verify_descending(&lower_bounds, stringify!($create_iterator)); |
| 1015 | + let target: Vec<_> = (0..lower_bounds.len()).rev().collect(); |
| 1016 | + assert_eq!(lower_bounds, target, "incorrect lower bounds: {}", context); |
1022 | 1017 | } |
1023 | | - { |
1024 | | - // with a predicate always returning true, the split*-iterators |
1025 | | - // become maximally long, so the size_hint upper bounds are correct |
1026 | | - |
1027 | | - macro_rules! p { |
1028 | | - () => { |
1029 | | - |_| true |
1030 | | - }; |
1031 | | - } |
1032 | | - let mut long_iterator = $create_iterator; |
1033 | | - let mut upper_bounds = vec![ |
1034 | | - long_iterator.size_hint().1.expect("split*-methods have known upper bound"), |
1035 | | - ]; |
1036 | | - while let Some(_) = long_iterator.next() { |
1037 | | - upper_bounds.push( |
1038 | | - long_iterator.size_hint().1.expect("split*-methods have known upper bound"), |
1039 | | - ); |
| 1018 | + Bounds::Upper => { |
| 1019 | + let mut upper_bounds = vec![it.size_hint().1]; |
| 1020 | + while let Some(_) = it.next() { |
| 1021 | + upper_bounds.push(it.size_hint().1); |
1040 | 1022 | } |
1041 | | - verify_descending(&upper_bounds, stringify!($create_iterator)); |
1042 | | - }}; |
| 1023 | + let target: Vec<_> = (0..upper_bounds.len()).map(Some).rev().collect(); |
| 1024 | + assert_eq!(upper_bounds, target, "incorrect upper bounds: {}", context); |
| 1025 | + } |
1043 | 1026 | } |
| 1027 | + } |
1044 | 1028 |
|
1045 | | - test_size_hint!(v.split(p!())); |
1046 | | - test_size_hint!(v.split_mut(p!())); |
1047 | | - test_size_hint!(v.splitn(0, p!())); |
1048 | | - test_size_hint!(v.splitn(1, p!())); |
1049 | | - test_size_hint!(v.splitn(2, p!())); |
1050 | | - test_size_hint!(v.splitn(3, p!())); |
1051 | | - test_size_hint!(v.splitn_mut(0, p!())); |
1052 | | - test_size_hint!(v.splitn_mut(1, p!())); |
1053 | | - test_size_hint!(v.splitn_mut(2, p!())); |
1054 | | - test_size_hint!(v.splitn_mut(3, p!())); |
1055 | | - test_size_hint!(v.split_inclusive(p!())); |
1056 | | - test_size_hint!(v.split_inclusive_mut(p!())); |
1057 | | - test_size_hint!(v.rsplit(p!())); |
1058 | | - test_size_hint!(v.rsplit_mut(p!())); |
1059 | | - test_size_hint!(v.rsplitn(0, p!())); |
1060 | | - test_size_hint!(v.rsplitn(1, p!())); |
1061 | | - test_size_hint!(v.rsplitn(2, p!())); |
1062 | | - test_size_hint!(v.rsplitn(3, p!())); |
1063 | | - test_size_hint!(v.rsplitn_mut(0, p!())); |
1064 | | - test_size_hint!(v.rsplitn_mut(1, p!())); |
1065 | | - test_size_hint!(v.rsplitn_mut(2, p!())); |
1066 | | - test_size_hint!(v.rsplitn_mut(3, p!())); |
| 1029 | + for len in 0..=2 { |
| 1030 | + let mut v: Vec<u8> = (0..len).collect(); |
| 1031 | + |
| 1032 | + // p: predicate, b: bound selection |
| 1033 | + for (p, b) in [ |
| 1034 | + // with a predicate always returning false, the split*-iterators |
| 1035 | + // become maximally short, so the size_hint lower bounds are correct |
| 1036 | + ((|_| false) as fn(&_) -> _, Bounds::Lower), |
| 1037 | + // with a predicate always returning true, the split*-iterators |
| 1038 | + // become maximally long, so the size_hint upper bounds are correct |
| 1039 | + ((|_| true) as fn(&_) -> _, Bounds::Upper), |
| 1040 | + ] { |
| 1041 | + use assert_precise_size_hints as a; |
| 1042 | + use format_args as f; |
| 1043 | + |
| 1044 | + a(v.split(p), b, "split"); |
| 1045 | + a(v.split_mut(p), b, "split_mut"); |
| 1046 | + a(v.split_inclusive(p), b, "split_inclusive"); |
| 1047 | + a(v.split_inclusive_mut(p), b, "split_inclusive_mut"); |
| 1048 | + a(v.rsplit(p), b, "rsplit"); |
| 1049 | + a(v.rsplit_mut(p), b, "rsplit_mut"); |
| 1050 | + |
| 1051 | + for n in 0..=3 { |
| 1052 | + a(v.splitn(n, p), b, f!("splitn, n = {}", n)); |
| 1053 | + a(v.splitn_mut(n, p), b, f!("splitn_mut, n = {}", n)); |
| 1054 | + a(v.rsplitn(n, p), b, f!("rsplitn, n = {}", n)); |
| 1055 | + a(v.rsplitn_mut(n, p), b, f!("rsplitn_mut, n = {}", n)); |
| 1056 | + } |
| 1057 | + } |
1067 | 1058 | } |
1068 | 1059 | } |
1069 | 1060 |
|
|
0 commit comments