1use binrw::{BinRead, BinResult, Endian};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum ApplyOptionKind {
6 IgnoreMissing,
8 IgnoreOldMismatch,
10}
11
12fn read_apply_option_kind<R: std::io::Read + std::io::Seek>(
13 reader: &mut R,
14 endian: Endian,
15 (): (),
16) -> BinResult<ApplyOptionKind> {
17 let raw = <u32 as BinRead>::read_options(reader, endian, ())?;
18 match raw {
19 1 => Ok(ApplyOptionKind::IgnoreMissing),
20 2 => Ok(ApplyOptionKind::IgnoreOldMismatch),
21 _ => Err(binrw::Error::Custom {
22 pos: 0,
23 err: Box::new(std::io::Error::new(
24 std::io::ErrorKind::InvalidData,
25 "unknown ApplyOption kind",
26 )),
27 }),
28 }
29}
30
31#[derive(BinRead, Debug, Clone, PartialEq, Eq)]
33#[br(big)]
34pub struct ApplyOption {
35 #[br(parse_with = read_apply_option_kind)]
37 pub kind: ApplyOptionKind,
38 #[br(pad_before = 4, map = |x: u32| x != 0)]
40 pub value: bool,
41}
42
43pub(crate) fn parse(body: &[u8]) -> crate::Result<ApplyOption> {
44 super::util::parse_be(body)
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 fn make_body(kind: u32, value: u32) -> Vec<u8> {
52 let mut body = Vec::new();
53 body.extend_from_slice(&kind.to_be_bytes());
54 body.extend_from_slice(&[0u8; 4]); body.extend_from_slice(&value.to_be_bytes());
56 body
57 }
58
59 #[test]
60 fn parses_apply_option_ignore_missing() {
61 let cmd = parse(&make_body(1, 0)).unwrap();
62 assert_eq!(cmd.kind, ApplyOptionKind::IgnoreMissing);
63 assert!(!cmd.value);
64 }
65
66 #[test]
67 fn parses_apply_option_ignore_old_mismatch() {
68 let cmd = parse(&make_body(2, 1)).unwrap();
69 assert_eq!(cmd.kind, ApplyOptionKind::IgnoreOldMismatch);
70 assert!(cmd.value);
71 }
72
73 #[test]
74 fn rejects_invalid_apply_option_kind() {
75 assert!(parse(&make_body(0, 0)).is_err());
76 assert!(parse(&make_body(3, 0)).is_err());
77 }
78}