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
use web_transport_proto::VarInt;
/// Stream direction.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StreamDir {
/// Bidirectional: both sides can send and receive.
Bi,
/// Unidirectional: only the initiator can send.
Uni,
}
/// A QUIC-style stream identifier encoding direction and initiator.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StreamId(pub VarInt);
impl StreamId {
/// Create a new stream ID with the given sequence number, direction, and initiator.
pub fn new(id: u64, dir: StreamDir, is_server: bool) -> Self {
let mut stream_id = id << 2;
if dir == StreamDir::Uni {
stream_id |= 0x02;
}
if is_server {
stream_id |= 0x01;
}
StreamId(VarInt::try_from(stream_id).expect("stream ID too large"))
}
/// Returns the stream direction (bidirectional or unidirectional).
pub fn dir(&self) -> StreamDir {
if self.0.into_inner() & 0x02 != 0 {
StreamDir::Uni
} else {
StreamDir::Bi
}
}
/// Returns true if this stream was initiated by the server.
pub fn server_initiated(&self) -> bool {
self.0.into_inner() & 0x01 != 0
}
/// Returns true if the given endpoint can receive on this stream.
pub fn can_recv(&self, is_server: bool) -> bool {
match self.dir() {
StreamDir::Uni => self.server_initiated() != is_server,
StreamDir::Bi => true,
}
}
/// Returns true if the given endpoint can send on this stream.
pub fn can_send(&self, is_server: bool) -> bool {
match self.dir() {
StreamDir::Uni => self.server_initiated() == is_server,
StreamDir::Bi => true,
}
}
}