texture2ddecoder 0.1.2

pure Rust no-std texture decoder
Documentation
use super::crn_consts::*;
use super::crn_static_huffman_data_model::*;
use super::crn_utils::*;

#[allow(non_camel_case_types)]
pub struct symbol_codec<'slice> {
    pub p_decode_buf: &'slice [u8],
    pub p_decode_buf_next: &'slice [u8],
    pub p_decode_buf_end: *const u8,
    pub decode_buf_size: u32,
    pub bit_buf: u32,
    pub bit_count: i32,
}

impl Default for symbol_codec<'_> {
    fn default() -> Self {
        symbol_codec {
            p_decode_buf: &[0; 0],
            p_decode_buf_next: &[0; 0],
            p_decode_buf_end: core::ptr::null(),
            decode_buf_size: 0,
            bit_buf: 0,
            bit_count: 0,
        }
    }
}

impl<'slice> symbol_codec<'slice> {
    pub fn start_decoding(&mut self, p_buf: &'slice [u8], buf_size: u32) -> bool {
        if buf_size == 0 {
            return false;
        }
        self.p_decode_buf = p_buf;
        self.p_decode_buf_next = p_buf;
        self.decode_buf_size = buf_size;
        self.p_decode_buf_end = (&p_buf[(buf_size - 1) as usize]) as *const u8;
        self.get_bits_init();
        true
    }

    pub fn decode_receive_static_data_model(&mut self, model: &mut StaticHuffmanDataModel) -> bool {
        let total_used_syms = match self.decode_bits(total_bits(MAX_SUPPORTED_SYMS as u32)) {
            Ok(total_used_syms) => total_used_syms,
            Err(_) => return false,
        };

        if total_used_syms == 0 {
            model.clear();
        }

        model.code_sizes.resize(total_used_syms as usize, 0);

        let num_codelength_codes_to_send = match self.decode_bits(5) {
            Ok(num_codelength_codes_to_send) => num_codelength_codes_to_send,
            Err(_) => return false,
        };

        if (num_codelength_codes_to_send < 1)
            || (num_codelength_codes_to_send > MAX_CODELENGTH_CODES as u32)
        {
            return false;
        }

        let mut dm = StaticHuffmanDataModel::default();
        dm.code_sizes.resize(MAX_CODELENGTH_CODES, 0);

        for &code_length_code in MOST_PROBABLE_CODELENGTH_CODES
            .iter()
            .take(num_codelength_codes_to_send as usize)
        {
            dm.code_sizes[code_length_code as usize] = match self.decode_bits(3) {
                Ok(s) => s as u8,
                Err(_) => return false,
            };
        }

        if !dm.prepare_decoder_tables() {
            return false;
        }

        let mut ofs: u32 = 0;
        while ofs < total_used_syms {
            let num_remaining: u32 = total_used_syms - ofs;

            let code: usize = match self.decode(&dm) {
                Ok(s) => s as usize,
                Err(_) => return false,
            };

            if code <= 16 {
                model.code_sizes[ofs as usize] = code as u8;
                ofs += 1;
            } else if code == SMALL_ZERO_RUN_CODE {
                let len = match self.decode_bits(SMALL_ZERO_RUN_EXTRA_BITS as u32) {
                    Ok(s) => s,
                    Err(_) => return false,
                } + MIN_SMALL_ZERO_RUN_SIZE as u32;

                if len > num_remaining {
                    return false;
                }

                ofs += len;
            } else if code == LARGE_ZERO_RUN_CODE {
                let len = match self.decode_bits(LARGE_ZERO_RUN_EXTRA_BITS as u32) {
                    Ok(s) => s,
                    Err(_) => return false,
                } + MIN_LARGE_ZERO_RUN_SIZE as u32;

                if len > num_remaining {
                    return false;
                }

                ofs += len;
            } else if (code == SMALL_REPEAT_CODE) || (code == LARGE_REPEAT_CODE) {
                let len: u32;

                if code == SMALL_REPEAT_CODE {
                    match self.decode_bits(SMALL_NON_ZERO_RUN_EXTRA_BITS as u32) {
                        Ok(s) => {
                            len = s + SMALL_MIN_NON_ZERO_RUN_SIZE as u32;
                        }
                        Err(_) => return false,
                    };
                } else {
                    match self.decode_bits(LARGE_NON_ZERO_RUN_EXTRA_BITS as u32) {
                        Ok(s) => {
                            len = s + LARGE_MIN_NON_ZERO_RUN_SIZE as u32;
                        }
                        Err(_) => return false,
                    };
                }

                if ofs == 0 || len > num_remaining {
                    return false;
                }

                let prev: u32 = model.code_sizes[(ofs - 1) as usize] as u32;
                if prev == 0 {
                    return false;
                }

                let end = ofs + len;
                while ofs < end {
                    model.code_sizes[ofs as usize] = prev as u8;
                    ofs += 1;
                }
            } else {
                return false;
            }
        }
        model.prepare_decoder_tables()
    }

    pub fn decode_bits(&mut self, num_bits: u32) -> Result<u32, bool> {
        if num_bits == 0_u32 {
            return Ok(0_u32);
        }
        if num_bits > 16_u32 {
            let a = match self.get_bits(num_bits - 16) {
                Ok(s) => s,
                Err(_) => return Err(false),
            };
            let b = match self.get_bits(16) {
                Ok(s) => s,
                Err(_) => return Err(false),
            };
            Ok((a << 16) | b)
        } else {
            self.get_bits(num_bits)
        }
    }

    pub fn decode(&mut self, model: &StaticHuffmanDataModel) -> Result<u32, bool> {
        let p_tables = &model.p_decode_tables;
        if self.bit_count < 24 {
            if self.bit_count < 16 {
                let mut c0: u32 = 0;
                let mut c1: u32 = 0;
                let mut p = self.p_decode_buf_next;
                if (&(p[0]) as *const u8) <= self.p_decode_buf_end {
                    c0 = p[0] as u32;
                    if (&(p[0]) as *const u8) < self.p_decode_buf_end {
                        p = &p[1..]
                    }
                };
                if (&(p[0]) as *const u8) <= self.p_decode_buf_end {
                    c1 = p[0] as u32;
                    if (&(p[0]) as *const u8) < self.p_decode_buf_end {
                        p = &p[1..]
                    }
                };
                self.p_decode_buf_next = p;
                self.bit_count += 16;
                let c: u32 = (c0 << 8) | c1;
                self.bit_buf |= c << (32 - self.bit_count);
            } else {
                let c: u32;
                if (&(self.p_decode_buf_next[0]) as *const u8) <= self.p_decode_buf_end {
                    c = self.p_decode_buf_next[0] as u32;
                    if (&(self.p_decode_buf_next[0]) as *const u8) < self.p_decode_buf_end {
                        self.p_decode_buf_next = &self.p_decode_buf_next[1..];
                    }
                } else {
                    c = 0
                };
                self.bit_count += 8;
                self.bit_buf |= c << (32 - self.bit_count);
            }
        }
        let k: u32 = (self.bit_buf >> 16) + 1;
        let sym: u32;
        let mut len: u32;
        if k <= p_tables.table_max_code {
            let t = p_tables.lookup[(self.bit_buf >> (32 - p_tables.table_bits)) as usize];
            if t == u32::MAX {
                return Err(false);
            }
            sym = t & (u16::MAX as u32);
            len = t >> 16;
            if model.code_sizes[sym as usize] as u32 != len {
                return Err(false);
            }
        } else {
            len = p_tables.decode_start_code_size;
            loop {
                if k <= p_tables.max_codes[(len - 1) as usize] {
                    break;
                }
                len += 1;
            }
            let val_ptr: i32 =
                p_tables.val_ptrs[(len - 1) as usize] + (self.bit_buf >> (32 - len)) as i32;
            if (val_ptr as u32) >= model.total_syms {
                return Err(false);
            }
            sym = p_tables.sorted_symbol_order[val_ptr as usize] as u32;
        }
        self.bit_buf <<= len;
        self.bit_count -= len as i32;
        Ok(sym)
    }

    pub fn stop_decoding(&mut self) {}

    fn get_bits_init(&mut self) {
        self.bit_buf = 0;
        self.bit_count = 0;
    }

    fn get_bits(&mut self, num_bits: u32) -> Result<u32, bool> {
        if num_bits > 32 {
            return Err(false);
        }
        while self.bit_count < num_bits as i32 {
            let mut c: u32 = 0;
            if self.p_decode_buf_next[0] as *const u8 <= self.p_decode_buf_end {
                c = self.p_decode_buf_next[0] as u32;
                if (self.p_decode_buf_next[0] as *const u8) < self.p_decode_buf_end {
                    self.p_decode_buf_next = &self.p_decode_buf_next[1..];
                }
            }
            self.bit_count += 8;
            if self.bit_count > BIT_BUF_SIZE as i32 {
                return Err(false);
            }
            self.bit_buf |= c << (BIT_BUF_SIZE - self.bit_count as usize);
        }
        let result: u32 = self.bit_buf >> (BIT_BUF_SIZE - num_bits as usize);
        self.bit_buf <<= num_bits;
        self.bit_count -= num_bits as i32;
        Ok(result)
    }
}