pub enum Command {
Short {
literal: u8,
length: u8,
offset: u16,
},
Medium {
literal: u8,
length: u8,
offset: u16,
},
Long {
literal: u8,
length: u16,
offset: u32,
},
Literal(u8),
Stop(u8),
}
Expand description
Possible actual control code values
§Split Numbers
Numbers are always “smashed” together into as small of a space as possible
EX: Getting the position from “0PPL-LLBB--PPPP-PPPP
”
- mask first byte:
(byte0 & 0b0110_0000)
=0PP0-0000
- shift left by 3:
(0PP0-0000 << 3)
=0000-00PP--0000-0000
- OR with second:
(0000-00PP--0000-0000 | 0000-0000--PPPP-PPPP)
=0000-00PP--PPPP-PPPP
Another way to do this would be to first shift right by 5 and so on
§Key for description:
- Len: Length of the command in bytes
- Literal: Possible range of number of literal bytes to copy
- Length: Possible range of copy length
- Position Range: Possible range of positions
- Layout: Bit layout of the command bytes
§Key for layout
0
or1
: headerP
: PositionL
: LengthB
: Literal bytes Length-
: Nibble Separator:
: Byte Separator
§Commands
Command | Len | Literal | Length | Position | Layout |
---|---|---|---|---|---|
Short | 2 | (0..=3) +0 | (3..=10) +3 | (1..=1024) +1 | 0PPL-LLBB:PPPP-PPPP |
Medium | 3 | (0..=3) +0 | (4..=67) +4 | (1..=16384) +1 | 10LL-LLLL:BBPP-PPPP:PPPP-PPPP |
Long | 4 | (0..=3) +0 | (5..=1028) +5 | (1..=131072) +1 | 110P-LLBB:PPPP-PPPP:PPPP-PPPP:LLLL-LLLL |
Literal | 1 | (4..=112) +4 | 0 | 0 | 111B-BBBB |
Stop | 1 | (0..=3) +0 | 0 | 0 | 1111-11BB |
§Extra Note on Literal Commands
Literal is a special command that has differently encoded values.
While the practical range is 4-112, literal values must always be an even multiple of 4. Before being encoded, the value is first decreased by 4 then shifted right by 2
§Why
Because all other codes can have an up to 3 byte literal payload, this means that the number of literals can be stored as (length / 4) + (length % 4). When a number is an even multiple of a power of 2, it can be encoded in less bits by bitshifting it before encoding and decoding. This lets an effective range of 0-112 for the length of literal commands in only 5 bits of data, since the first 3 bits are the huffman header.
If this is unclear, here’s the process written out:
We want to encode a literal length of 97
- take
97 % 4
to get the “leftover” length - this will be used in next command following the literal - take
(97 - 4) >> 2
to get the value to encode into the literal value - create a literal command with the result from 2, take that number of literals from the current literal buffer and write to stream
- in the next command, encode the leftover literal value from 1
One extra unusual detail is that despite that it seems like te cap from the
bitshift should be 128, in practice it’s limited to 112. The way the
original reference implementation worked was to read the huffman encoded
headers via just checking if the first byte read with within certain decimal
ranges. refpack
implements this similarly for maximum compatibility. If
the first byte read is within 252..=255
, it’s interpreted as a stopcode.
The highest allowed values of 112 is encoded as 0b1111_1011
which is 251
exactly. Any higher of a value would start seeping in to the stopcode range.
Variants§
Short
Represents a two byte copy command
Medium
Represents a three byte copy command
Long
Represents a four byte copy command
Literal(u8)
Represents exclusively writing literal bytes from the stream
u8: number of literal bytes following the command to write to the stream
Stop(u8)
Represents an end of stream, when this command is encountered during decompression it’s evaluated and then decompression halts
u8: Number of literal bytes to write to the stream before ending decompression
Implementations§
Source§impl Command
impl Command
Sourcepub fn new(offset: usize, length: usize, literal: usize) -> Self
pub fn new(offset: usize, length: usize, literal: usize) -> Self
Create a new copy type Command
struct.
§Panics
Panics if you attempt to create an invalid Command in some way
Sourcepub fn new_literal(length: usize) -> Self
pub fn new_literal(length: usize) -> Self
Creates a new literal command block
§Panics
Panics if you attempt to create too long of a literal command. This depends on control mode used.
Sourcepub fn new_stop(literal_length: usize) -> Self
pub fn new_stop(literal_length: usize) -> Self
Creates a new stopcode command block
§Panics
Panics if you attempt to create too long of a stop code. This depends on control mode used.
Sourcepub fn num_of_literal(self) -> Option<usize>
pub fn num_of_literal(self) -> Option<usize>
Get number of literal bytes on the command, if they have any
Returns None
if the length is 0
Sourcepub fn offset_copy(self) -> Option<(usize, usize)>
pub fn offset_copy(self) -> Option<(usize, usize)>
Get the offset and length of a copy command as a (usize, usize)
tuple.
Returns None
if self
is not a copy command.
Sourcepub fn read_short(
first: u8,
reader: &mut (impl Read + Seek),
) -> RefPackResult<Command>
pub fn read_short( first: u8, reader: &mut (impl Read + Seek), ) -> RefPackResult<Command>
Reference read implementation of short copy commands. See structure definition for documentation
§Errors
- RefPackError::Io: Failed to get remaining single byte from reader
Sourcepub fn read_medium(
first: u8,
reader: &mut (impl Read + Seek),
) -> RefPackResult<Command>
pub fn read_medium( first: u8, reader: &mut (impl Read + Seek), ) -> RefPackResult<Command>
Reference read implementation of medium copy commands. See struct definition for documentation
§Errors
- RefPackError::Io: Failed to get remaining two bytes from reader
Sourcepub fn read_long(
first: u8,
reader: &mut (impl Read + Seek),
) -> RefPackResult<Command>
pub fn read_long( first: u8, reader: &mut (impl Read + Seek), ) -> RefPackResult<Command>
Reference read implementation of long commands. See struct definition for documentation
§Errors
- RefPackError::Io: Failed to get remaining three bytes from the reader
Sourcepub fn read_literal(first: u8) -> Command
pub fn read_literal(first: u8) -> Command
Reference read implementation of literal commands. See struct definition for documentation
Sourcepub fn read_stop(first: u8) -> Command
pub fn read_stop(first: u8) -> Command
Reference read implementation of literal commands. See struct definition for documentation
Sourcepub fn read(reader: &mut (impl Read + Seek)) -> RefPackResult<Self>
pub fn read(reader: &mut (impl Read + Seek)) -> RefPackResult<Self>
Reads and decodes a command from a Read + Seek
reader.
§Errors
- RefPackError::Io: Generic IO error occurred while attempting to read data
Sourcepub fn write_short(
offset: u16,
length: u8,
literal: u8,
writer: &mut (impl Write + Seek),
) -> RefPackResult<()>
pub fn write_short( offset: u16, length: u8, literal: u8, writer: &mut (impl Write + Seek), ) -> RefPackResult<()>
Reference write implementation of short copy commands. See struct definition for specification
§Errors
- RefPackError::Io: Generic IO error occurred while attempting to write data
Sourcepub fn write_medium(
offset: u16,
length: u8,
literal: u8,
writer: &mut (impl Write + Seek),
) -> RefPackResult<()>
pub fn write_medium( offset: u16, length: u8, literal: u8, writer: &mut (impl Write + Seek), ) -> RefPackResult<()>
Reference write implementation of medium copy commands. See struct definition for specification
§Errors
- RefPackError::Io: Generic IO error occurred while attempting to write data
Sourcepub fn write_long(
offset: u32,
length: u16,
literal: u8,
writer: &mut (impl Write + Seek),
) -> RefPackResult<()>
pub fn write_long( offset: u32, length: u16, literal: u8, writer: &mut (impl Write + Seek), ) -> RefPackResult<()>
Reference write implementation of long copy commands. See struct definition for specification
§Errors
- RefPackError::Io: Generic IO error occurred while attempting to write data
Sourcepub fn write_literal(
literal: u8,
writer: &mut (impl Write + Seek),
) -> RefPackResult<()>
pub fn write_literal( literal: u8, writer: &mut (impl Write + Seek), ) -> RefPackResult<()>
Reference write implementation of literal commands. See struct definition for specification
§Errors
- RefPackError::Io: Generic IO error occurred while attempting to write data
Sourcepub fn write_stop(
number: u8,
writer: &mut (impl Write + Seek),
) -> RefPackResult<()>
pub fn write_stop( number: u8, writer: &mut (impl Write + Seek), ) -> RefPackResult<()>
Reference write implementation of stopcode. See struct definition for specification
§Errors
- RefPackError::Io: Generic IO error occurred while attempting to write data
Sourcepub fn write(self, writer: &mut (impl Write + Seek)) -> RefPackResult<()>
pub fn write(self, writer: &mut (impl Write + Seek)) -> RefPackResult<()>
Encodes and writes a command to a Write + Seek
writer
§Errors
- RefPackError::Io: Generic IO error occurred while attempting to write data