1use std::cmp::Ordering;
7use std::fmt;
8use std::time::Instant;
9
10use arrayvec::ArrayVec;
11use nom::bytes::complete::take;
12use nom::number::complete::{be_u16, be_u8};
13use nom::IResult;
14
15use crate::buffer::Buf;
16use crate::time_tricks::InstantExt;
17use crate::SeededRng;
18
19pub type NamedGroupVec = ArrayVec<NamedGroup, { NamedGroup::supported().len() }>;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub struct Random {
35 pub bytes: [u8; 32],
37}
38
39impl Random {
40 pub fn new(rng: &mut SeededRng) -> Self {
42 Self {
43 bytes: rng.random(),
44 }
45 }
46
47 pub fn new_with_time(now: Instant, rng: &mut SeededRng) -> Self {
49 let gmt_duration = now.to_unix_duration();
50 let gmt_unix_time = gmt_duration.as_secs() as u32;
52
53 let random_bytes: [u8; 28] = rng.random();
54
55 let mut bytes = [0u8; 32];
56 bytes[..4].copy_from_slice(&gmt_unix_time.to_be_bytes());
57 bytes[4..].copy_from_slice(&random_bytes);
58
59 Self { bytes }
60 }
61
62 pub fn parse(input: &[u8]) -> IResult<&[u8], Random> {
64 let (input, data) = take(32_usize)(input)?;
65 let mut bytes = [0u8; 32];
66 bytes.copy_from_slice(data);
67 Ok((input, Random { bytes }))
68 }
69
70 pub fn serialize(&self, output: &mut Buf) {
72 output.extend_from_slice(&self.bytes);
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub enum NamedGroup {
86 Sect163k1,
88 Sect163r1,
90 Sect163r2,
92 Sect193r1,
94 Sect193r2,
96 Sect233k1,
98 Sect233r1,
100 Sect239k1,
102 Sect283k1,
104 Sect283r1,
106 Sect409k1,
108 Sect409r1,
110 Sect571k1,
112 Sect571r1,
114 Secp160k1,
116 Secp160r1,
118 Secp160r2,
120 Secp192k1,
122 Secp192r1,
124 Secp224k1,
126 Secp224r1,
128 Secp256k1,
130 Secp256r1,
132 Secp384r1,
134 Secp521r1,
136 X25519,
138 X448,
140 Unknown(u16),
142}
143
144impl NamedGroup {
145 pub fn from_u16(value: u16) -> Self {
147 match value {
148 1 => NamedGroup::Sect163k1,
149 2 => NamedGroup::Sect163r1,
150 3 => NamedGroup::Sect163r2,
151 4 => NamedGroup::Sect193r1,
152 5 => NamedGroup::Sect193r2,
153 6 => NamedGroup::Sect233k1,
154 7 => NamedGroup::Sect233r1,
155 8 => NamedGroup::Sect239k1,
156 9 => NamedGroup::Sect283k1,
157 10 => NamedGroup::Sect283r1,
158 11 => NamedGroup::Sect409k1,
159 12 => NamedGroup::Sect409r1,
160 13 => NamedGroup::Sect571k1,
161 14 => NamedGroup::Sect571r1,
162 15 => NamedGroup::Secp160k1,
163 16 => NamedGroup::Secp160r1,
164 17 => NamedGroup::Secp160r2,
165 18 => NamedGroup::Secp192k1,
166 19 => NamedGroup::Secp192r1,
167 20 => NamedGroup::Secp224k1,
168 21 => NamedGroup::Secp224r1,
169 22 => NamedGroup::Secp256k1,
170 23 => NamedGroup::Secp256r1,
171 24 => NamedGroup::Secp384r1,
172 25 => NamedGroup::Secp521r1,
173 29 => NamedGroup::X25519,
174 30 => NamedGroup::X448,
175 _ => NamedGroup::Unknown(value),
176 }
177 }
178
179 pub fn as_u16(&self) -> u16 {
181 match self {
182 NamedGroup::Sect163k1 => 1,
183 NamedGroup::Sect163r1 => 2,
184 NamedGroup::Sect163r2 => 3,
185 NamedGroup::Sect193r1 => 4,
186 NamedGroup::Sect193r2 => 5,
187 NamedGroup::Sect233k1 => 6,
188 NamedGroup::Sect233r1 => 7,
189 NamedGroup::Sect239k1 => 8,
190 NamedGroup::Sect283k1 => 9,
191 NamedGroup::Sect283r1 => 10,
192 NamedGroup::Sect409k1 => 11,
193 NamedGroup::Sect409r1 => 12,
194 NamedGroup::Sect571k1 => 13,
195 NamedGroup::Sect571r1 => 14,
196 NamedGroup::Secp160k1 => 15,
197 NamedGroup::Secp160r1 => 16,
198 NamedGroup::Secp160r2 => 17,
199 NamedGroup::Secp192k1 => 18,
200 NamedGroup::Secp192r1 => 19,
201 NamedGroup::Secp224k1 => 20,
202 NamedGroup::Secp224r1 => 21,
203 NamedGroup::Secp256k1 => 22,
204 NamedGroup::Secp256r1 => 23,
205 NamedGroup::Secp384r1 => 24,
206 NamedGroup::Secp521r1 => 25,
207 NamedGroup::X25519 => 29,
208 NamedGroup::X448 => 30,
209 NamedGroup::Unknown(value) => *value,
210 }
211 }
212
213 pub fn parse(input: &[u8]) -> IResult<&[u8], NamedGroup> {
215 let (input, value) = be_u16(input)?;
216 Ok((input, NamedGroup::from_u16(value)))
217 }
218
219 pub fn is_supported(&self) -> bool {
221 Self::supported().contains(self)
222 }
223
224 pub const fn all() -> &'static [NamedGroup; 27] {
226 &[
227 NamedGroup::Sect163k1,
228 NamedGroup::Sect163r1,
229 NamedGroup::Sect163r2,
230 NamedGroup::Sect193r1,
231 NamedGroup::Sect193r2,
232 NamedGroup::Sect233k1,
233 NamedGroup::Sect233r1,
234 NamedGroup::Sect239k1,
235 NamedGroup::Sect283k1,
236 NamedGroup::Sect283r1,
237 NamedGroup::Sect409k1,
238 NamedGroup::Sect409r1,
239 NamedGroup::Sect571k1,
240 NamedGroup::Sect571r1,
241 NamedGroup::Secp160k1,
242 NamedGroup::Secp160r1,
243 NamedGroup::Secp160r2,
244 NamedGroup::Secp192k1,
245 NamedGroup::Secp192r1,
246 NamedGroup::Secp224k1,
247 NamedGroup::Secp224r1,
248 NamedGroup::Secp256k1,
249 NamedGroup::Secp256r1,
250 NamedGroup::Secp384r1,
251 NamedGroup::Secp521r1,
252 NamedGroup::X25519,
253 NamedGroup::X448,
254 ]
255 }
256
257 pub const fn supported() -> &'static [NamedGroup; 4] {
259 &[
260 NamedGroup::X25519,
261 NamedGroup::Secp256r1,
262 NamedGroup::Secp384r1,
263 NamedGroup::Secp521r1,
264 ]
265 }
266}
267
268#[derive(Debug, Clone, Copy, PartialEq, Eq)]
277#[allow(non_camel_case_types)]
278pub enum HashAlgorithm {
279 None,
281 MD5,
283 SHA1,
285 SHA224,
287 SHA256,
289 SHA384,
291 SHA512,
293 Unknown(u8),
295}
296
297impl Default for HashAlgorithm {
298 fn default() -> Self {
299 Self::Unknown(0)
300 }
301}
302
303impl HashAlgorithm {
304 pub fn from_u8(value: u8) -> Self {
306 match value {
307 0 => HashAlgorithm::None,
308 1 => HashAlgorithm::MD5,
309 2 => HashAlgorithm::SHA1,
310 3 => HashAlgorithm::SHA224,
311 4 => HashAlgorithm::SHA256,
312 5 => HashAlgorithm::SHA384,
313 6 => HashAlgorithm::SHA512,
314 _ => HashAlgorithm::Unknown(value),
315 }
316 }
317
318 pub fn as_u8(&self) -> u8 {
320 match self {
321 HashAlgorithm::None => 0,
322 HashAlgorithm::MD5 => 1,
323 HashAlgorithm::SHA1 => 2,
324 HashAlgorithm::SHA224 => 3,
325 HashAlgorithm::SHA256 => 4,
326 HashAlgorithm::SHA384 => 5,
327 HashAlgorithm::SHA512 => 6,
328 HashAlgorithm::Unknown(value) => *value,
329 }
330 }
331
332 pub fn parse(input: &[u8]) -> IResult<&[u8], HashAlgorithm> {
334 let (input, value) = be_u8(input)?;
335 Ok((input, HashAlgorithm::from_u8(value)))
336 }
337
338 pub fn output_len(&self) -> usize {
340 match self {
341 HashAlgorithm::None => 0,
342 HashAlgorithm::MD5 => 16,
343 HashAlgorithm::SHA1 => 20,
344 HashAlgorithm::SHA224 => 28,
345 HashAlgorithm::SHA256 => 32,
346 HashAlgorithm::SHA384 => 48,
347 HashAlgorithm::SHA512 => 64,
348 HashAlgorithm::Unknown(_) => 0,
349 }
350 }
351}
352
353#[derive(Debug, Clone, Copy, PartialEq, Eq)]
362#[allow(non_camel_case_types)]
363pub enum SignatureAlgorithm {
364 Anonymous,
366 RSA,
368 DSA,
370 ECDSA,
372 Unknown(u8),
374}
375
376impl Default for SignatureAlgorithm {
377 fn default() -> Self {
378 Self::Unknown(0)
379 }
380}
381
382impl SignatureAlgorithm {
383 pub fn from_u8(value: u8) -> Self {
385 match value {
386 0 => SignatureAlgorithm::Anonymous,
387 1 => SignatureAlgorithm::RSA,
388 2 => SignatureAlgorithm::DSA,
389 3 => SignatureAlgorithm::ECDSA,
390 _ => SignatureAlgorithm::Unknown(value),
391 }
392 }
393
394 pub fn as_u8(&self) -> u8 {
396 match self {
397 SignatureAlgorithm::Anonymous => 0,
398 SignatureAlgorithm::RSA => 1,
399 SignatureAlgorithm::DSA => 2,
400 SignatureAlgorithm::ECDSA => 3,
401 SignatureAlgorithm::Unknown(value) => *value,
402 }
403 }
404
405 pub fn parse(input: &[u8]) -> IResult<&[u8], SignatureAlgorithm> {
407 let (input, value) = be_u8(input)?;
408 Ok((input, SignatureAlgorithm::from_u8(value)))
409 }
410}
411
412#[derive(Debug, Clone, Copy, PartialEq, Eq)]
421pub enum ContentType {
422 ChangeCipherSpec,
424 Alert,
426 Handshake,
428 ApplicationData,
430 Ack,
432 Unknown(u8),
434}
435
436impl Default for ContentType {
437 fn default() -> Self {
438 Self::Unknown(0)
439 }
440}
441
442impl ContentType {
443 pub fn from_u8(value: u8) -> Self {
445 match value {
446 20 => ContentType::ChangeCipherSpec,
447 21 => ContentType::Alert,
448 22 => ContentType::Handshake,
449 23 => ContentType::ApplicationData,
450 26 => ContentType::Ack,
451 _ => ContentType::Unknown(value),
452 }
453 }
454
455 pub fn as_u8(&self) -> u8 {
457 match self {
458 ContentType::ChangeCipherSpec => 20,
459 ContentType::Alert => 21,
460 ContentType::Handshake => 22,
461 ContentType::ApplicationData => 23,
462 ContentType::Ack => 26,
463 ContentType::Unknown(value) => *value,
464 }
465 }
466
467 pub fn parse(input: &[u8]) -> IResult<&[u8], ContentType> {
469 let (input, byte) = be_u8(input)?;
470 Ok((input, Self::from_u8(byte)))
471 }
472}
473
474#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
483pub struct Sequence {
484 pub epoch: u16,
486 pub sequence_number: u64,
488}
489
490impl Sequence {
491 pub fn new(epoch: u16) -> Self {
493 Self {
494 epoch,
495 sequence_number: 0,
496 }
497 }
498}
499
500impl fmt::Display for Sequence {
501 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502 write!(
503 f,
504 "[epoch: {}, sequence_number: {}]",
505 self.epoch, self.sequence_number,
506 )
507 }
508}
509
510impl Ord for Sequence {
511 fn cmp(&self, other: &Self) -> Ordering {
512 if self.epoch < other.epoch {
513 Ordering::Less
514 } else if self.epoch > other.epoch {
515 Ordering::Greater
516 } else {
517 self.sequence_number.cmp(&other.sequence_number)
518 }
519 }
520}
521
522impl PartialOrd for Sequence {
523 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
524 Some(self.cmp(other))
525 }
526}
527
528#[derive(Debug, Clone, Copy, PartialEq, Eq)]
538#[allow(non_camel_case_types)]
539pub enum SignatureScheme {
540 ECDSA_SECP256R1_SHA256,
542 ECDSA_SECP384R1_SHA384,
544 ECDSA_SECP521R1_SHA512,
546 ED25519,
548 ED448,
550 RSA_PSS_RSAE_SHA256,
552 RSA_PSS_RSAE_SHA384,
554 RSA_PSS_RSAE_SHA512,
556 RSA_PSS_PSS_SHA256,
558 RSA_PSS_PSS_SHA384,
560 RSA_PSS_PSS_SHA512,
562 RSA_PKCS1_SHA256,
564 RSA_PKCS1_SHA384,
566 RSA_PKCS1_SHA512,
568 Unknown(u16),
570}
571
572impl SignatureScheme {
573 pub fn from_u16(value: u16) -> Self {
575 match value {
576 0x0403 => SignatureScheme::ECDSA_SECP256R1_SHA256,
577 0x0503 => SignatureScheme::ECDSA_SECP384R1_SHA384,
578 0x0603 => SignatureScheme::ECDSA_SECP521R1_SHA512,
579 0x0807 => SignatureScheme::ED25519,
580 0x0808 => SignatureScheme::ED448,
581 0x0804 => SignatureScheme::RSA_PSS_RSAE_SHA256,
582 0x0805 => SignatureScheme::RSA_PSS_RSAE_SHA384,
583 0x0806 => SignatureScheme::RSA_PSS_RSAE_SHA512,
584 0x0809 => SignatureScheme::RSA_PSS_PSS_SHA256,
585 0x080a => SignatureScheme::RSA_PSS_PSS_SHA384,
586 0x080b => SignatureScheme::RSA_PSS_PSS_SHA512,
587 0x0401 => SignatureScheme::RSA_PKCS1_SHA256,
588 0x0501 => SignatureScheme::RSA_PKCS1_SHA384,
589 0x0601 => SignatureScheme::RSA_PKCS1_SHA512,
590 _ => SignatureScheme::Unknown(value),
591 }
592 }
593
594 pub fn as_u16(&self) -> u16 {
596 match self {
597 SignatureScheme::ECDSA_SECP256R1_SHA256 => 0x0403,
598 SignatureScheme::ECDSA_SECP384R1_SHA384 => 0x0503,
599 SignatureScheme::ECDSA_SECP521R1_SHA512 => 0x0603,
600 SignatureScheme::ED25519 => 0x0807,
601 SignatureScheme::ED448 => 0x0808,
602 SignatureScheme::RSA_PSS_RSAE_SHA256 => 0x0804,
603 SignatureScheme::RSA_PSS_RSAE_SHA384 => 0x0805,
604 SignatureScheme::RSA_PSS_RSAE_SHA512 => 0x0806,
605 SignatureScheme::RSA_PSS_PSS_SHA256 => 0x0809,
606 SignatureScheme::RSA_PSS_PSS_SHA384 => 0x080a,
607 SignatureScheme::RSA_PSS_PSS_SHA512 => 0x080b,
608 SignatureScheme::RSA_PKCS1_SHA256 => 0x0401,
609 SignatureScheme::RSA_PKCS1_SHA384 => 0x0501,
610 SignatureScheme::RSA_PKCS1_SHA512 => 0x0601,
611 SignatureScheme::Unknown(value) => *value,
612 }
613 }
614
615 pub fn parse(input: &[u8]) -> IResult<&[u8], SignatureScheme> {
617 let (input, value) = be_u16(input)?;
618 Ok((input, SignatureScheme::from_u16(value)))
619 }
620
621 pub fn is_supported(&self) -> bool {
623 Self::SUPPORTED.contains(self)
624 }
625
626 pub fn all() -> &'static [SignatureScheme] {
628 &[
629 SignatureScheme::ECDSA_SECP256R1_SHA256,
630 SignatureScheme::ECDSA_SECP384R1_SHA384,
631 SignatureScheme::ECDSA_SECP521R1_SHA512,
632 SignatureScheme::ED25519,
633 SignatureScheme::ED448,
634 SignatureScheme::RSA_PSS_RSAE_SHA256,
635 SignatureScheme::RSA_PSS_RSAE_SHA384,
636 SignatureScheme::RSA_PSS_RSAE_SHA512,
637 SignatureScheme::RSA_PSS_PSS_SHA256,
638 SignatureScheme::RSA_PSS_PSS_SHA384,
639 SignatureScheme::RSA_PSS_PSS_SHA512,
640 SignatureScheme::RSA_PKCS1_SHA256,
641 SignatureScheme::RSA_PKCS1_SHA384,
642 SignatureScheme::RSA_PKCS1_SHA512,
643 ]
644 }
645
646 const SUPPORTED: &[SignatureScheme] = &[
647 SignatureScheme::ECDSA_SECP256R1_SHA256,
648 SignatureScheme::ECDSA_SECP384R1_SHA384,
649 ];
650
651 pub fn supported() -> ArrayVec<SignatureScheme, 2> {
653 let mut schemes = ArrayVec::new();
654 schemes.push(SignatureScheme::ECDSA_SECP256R1_SHA256);
655 schemes.push(SignatureScheme::ECDSA_SECP384R1_SHA384);
656 schemes
657 }
658
659 pub fn hash_algorithm(&self) -> HashAlgorithm {
661 match self {
662 SignatureScheme::ECDSA_SECP256R1_SHA256
663 | SignatureScheme::RSA_PSS_RSAE_SHA256
664 | SignatureScheme::RSA_PSS_PSS_SHA256
665 | SignatureScheme::RSA_PKCS1_SHA256 => HashAlgorithm::SHA256,
666 SignatureScheme::ECDSA_SECP384R1_SHA384
667 | SignatureScheme::RSA_PSS_RSAE_SHA384
668 | SignatureScheme::RSA_PSS_PSS_SHA384
669 | SignatureScheme::RSA_PKCS1_SHA384 => HashAlgorithm::SHA384,
670 SignatureScheme::ECDSA_SECP521R1_SHA512
671 | SignatureScheme::RSA_PSS_RSAE_SHA512
672 | SignatureScheme::RSA_PSS_PSS_SHA512
673 | SignatureScheme::RSA_PKCS1_SHA512 => HashAlgorithm::SHA512,
674 SignatureScheme::ED25519 | SignatureScheme::ED448 => HashAlgorithm::None,
676 SignatureScheme::Unknown(_) => HashAlgorithm::Unknown(0),
677 }
678 }
679}
680
681#[derive(Debug, Clone, Copy, PartialEq, Eq)]
690#[allow(non_camel_case_types)]
691pub enum Dtls13CipherSuite {
692 AES_128_GCM_SHA256,
694 AES_256_GCM_SHA384,
696 CHACHA20_POLY1305_SHA256,
698 AES_128_CCM_SHA256,
700 AES_128_CCM_8_SHA256,
702 Unknown(u16),
704}
705
706impl Dtls13CipherSuite {
707 pub fn from_u16(value: u16) -> Self {
709 match value {
710 0x1301 => Dtls13CipherSuite::AES_128_GCM_SHA256,
711 0x1302 => Dtls13CipherSuite::AES_256_GCM_SHA384,
712 0x1303 => Dtls13CipherSuite::CHACHA20_POLY1305_SHA256,
713 0x1304 => Dtls13CipherSuite::AES_128_CCM_SHA256,
714 0x1305 => Dtls13CipherSuite::AES_128_CCM_8_SHA256,
715 _ => Dtls13CipherSuite::Unknown(value),
716 }
717 }
718
719 pub fn as_u16(&self) -> u16 {
721 match self {
722 Dtls13CipherSuite::AES_128_GCM_SHA256 => 0x1301,
723 Dtls13CipherSuite::AES_256_GCM_SHA384 => 0x1302,
724 Dtls13CipherSuite::CHACHA20_POLY1305_SHA256 => 0x1303,
725 Dtls13CipherSuite::AES_128_CCM_SHA256 => 0x1304,
726 Dtls13CipherSuite::AES_128_CCM_8_SHA256 => 0x1305,
727 Dtls13CipherSuite::Unknown(value) => *value,
728 }
729 }
730
731 pub fn parse(input: &[u8]) -> IResult<&[u8], Dtls13CipherSuite> {
733 let (input, value) = be_u16(input)?;
734 Ok((input, Dtls13CipherSuite::from_u16(value)))
735 }
736
737 pub fn hash_algorithm(&self) -> HashAlgorithm {
739 match self {
740 Dtls13CipherSuite::AES_128_GCM_SHA256
741 | Dtls13CipherSuite::CHACHA20_POLY1305_SHA256
742 | Dtls13CipherSuite::AES_128_CCM_SHA256
743 | Dtls13CipherSuite::AES_128_CCM_8_SHA256 => HashAlgorithm::SHA256,
744 Dtls13CipherSuite::AES_256_GCM_SHA384 => HashAlgorithm::SHA384,
745 Dtls13CipherSuite::Unknown(_) => HashAlgorithm::Unknown(0),
746 }
747 }
748
749 pub fn is_supported(&self) -> bool {
751 Self::supported().contains(self)
752 }
753
754 pub fn all() -> &'static [Dtls13CipherSuite] {
756 &[
757 Dtls13CipherSuite::AES_128_GCM_SHA256,
758 Dtls13CipherSuite::AES_256_GCM_SHA384,
759 Dtls13CipherSuite::CHACHA20_POLY1305_SHA256,
760 Dtls13CipherSuite::AES_128_CCM_SHA256,
761 Dtls13CipherSuite::AES_128_CCM_8_SHA256,
762 ]
763 }
764
765 pub fn supported() -> &'static [Dtls13CipherSuite] {
767 &[
768 Dtls13CipherSuite::AES_128_GCM_SHA256,
769 Dtls13CipherSuite::AES_256_GCM_SHA384,
770 ]
771 }
772
773 pub fn verify_data_length(&self) -> usize {
775 self.hash_algorithm().output_len()
776 }
777}
778
779#[derive(Debug, Clone, Copy, PartialEq, Eq)]
787pub enum ProtocolVersion {
788 DTLS1_0,
790 DTLS1_2,
792 DTLS1_3,
794 Unknown(u16),
796}
797
798impl Default for ProtocolVersion {
799 fn default() -> Self {
800 Self::Unknown(0)
801 }
802}
803
804impl ProtocolVersion {
805 pub fn as_u16(&self) -> u16 {
807 match self {
808 ProtocolVersion::DTLS1_0 => 0xFEFF,
809 ProtocolVersion::DTLS1_2 => 0xFEFD,
810 ProtocolVersion::DTLS1_3 => 0xFEFC,
811 ProtocolVersion::Unknown(value) => *value,
812 }
813 }
814
815 pub fn parse(input: &[u8]) -> IResult<&[u8], ProtocolVersion> {
817 let (input, version) = be_u16(input)?;
818 let protocol_version = match version {
819 0xFEFF => ProtocolVersion::DTLS1_0,
820 0xFEFD => ProtocolVersion::DTLS1_2,
821 0xFEFC => ProtocolVersion::DTLS1_3,
822 _ => ProtocolVersion::Unknown(version),
823 };
824 Ok((input, protocol_version))
825 }
826
827 pub fn serialize(&self, output: &mut crate::buffer::Buf) {
829 output.extend_from_slice(&self.as_u16().to_be_bytes());
830 }
831}
832
833#[derive(Debug, Clone, Copy, PartialEq, Eq)]
842pub enum CompressionMethod {
843 Null,
845 Deflate,
847 Unknown(u8),
849}
850
851impl Default for CompressionMethod {
852 fn default() -> Self {
853 Self::Unknown(0)
854 }
855}
856
857impl CompressionMethod {
858 pub fn from_u8(value: u8) -> Self {
860 match value {
861 0x00 => CompressionMethod::Null,
862 0x01 => CompressionMethod::Deflate,
863 _ => CompressionMethod::Unknown(value),
864 }
865 }
866
867 pub fn is_supported(&self) -> bool {
869 Self::supported().contains(self)
870 }
871
872 pub const fn all() -> &'static [CompressionMethod; 2] {
874 &[CompressionMethod::Null, CompressionMethod::Deflate]
875 }
876
877 pub const fn supported() -> &'static [CompressionMethod; 1] {
883 &[CompressionMethod::Null]
884 }
885
886 pub fn as_u8(&self) -> u8 {
888 match self {
889 CompressionMethod::Null => 0x00,
890 CompressionMethod::Deflate => 0x01,
891 CompressionMethod::Unknown(value) => *value,
892 }
893 }
894
895 pub fn parse(input: &[u8]) -> IResult<&[u8], CompressionMethod> {
897 let (input, value) = be_u8(input)?;
898 Ok((input, CompressionMethod::from_u8(value)))
899 }
900}
901
902#[cfg(test)]
903mod tests {
904 use super::*;
905
906 #[test]
907 fn random_parse() {
908 let data = [
909 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
910 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
911 0x1D, 0x1E, 0x1F, 0x20,
912 ];
913
914 let expected = Random { bytes: data };
915
916 let (_, parsed) = Random::parse(&data).unwrap();
917 assert_eq!(parsed, expected);
918 }
919
920 #[test]
921 fn random_serialize() {
922 let random = Random {
923 bytes: [
924 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
925 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
926 0x1D, 0x1E, 0x1F, 0x20,
927 ],
928 };
929
930 let mut serialized = Buf::new();
931 random.serialize(&mut serialized);
932
933 assert_eq!(&*serialized, &random.bytes);
934 }
935
936 #[test]
937 fn compression_supported_has_only_null() {
938 let supported = CompressionMethod::supported();
939 assert_eq!(
940 supported,
941 &[CompressionMethod::Null],
942 "Only Null compression should be supported"
943 );
944 }
945
946 #[test]
947 fn random_parse_roundtrip() {
948 let data = [
949 0x5F, 0x37, 0xA9, 0x4B, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
951 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
952 ];
953
954 let (_, parsed) = Random::parse(&data).unwrap();
955 let mut serialized = Buf::new();
956 parsed.serialize(&mut serialized);
957
958 assert_eq!(&*serialized, &data[..]);
959 }
960}