1use core::convert::TryInto;
20
21pub fn checksum<I, J>(spans: I) -> u16
22where
23 I: IntoIterator<Item = J>,
24 J: AsRef<[u8]>,
25{
26 let mut accum = 0u32;
27
28 for span in spans.into_iter() {
29 accum += sum(span.as_ref()) as u32;
30 }
31
32 accum = (accum >> 16) + (accum & 0xffff);
33 !(((accum >> 16) as u16) + (accum as u16))
34}
35
36fn sum(mut buffer: &[u8]) -> u16 {
37 let mut accum = 0;
38
39 while buffer.len() >= 32 {
40 let mut b = &buffer[..32];
41 while b.len() >= 2 {
42 accum += u16::from_be_bytes(b[0..=1].try_into().unwrap()) as u32;
43 b = &b[2..];
44 }
45 buffer = &buffer[32..];
46 }
47
48 while buffer.len() >= 2 {
49 accum += u16::from_be_bytes(buffer[0..=1].try_into().unwrap()) as u32;
50 buffer = &buffer[2..];
51 }
52
53 if let Some(&value) = buffer.first() {
54 accum += (value as u32) << 8;
55 }
56
57 accum = (accum >> 16) + (accum & 0xffff);
58 ((accum >> 16) as u16) + (accum as u16)
59}