preflate-rs 0.7.0

Decompresses existing DEFLATE streams to allow for better compression (eg with ZStandard) while allowing the exact original binary DEFLATE stream to be recreated by detecting the parameters used during compression.
Documentation
use bitcode::{Decode, Encode};

#[derive(Encode, Decode, Debug, Copy, Clone, Eq, PartialEq, Default)]
pub enum HashAlgorithm {
    #[default]
    None,
    Zlib {
        hash_mask: u16,
        hash_shift: u32,
    },
    MiniZFast,

    /// Libflate 4 byte hash only
    Libdeflate4Fast,
    /// Libflate 4 byte hash with 3 byte secondary hash
    Libdeflate4,

    ZlibNG,
    RandomVector,
    Crc32cHash,
}

const HASH_ALGORITHM_NONE: u16 = 0;
const HASH_ALGORITHM_ZLIB: u16 = 1;
const HASH_ALGORITHM_MINIZ_FAST: u16 = 2;
const HASH_ALGORITHM_LIBDEFLATE4: u16 = 3;
const HASH_ALGORITHM_LIBDEFLATE4_FAST: u16 = 4;
const HASH_ALGORITHM_ZLIBNG: u16 = 5;
const HASH_ALGORITHM_RANDOMVECTOR: u16 = 6;
const HASH_ALGORITHM_CRC32C: u16 = 7;

impl HashAlgorithm {
    pub fn to_u16(self) -> u16 {
        match self {
            HashAlgorithm::None => HASH_ALGORITHM_NONE,
            HashAlgorithm::Zlib {
                hash_mask,
                hash_shift,
            } => {
                HASH_ALGORITHM_ZLIB
                    | ((hash_mask.trailing_ones() as u16) << 8)
                    | ((hash_shift as u16) << 12)
            }
            HashAlgorithm::MiniZFast => HASH_ALGORITHM_MINIZ_FAST,
            HashAlgorithm::Libdeflate4Fast => HASH_ALGORITHM_LIBDEFLATE4_FAST,
            HashAlgorithm::Libdeflate4 => HASH_ALGORITHM_LIBDEFLATE4,
            HashAlgorithm::ZlibNG => HASH_ALGORITHM_ZLIBNG,
            HashAlgorithm::RandomVector => HASH_ALGORITHM_RANDOMVECTOR,
            HashAlgorithm::Crc32cHash => HASH_ALGORITHM_CRC32C,
        }
    }

    pub fn from_u16(v: u16) -> Option<Self> {
        match v & 0xff {
            HASH_ALGORITHM_NONE => Some(HashAlgorithm::None),
            HASH_ALGORITHM_ZLIB => {
                let hash_mask = (1 << ((v >> 8) & 0xf)) - 1;
                let hash_shift = (v >> 12) & 0xf;
                Some(HashAlgorithm::Zlib {
                    hash_mask,
                    hash_shift: hash_shift.into(),
                })
            }
            HASH_ALGORITHM_MINIZ_FAST => Some(HashAlgorithm::MiniZFast),
            HASH_ALGORITHM_LIBDEFLATE4_FAST => Some(HashAlgorithm::Libdeflate4Fast),
            HASH_ALGORITHM_LIBDEFLATE4 => Some(HashAlgorithm::Libdeflate4),
            HASH_ALGORITHM_ZLIBNG => Some(HashAlgorithm::ZlibNG),
            HASH_ALGORITHM_RANDOMVECTOR => Some(HashAlgorithm::RandomVector),
            HASH_ALGORITHM_CRC32C => Some(HashAlgorithm::Crc32cHash),
            _ => None,
        }
    }
}

#[test]
fn roundtrip_hash_algorithm_to_int() {
    let test_hashes = [
        HashAlgorithm::Zlib {
            hash_mask: 0x7ff,
            hash_shift: 3,
        },
        HashAlgorithm::MiniZFast,
        HashAlgorithm::Libdeflate4Fast,
        HashAlgorithm::Libdeflate4,
        HashAlgorithm::ZlibNG,
        HashAlgorithm::RandomVector,
        HashAlgorithm::Crc32cHash,
    ];

    for &hash in test_hashes.iter() {
        let hash_int = hash.to_u16();
        let hash2 = HashAlgorithm::from_u16(hash_int).unwrap();
        assert_eq!(hash, hash2);
    }
}

pub trait HashImplementation: Default + Copy + Clone {
    const NUM_HASH_BYTES: usize;

    fn get_hash(&self, b: &[u8]) -> u16;
    fn algorithm(&self) -> HashAlgorithm;
}

#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct ZlibRotatingHashFixed<const HASH_SHIFT: u32, const HASH_MASK: u32> {}

impl<const HASH_SHIFT: u32, const HASH_MASK: u32> HashImplementation
    for ZlibRotatingHashFixed<HASH_SHIFT, HASH_MASK>
{
    const NUM_HASH_BYTES: usize = 3;

    fn get_hash(&self, b: &[u8]) -> u16 {
        assert!(b.len() >= 3);

        let c = u32::from(b[0]);
        let c = (c << HASH_SHIFT) ^ u32::from(b[1]);
        let c = (c << HASH_SHIFT) ^ u32::from(b[2]);
        (c & HASH_MASK) as u16
    }

    fn algorithm(&self) -> HashAlgorithm {
        HashAlgorithm::Zlib {
            hash_mask: HASH_MASK as u16,
            hash_shift: HASH_SHIFT,
        }
    }
}

#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct ZlibRotatingHash {
    pub hash_mask: u16,
    pub hash_shift: u32,
}

impl HashImplementation for ZlibRotatingHash {
    const NUM_HASH_BYTES: usize = 3;

    fn get_hash(&self, b: &[u8]) -> u16 {
        assert!(b.len() >= 3);

        let c = u16::from(b[0]);
        let c = (c << self.hash_shift) ^ u16::from(b[1]);
        let c = (c << self.hash_shift) ^ u16::from(b[2]);
        c & self.hash_mask
    }

    fn algorithm(&self) -> HashAlgorithm {
        HashAlgorithm::Zlib {
            hash_mask: self.hash_mask,
            hash_shift: self.hash_shift,
        }
    }
}

#[derive(Default, Copy, Clone)]
pub struct MiniZHash {}

/// Size of hash chain for fast compression mode.
pub const MINIZ_LEVEL1_HASH_SIZE_MASK: u16 = 4095;

impl HashImplementation for MiniZHash {
    const NUM_HASH_BYTES: usize = 3;

    fn get_hash(&self, b: &[u8]) -> u16 {
        assert!(b.len() >= 3);

        let hash = u32::from(b[0]) | (u32::from(b[1]) << 8) | (u32::from(b[2]) << 16);

        ((hash ^ (hash >> 17)) & u32::from(MINIZ_LEVEL1_HASH_SIZE_MASK)) as u16
    }

    fn algorithm(&self) -> HashAlgorithm {
        HashAlgorithm::MiniZFast
    }
}

/// Fast version of Libflate hash that doesn't use a secondary 3
/// byte hash. This is used by level 1 compression.
#[derive(Default, Copy, Clone)]
pub struct LibdeflateHash4Fast {}

impl HashImplementation for LibdeflateHash4Fast {
    const NUM_HASH_BYTES: usize = 4;

    fn get_hash(&self, b: &[u8]) -> u16 {
        let hash = u32::from_le_bytes(b[..4].try_into().unwrap());

        (hash.wrapping_mul(0x1E35A7BD) >> 16) as u16
    }

    fn algorithm(&self) -> HashAlgorithm {
        HashAlgorithm::Libdeflate4Fast
    }
}

#[derive(Default, Copy, Clone)]
pub struct LibdeflateHash4 {}

impl HashImplementation for LibdeflateHash4 {
    const NUM_HASH_BYTES: usize = 4;

    fn get_hash(&self, b: &[u8]) -> u16 {
        let hash = u32::from_le_bytes(b[..4].try_into().unwrap());

        (hash.wrapping_mul(0x1E35A7BD) >> 16) as u16
    }

    fn algorithm(&self) -> HashAlgorithm {
        HashAlgorithm::Libdeflate4
    }
}

/// This is the 3 byte version of the libdeflate hash algorithm, which is used
/// as a secondary hash value to find 3 byte matches within the first 4096K if
/// we fail to find any four byte matches with the primary hash.
#[derive(Default, Copy, Clone)]
pub struct LibdeflateHash3Secondary {}

impl HashImplementation for LibdeflateHash3Secondary {
    const NUM_HASH_BYTES: usize = 3;

    fn get_hash(&self, b: &[u8]) -> u16 {
        assert!(b.len() >= 3);

        let hash = u32::from(b[0]) | (u32::from(b[1]) << 8) | (u32::from(b[2]) << 16);

        (hash.wrapping_mul(0x1E35A7BD) >> 17) as u16
    }

    fn algorithm(&self) -> HashAlgorithm {
        unimplemented!("shoudln't get called on secondary hash");
    }
}

#[derive(Default, Copy, Clone)]
pub struct ZlibNGHash {}

impl HashImplementation for ZlibNGHash {
    const NUM_HASH_BYTES: usize = 4;

    fn get_hash(&self, b: &[u8]) -> u16 {
        let hash = u32::from_le_bytes(b[..4].try_into().unwrap());

        (hash.wrapping_mul(2654435761) >> 16) as u16
    }

    fn algorithm(&self) -> HashAlgorithm {
        HashAlgorithm::ZlibNG
    }
}

#[derive(Default, Copy, Clone)]
pub struct Crc32cHash {}

impl HashImplementation for Crc32cHash {
    const NUM_HASH_BYTES: usize = 4;

    fn get_hash(&self, b: &[u8]) -> u16 {
        assert!(b.len() >= 4);

        let mut crc = CRC32C_TABLE[b[0] as usize];
        crc = (crc >> 8) ^ CRC32C_TABLE[((crc ^ u32::from(b[1])) & 0xFF) as usize];
        crc = (crc >> 8) ^ CRC32C_TABLE[((crc ^ u32::from(b[2])) & 0xFF) as usize];
        crc = (crc >> 8) ^ CRC32C_TABLE[((crc ^ u32::from(b[3])) & 0xFF) as usize];

        crc as u16
    }

    fn algorithm(&self) -> HashAlgorithm {
        HashAlgorithm::Crc32cHash
    }
}

static CRC32C_TABLE: [u32; 256] = [
    0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
    0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
    0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
    0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
    0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
    0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
    0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
    0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
    0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
    0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
    0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
    0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
    0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
    0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
    0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
    0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
    0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
    0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
    0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
    0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
    0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
    0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
    0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
    0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
    0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
    0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
    0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
    0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
    0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
    0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
    0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
    0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
];

/// This vector uses a lookup into a table for random values
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
pub struct RandomVectorHash {}

static RANDOM_VECTOR: [u16; 768] = [
    0x499d, 0x3dc2, 0x2d07, 0x705b, 0x7a76, 0x3469, 0x59db, 0x0c58, 0x2b72, 0x412d, 0x1246, 0x2095,
    0x1c1c, 0x4726, 0x5f45, 0x2c4e, 0x7b1b, 0x1e70, 0x2743, 0x554f, 0x1334, 0x5328, 0x78c1, 0x41cc,
    0x4b2c, 0x62a5, 0x1d93, 0x4aa4, 0x64c8, 0x65f0, 0x194d, 0x1ac0, 0x3f96, 0x41df, 0x4389, 0x065b,
    0x4b74, 0x15e2, 0x0389, 0x0b7e, 0x5778, 0x5d95, 0x7ffc, 0x1e6f, 0x5465, 0x23d3, 0x01ab, 0x567e,
    0x0b3b, 0x6c2f, 0x5e4d, 0x2641, 0x03a4, 0x1214, 0x4b01, 0x48f3, 0x7ba9, 0x7009, 0x1270, 0x0e67,
    0x40e8, 0x710d, 0x6b7f, 0x1418, 0x45f6, 0x2785, 0x4725, 0x7904, 0x14a2, 0x71b8, 0x3189, 0x6ccc,
    0x4d66, 0x701e, 0x4148, 0x6c05, 0x01a8, 0x5ff1, 0x4fbb, 0x0a2a, 0x541d, 0x4378, 0x3f15, 0x3677,
    0x0d82, 0x578b, 0x345d, 0x6052, 0x0beb, 0x553d, 0x4d89, 0x1315, 0x311c, 0x3f33, 0x226d, 0x3223,
    0x478b, 0x487b, 0x5326, 0x160e, 0x05b3, 0x486d, 0x0f2f, 0x1ecc, 0x04b7, 0x01a0, 0x6f70, 0x425c,
    0x3d3f, 0x1610, 0x4211, 0x68d3, 0x3041, 0x7ddf, 0x5967, 0x36f3, 0x31a5, 0x2137, 0x4692, 0x56de,
    0x53d8, 0x4466, 0x5720, 0x6d64, 0x3421, 0x6979, 0x3151, 0x5ee6, 0x0e2f, 0x35d8, 0x30ff, 0x3070,
    0x19b1, 0x4651, 0x6b4f, 0x4cea, 0x7991, 0x4e0b, 0x2d3f, 0x3d1e, 0x09a0, 0x4bac, 0x0571, 0x079a,
    0x4380, 0x411a, 0x4012, 0x57f5, 0x0f7a, 0x5ae9, 0x1b6d, 0x6f3c, 0x3b37, 0x0b66, 0x60af, 0x17b9,
    0x77df, 0x286f, 0x14c9, 0x2274, 0x1d96, 0x67dc, 0x7801, 0x68d9, 0x0942, 0x1c06, 0x4922, 0x7a4b,
    0x1732, 0x6c5d, 0x4928, 0x3c70, 0x64fa, 0x6ce8, 0x2979, 0x163b, 0x4379, 0x64ee, 0x37d3, 0x5bf2,
    0x1725, 0x5749, 0x26aa, 0x13e7, 0x1e82, 0x2226, 0x723c, 0x4677, 0x4a6f, 0x0e39, 0x6431, 0x50f7,
    0x7ff9, 0x7b82, 0x2307, 0x7254, 0x1c17, 0x1d2c, 0x580d, 0x3b5f, 0x3e99, 0x46ee, 0x3105, 0x5d19,
    0x38bb, 0x4134, 0x21bc, 0x068a, 0x0e6b, 0x5aa7, 0x68ef, 0x2bd2, 0x71b5, 0x0db8, 0x28c5, 0x5a48,
    0x14ad, 0x1ec0, 0x2c71, 0x690c, 0x1559, 0x5638, 0x73b2, 0x26c6, 0x301b, 0x2aad, 0x256f, 0x15fd,
    0x7e60, 0x5a5a, 0x70a8, 0x70a2, 0x3c76, 0x5a00, 0x49b3, 0x0f1d, 0x7a43, 0x18d8, 0x56e1, 0x6101,
    0x3f86, 0x4ad9, 0x26b4, 0x0305, 0x388c, 0x13e2, 0x36e9, 0x35e4, 0x587c, 0x2e31, 0x5ecb, 0x2ed3,
    0x4493, 0x40a6, 0x0d5c, 0x57de, 0x5b6b, 0x656c, 0x1ca2, 0x167c, 0x65a5, 0x7597, 0x1f4f, 0x47dd,
    0x602c, 0x2169, 0x7ccb, 0x7719, 0x07a3, 0x735b, 0x1afd, 0x6315, 0x1fba, 0x36fe, 0x5961, 0x4c63,
    0x79af, 0x1126, 0x269a, 0x312f, 0x3d20, 0x1783, 0x334b, 0x44a8, 0x6580, 0x2f6b, 0x5174, 0x5daf,
    0x01b4, 0x15b8, 0x33c1, 0x5c4b, 0x302f, 0x73bf, 0x59ce, 0x0b13, 0x1c9b, 0x2e1b, 0x27f7, 0x00a7,
    0x7c7e, 0x6763, 0x202e, 0x7a6d, 0x4a1c, 0x20dd, 0x591d, 0x7edb, 0x7c3b, 0x7532, 0x1909, 0x1dd6,
    0x466a, 0x72d0, 0x2c9a, 0x79d7, 0x0fda, 0x6dc0, 0x4907, 0x0a6c, 0x3f75, 0x34cc, 0x6e42, 0x35e4,
    0x6dbb, 0x51f0, 0x2af5, 0x441f, 0x6907, 0x27d9, 0x540b, 0x7095, 0x6723, 0x66b3, 0x1f85, 0x6213,
    0x405b, 0x06ed, 0x1d8b, 0x6550, 0x2585, 0x002e, 0x3c07, 0x5208, 0x7933, 0x3897, 0x777d, 0x03db,
    0x4d9f, 0x50cc, 0x31f1, 0x3213, 0x4a70, 0x6e2f, 0x78c4, 0x5c1e, 0x391e, 0x0e49, 0x007b, 0x7c8f,
    0x55d8, 0x51b7, 0x4477, 0x61ac, 0x7eb2, 0x330e, 0x1882, 0x4d04, 0x4b59, 0x3188, 0x74f5, 0x3ebe,
    0x2a7f, 0x6b8e, 0x705b, 0x6688, 0x1cfc, 0x084d, 0x60ed, 0x1cd9, 0x5799, 0x1f59, 0x0beb, 0x6732,
    0x6640, 0x782b, 0x455f, 0x5910, 0x7066, 0x26b0, 0x26d2, 0x7e26, 0x22bd, 0x15b3, 0x634e, 0x24f0,
    0x4649, 0x282b, 0x5631, 0x4539, 0x1b49, 0x4023, 0x48b1, 0x115b, 0x6ca6, 0x5bde, 0x4f40, 0x288f,
    0x4106, 0x6f41, 0x62fe, 0x09b1, 0x7929, 0x71e0, 0x2a80, 0x2164, 0x66be, 0x3fa8, 0x094b, 0x4a09,
    0x1177, 0x355f, 0x645a, 0x2940, 0x5a2a, 0x5369, 0x7ade, 0x0a66, 0x74e8, 0x6502, 0x6cbb, 0x1971,
    0x2ba3, 0x0ab5, 0x2f4f, 0x4539, 0x150e, 0x1dc4, 0x3262, 0x04ed, 0x5df0, 0x35af, 0x5c4a, 0x4fb4,
    0x5fcd, 0x0dc7, 0x6fef, 0x266e, 0x0be6, 0x69d9, 0x5e02, 0x4650, 0x561f, 0x03e8, 0x26e5, 0x4778,
    0x6be3, 0x4375, 0x1559, 0x7786, 0x0653, 0x2a4a, 0x4825, 0x70f0, 0x56f2, 0x596f, 0x4f6b, 0x0937,
    0x4e89, 0x5390, 0x5bf9, 0x03ea, 0x1eb7, 0x1296, 0x1966, 0x77bc, 0x6d2a, 0x3cf1, 0x43a7, 0x01a3,
    0x2e0f, 0x696e, 0x5654, 0x4ba6, 0x66be, 0x6b16, 0x2c6c, 0x3db4, 0x7b52, 0x2d5f, 0x0b3c, 0x7391,
    0x25f7, 0x45bf, 0x44c7, 0x7052, 0x3da7, 0x117c, 0x0797, 0x20b9, 0x6b35, 0x61bc, 0x511a, 0x2168,
    0x7693, 0x6de2, 0x4c7c, 0x04e1, 0x234a, 0x1e36, 0x16c7, 0x2b67, 0x5c40, 0x1dd8, 0x7164, 0x77cc,
    0x0c10, 0x6789, 0x1a4b, 0x42dd, 0x5ea5, 0x545a, 0x2c55, 0x0eb7, 0x6126, 0x48b6, 0x1a5b, 0x093d,
    0x77ee, 0x75d6, 0x5e4c, 0x0153, 0x2b53, 0x5587, 0x4e6d, 0x4cff, 0x2afb, 0x37e1, 0x4f61, 0x6ff2,
    0x1758, 0x74b2, 0x0b70, 0x4146, 0x51b8, 0x51fe, 0x6fae, 0x696b, 0x0a58, 0x43d0, 0x623e, 0x57c4,
    0x07f8, 0x712c, 0x1221, 0x7378, 0x7c69, 0x7bd0, 0x00f4, 0x35de, 0x6cd7, 0x4947, 0x6344, 0x1575,
    0x67ed, 0x1bd0, 0x45f3, 0x3d2d, 0x0bd1, 0x66c8, 0x7c11, 0x47b0, 0x19bb, 0x6695, 0x6509, 0x5eed,
    0x4e6a, 0x19ac, 0x3234, 0x5dab, 0x3a2b, 0x7a79, 0x5c58, 0x2347, 0x434b, 0x32a7, 0x3eb5, 0x1a2a,
    0x02ec, 0x1f61, 0x62a7, 0x70c0, 0x228e, 0x445d, 0x5ab6, 0x401c, 0x5404, 0x41cd, 0x46a9, 0x3358,
    0x1cb1, 0x67d6, 0x3106, 0x7ae3, 0x1ea6, 0x2ad7, 0x07d5, 0x7aa5, 0x750a, 0x6601, 0x595b, 0x4867,
    0x7b8c, 0x0c0c, 0x3f99, 0x7843, 0x27ac, 0x7a3c, 0x7928, 0x20d9, 0x024f, 0x6c8f, 0x1b90, 0x1142,
    0x75c0, 0x0227, 0x1cb7, 0x4863, 0x7705, 0x553f, 0x7d44, 0x6dff, 0x5f8c, 0x3dae, 0x1984, 0x2410,
    0x757d, 0x6403, 0x567c, 0x4bda, 0x49de, 0x10e9, 0x6a0a, 0x2054, 0x5cb1, 0x534e, 0x0206, 0x7a42,
    0x66b3, 0x18f0, 0x604f, 0x1b4f, 0x2b97, 0x1a34, 0x0284, 0x5d71, 0x0642, 0x6390, 0x6d85, 0x2e2a,
    0x17d9, 0x3d3f, 0x35d6, 0x4118, 0x5700, 0x3e89, 0x6ddb, 0x0dc2, 0x6750, 0x232e, 0x566b, 0x77b6,
    0x607f, 0x31cc, 0x0c29, 0x602b, 0x50f6, 0x6ac0, 0x305c, 0x181a, 0x4c16, 0x701b, 0x7b3d, 0x20c5,
    0x3359, 0x7034, 0x1837, 0x090a, 0x5f2d, 0x5837, 0x53dd, 0x6827, 0x0afb, 0x2968, 0x5983, 0x3a36,
    0x6a3b, 0x0b8e, 0x04e4, 0x3bf7, 0x3bba, 0x2c2b, 0x084e, 0x5ad4, 0x0da4, 0x6828, 0x7332, 0x15f4,
    0x034d, 0x1c30, 0x6907, 0x6c5f, 0x07c3, 0x0154, 0x69d0, 0x6779, 0x30bc, 0x7bf6, 0x702e, 0x614c,
    0x2696, 0x76ff, 0x0463, 0x56f7, 0x5cfa, 0x6bf7, 0x6cbc, 0x57d9, 0x4d25, 0x10fb, 0x4e57, 0x3668,
    0x091c, 0x63a8, 0x1a6d, 0x60b1, 0x5675, 0x62ca, 0x5a16, 0x550e, 0x3b66, 0x1479, 0x6827, 0x1511,
    0x64e9, 0x7ee7, 0x7b8d, 0x4137, 0x1c46, 0x44e9, 0x6d7c, 0x1709, 0x646e, 0x620a, 0x497a, 0x2971,
    0x23df, 0x1451, 0x558d, 0x693c, 0x52d6, 0x27e1, 0x487d, 0x404e, 0x092b, 0x1f57, 0x33b7, 0x3748,
];

impl HashImplementation for RandomVectorHash {
    const NUM_HASH_BYTES: usize = 3;

    fn get_hash(&self, b: &[u8]) -> u16 {
        assert!(b.len() >= 3);

        RANDOM_VECTOR[b[0] as usize]
            ^ RANDOM_VECTOR[b[1] as usize + 256]
            ^ RANDOM_VECTOR[b[2] as usize + 512]
    }

    fn algorithm(&self) -> HashAlgorithm {
        HashAlgorithm::RandomVector
    }
}