|
| 1 | +use std::io::{self, Read, Write}; |
| 2 | + |
| 3 | +pub fn write_compact_size<W: Write>(value: u64, writer: &mut W) -> Result<(), io::Error> { |
| 4 | + match value { |
| 5 | + 0..=0xFC => { |
| 6 | + writer.write_all(&[value as u8]) // Cast ok because of match. |
| 7 | + } |
| 8 | + 0xFD..=0xFFFF => { |
| 9 | + let v = (value as u16).to_le_bytes(); // Cast ok because of match. |
| 10 | + writer.write_all(&[0xFD, v[0], v[1]]) |
| 11 | + } |
| 12 | + 0x10000..=0xFFFFFFFF => { |
| 13 | + let v = (value as u32).to_le_bytes(); // Cast ok because of match. |
| 14 | + writer.write_all(&[0xFE, v[0], v[1], v[2], v[3]]) |
| 15 | + } |
| 16 | + _ => panic!("unexpected large offset"), |
| 17 | + } |
| 18 | +} |
| 19 | + |
| 20 | +pub fn read_compact_size<R: Read>(reader: &mut R) -> Result<u64, io::Error> { |
| 21 | + let mut buf: [u8; 1] = [0; 1]; |
| 22 | + reader.read_exact(&mut buf)?; |
| 23 | + let prefix = buf[0]; |
| 24 | + match prefix { |
| 25 | + 0xFD => { |
| 26 | + let mut buf: [u8; 2] = [0; 2]; |
| 27 | + reader.read_exact(&mut buf)?; |
| 28 | + Ok(u16::from_le_bytes(buf) as u64) |
| 29 | + } |
| 30 | + 0xFE => { |
| 31 | + let mut buf: [u8; 4] = [0; 4]; |
| 32 | + reader.read_exact(&mut buf)?; |
| 33 | + Ok(u32::from_le_bytes(buf) as u64) |
| 34 | + } |
| 35 | + 0..=0xFC => Ok(prefix as u64), |
| 36 | + _ => panic!("unexpected large offset"), |
| 37 | + } |
| 38 | +} |
| 39 | + |
| 40 | +#[cfg(test)] |
| 41 | +mod tests { |
| 42 | + use crate::{read_compact_size, write_compact_size}; |
| 43 | + |
| 44 | + #[test] |
| 45 | + fn deser_roundtrip() { |
| 46 | + let mut buf = Vec::new(); |
| 47 | + let less: u8 = 0xFB; |
| 48 | + write_compact_size(less as u64, &mut buf).unwrap(); |
| 49 | + let read_cs = read_compact_size(&mut buf.as_slice()).unwrap(); |
| 50 | + let cast_less = read_cs as u8; |
| 51 | + assert_eq!(less, cast_less); |
| 52 | + let mut buf = Vec::new(); |
| 53 | + let median: u16 = 0xFFF; |
| 54 | + write_compact_size(median as u64, &mut buf).unwrap(); |
| 55 | + let read_cs = read_compact_size(&mut buf.as_slice()).unwrap(); |
| 56 | + let cast_median = read_cs as u16; |
| 57 | + assert_eq!(median, cast_median); |
| 58 | + let mut buf = Vec::new(); |
| 59 | + let more: u32 = 0xFFFFF; |
| 60 | + write_compact_size(more as u64, &mut buf).unwrap(); |
| 61 | + let read_cs = read_compact_size(&mut buf.as_slice()).unwrap(); |
| 62 | + let cast_more = read_cs as u32; |
| 63 | + assert_eq!(more, cast_more); |
| 64 | + } |
| 65 | +} |
0 commit comments