VoIPとSIPを通じてRustを勉強する：ざつにRTP parser/builder作成編

# はじめに
本記事は自分のためでしかないアドベントカレンダー2024の記事です。
記事は２５記事書くと思いますが期待はせずにお願いします

# RTPパーサ/ビルダ
ざつに作成しました
## RTPパーサ
~~~rtp_parser.rs
struct RtpPacketParser<'a> {
    rtp_packet: &'a [u8],
}

impl<'a> RtpPacketParser<'a> {
    pub fn new(rtp_packet: &'a [u8]) -> Self {
        let retval = RtpPacketParser {
            rtp_packet: &rtp_packet,
        };

        return retval;
    }

    fn version(&self) -> u8 {
        return self.rtp_packet[0] & 0b0000_0011;
    }

    fn padding(&self) -> u8 {
        return self.rtp_packet[0] & 0b0000_0100;
    }

    fn extension(&self) -> u8 {
        return self.rtp_packet[0] & 0b0000_1000;
    }

    fn csrc_count(&self) -> u8 {
        return self.rtp_packet[0] & 0b1111_0000;
    }
    fn payload_type(&self) -> u8 {
        return self.rtp_packet[1];
    }
    fn sequence_number(&self) -> u16 {
        return u16::from_be_bytes(self.rtp_packet[2..4].try_into().unwrap());
    }

    fn time_stamp(&self) -> u32 {
        return u32::from_be_bytes(self.rtp_packet[4..8].try_into().unwrap());
    }
    fn ssrc(&self) -> u32 {
        return u32::from_be_bytes(self.rtp_packet[8..12].try_into().unwrap());
    }

    fn payload(&self) -> &'a [u8] {
        return &self.rtp_packet[12..self.rtp_packet.len()];
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_all() {
        let hoge = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1];
        let packet = RtpPacketParser::new(&hoge);

        println!("{:?}", packet.ssrc());
        println!("{:?}", packet.payload_type());
    }
}

~~~
## RTPビルダ
~~~rtp_builder.rs
pub struct RtpBuilder<'a> {
    version: u8,
    padding: u8,
    extension: u8,
    csrc_count: u8,
    marker: u8,
    payload_type: u8,
    sequence_number: u16,
    time_stamp: u32,
    ssrc: u32,
    payload: Option<&'a [u8]>,
}

impl<'a> RtpBuilder<'a> {
    pub fn new() -> Self {
        RtpBuilder {
            version: 0,
            padding: 0,
            extension: 0,
            csrc_count: 0,
            marker: 0,
            payload_type: 0xFF,
            sequence_number: 0,
            time_stamp: 0,
            ssrc: 0,
            payload: None,
        }
    }
    fn version(mut self, version: u8) -> Self {
        self.version = version;
        self
    }
    fn padding(mut self, padding: u8) -> Self {
        self.padding = padding;
        self
    }
    fn extension(mut self, extension: u8) -> Self {
        self.extension = extension;
        self
    }
    fn csrc_count(mut self, csrc_count: u8) -> Self {
        self.csrc_count = csrc_count;
        self
    }
    fn marker(mut self, marker: u8) -> Self {
        self.marker = marker;
        self
    }
    fn payload_type(mut self, payload_type: u8) -> Self {
        self.payload_type = payload_type;
        self
    }
    fn sequence_number(mut self, sequence_number: u16) -> Self {
        self.sequence_number = sequence_number;
        self
    }
    fn time_stamp(mut self, time_stamp: u32) -> Self {
        self.time_stamp = time_stamp;
        self
    }
    fn ssrc(mut self, ssrc: u32) -> Self {
        self.ssrc = ssrc;
        self
    }

    fn payload(mut self, payload: &'a [u8]) -> Self {
        self.payload = Some(payload);
        self
    }

    fn build(&self, rtp_packet: &mut [u8]) {
        rtp_packet[0] = self.version;
        rtp_packet[0] |= self.padding << 2;
        rtp_packet[0] |= self.extension << 3;
        rtp_packet[0] |= self.csrc_count << 4;

        rtp_packet[1] = self.payload_type;

        rtp_packet[2..4].copy_from_slice(&self.sequence_number.to_be_bytes());
        rtp_packet[4..8].copy_from_slice(&self.time_stamp.to_be_bytes());
        rtp_packet[8..12].copy_from_slice(&self.ssrc.to_be_bytes());
        if let Some(payload) = self.payload {
            rtp_packet[12..(12 + payload.len())].copy_from_slice(payload);
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_all() {
        let payload = [1u8; 4];
        let mut hoge = [0u8; 16];
        let packet: () = RtpBuilder::new()
            .payload_type(1)
            .payload(&payload)
            .build(hoge.as_mut_slice());
        println!("{:?}", hoge);
    }
}

~~~
# おわりに
Rust何もわからん