• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

butlergroup / rust-libp2p / 18610913338

18 Oct 2025 04:41AM UTC coverage: 78.379% (+2.5%) from 75.842%
18610913338

push

github

butlergroup
	modified:   .github/workflows/ci.yml

36944 of 47135 relevant lines covered (78.38%)

37728.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.48
/swarm/src/stream_protocol.rs
1
use std::{
2
    fmt,
3
    hash::{Hash, Hasher},
4
    sync::Arc,
5
};
6

7
use either::Either;
8

9
/// Identifies a protocol for a stream.
10
///
11
/// libp2p nodes use stream protocols to negotiate what to do with a newly opened stream.
12
/// Stream protocols are string-based and must start with a forward slash: `/`.
13
#[derive(Clone, Eq)]
14
pub struct StreamProtocol {
15
    inner: Either<&'static str, Arc<str>>,
16
}
17

18
impl StreamProtocol {
19
    /// Construct a new protocol from a static string slice.
20
    ///
21
    /// # Panics
22
    ///
23
    /// This function panics if the protocol does not start with a forward slash: `/`.
24
    pub const fn new(s: &'static str) -> Self {
106✔
25
        match s.as_bytes() {
106✔
26
            [b'/', ..] => {}
106✔
27
            _ => panic!("Protocols should start with a /"),
×
28
        }
29

30
        StreamProtocol {
106✔
31
            inner: Either::Left(s),
106✔
32
        }
106✔
33
    }
106✔
34

35
    /// Attempt to construct a protocol from an owned string.
36
    ///
37
    /// This function will fail if the protocol does not start with a forward slash: `/`.
38
    /// Where possible, you should use [`StreamProtocol::new`] instead to avoid allocations.
39
    pub fn try_from_owned(protocol: String) -> Result<Self, InvalidProtocol> {
45,784✔
40
        if !protocol.starts_with('/') {
45,784✔
41
            return Err(InvalidProtocol::missing_forward_slash());
×
42
        }
45,784✔
43

44
        Ok(StreamProtocol {
45,784✔
45
            // FIXME: Can we somehow reuse the
45,784✔
46
            // allocation from the owned string?
45,784✔
47
            inner: Either::Right(Arc::from(protocol)),
45,784✔
48
        })
45,784✔
49
    }
45,784✔
50
}
51

52
impl AsRef<str> for StreamProtocol {
53
    fn as_ref(&self) -> &str {
1,595,995✔
54
        either::for_both!(&self.inner, s => s)
1,595,995✔
55
    }
1,595,995✔
56
}
57

58
impl fmt::Debug for StreamProtocol {
59
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1✔
60
        either::for_both!(&self.inner, s => s.fmt(f))
1✔
61
    }
1✔
62
}
63

64
impl fmt::Display for StreamProtocol {
65
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
591✔
66
        self.inner.fmt(f)
591✔
67
    }
591✔
68
}
69

70
impl PartialEq<&str> for StreamProtocol {
71
    fn eq(&self, other: &&str) -> bool {
20✔
72
        self.as_ref() == *other
20✔
73
    }
20✔
74
}
75

76
impl PartialEq<StreamProtocol> for &str {
77
    fn eq(&self, other: &StreamProtocol) -> bool {
68✔
78
        *self == other.as_ref()
68✔
79
    }
68✔
80
}
81

82
impl PartialEq for StreamProtocol {
83
    fn eq(&self, other: &Self) -> bool {
259✔
84
        self.as_ref() == other.as_ref()
259✔
85
    }
259✔
86
}
87

88
impl Hash for StreamProtocol {
89
    fn hash<H: Hasher>(&self, state: &mut H) {
2,487✔
90
        self.as_ref().hash(state)
2,487✔
91
    }
2,487✔
92
}
93

94
#[derive(Debug)]
95
pub struct InvalidProtocol {
96
    // private field to prevent construction outside of this module
97
    _private: (),
98
}
99

100
impl InvalidProtocol {
101
    pub(crate) fn missing_forward_slash() -> Self {
×
102
        InvalidProtocol { _private: () }
×
103
    }
×
104
}
105

106
impl fmt::Display for InvalidProtocol {
107
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
×
108
        write!(
×
109
            f,
×
110
            "invalid protocol: string does not start with a forward slash"
×
111
        )
112
    }
×
113
}
114

115
impl std::error::Error for InvalidProtocol {}
116

117
#[cfg(test)]
118
mod tests {
119
    use super::*;
120

121
    #[test]
122
    fn stream_protocol_print() {
1✔
123
        let protocol = StreamProtocol::new("/foo/bar/1.0.0");
1✔
124

125
        let debug = format!("{protocol:?}");
1✔
126
        let display = format!("{protocol}");
1✔
127

128
        assert_eq!(
1✔
129
            debug, r#""/foo/bar/1.0.0""#,
130
            "protocol to debug print as string with quotes"
131
        );
132
        assert_eq!(
1✔
133
            display, "/foo/bar/1.0.0",
134
            "protocol to display print as string without quotes"
135
        );
136
    }
1✔
137
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc