ojcmp/compare/
strict.rs

1use super::{CompareError, Comparison};
2
3use std::cmp::Ordering;
4use std::io::{self, BufRead};
5
6pub fn try_strict_compare(
7    std_reader: &mut impl BufRead,
8    user_reader: &mut impl BufRead,
9) -> Result<Comparison, CompareError> {
10    strict_compare(std_reader, user_reader).map_err(CompareError::Io)
11}
12
13fn fill_buf(reader: &mut impl BufRead) -> io::Result<Option<&[u8]>> {
14    let buf = reader.fill_buf()?;
15    if buf.is_empty() {
16        Ok(None)
17    } else {
18        Ok(Some(buf))
19    }
20}
21
22fn strict_compare(
23    std_reader: &mut impl BufRead,
24    user_reader: &mut impl BufRead,
25) -> io::Result<Comparison> {
26    loop {
27        let std_buf = fill_buf(std_reader)?;
28        let user_buf = fill_buf(user_reader)?;
29        let std_len;
30        let user_len;
31
32        match (std_buf, user_buf) {
33            (None, None) => return Ok(Comparison::AC),
34            (Some(_), None) | (None, Some(_)) => return Ok(Comparison::WA),
35            (Some(lhs), Some(rhs)) => match lhs.len().cmp(&rhs.len()) {
36                Ordering::Equal => {
37                    if lhs != rhs {
38                        return Ok(Comparison::WA);
39                    }
40                    std_len = lhs.len();
41                    user_len = rhs.len();
42                }
43                Ordering::Less => {
44                    let rhs = &rhs[..lhs.len()];
45                    if lhs != rhs {
46                        return Ok(Comparison::WA);
47                    }
48                    std_len = lhs.len();
49                    user_len = rhs.len();
50                }
51                Ordering::Greater => {
52                    let lhs = &lhs[..rhs.len()];
53                    if lhs != rhs {
54                        return Ok(Comparison::WA);
55                    }
56                    std_len = lhs.len();
57                    user_len = rhs.len();
58                }
59            },
60        }
61        std_reader.consume(std_len);
62        user_reader.consume(user_len);
63    }
64}
65
66#[test]
67fn test_strict_comparer() {
68    macro_rules! judge {
69        ($ret:expr, $std:expr,$user:expr) => {{
70            let mut std: &[u8] = $std.as_ref();
71            let mut user: &[u8] = $user.as_ref();
72
73            let ret = strict_compare(&mut std, &mut user).unwrap();
74            assert_eq!(ret, $ret);
75        }};
76    }
77
78    use Comparison::*;
79
80    judge!(AC, b"", b"");
81    judge!(AC, b"1", b"1");
82    judge!(AC, b"12", b"12");
83
84    judge!(WA, b"", b"a");
85    judge!(WA, b"a", b"");
86    judge!(WA, b"ab", b"ba");
87    judge!(WA, b"cc", b"ccc");
88    judge!(WA, b"ccc", b"cc");
89}