mutnet 0.7.0

Unsafe-free and allocation-free, no-std network protocol parsing and in-place manipulation library.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
//! Internet checksum calculation.
#[cfg(all(not(feature = "remove_checksum"), kani))]
mod verification;

/// Reduces a `u64` to a `u16` via one's complement addition and converts the result to big endian if required
#[cfg(not(feature = "remove_checksum"))]
#[inline]
pub(crate) fn finalize_checksum(checksum: u64) -> u16 {
    let (mut checksum, carry) = ((checksum >> 32) as u32).overflowing_add(checksum as u32);
    checksum += u32::from(carry);

    let (mut checksum, carry) = ((checksum >> 16) as u16).overflowing_add(checksum as u16);
    checksum += u16::from(carry);

    !checksum.to_be()
}

/// Calculates the internet checksum for buffers up to and including 64 bytes.
///
/// # Panics
///
/// Panics if the `buf` length is longer than 64 bytes.
///
/// # Examples
/// ```
/// # use mutnet::checksum::internet_checksum_up_to_64_bytes;
/// let buffer = [0xFF, 10];
/// assert_eq!(0xF5, internet_checksum_up_to_64_bytes(&buffer));
/// ```
#[cfg(not(feature = "remove_checksum"))]
#[inline]
pub fn internet_checksum_up_to_64_bytes(buf: &[u8]) -> u16 {
    assert!(buf.len() <= 64);
    let checksum = checksum_match_64_bytes(buf);

    finalize_checksum(checksum)
}

#[cfg(feature = "remove_checksum")]
/// Used for layer verification, with actual checksum calculation, the proofs do not finish.
#[inline]
pub fn internet_checksum_up_to_64_bytes(_buf: &[u8]) -> u16 {
    0
}

/// Calculates the intermediary internet checksum for the provided `buf` via the method described in
/// <https://www.ietf.org/rfc/rfc1071.txt> without finalizing the checksum.
///
/// This method can be used to calculate parts of a checksum (e.g. the TCP pseudo header).
/// Use [`internet_checksum`] to use the intermediary in a checksum calculation.
///
/// # Panics
/// Panics if:
/// - the `CHUNK_SIZE` is smaller than four.
/// - the `CHUNK_SIZE` is larger than 64.
/// - the `CHUNK_SIZE` is not divisible by 4.
///
/// # Examples
/// ```
/// # use mutnet::checksum::{internet_checksum_intermediary, internet_checksum};
/// let buffer1 = [0xFF, 10];
/// let buffer2 = [0xAA, 10];
/// let intermediary = internet_checksum_intermediary::<4>(&buffer1);
/// assert_eq!(0x56ea, internet_checksum::<4>(intermediary, &buffer2));
/// ```
#[cfg(not(feature = "remove_checksum"))]
#[inline]
pub fn internet_checksum_intermediary<const CHUNK_SIZE: usize>(buf: &[u8]) -> u64 {
    assert!(CHUNK_SIZE <= 64);
    assert!(CHUNK_SIZE >= 4);
    assert_eq!(CHUNK_SIZE % 4, 0);

    let buf_iterator = buf.chunks_exact(CHUNK_SIZE);
    let buf_remainder = buf_iterator.remainder();
    let mut checksum = buf_iterator.fold(0, |mut acc, buf_part| {
        for chunk in 0..CHUNK_SIZE / 4 {
            acc += u64::from(u32::from_ne_bytes(
                buf_part[chunk * 4..chunk * 4 + 4].try_into().unwrap(),
            ));
        }

        acc
    });
    checksum += checksum_match_64_bytes(buf_remainder);
    checksum
}

#[cfg(feature = "remove_checksum")]
/// Used for layer verification, with actual checksum calculation, the proofs do not finish.
#[inline]
pub fn internet_checksum_intermediary<const CHUNK_SIZE: usize>(_buf: &[u8]) -> u64 {
    0
}

/// Calculates the internet checksum for the provided `buf` via the method described in <https://www.ietf.org/rfc/rfc1071.txt>.
///
/// If a part of the checksum was computed via [`internet_checksum_intermediary`], the intermediary
/// can be provided via `checksum_part`.
///
/// The size of the chunk processes in one loop iteration can be configured via `CHUNK_SIZE`.
/// Micro-benchmarks showed four to be a good general choice for varied buffer lengths.
/// If you only deal with very similar lengths of buffers, it may be beneficial to benchmark your
/// specific case.
///
/// # Panics
/// Panics if:
/// - the `CHUNK_SIZE` is smaller than four.
/// - the `CHUNK_SIZE` is larger than 64.
/// - the `CHUNK_SIZE` is not divisible by 4.
///
/// # Examples
/// ```
/// # use mutnet::checksum::{internet_checksum_intermediary, internet_checksum};
/// let buffer = [0xFF, 10];
/// assert_eq!(0xF5, internet_checksum::<4>(0, &buffer));
/// ```
#[cfg(not(feature = "remove_checksum"))]
#[inline]
pub fn internet_checksum<const CHUNK_SIZE: usize>(mut checksum_part: u64, buf: &[u8]) -> u16 {
    checksum_part += internet_checksum_intermediary::<CHUNK_SIZE>(buf);
    finalize_checksum(checksum_part)
}

#[cfg(feature = "remove_checksum")]
/// Used for layer verification, with actual checksum calculation, the proofs do not finish.
#[inline]
pub fn internet_checksum<const CHUNK_SIZE: usize>(_checksum_part: u64, _buf: &[u8]) -> u16 {
    0
}

/// Matches the length of the provided `buf` up to and including 64 bytes of length and calculates
/// the checksum without loop.
#[cfg(not(feature = "remove_checksum"))]
#[inline]
pub(crate) fn checksum_match_64_bytes(buf: &[u8]) -> u64 {
    let mut checksum = 0;
    match buf.len() {
        1 => {
            checksum += u64::from(u16::from_ne_bytes([buf[0], 0]));
        }
        2 => {
            checksum += u64::from(u16::from_ne_bytes(buf[0..2].try_into().unwrap()));
        }
        3 => {
            checksum += u64::from(u16::from_ne_bytes(buf[0..2].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[2], 0]));
        }
        4 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
        }
        5 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[4], 0]));
        }
        6 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[4..6].try_into().unwrap()));
        }
        7 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[4..6].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[6], 0]));
        }
        8 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
        }
        9 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[8], 0]));
        }
        10 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[8..10].try_into().unwrap()));
        }
        11 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[8..10].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[10], 0]));
        }
        12 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
        }
        13 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[12], 0]));
        }
        14 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[12..14].try_into().unwrap()));
        }
        15 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[12..14].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[14], 0]));
        }
        16 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
        }
        17 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[16], 0]));
        }
        18 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[16..18].try_into().unwrap()));
        }
        19 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[16..18].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[18], 0]));
        }
        20 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
        }
        21 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[20], 0]));
        }
        22 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[20..22].try_into().unwrap()));
        }
        23 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[20..22].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[22], 0]));
        }
        24 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
        }
        25 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[24], 0]));
        }
        26 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[24..26].try_into().unwrap()));
        }
        27 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[24..26].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[26], 0]));
        }
        28 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
        }
        29 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[28], 0]));
        }
        30 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[28..30].try_into().unwrap()));
        }
        31 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[28..30].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[30], 0]));
        }
        32 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
        }
        33 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[32], 0]));
        }
        34 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[32..34].try_into().unwrap()));
        }
        35 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[32..34].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[34], 0]));
        }
        36 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
        }
        37 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[36], 0]));
        }
        38 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[36..38].try_into().unwrap()));
        }
        39 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[36..38].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[38], 0]));
        }
        40 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
        }
        41 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[40], 0]));
        }
        42 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[40..42].try_into().unwrap()));
        }
        43 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[40..42].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[42], 0]));
        }
        44 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
        }
        45 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[44], 0]));
        }
        46 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[44..46].try_into().unwrap()));
        }
        47 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[44..46].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[46], 0]));
        }
        48 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
        }
        49 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[48], 0]));
        }
        50 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[48..50].try_into().unwrap()));
        }
        51 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[48..50].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[50], 0]));
        }
        52 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
        }
        53 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[52], 0]));
        }
        54 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[52..54].try_into().unwrap()));
        }
        55 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[52..54].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[54], 0]));
        }
        56 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
        }
        57 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[56], 0]));
        }
        58 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[56..58].try_into().unwrap()));
        }
        59 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[56..58].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[58], 0]));
        }
        60 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[56..60].try_into().unwrap()));
        }
        61 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[56..60].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[60], 0]));
        }
        62 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[56..60].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[60..62].try_into().unwrap()));
        }
        63 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[56..60].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes(buf[60..62].try_into().unwrap()));
            checksum += u64::from(u16::from_ne_bytes([buf[62], 0]));
        }
        64 => {
            checksum += u64::from(u32::from_ne_bytes(buf[0..4].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[4..8].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[8..12].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[12..16].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[16..20].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[20..24].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[24..28].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[28..32].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[32..36].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[36..40].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[40..44].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[44..48].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[48..52].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[52..56].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[56..60].try_into().unwrap()));
            checksum += u64::from(u32::from_ne_bytes(buf[60..64].try_into().unwrap()));
        }
        _ => {}
    }
    checksum
}

#[cfg(test)]
mod tests {
    use crate::checksum::internet_checksum;

    #[rustfmt::skip]
    #[allow(clippy::unusual_byte_groupings)]
    static CHECK_CHECKSUM: &[u8] = &[
        // Version & IHL
        0x45,
        // DSCP & ECN
        0b001010_00,
        // Total length
        0x00, 0x14,
        // Identification
        0x12, 0x34,
        // Flags & Fragment offset
        0x00, 0x00,
        // TTL
        0x01,
        // Protocol
        0x06,
        // Header Checksum
        0xA9, 0x86,
        // Source
        0x7f, 0x00, 0x00, 0x1,
        // Destination
        0x7f, 0x00, 0x00, 0x1,
    ];

    #[rustfmt::skip]
    #[allow(clippy::unusual_byte_groupings)]
    static CALC_CHECKSUM: &[u8] = &[
        // Version & IHL
        0x45,
        // DSCP & ECN
        0b001010_00,
        // Total length
        0x00, 0x14,
        // Identification
        0x12, 0x34,
        // Flags & Fragment offset
        0x00, 0x00,
        // TTL
        0x01,
        // Protocol
        0x06,
        // Header Checksum
        0x00, 0x00,
        // Source
        0x7f, 0x00, 0x00, 0x1,
        // Destination
        0x7f, 0x00, 0x00, 0x1,
    ];

    static BYTES_550: &[u8; 550] = &[0xFF; 550];
    static BYTES_1500: &[u8; 1500] = &[0xFF; 1500];

    #[test]
    fn test_checksum() {
        assert_eq!(internet_checksum::<8>(0, CHECK_CHECKSUM), 0);
        assert_eq!(internet_checksum::<8>(0, CALC_CHECKSUM), 0xA986);
    }

    #[test]
    fn test_checksum_odd() {
        assert_eq!(internet_checksum::<8>(0, &[0xFA_u8.to_le()]), !0xFA00);
        assert_eq!(
            internet_checksum::<8>(0, &[0xFA_u8.to_le(), 0xFA_u8.to_le(), 0xFA_u8.to_le()]),
            !0xF4FB
        );
    }

    #[test]
    fn test_checksum_550() {
        assert_eq!(internet_checksum::<8>(0, BYTES_550), 0);
    }

    #[test]
    fn test_checksum_1500() {
        assert_eq!(internet_checksum::<8>(0, BYTES_1500), 0);
    }
}