crcany-core 0.0.2

Core implementation of crcany library.
Documentation
use crate::crc::Crc;
use crate::spec::Spec;
use crate::util::{ones, reverse};

pub struct BitwiseModel {
    spec: Spec,
    // if true, reflect input and output
    reflect: bool,
    // if true, reverse output
    reverse: bool,
    // polynomial representation (sans x^width)
    poly: u128,
    // CRC of a zero-length sequence
    init: u128,
}

impl BitwiseModel {
    pub fn reflect(&self) -> bool {
        self.reflect
    }

    pub fn reverse(&self) -> bool {
        self.reverse
    }

    pub fn width(&self) -> u16 {
        self.spec.width
    }

    pub fn init(&self) -> u128 {
        self.init as _
    }

    pub fn xorout(&self) -> u128 {
        self.spec.xorout
    }

    pub fn from_spec(spec: Spec) -> BitwiseModel {
        let poly = if spec.refin {
            reverse(spec.poly, spec.width)
        } else {
            spec.poly
        };

        let init = spec.xorout
            ^ if spec.refout {
                reverse(spec.init, spec.width)
            } else {
                spec.init
            };

        let reflect = spec.refin;
        let reverse = spec.refin ^ spec.refout;

        BitwiseModel {
            spec,
            reflect,
            reverse,
            poly,
            init,
        }
    }
}

impl Crc for BitwiseModel {
    type Int = u128;

    fn init(&self) -> u128 {
        self.init as _
    }

    fn add_bytes(&self, mut crc: u128, data: &[u8]) -> u128 {
        if data.is_empty() {
            return crc;
        }

        //println!("here0:  {:#06x}", crc);

        crc ^= self.spec.xorout;

        //println!("here1:  {:#06x}", crc);

        if self.reverse {
            crc = reverse(crc, self.spec.width);
        }

        //println!("here2:  {:#06x}", crc);

        if self.reflect {
            crc &= ones(self.spec.width);
            for byte in data {
                crc ^= *byte as u128;
                for _ in 0..8 {
                    crc = if crc & 1 != 0 {
                        (crc >> 1) ^ self.poly
                    } else {
                        crc >> 1
                    };
                }
            }
        } else if self.spec.width <= 8 {
            let shift = 8 - self.spec.width;
            let poly = self.poly << shift;

            crc <<= shift;

            //println!("herex:  {:#06x}", crc);

            for byte in data {
                //println!("CRC:  {:#06x}", crc);
                //println!("BYTE: {:#06x}", *byte);
                crc ^= *byte as u128;
                //println!("CRC^: {:#06x}", crc);
                for _ in 0..8 {
                    crc = if crc & 0x80 != 0 {
                        (crc << 1) ^ poly
                    } else {
                        crc << 1
                    };
                    //println!("CRC{}: {:#06x}", k, crc);
                }
            }

            crc >>= shift;

            crc &= ones(self.spec.width);

            //println!("CRC:  {:#06x}", crc);
        } else {
            let mask = 1 << (self.spec.width - 1);
            let shift = self.spec.width - 8;

            for byte in data {
                crc ^= (*byte as u128) << shift;
                for _ in 0..8 {
                    crc = if crc & mask != 0 {
                        (crc << 1) ^ self.poly
                    } else {
                        crc << 1
                    };
                }
            }

            crc &= ones(self.spec.width);
        }

        //println!("here3:  {:#06x}", crc);

        if self.reverse {
            crc = reverse(crc, self.spec.width);
        }

        //println!("here4:  {:#06x}", crc);

        crc ^= self.spec.xorout;

        //println!("here5:  {:#06x}", crc);

        crc as _
    }
}