conmonrs/streaming_server/
stream_protocol.rs1use std::{fmt, time::Duration};
5
6pub(super) const STREAM_TYPE_HEADER: &str = "streamType";
8
9pub(super) const STREAM_CREATION_TIMEOUT: Duration = Duration::from_secs(30);
12
13pub(super) fn first_supported<'a, T: Copy>(
16 requested: impl IntoIterator<Item = &'a str>,
17 supported: &[(&'static str, T)],
18) -> Option<(T, &'static str)> {
19 requested.into_iter().find_map(|protocol| {
20 supported
21 .iter()
22 .find_map(|(name, value)| (*name == protocol).then_some((*value, *name)))
23 })
24}
25
26const MAX_LOGGED_LEN: usize = 64;
28
29pub(super) struct ClientStr<'a>(pub &'a str);
32
33impl fmt::Debug for ClientStr<'_> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self.0.char_indices().nth(MAX_LOGGED_LEN) {
36 Some((end, _)) => write!(f, "{:?}...", &self.0[..end]),
37 None => write!(f, "{:?}", self.0),
38 }
39 }
40}
41
42pub(super) struct ClientBytes<'a>(pub &'a [u8]);
44
45impl fmt::Debug for ClientBytes<'_> {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 let end = self.0.len().min(MAX_LOGGED_LEN);
48 write!(f, "\"{}\"", self.0[..end].escape_ascii())?;
49 if end < self.0.len() {
50 write!(f, "...")?;
51 }
52 Ok(())
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn client_strings_get_escaped_and_cut_off() {
62 assert_eq!(format!("{:?}", ClientStr("a\nb")), r#""a\nb""#);
63 let long = "x".repeat(MAX_LOGGED_LEN + 1);
64 assert_eq!(
65 format!("{:?}", ClientStr(&long)),
66 format!("{:?}...", &long[..MAX_LOGGED_LEN])
67 );
68 assert_eq!(
69 format!("{:?}", ClientStr(&long[1..])),
70 format!("{:?}", &long[1..])
71 );
72 let wide = "\u{e9}".repeat(MAX_LOGGED_LEN + 1);
74 assert!(format!("{:?}", ClientStr(&wide)).ends_with("\"..."));
75
76 assert_eq!(format!("{:?}", ClientBytes(b"a\n\xff")), r#""a\n\xff""#);
77 assert_eq!(
78 format!("{:?}", ClientBytes(long.as_bytes())),
79 format!("\"{}\"...", &long[..MAX_LOGGED_LEN])
80 );
81 }
82}