Function spectrusty_formats::tap::try_checksum
source · pub fn try_checksum<I: IntoIterator<Item = Result<u8>>>(iter: I) -> Result<u8>
Expand description
Calculates bit toggle checksum from the given iterator of the result of u8
.
Useful with std::io::Bytes.
Examples found in repository?
src/tap/read.rs (line 172)
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
fn try_from(rd: &mut Take<R>) -> Result<Self> {
let limit = match rd.limit() {
0 => {
return Ok(TapChunkInfo::Empty)
}
limit if limit > u16::max_value().into() => {
return Err(Error::new(ErrorKind::InvalidData, "Not a proper TAP chunk: too large"));
}
limit => limit
};
let mut flag: u8 = 0;
rd.read_exact(slice::from_mut(&mut flag))?;
if limit == 1 {
return Ok(TapChunkInfo::Unknown { size: 1, flag })
}
match flag {
HEAD_BLOCK_FLAG if limit == HEADER_SIZE as u64 => {
let mut header: [u8; HEADER_SIZE - 1] = Default::default();
rd.read_exact(&mut header)?;
if checksum(header) != flag {
Ok(TapChunkInfo::Unknown { size: limit as u16, flag })
}
else {
Header::try_from(&header[..HEADER_SIZE - 2])
.map(TapChunkInfo::Head)
.or(Ok(TapChunkInfo::Unknown { size: limit as u16, flag }))
}
}
DATA_BLOCK_FLAG => {
let checksum = try_checksum(rd.by_ref().bytes())? ^ flag;
if rd.limit() != 0 {
return Err(Error::new(ErrorKind::InvalidData, "Not a proper TAP block: invalid length"));
}
Ok(TapChunkInfo::Data{ length: limit as u16 - 2, checksum })
}
flag => {
// TODO: perhaps check length and read to eof
Ok(TapChunkInfo::Unknown { size: limit as u16, flag })
}
}
}