#encode-decode #function #integer #generate #pointers #mayda

nightly mayda_macros

Macros to generate basic encoding and decoding functions used by mayda

5 releases

Uses old Rust 2015

0.1.4 Sep 21, 2017
0.1.3 Jul 13, 2016
0.1.2 Jun 20, 2016
0.1.1 Jun 13, 2016
0.1.0 Jun 11, 2016

#649 in Compression

22 downloads per month
Used in 2 crates (via mayda_codec)

MIT/Apache

32KB
697 lines

Compiler plugins to generate basic encoding and decoding functions. The functions generated by the encode! and decode! syntax extensions follow the convention encode_T_a_b. The functions generated by the encode_simd! and decode_simd! syntax extensions follow the convention encode_simd_T_a. The functions generated by the encode_util! syntax extention follow the conventions encode_delta_T and encode_zz_shift_T. T is one of the unsigned integer types, a is the number of bits per integer, and b is the number of integers encoded.

encode! and decode! take as arguments the unsigned integer type width in bits and a step for the number of integers (a divisor of 32). Functions are generated for numbers of bits in the interval 0...max_bits, and for numbers of integers in multiples of the step up to 32. encode_simd! and decode_simd! take as arguments the unsigned integer type width in bits and a path to the relevant simd module. Functions are generated for numbers of bits in the interval 0...max_bits, and for exactly 128 integers. encode_util! takes as arguments the unsigned integer type width in bits and a path to the relevant simd module. Functions are generated for the type width and for an arbitrary number of integers.

Pointers to the functions generated by encode! and decode! are available in ENCODE_T and DECODE_T, respectively, with the pointer for encode_T_a_b at ENCODE_T[a][b / c - 1] where c is the step. Pointers to the functions generated by encode_simd! and decode_simd! are availabe in ENCODE_SIMD_T and DECODE_SIMD_T, respectively, with the pointer for encode_simd_T_a at ENCODE_SIMD_T[a]. The functions generated by encode_util! are public. All arrays are public and constant.

Safety

The functions generated by this crate use wildly unsafe pointer operations. You must verify that enough memory is already allocated after the pointers that the offsets are valid. They are not intended to be used outside the mayda crate.

Examples

The syntax extensions defined in this crate can be invoked as

encode!(u32, 32, 8);
decode!(u32, 32, 8);

This is replaced by 128 functions that encode u32 integers and 128 functions that decode u32 integers. For example, the functions that encode and decode the 24 least significant bits of 8 u32 integers are

unsafe fn encode_u32_24_8(mut i_ptr: *const u32, mut s_ptr: *mut u32) {
    let mut out = *i_ptr as u32;
    i_ptr = i_ptr.offset(1);
    out |= (*i_ptr as u32) << 24usize;
    *s_ptr = out;
    s_ptr = s_ptr.offset(1);
    out = (*i_ptr >> 8usize) as u32;
    i_ptr = i_ptr.offset(1);
    out |= (*i_ptr as u32) << 16usize;
    *s_ptr = out;
    s_ptr = s_ptr.offset(1);
    out = (*i_ptr >> 16usize) as u32;
    i_ptr = i_ptr.offset(1);
    out |= (*i_ptr as u32) << 8usize;
    i_ptr = i_ptr.offset(1);
    *s_ptr = out;
    s_ptr = s_ptr.offset(1);
    out = *i_ptr as u32;
    i_ptr = i_ptr.offset(1);
    out |= (*i_ptr as u32) << 24usize;
    *s_ptr = out;
    s_ptr = s_ptr.offset(1);
    out = (*i_ptr >> 8usize) as u32;
    i_ptr = i_ptr.offset(1);
    out |= (*i_ptr as u32) << 16usize;
    *s_ptr = out;
    s_ptr = s_ptr.offset(1);
    out = (*i_ptr >> 16usize) as u32;
    i_ptr = i_ptr.offset(1);
    out |= (*i_ptr as u32) << 8usize;
    *s_ptr = out;
}

unsafe fn decode_u32_24_8(mut s_ptr: *const u32, mut o_ptr: *mut u32) {
    let mask: u32 = !0 >> 8usize;
    let mut out;
    out = *s_ptr as u32;
    *o_ptr = out & mask;
    o_ptr = o_ptr.offset(1);
    out = (*s_ptr >> 24usize) as u32;
    s_ptr = s_ptr.offset(1);
    out |= (*s_ptr as u32) << 8usize;
    *o_ptr = out & mask;
    o_ptr = o_ptr.offset(1);
    out = (*s_ptr >> 16usize) as u32;
    s_ptr = s_ptr.offset(1);
    out |= (*s_ptr as u32) << 16usize;
    *o_ptr = out & mask;
    o_ptr = o_ptr.offset(1);
    out = (*s_ptr >> 8usize) as u32;
    *o_ptr = out & mask;
    o_ptr = o_ptr.offset(1);
    s_ptr = s_ptr.offset(1);
    out = *s_ptr as u32;
    *o_ptr = out & mask;
    o_ptr = o_ptr.offset(1);
    out = (*s_ptr >> 24usize) as u32;
    s_ptr = s_ptr.offset(1);
    out |= (*s_ptr as u32) << 8usize;
    *o_ptr = out & mask;
    o_ptr = o_ptr.offset(1);
    out = (*s_ptr >> 16usize) as u32;
    s_ptr = s_ptr.offset(1);
    out |= (*s_ptr as u32) << 16usize;
    *o_ptr = out & mask;
    o_ptr = o_ptr.offset(1);
    out = (*s_ptr >> 8usize) as u32;
    *o_ptr = out & mask;
}

No runtime deps