// Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![cfg_attr(coverage_nightly, feature(coverage_attribute))] pub mod bytes; mod codec; pub mod datagram; pub mod event; #[cfg(feature = "build-fuzzing-corpus")] mod fuzz; pub mod header; pub mod hrtime; mod incrdecoder; pub mod log; pub mod qlog; pub mod tos; use std::fmt::Write as _; use enum_map::Enum; use strum::Display; #[cfg(feature = "build-fuzzing-corpus")] pub use self::fuzz::write_item_to_fuzzing_corpus; pub use self::{ bytes::Bytes, codec::{Buffer, Decoder, Encoder, MAX_VARINT}, datagram::Datagram, header::Header, incrdecoder::{IncrementalDecoderBuffer, IncrementalDecoderIgnore, IncrementalDecoderUint}, tos::{Dscp, Ecn, Tos}, }; #[must_use] pub fn hex>(buf: A) -> String { let mut ret = String::with_capacity(buf.as_ref().len() * 2); for b in buf.as_ref() { write!(&mut ret, "{b:02x}").expect("write OK"); } ret } #[must_use] pub fn hex_snip_middle>(buf: A) -> String { const SHOW_LEN: usize = 8; let buf = buf.as_ref(); if buf.len() <= SHOW_LEN * 2 { hex_with_len(buf) } else { let mut ret = String::with_capacity(SHOW_LEN * 2 + 16); write!(&mut ret, "[{}]: ", buf.len()).expect("write OK"); for b in &buf[..SHOW_LEN] { write!(&mut ret, "{b:02x}").expect("write OK"); } ret.push_str(".."); for b in &buf[buf.len() - SHOW_LEN..] { write!(&mut ret, "{b:02x}").expect("write OK"); } ret } } #[must_use] pub fn hex_with_len>(buf: A) -> String { let buf = buf.as_ref(); let mut ret = String::with_capacity(10 + buf.len() * 2); write!(&mut ret, "[{}]: ", buf.len()).expect("write OK"); for b in buf { write!(&mut ret, "{b:02x}").expect("write OK"); } ret } #[must_use] pub const fn const_max(a: usize, b: usize) -> usize { [a, b][(a <= b) as usize] } #[must_use] pub const fn const_min(a: usize, b: usize) -> usize { [a, b][(a > b) as usize] } #[derive(Debug, PartialEq, Eq, Copy, Clone, Enum, Display)] /// Client or Server. pub enum Role { Client, Server, } impl Role { #[must_use] pub const fn remote(self) -> Self { match self { Self::Client => Self::Server, Self::Server => Self::Client, } } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MessageType { Request, Response, } #[cfg(test)] #[cfg_attr(coverage_nightly, coverage(off))] mod tests { use super::*; #[test] fn hex_output() { assert_eq!(hex([]), ""); assert_eq!(hex([0xab, 0xcd]), "abcd"); } #[test] fn const_minmax() { for (a, b, min, max) in [(2, 5, 2, 5), (5, 2, 2, 5), (3, 3, 3, 3)] { assert_eq!(const_min(a, b), min); assert_eq!(const_max(a, b), max); } } #[test] fn hex_snip_middle_boundary() { let short: Vec = (0..16).collect(); assert!(hex_snip_middle(&short).ends_with("0e0f")); let long: Vec = (0..20).collect(); let s = hex_snip_middle(&long); assert!(s.starts_with("[20]: 00") && s.contains("..") && s.ends_with("1213")); } }