1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! The single error type of the crate.
use std::fmt;
/// Errors produced by the patch deserializer / applier.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum PatchError {
/// Patch ended in the middle of an opcode.
UnexpectedEof,
/// Opcode tag is neither `Copy` nor `Add`.
InvalidOpcode(u8),
/// `Copy` references a range outside `old`.
CopyOutOfBounds {
/// Requested offset.
offset: u32,
/// Requested length.
len: u32,
/// Actual length of `old`.
old_len: usize,
},
/// Arithmetic overflow while computing a copy/add range. Indicates a
/// crafted or corrupted patch.
Overflow,
/// `make_patch` was called with an input larger than `u32::MAX` bytes.
InputTooLarge {
/// The offending length.
len: usize,
},
/// Patch header names a format version this build cannot read.
UnsupportedVersion(u8),
/// The patch was built against a different base document. Applying it
/// anyway would silently produce a plausible but wrong result.
WrongBase {
/// Base length the patch was built against.
expected_len: u64,
/// Base fingerprint the patch was built against.
expected_hash: u64,
/// Length of the base it was applied to.
actual_len: u64,
/// Fingerprint of the base it was applied to.
actual_hash: u64,
},
}
impl fmt::Display for PatchError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
PatchError::UnexpectedEof => f.write_str("unexpected end of patch"),
PatchError::InvalidOpcode(tag) => write!(f, "invalid opcode tag: 0x{tag:02X}"),
PatchError::CopyOutOfBounds {
offset,
len,
old_len,
} => write!(
f,
"copy out of bounds: offset={offset} len={len} old_len={old_len}"
),
PatchError::Overflow => f.write_str("arithmetic overflow in patch range"),
PatchError::InputTooLarge { len } => {
write!(f, "input too large for patch format: {len} bytes")
}
PatchError::UnsupportedVersion(version) => {
write!(f, "unsupported patch format version: {version}")
}
PatchError::WrongBase {
expected_len,
expected_hash,
actual_len,
actual_hash,
} => write!(
f,
"patch was built against a different base: \
expected len={expected_len} hash={expected_hash:016x}, \
got len={actual_len} hash={actual_hash:016x}"
),
}
}
}
impl std::error::Error for PatchError {}