wtransport_proto/capsule/
mod.rs

1use crate::bytes::BytesReader;
2use crate::frame::Frame;
3use crate::frame::FrameKind;
4use crate::varint::VarInt;
5
6/// An HTTP3 [`Capsule`] type.
7#[derive(Copy, Clone, Debug)]
8pub enum CapsuleKind {
9    /// Close WebTransport Capsule type.
10    CloseWebTransportSession,
11}
12
13impl CapsuleKind {
14    const fn parse(id: VarInt) -> Option<Self> {
15        match id {
16            capsule_types::CAPSULE_TYPE_CLOSE_WEBTRANSPORT_SESSION => {
17                Some(CapsuleKind::CloseWebTransportSession)
18            }
19            _ => None,
20        }
21    }
22}
23
24/// An HTTP3 Capsule.
25#[derive(Debug)]
26pub struct Capsule<'a> {
27    kind: CapsuleKind,
28    payload: &'a [u8],
29}
30
31impl<'a> Capsule<'a> {
32    /// Parses a capsule from an HTTP3 frame.
33    ///
34    /// # Panics
35    ///
36    /// Panics if `frame` is not [`Data`](`FrameKind::Data`) type.
37    pub fn with_frame(frame: &'a Frame<'a>) -> Option<Self> {
38        assert!(matches!(frame.kind(), FrameKind::Data));
39
40        let mut payload = frame.payload();
41        let kind = CapsuleKind::parse(payload.get_varint()?)?;
42        let payload_length = payload.get_varint()?;
43        let payload = payload.get_bytes(payload_length.into_inner() as usize)?;
44
45        Some(Self { kind, payload })
46    }
47
48    /// The [`CapsuleKind`] of this capsule.
49    pub fn kind(&self) -> CapsuleKind {
50        self.kind
51    }
52
53    /// Returns the payload of this `Capsule`.
54    pub fn payload(&self) -> &[u8] {
55        self.payload
56    }
57}
58
59mod capsule_types {
60    use crate::varint::VarInt;
61
62    pub const CAPSULE_TYPE_CLOSE_WEBTRANSPORT_SESSION: VarInt = VarInt::from_u32(0x2843);
63}
64
65/// Capsules types implementations.
66pub mod capsules {
67    pub use super::close_wt_session::CloseWebTransportSession;
68}
69
70mod close_wt_session;
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn capsule_close_wt_session() {
78        let frame = Frame::new_data(vec![104, 67, 4, 0, 0, 0, 0u8].into());
79        let capsule = Capsule::with_frame(&frame).unwrap();
80        let close =
81            capsules::CloseWebTransportSession::with_capsule(&capsule).expect("Should parse");
82        assert_eq!(close.error_code(), VarInt::from_u32(0));
83        assert_eq!(close.reason(), "");
84    }
85}