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}