Enum Command

Source
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

  1. mask first byte: (byte0 & 0b0110_0000) = 0PP0-0000
  2. shift left by 3: (0PP0-0000 << 3) = 0000-00PP--0000-0000
  3. 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 or 1: header
  • P: Position
  • L: Length
  • B: Literal bytes Length
  • -: Nibble Separator
  • :: Byte Separator

§Commands

CommandLenLiteralLengthPositionLayout
Short2(0..=3) +0(3..=10) +3(1..=1024) +10PPL-LLBB:PPPP-PPPP
Medium3(0..=3) +0(4..=67) +4(1..=16384) +110LL-LLLL:BBPP-PPPP:PPPP-PPPP
Long4(0..=3) +0(5..=1028) +5(1..=131072) +1110P-LLBB:PPPP-PPPP:PPPP-PPPP:LLLL-LLLL
Literal1(4..=112) +400111B-BBBB
Stop1(0..=3) +0001111-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

  1. take 97 % 4 to get the “leftover” length - this will be used in next command following the literal
  2. take (97 - 4) >> 2 to get the value to encode into the literal value
  3. create a literal command with the result from 2, take that number of literals from the current literal buffer and write to stream
  4. 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

Fields

§literal: u8
§length: u8
§offset: u16
§

Medium

Represents a three byte copy command

Fields

§literal: u8
§length: u8
§offset: u16
§

Long

Represents a four byte copy command

Fields

§literal: u8
§length: u16
§offset: u32
§

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

Source

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

Source

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.

Source

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.

Source

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

Source

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.

Source

pub fn is_stop(self) -> bool

Returns true if the command is a stopcode, false if it is not.

Source

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
Source

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
Source

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
Source

pub fn read_literal(first: u8) -> Command

Reference read implementation of literal commands. See struct definition for documentation

Source

pub fn read_stop(first: u8) -> Command

Reference read implementation of literal commands. See struct definition for documentation

Source

pub fn read(reader: &mut (impl Read + Seek)) -> RefPackResult<Self>

Reads and decodes a command from a Read + Seek reader.

§Errors
Source

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
Source

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
Source

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
Source

pub fn write_literal( literal: u8, writer: &mut (impl Write + Seek), ) -> RefPackResult<()>

Reference write implementation of literal commands. See struct definition for specification

§Errors
Source

pub fn write_stop( number: u8, writer: &mut (impl Write + Seek), ) -> RefPackResult<()>

Reference write implementation of stopcode. See struct definition for specification

§Errors
Source

pub fn write(self, writer: &mut (impl Write + Seek)) -> RefPackResult<()>

Encodes and writes a command to a Write + Seek writer

§Errors

Trait Implementations§

Source§

impl Clone for Command

Source§

fn clone(&self) -> Command

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Command

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Command

Source§

fn eq(&self, other: &Command) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Command

Source§

impl Eq for Command

Source§

impl StructuralPartialEq for Command

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.