1use std::convert::TryFrom;
4use std::str::FromStr;
5
6use bytes::{Buf, Bytes};
7
8use crate::{
9 error::Code,
10 proto::{stream::StreamId, varint::VarInt},
11 Error,
12};
13
14#[derive(Copy, PartialEq, Debug, Clone)]
18pub struct Protocol(ProtocolInner);
19
20impl Protocol {
21 pub const WEB_TRANSPORT: Protocol = Protocol(ProtocolInner::WebTransport);
23}
24
25#[derive(Copy, PartialEq, Debug, Clone)]
26enum ProtocolInner {
27 WebTransport,
28}
29
30pub struct InvalidProtocol;
32
33impl FromStr for Protocol {
34 type Err = InvalidProtocol;
35
36 fn from_str(s: &str) -> Result<Self, Self::Err> {
37 match s {
38 "webtransport" => Ok(Self(ProtocolInner::WebTransport)),
39 _ => Err(InvalidProtocol),
40 }
41 }
42}
43
44pub struct Datagram<B = Bytes> {
47 stream_id: StreamId,
49 payload: B,
51}
52
53impl<B> Datagram<B>
54where
55 B: Buf,
56{
57 pub fn new(stream_id: StreamId, payload: B) -> Self {
59 assert!(
60 stream_id.into_inner() % 4 == 0,
61 "StreamId is not divisible by 4"
62 );
63 Self { stream_id, payload }
64 }
65
66 pub fn decode(mut buf: B) -> Result<Self, Error> {
68 let q_stream_id = VarInt::decode(&mut buf)
69 .map_err(|_| Code::H3_DATAGRAM_ERROR.with_cause("Malformed datagram frame"))?;
70
71 let stream_id = StreamId::try_from(u64::from(q_stream_id) * 4)
80 .map_err(|_| Code::H3_DATAGRAM_ERROR.with_cause("Invalid stream id"))?;
81
82 let payload = buf;
83
84 Ok(Self { stream_id, payload })
85 }
86
87 #[inline]
88 pub fn stream_id(&self) -> StreamId {
90 self.stream_id
91 }
92
93 #[inline]
94 pub fn payload(&self) -> &B {
96 &self.payload
97 }
98
99 pub fn encode<D: bytes::BufMut>(self, buf: &mut D) {
101 (VarInt::from(self.stream_id) / 4).encode(buf);
102 buf.put(self.payload);
103 }
104
105 pub fn into_payload(self) -> B {
107 self.payload
108 }
109}