pub const CRC16_SEED: u16 = 0xC0C1;
pub const CRC16_TABLE: [u16; 256] = [
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741,
0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941,
0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341,
0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,
0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41,
0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141,
0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41,
0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541,
0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741,
0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941,
0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,
0x4100, 0x81C1, 0x8081, 0x4040,
];
pub const CRC32_TABLE: [u32; 256] = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
];
pub fn crc16(seed: u16, data: &[u8]) -> u16 {
data.iter().fold(seed, |crc, &byte| {
let index = (byte ^ (crc as u8)) as usize;
(crc >> 8) ^ CRC16_TABLE[index]
})
}
pub fn crc32(data: &[u8]) -> u32 {
let acc = data.iter().fold(!0u32, |crc, &byte| {
let index = ((crc ^ byte as u32) & 0xFF) as usize;
(crc >> 8) ^ CRC32_TABLE[index]
});
!acc
}
pub fn crc32_with_seed(seed: u32, data: &[u8]) -> u32 {
let inverted_seed = !seed;
let acc = data.iter().fold(inverted_seed, |crc, &byte| {
let index = ((crc ^ byte as u32) & 0xFF) as usize;
(crc >> 8) ^ CRC32_TABLE[index]
});
!acc
}
pub const CRC64_POLY: u64 = 0x95AC9329AC4BC9B5;
pub const CRC64_TABLE: [u64; 256] = [
0x0000000000000000,
0x7AD870C830358979,
0xF5B0E190606B12F2,
0x8F689158505E9B8B,
0xC038E5739841B68F,
0xBAE095BBA8743FF6,
0x358804E3F82AA47D,
0x4F50742BC81F2D04,
0xAB28ECB46814FE75,
0xD1F09C7C5821770C,
0x5E980D24087FEC87,
0x24407DEC384A65FE,
0x6B1009C7F05548FA,
0x11C8790FC060C183,
0x9EA0E857903E5A08,
0xE478989FA00BD371,
0x7D08FF3B88BE6F81,
0x07D08FF3B88BE6F8,
0x88B81EABE8D57D73,
0xF2606E63D8E0F40A,
0xBD301A4810FFD90E,
0xC7E86A8020CA5077,
0x4880FBD87094CBFC,
0x32588B1040A14285,
0xD620138FE0AA91F4,
0xACF86347D09F188D,
0x2390F21F80C18306,
0x594882D7B0F40A7F,
0x1618F6FC78EB277B,
0x6CC0863448DEAE02,
0xE3A8176C18803589,
0x997067A428B5BCF0,
0xFA11FE77117CDF02,
0x80C98EBF2149567B,
0x0FA11FE77117CDF0,
0x75796F2F41224489,
0x3A291B04893D698D,
0x40F16BCCB908E0F4,
0xCF99FA94E9567B7F,
0xB5418A5CD963F206,
0x513912C379682177,
0x2BE1620B495DA80E,
0xA489F35319033385,
0xDE51839B2936BAFC,
0x9101F7B0E12997F8,
0xEBD98778D11C1E81,
0x64B116208142850A,
0x1E6966E8B1770C73,
0x8719014C99C2B083,
0xFDC17184A9F739FA,
0x72A9E0DCF9A9A271,
0x08719014C99C2B08,
0x4721E43F0183060C,
0x3DF994F731B68F75,
0xB29105AF61E814FE,
0xC849756751DD9D87,
0x2C31EDF8F1D64EF6,
0x56E99D30C1E3C78F,
0xD9810C6891BD5C04,
0xA3597CA0A188D57D,
0xEC09088B6997F879,
0x96D1784359A27100,
0x19B9E91B09FCEA8B,
0x636199D339C963F2,
0xDF7ADABD7A6E2D6F,
0xA5A2AA754A5BA416,
0x2ACA3B2D1A053F9D,
0x50124BE52A30B6E4,
0x1F423FCEE22F9BE0,
0x659A4F06D21A1299,
0xEAF2DE5E82448912,
0x902AAE96B271006B,
0x74523609127AD31A,
0x0E8A46C1224F5A63,
0x81E2D7997211C1E8,
0xFB3AA75142244891,
0xB46AD37A8A3B6595,
0xCEB2A3B2BA0EECEC,
0x41DA32EAEA507767,
0x3B024222DA65FE1E,
0xA2722586F2D042EE,
0xD8AA554EC2E5CB97,
0x57C2C41692BB501C,
0x2D1AB4DEA28ED965,
0x624AC0F56A91F461,
0x1892B03D5AA47D18,
0x97FA21650AFAE693,
0xED2251AD3ACF6FEA,
0x095AC9329AC4BC9B,
0x7382B9FAAAF135E2,
0xFCEA28A2FAAFAE69,
0x8632586ACA9A2710,
0xC9622C4102850A14,
0xB3BA5C8932B0836D,
0x3CD2CDD162EE18E6,
0x460ABD1952DB919F,
0x256B24CA6B12F26D,
0x5FB354025B277B14,
0xD0DBC55A0B79E09F,
0xAA03B5923B4C69E6,
0xE553C1B9F35344E2,
0x9F8BB171C366CD9B,
0x10E3202993385610,
0x6A3B50E1A30DDF69,
0x8E43C87E03060C18,
0xF49BB8B633338561,
0x7BF329EE636D1EEA,
0x012B592653589793,
0x4E7B2D0D9B47BA97,
0x34A35DC5AB7233EE,
0xBBCBCC9DFB2CA865,
0xC113BC55CB19211C,
0x5863DBF1E3AC9DEC,
0x22BBAB39D3991495,
0xADD33A6183C78F1E,
0xD70B4AA9B3F20667,
0x985B3E827BED2B63,
0xE2834E4A4BD8A21A,
0x6DEBDF121B863991,
0x1733AFDA2BB3B0E8,
0xF34B37458BB86399,
0x8993478DBB8DEAE0,
0x06FBD6D5EBD3716B,
0x7C23A61DDBE6F812,
0x3373D23613F9D516,
0x49ABA2FE23CC5C6F,
0xC6C333A67392C7E4,
0xBC1B436E43A74E9D,
0x95AC9329AC4BC9B5,
0xEF74E3E19C7E40CC,
0x601C72B9CC20DB47,
0x1AC40271FC15523E,
0x5594765A340A7F3A,
0x2F4C0692043FF643,
0xA02497CA54616DC8,
0xDAFCE7026454E4B1,
0x3E847F9DC45F37C0,
0x445C0F55F46ABEB9,
0xCB349E0DA4342532,
0xB1ECEEC59401AC4B,
0xFEBC9AEE5C1E814F,
0x8464EA266C2B0836,
0x0B0C7B7E3C7593BD,
0x71D40BB60C401AC4,
0xE8A46C1224F5A634,
0x927C1CDA14C02F4D,
0x1D148D82449EB4C6,
0x67CCFD4A74AB3DBF,
0x289C8961BCB410BB,
0x5244F9A98C8199C2,
0xDD2C68F1DCDF0249,
0xA7F41839ECEA8B30,
0x438C80A64CE15841,
0x3954F06E7CD4D138,
0xB63C61362C8A4AB3,
0xCCE411FE1CBFC3CA,
0x83B465D5D4A0EECE,
0xF96C151DE49567B7,
0x76048445B4CBFC3C,
0x0CDCF48D84FE7545,
0x6FBD6D5EBD3716B7,
0x15651D968D029FCE,
0x9A0D8CCEDD5C0445,
0xE0D5FC06ED698D3C,
0xAF85882D2576A038,
0xD55DF8E515432941,
0x5A3569BD451DB2CA,
0x20ED197575283BB3,
0xC49581EAD523E8C2,
0xBE4DF122E51661BB,
0x3125607AB548FA30,
0x4BFD10B2857D7349,
0x04AD64994D625E4D,
0x7E7514517D57D734,
0xF11D85092D094CBF,
0x8BC5F5C11D3CC5C6,
0x12B5926535897936,
0x686DE2AD05BCF04F,
0xE70573F555E26BC4,
0x9DDD033D65D7E2BD,
0xD28D7716ADC8CFB9,
0xA85507DE9DFD46C0,
0x273D9686CDA3DD4B,
0x5DE5E64EFD965432,
0xB99D7ED15D9D8743,
0xC3450E196DA80E3A,
0x4C2D9F413DF695B1,
0x36F5EF890DC31CC8,
0x79A59BA2C5DC31CC,
0x037DEB6AF5E9B8B5,
0x8C157A32A5B7233E,
0xF6CD0AFA9582AA47,
0x4AD64994D625E4DA,
0x300E395CE6106DA3,
0xBF66A804B64EF628,
0xC5BED8CC867B7F51,
0x8AEEACE74E645255,
0xF036DC2F7E51DB2C,
0x7F5E4D772E0F40A7,
0x05863DBF1E3AC9DE,
0xE1FEA520BE311AAF,
0x9B26D5E88E0493D6,
0x144E44B0DE5A085D,
0x6E963478EE6F8124,
0x21C640532670AC20,
0x5B1E309B16452559,
0xD476A1C3461BBED2,
0xAEAED10B762E37AB,
0x37DEB6AF5E9B8B5B,
0x4D06C6676EAE0222,
0xC26E573F3EF099A9,
0xB8B627F70EC510D0,
0xF7E653DCC6DA3DD4,
0x8D3E2314F6EFB4AD,
0x0256B24CA6B12F26,
0x788EC2849684A65F,
0x9CF65A1B368F752E,
0xE62E2AD306BAFC57,
0x6946BB8B56E467DC,
0x139ECB4366D1EEA5,
0x5CCEBF68AECEC3A1,
0x2616CFA09EFB4AD8,
0xA97E5EF8CEA5D153,
0xD3A62E30FE90582A,
0xB0C7B7E3C7593BD8,
0xCA1FC72BF76CB2A1,
0x45775673A732292A,
0x3FAF26BB9707A053,
0x70FF52905F188D57,
0x0A2722586F2D042E,
0x854FB3003F739FA5,
0xFF97C3C80F4616DC,
0x1BEF5B57AF4DC5AD,
0x61372B9F9F784CD4,
0xEE5FBAC7CF26D75F,
0x9487CA0FFF135E26,
0xDBD7BE24370C7322,
0xA10FCEEC0739FA5B,
0x2E675FB4576761D0,
0x54BF2F7C6752E8A9,
0xCDCF48D84FE75459,
0xB71738107FD2DD20,
0x387FA9482F8C46AB,
0x42A7D9801FB9CFD2,
0x0DF7ADABD7A6E2D6,
0x772FDD63E7936BAF,
0xF8474C3BB7CDF024,
0x829F3CF387F8795D,
0x66E7A46C27F3AA2C,
0x1C3FD4A417C62355,
0x935745FC4798B8DE,
0xE98F353477AD31A7,
0xA6DF411FBFB21CA3,
0xDC0731D78F8795DA,
0x536FA08FDFD90E51,
0x29B7D047EFEC8728,
];
pub fn crc64(data: &[u8]) -> u64 {
data.iter().fold(0u64, |crc, &byte| {
let index = ((crc ^ byte as u64) & 0xFF) as usize;
(crc >> 8) ^ CRC64_TABLE[index]
})
}
pub fn crc64_with_seed(seed: u64, data: &[u8]) -> u64 {
data.iter().fold(seed, |crc, &byte| {
let index = ((crc ^ byte as u64) & 0xFF) as usize;
(crc >> 8) ^ CRC64_TABLE[index]
})
}
pub const CRC64_POLY_NORMAL: u64 = 0x42F0E1EBA9EA3693;
pub const CRC64_TABLE_NORMAL: [u64; 256] = [
0x0000000000000000,
0x42F0E1EBA9EA3693,
0x85E1C3D753D46D26,
0xC711223CFA3E5BB5,
0x493366450E42ECDF,
0x0BC387AEA7A8DA4C,
0xCCD2A5925D9681F9,
0x8E224479F47CB76A,
0x9266CC8A1C85D9BE,
0xD0962D61B56FEF2D,
0x17870F5D4F51B498,
0x5577EEB6E6BB820B,
0xDB55AACF12C73561,
0x99A54B24BB2D03F2,
0x5EB4691841135847,
0x1C4488F3E8F96ED4,
0x663D78FF90E185EF,
0x24CD9914390BB37C,
0xE3DCBB28C335E8C9,
0xA12C5AC36ADFDE5A,
0x2F0E1EBA9EA36930,
0x6DFEFF5137495FA3,
0xAAEFDD6DCD770416,
0xE81F3C86649D3285,
0xF45BB4758C645C51,
0xB6AB559E258E6AC2,
0x71BA77A2DFB03177,
0x334A9649765A07E4,
0xBD68D2308226B08E,
0xFF9833DB2BCC861D,
0x388911E7D1F2DDA8,
0x7A79F00C7818EB3B,
0xCC7AF1FF21C30BDE,
0x8E8A101488293D4D,
0x499B3228721766F8,
0x0B6BD3C3DBFD506B,
0x854997BA2F81E701,
0xC7B97651866BD192,
0x00A8546D7C558A27,
0x4258B586D5BFBCB4,
0x5E1C3D753D46D260,
0x1CECDC9E94ACE4F3,
0xDBFDFEA26E92BF46,
0x990D1F49C77889D5,
0x172F5B3033043EBF,
0x55DFBADB9AEE082C,
0x92CE98E760D05399,
0xD03E790CC93A650A,
0xAA478900B1228E31,
0xE8B768EB18C8B8A2,
0x2FA64AD7E2F6E317,
0x6D56AB3C4B1CD584,
0xE374EF45BF6062EE,
0xA1840EAE168A547D,
0x66952C92ECB40FC8,
0x2465CD79455E395B,
0x3821458AADA7578F,
0x7AD1A461044D611C,
0xBDC0865DFE733AA9,
0xFF3067B657990C3A,
0x711223CFA3E5BB50,
0x33E2C2240A0F8DC3,
0xF4F3E018F031D676,
0xB60301F359DBE0E5,
0xDA050215EA6C212F,
0x98F5E3FE438617BC,
0x5FE4C1C2B9B84C09,
0x1D14202910527A9A,
0x93366450E42ECDF0,
0xD1C685BB4DC4FB63,
0x16D7A787B7FAA0D6,
0x5427466C1E109645,
0x4863CE9FF6E9F891,
0x0A932F745F03CE02,
0xCD820D48A53D95B7,
0x8F72ECA30CD7A324,
0x0150A8DAF8AB144E,
0x43A04931514122DD,
0x84B16B0DAB7F7968,
0xC6418AE602954FFB,
0xBC387AEA7A8DA4C0,
0xFEC89B01D3679253,
0x39D9B93D2959C9E6,
0x7B2958D680B3FF75,
0xF50B1CAF74CF481F,
0xB7FBFD44DD257E8C,
0x70EADF78271B2539,
0x321A3E938EF113AA,
0x2E5EB66066087D7E,
0x6CAE578BCFE24BED,
0xABBF75B735DC1058,
0xE94F945C9C3626CB,
0x676DD025684A91A1,
0x259D31CEC1A0A732,
0xE28C13F23B9EFC87,
0xA07CF2199274CA14,
0x167FF3EACBAF2AF1,
0x548F120162451C62,
0x939E303D987B47D7,
0xD16ED1D631917144,
0x5F4C95AFC5EDC62E,
0x1DBC74446C07F0BD,
0xDAAD56789639AB08,
0x985DB7933FD39D9B,
0x84193F60D72AF34F,
0xC6E9DE8B7EC0C5DC,
0x01F8FCB784FE9E69,
0x43081D5C2D14A8FA,
0xCD2A5925D9681F90,
0x8FDAB8CE70822903,
0x48CB9AF28ABC72B6,
0x0A3B7B1923564425,
0x70428B155B4EAF1E,
0x32B26AFEF2A4998D,
0xF5A348C2089AC238,
0xB753A929A170F4AB,
0x3971ED50550C43C1,
0x7B810CBBFCE67552,
0xBC902E8706D82EE7,
0xFE60CF6CAF321874,
0xE224479F47CB76A0,
0xA0D4A674EE214033,
0x67C58448141F1B86,
0x253565A3BDF52D15,
0xAB1721DA49899A7F,
0xE9E7C031E063ACEC,
0x2EF6E20D1A5DF759,
0x6C0603E6B3B7C1CA,
0xF6FAE5C07D3274CD,
0xB40A042BD4D8425E,
0x731B26172EE619EB,
0x31EBC7FC870C2F78,
0xBFC9838573709812,
0xFD39626EDA9AAE81,
0x3A28405220A4F534,
0x78D8A1B9894EC3A7,
0x649C294A61B7AD73,
0x266CC8A1C85D9BE0,
0xE17DEA9D3263C055,
0xA38D0B769B89F6C6,
0x2DAF4F0F6FF541AC,
0x6F5FAEE4C61F773F,
0xA84E8CD83C212C8A,
0xEABE6D3395CB1A19,
0x90C79D3FEDD3F122,
0xD2377CD44439C7B1,
0x15265EE8BE079C04,
0x57D6BF0317EDAA97,
0xD9F4FB7AE3911DFD,
0x9B041A914A7B2B6E,
0x5C1538ADB04570DB,
0x1EE5D94619AF4648,
0x02A151B5F156289C,
0x4051B05E58BC1E0F,
0x87409262A28245BA,
0xC5B073890B687329,
0x4B9237F0FF14C443,
0x0962D61B56FEF2D0,
0xCE73F427ACC0A965,
0x8C8315CC052A9FF6,
0x3A80143F5CF17F13,
0x7870F5D4F51B4980,
0xBF61D7E80F251235,
0xFD913603A6CF24A6,
0x73B3727A52B393CC,
0x31439391FB59A55F,
0xF652B1AD0167FEEA,
0xB4A25046A88DC879,
0xA8E6D8B54074A6AD,
0xEA16395EE99E903E,
0x2D071B6213A0CB8B,
0x6FF7FA89BA4AFD18,
0xE1D5BEF04E364A72,
0xA3255F1BE7DC7CE1,
0x64347D271DE22754,
0x26C49CCCB40811C7,
0x5CBD6CC0CC10FAFC,
0x1E4D8D2B65FACC6F,
0xD95CAF179FC497DA,
0x9BAC4EFC362EA149,
0x158E0A85C2521623,
0x577EEB6E6BB820B0,
0x906FC95291867B05,
0xD29F28B9386C4D96,
0xCEDBA04AD0952342,
0x8C2B41A1797F15D1,
0x4B3A639D83414E64,
0x09CA82762AAB78F7,
0x87E8C60FDED7CF9D,
0xC51827E4773DF90E,
0x020905D88D03A2BB,
0x40F9E43324E99428,
0x2CFFE7D5975E55E2,
0x6E0F063E3EB46371,
0xA91E2402C48A38C4,
0xEBEEC5E96D600E57,
0x65CC8190991CB93D,
0x273C607B30F68FAE,
0xE02D4247CAC8D41B,
0xA2DDA3AC6322E288,
0xBE992B5F8BDB8C5C,
0xFC69CAB42231BACF,
0x3B78E888D80FE17A,
0x7988096371E5D7E9,
0xF7AA4D1A85996083,
0xB55AACF12C735610,
0x724B8ECDD64D0DA5,
0x30BB6F267FA73B36,
0x4AC29F2A07BFD00D,
0x08327EC1AE55E69E,
0xCF235CFD546BBD2B,
0x8DD3BD16FD818BB8,
0x03F1F96F09FD3CD2,
0x41011884A0170A41,
0x86103AB85A2951F4,
0xC4E0DB53F3C36767,
0xD8A453A01B3A09B3,
0x9A54B24BB2D03F20,
0x5D45907748EE6495,
0x1FB5719CE1045206,
0x919735E51578E56C,
0xD367D40EBC92D3FF,
0x1476F63246AC884A,
0x568617D9EF46BED9,
0xE085162AB69D5E3C,
0xA275F7C11F7768AF,
0x6564D5FDE549331A,
0x279434164CA30589,
0xA9B6706FB8DFB2E3,
0xEB46918411358470,
0x2C57B3B8EB0BDFC5,
0x6EA7525342E1E956,
0x72E3DAA0AA188782,
0x30133B4B03F2B111,
0xF7021977F9CCEAA4,
0xB5F2F89C5026DC37,
0x3BD0BCE5A45A6B5D,
0x79205D0E0DB05DCE,
0xBE317F32F78E067B,
0xFCC19ED95E6430E8,
0x86B86ED5267CDBD3,
0xC4488F3E8F96ED40,
0x0359AD0275A8B6F5,
0x41A94CE9DC428066,
0xCF8B0890283E370C,
0x8D7BE97B81D4019F,
0x4A6ACB477BEA5A2A,
0x089A2AACD2006CB9,
0x14DEA25F3AF9026D,
0x562E43B4931334FE,
0x913F6188692D6F4B,
0xD3CF8063C0C759D8,
0x5DEDC41A34BBEEB2,
0x1F1D25F19D51D821,
0xD80C07CD676F8394,
0x9AFCE626CE85B507,
];
pub fn crc64_normal(seed: u64, data: &[u8]) -> u64 {
data.iter().fold(seed, |crc, &byte| {
let index = ((byte as u64) ^ (crc >> 56)) & 0xFF;
CRC64_TABLE_NORMAL[index as usize] ^ (crc << 8)
})
}
pub fn update_seed2(initial_seed: u64, data_length: u32) -> u64 {
let len = data_length as u64;
let seed = (initial_seed.wrapping_add(len))
.wrapping_mul(0x343FD)
.wrapping_add(0x269EC3);
let seed = seed
.wrapping_mul(0x1_000343FD)
.wrapping_add(len.wrapping_add(0x269EC3));
!seed
}
pub fn update_seed1(initial_seed: u64, data_length: u32) -> u64 {
let len = data_length as u64;
let mut seed = (initial_seed.wrapping_add(len))
.wrapping_mul(0x343FD)
.wrapping_add(0x269EC3);
seed |= seed
.wrapping_mul(0x343FDu64 << 32)
.wrapping_add(0x269EC3u64 << 32);
!seed
}
pub fn dwg_ac21_normal_crc64(seed: u64, data_length: u32, data: &[u8]) -> u64 {
let reordered = reorder_for_crc(data);
let iv = update_seed2(seed, data_length);
!crc64_normal(iv, &reordered)
}
pub fn dwg_ac21_normal_crc64_seed1(seed: u64, data_length: u32, data: &[u8]) -> u64 {
let reordered = reorder_for_crc(data);
let iv = update_seed1(seed, data_length);
!crc64_normal(iv, &reordered)
}
pub fn dwg_ac21_mirrored_crc64(seed: u64, data_length: u32, data: &[u8]) -> u64 {
let reordered = reorder_for_crc(data);
let iv = update_seed1(seed, data_length);
crc64_with_seed(iv, &reordered)
}
pub fn dwg_ac21_check_data_normal_crc64(random2: u64, data: &[u8]) -> u64 {
let reordered = reorder_for_crc(data);
!crc64_normal(!random2, &reordered)
}
pub fn dwg_ac21_check_data_mirrored_crc64(random1: u64, data: &[u8]) -> u64 {
let reordered = reorder_for_crc(data);
crc64_with_seed(!random1, &reordered)
}
pub fn reorder_for_crc(data: &[u8]) -> Vec<u8> {
let mut result = Vec::with_capacity(data.len());
let full_blocks = data.len() / 8;
let remainder = data.len() % 8;
for b in 0..full_blocks {
let base = b * 8;
result.push(data[base + 6]);
result.push(data[base + 7]);
result.push(data[base + 4]);
result.push(data[base + 5]);
result.push(data[base + 2]);
result.push(data[base + 3]);
result.push(data[base + 0]);
result.push(data[base + 1]);
}
let base = full_blocks * 8;
match remainder {
0 => {}
1 => {
result.push(data[base]);
}
2 => {
result.push(data[base]);
result.push(data[base + 1]);
}
3 => {
result.push(data[base]);
result.push(data[base + 1]);
result.push(data[base + 2]);
}
4 => {
result.push(data[base + 2]);
result.push(data[base + 3]);
result.push(data[base + 0]);
result.push(data[base + 1]);
}
5 => {
result.push(data[base + 2]);
result.push(data[base + 3]);
result.push(data[base + 0]);
result.push(data[base + 1]);
result.push(data[base + 4]);
}
6 => {
result.push(data[base + 2]);
result.push(data[base + 3]);
result.push(data[base + 0]);
result.push(data[base + 1]);
result.push(data[base + 4]);
result.push(data[base + 5]);
}
7 => {
result.push(data[base + 2]);
result.push(data[base + 3]);
result.push(data[base + 0]);
result.push(data[base + 1]);
result.push(data[base + 4]);
result.push(data[base + 5]);
result.push(data[base + 6]);
}
_ => unreachable!(),
}
result
}
pub fn dwg_ac21_header_crc64(metadata: &[u8]) -> u64 {
assert!(
metadata.len() >= 0x110,
"Metadata buffer must be at least 0x110 bytes"
);
let data_len = 0x110u32;
let mut buf = [0u8; 0x110];
buf.copy_from_slice(&metadata[..0x110]);
buf[0x108..0x110].fill(0);
let reordered = reorder_for_crc(&buf);
let iv = update_seed2(0, data_len);
let crc = crc64_normal(iv, &reordered);
!crc
}
pub fn dwg_ac21_page_checksum(seed: u32, data: &[u8]) -> u32 {
let seed64 = (seed as u64)
.wrapping_add(data.len() as u64)
.wrapping_mul(0x343FD)
.wrapping_add(0x269EC3);
let mut sum1: u32 = (seed64 & 0xFFFF) as u32;
let mut sum2: u32 = ((seed64 >> 16) & 0xFFFF) as u32;
const CHUNK_SIZE: usize = 0x15B0; const MODULUS: u32 = 0xFFF1;
let mut offset: usize = 0;
let total = data.len();
while offset < total {
let chunk_end = (offset + CHUNK_SIZE).min(total);
let chunk = &data[offset..chunk_end];
let mut i = 0;
while i + 8 <= chunk.len() {
let b = &chunk[i..i + 8];
sum1 += b[6] as u32;
sum2 += sum1;
sum1 += b[7] as u32;
sum2 += sum1;
sum1 += b[4] as u32;
sum2 += sum1;
sum1 += b[5] as u32;
sum2 += sum1;
sum1 += b[2] as u32;
sum2 += sum1;
sum1 += b[3] as u32;
sum2 += sum1;
sum1 += b[0] as u32;
sum2 += sum1;
sum1 += b[1] as u32;
sum2 += sum1;
i += 8;
}
let remaining = chunk.len() - i;
let r = &chunk[i..];
if remaining >= 4 {
sum1 += r[2] as u32;
sum2 += sum1;
sum1 += r[3] as u32;
sum2 += sum1;
sum1 += r[0] as u32;
sum2 += sum1;
sum1 += r[1] as u32;
sum2 += sum1;
for j in 4..remaining {
sum1 += r[j] as u32;
sum2 += sum1;
}
} else {
for j in 0..remaining {
sum1 += r[j] as u32;
sum2 += sum1;
}
}
sum1 %= MODULUS;
sum2 %= MODULUS;
offset = chunk_end;
}
(sum2 << 16) | (sum1 & 0xFFFF)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_crc16_empty() {
assert_eq!(crc16(CRC16_SEED, &[]), CRC16_SEED);
}
#[test]
fn test_crc16_basic() {
let result = crc16(CRC16_SEED, &[0x00]);
assert_ne!(result, CRC16_SEED);
}
#[test]
fn test_crc16_incremental() {
let data = b"Hello, DWG!";
let full = crc16(CRC16_SEED, data);
let partial1 = crc16(CRC16_SEED, &data[..5]);
let partial2 = crc16(partial1, &data[5..]);
assert_eq!(full, partial2);
}
#[test]
fn test_crc32_empty() {
assert_eq!(crc32(&[]), 0x00000000);
}
#[test]
fn test_crc32_known_value() {
let result = crc32(b"123456789");
assert_eq!(result, 0xCBF43926);
}
#[test]
fn test_crc32_with_seed_default() {
let data = b"test data";
assert_eq!(crc32(data), crc32_with_seed(0x00000000, data));
}
#[test]
fn test_crc16_table_first_entries() {
assert_eq!(CRC16_TABLE[0], 0x0000);
assert_eq!(CRC16_TABLE[1], 0xC0C1);
assert_eq!(CRC16_TABLE[2], 0xC181);
assert_eq!(CRC16_TABLE[255], 0x4040);
}
#[test]
fn test_crc32_table_first_entries() {
assert_eq!(CRC32_TABLE[0], 0x00000000);
assert_eq!(CRC32_TABLE[1], 0x77073096);
assert_eq!(CRC32_TABLE[255], 0x2D02EF8D);
}
#[test]
fn test_crc64_table_generated_correctly() {
assert_eq!(CRC64_TABLE[0], 0x0000000000000000);
assert_eq!(CRC64_TABLE[1], 0x7AD870C830358979);
assert_eq!(CRC64_TABLE[2], 0xF5B0E190606B12F2);
assert_eq!(CRC64_TABLE[128], CRC64_POLY); assert_eq!(CRC64_TABLE[255], 0x29B7D047EFEC8728);
}
#[test]
fn test_crc64_table_regenerate() {
let mut table = [0u64; 256];
for i in 0..256u64 {
let mut crc = i;
for _ in 0..8 {
if crc & 1 == 1 {
crc = (crc >> 1) ^ CRC64_POLY;
} else {
crc >>= 1;
}
}
table[i as usize] = crc;
}
assert_eq!(table, CRC64_TABLE);
}
#[test]
fn test_crc64_empty() {
assert_eq!(crc64(&[]), 0x0000000000000000);
}
#[test]
fn test_crc64_known_value() {
let result = crc64(b"123456789");
let mut expected = 0u64;
for &b in b"123456789" {
let index = ((expected ^ b as u64) & 0xFF) as usize;
expected = (expected >> 8) ^ CRC64_TABLE[index];
}
assert_eq!(result, expected);
}
#[test]
fn test_crc64_single_byte() {
assert_eq!(crc64(&[0x00]), CRC64_TABLE[0]);
assert_eq!(crc64(&[0x01]), CRC64_TABLE[1]);
assert_eq!(crc64(&[0xFF]), CRC64_TABLE[255]);
}
#[test]
fn test_crc64_incremental() {
let data = b"Hello, DWG 2007!";
let full = crc64(data);
let partial1 = crc64_with_seed(0, &data[..8]);
let partial2 = crc64_with_seed(partial1, &data[8..]);
assert_eq!(full, partial2);
}
#[test]
fn test_crc64_different_data_different_crc() {
let crc_a = crc64(b"AAAA");
let crc_b = crc64(b"BBBB");
assert_ne!(crc_a, crc_b);
}
#[test]
fn test_crc64_normal_table_generated_correctly() {
assert_eq!(CRC64_TABLE_NORMAL[0], 0x0000000000000000);
}
#[test]
fn test_crc64_normal_table_regenerate() {
let mut table = [0u64; 256];
for i in 0..256u64 {
let mut crc = i << 56;
for _ in 0..8 {
if crc & (1u64 << 63) != 0 {
crc = (crc << 1) ^ CRC64_POLY_NORMAL;
} else {
crc <<= 1;
}
}
table[i as usize] = crc;
}
assert_eq!(table, CRC64_TABLE_NORMAL);
}
#[test]
fn test_crc64_normal_known_value() {
let result = crc64_normal(0, b"123456789");
assert_eq!(result, 0x6C40DF5F0B497347);
}
#[test]
fn test_update_seed2_for_0x110() {
let iv = update_seed2(0, 0x110);
let iv2 = update_seed2(0, 0x110);
assert_eq!(iv, iv2);
assert_ne!(iv, 0);
let iv_other = update_seed2(0, 0x200);
assert_ne!(iv, iv_other);
}
#[test]
fn test_update_seed2_deterministic() {
assert_eq!(update_seed2(0, 100), update_seed2(0, 100));
assert_eq!(update_seed2(42, 256), update_seed2(42, 256));
}
}