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));
}
}