ogg/
crc.rs

1// Ogg decoder and encoder written in Rust
2//
3// Copyright (c) 2016-2017 est31 <MTest31@outlook.com>
4// and contributors. All rights reserved.
5// Redistribution or use only under the terms
6// specified in the LICENSE file attached to this
7// source distribution.
8
9/*!
10Implementation of the CRC algorithm with the
11vorbis specific parameters and setup
12*/
13
14// Lookup table to enable bytewise CRC32 calculation
15// Created using the crc32-table-generate example.
16//
17static CRC_LOOKUP_ARRAY : &[u32] = &[
18	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
19	0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
20	0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
21	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
22	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
23	0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
24	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
25	0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
26	0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
27	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
28	0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
29	0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
30	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
31	0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
32	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
33	0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
34	0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
35	0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
36	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
37	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
38	0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
39	0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
40	0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
41	0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
42	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
43	0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
44	0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
45	0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
46	0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
47	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
48	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
49	0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
50	0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
51	0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
52	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
53	0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
54	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
55	0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
56	0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
57	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
58	0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
59	0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
60	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
61	0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
62	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
63	0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
64	0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
65	0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
66	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
67	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
68	0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
69	0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
70	0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
71	0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
72	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
73	0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
74	0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
75	0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
76	0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
77	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
78	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
79	0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
80	0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
81	0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4];
82
83/*
84// Const implementation: TODO adopt it once MSRV > 1.46
85static CRC_LOOKUP_ARRAY :&[u32] = &lookup_array();
86
87const fn get_tbl_elem(idx :u32) -> u32 {
88	let mut r :u32 = idx << 24;
89	let mut i = 0;
90	while i < 8 {
91		r = (r << 1) ^ (-(((r >> 31) & 1) as i32) as u32 & 0x04c11db7);
92		i += 1;
93	}
94	return r;
95}
96
97const fn lookup_array() -> [u32; 0x100] {
98	let mut lup_arr :[u32; 0x100] = [0; 0x100];
99	let mut i = 0;
100	while i < 0x100 {
101		lup_arr[i] = get_tbl_elem(i as u32);
102		i += 1;
103	}
104	lup_arr
105}
106*/
107
108#[cfg(test)]
109pub fn vorbis_crc32(array :&[u8]) -> u32 {
110	return vorbis_crc32_update(0, array);
111}
112
113pub fn vorbis_crc32_update(cur :u32, array :&[u8]) -> u32 {
114	let mut ret :u32 = cur;
115	for av in array {
116		ret = (ret << 8) ^ CRC_LOOKUP_ARRAY[(*av as u32 ^ (ret >> 24)) as usize];
117	}
118	return ret;
119}
120
121#[test]
122fn test_crc32() {
123	// Test page taken from real Ogg file
124	let test_arr = &[
125	0x4f, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00,
126	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xa3,
127	0x90, 0x5b, 0x00, 0x00, 0x00, 0x00,
128	// The spec requires us to zero out the CRC field
129	/*0x6d, 0x94, 0x4e, 0x3d,*/ 0x00, 0x00, 0x00, 0x00,
130	0x01, 0x1e, 0x01, 0x76, 0x6f, 0x72,
131	0x62, 0x69, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02,
132	0x44, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133	0x80, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
134	0xb8, 0x01];
135	println!("");
136	println!("CRC of \"==!\" calculated as 0x{:08x} (expected 0x9f858776)", vorbis_crc32(&[61,61,33]));
137	println!("Test page CRC calculated as 0x{:08x} (expected 0x3d4e946d)", vorbis_crc32(test_arr));
138	assert_eq!(vorbis_crc32(&[61,61,33]), 0x9f858776);
139	assert_eq!(vorbis_crc32(test_arr), 0x3d4e946d);
140	assert_eq!(vorbis_crc32(&test_arr[0 .. 27]), 0x7b374db8);
141}