gawires_patch/
lib.rs

1use byteorder::{LittleEndian, ReadBytesExt};
2use integer_encoding::VarIntReader;
3use std::{
4    cmp::min,
5    error::Error as StdError,
6    fmt,
7    io::{self, ErrorKind, Read, Seek, SeekFrom},
8};
9
10pub const MAGIC: u32 = 0xB1DF;
11pub const VERSION: u32 = 0x1000;
12
13#[derive(Debug)]
14pub enum DecodeError {
15    IO(io::Error),
16    WrongMagic(u32),
17    WrongVersion(u32),
18}
19
20impl fmt::Display for DecodeError {
21    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
22        match self {
23            DecodeError::IO(_) => write!(f, "I/O error"),
24            DecodeError::WrongMagic(e) => {
25                write!(f, "wrong magic: expected `{:X}`, got `{:X}`", MAGIC, e)
26            }
27            DecodeError::WrongVersion(e) => {
28                write!(f, "wrong version: expected `{:X}`, got `{:X}`", VERSION, e)
29            }
30        }
31    }
32}
33
34impl StdError for DecodeError {
35    fn source(&self) -> Option<&(dyn StdError + 'static)> {
36        match self {
37            DecodeError::IO(e) => Some(e),
38            DecodeError::WrongMagic { .. } => None,
39            DecodeError::WrongVersion { .. } => None,
40        }
41    }
42}
43
44impl From<io::Error> for DecodeError {
45    fn from(source: io::Error) -> Self {
46        DecodeError::IO(source)
47    }
48}
49
50pub struct Reader<R, RS>
51where
52    R: Read,
53    RS: Read + Seek,
54{
55    patch: R,
56    old: RS,
57    state: ReaderState,
58    buf: Vec<u8>,
59}
60
61#[derive(Debug)]
62enum ReaderState {
63    Initial,
64    Add(usize),
65    Copy(usize),
66    Final,
67}
68
69impl<R, RS> Reader<R, RS>
70where
71    R: Read,
72    RS: Read + Seek,
73{
74    pub fn new(mut patch: R, old: RS) -> Result<Self, DecodeError> {
75        let magic = patch.read_u32::<LittleEndian>()?;
76        if magic != MAGIC {
77            return Err(DecodeError::WrongMagic(magic));
78        }
79
80        let version = patch.read_u32::<LittleEndian>()?;
81        if version != VERSION {
82            return Err(DecodeError::WrongMagic(version));
83        }
84
85        Ok(Self {
86            patch,
87            old,
88            state: ReaderState::Initial,
89            buf: vec![0u8; 4096],
90        })
91    }
92}
93
94impl<R, RS> Read for Reader<R, RS>
95where
96    R: Read,
97    RS: Read + Seek,
98{
99    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
100        let mut read: usize = 0;
101
102        while !buf.is_empty() {
103            let processed = match self.state {
104                ReaderState::Initial => match self.patch.read_varint() {
105                    Ok(add_len) => {
106                        self.state = ReaderState::Add(add_len);
107                        0
108                    }
109                    Err(e) => match e.kind() {
110                        ErrorKind::UnexpectedEof => {
111                            self.state = ReaderState::Final;
112                            0
113                        }
114                        _ => {
115                            return Err(e);
116                        }
117                    },
118                },
119                ReaderState::Add(add_len) => {
120                    let n = min(min(add_len, buf.len()), self.buf.len());
121
122                    let out = &mut buf[..n];
123                    self.old.read_exact(out)?;
124
125                    let dif = &mut self.buf[..n];
126                    self.patch.read_exact(dif)?;
127
128                    for i in 0..n {
129                        out[i] = out[i].wrapping_add(dif[i]);
130                    }
131
132                    if add_len == n {
133                        let copy_len: usize = self.patch.read_varint()?;
134                        self.state = ReaderState::Copy(copy_len)
135                    } else {
136                        self.state = ReaderState::Add(add_len - n);
137                    }
138
139                    n
140                }
141                ReaderState::Copy(copy_len) => {
142                    let n = min(copy_len, buf.len());
143
144                    let out = &mut buf[..n];
145                    self.patch.read_exact(out)?;
146
147                    if copy_len == n {
148                        let seek: i64 = self.patch.read_varint()?;
149                        self.old.seek(SeekFrom::Current(seek))?;
150                        self.state = ReaderState::Initial;
151                    } else {
152                        self.state = ReaderState::Copy(copy_len - n);
153                    }
154
155                    n
156                }
157                ReaderState::Final => {
158                    break;
159                }
160            };
161            read += processed;
162            buf = &mut buf[processed..];
163        }
164
165        Ok(read)
166    }
167}