mumble-rs 0.1.1

A small simple crate to communicate with a mumble server
Documentation
use crate::proto::*;
use crate::MumbleMessage;
use anyhow::bail;
use bytes::{Buf, BufMut, BytesMut};
use prost::Message;
use tokio_util::codec::{Decoder, Encoder};

pub struct MumbleTcpCodec {}

impl MumbleTcpCodec {
    pub fn new() -> Self {
        Self {}
    }
}

impl Decoder for MumbleTcpCodec {
    type Item = MumbleMessage;
    type Error = anyhow::Error;

    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
        if src.len() < 6 {
            return Ok(None);
        }

        let (message_type, rest) = src.split_at(2);
        let (message_length, rest) = rest.split_at(4);
        let message_type = u16::from_be_bytes(message_type.try_into()?) as usize;
        let message_length = u32::from_be_bytes(message_length.try_into()?) as usize;

        if message_length + 6 > src.len() {
            src.reserve(message_length + 6 - src.len());
            return Ok(None);
        }

        let (message_data, _) = rest.split_at(message_length);
        let mut mumble_message: Option<MumbleMessage> = None;

        match message_type {
            0 => {
                mumble_message = Some(MumbleMessage::Version {
                    data: Version::decode(message_data)?,
                });
            }
            1 => {
                mumble_message = Some(MumbleMessage::UdpTunnel {
                    data: UdpTunnel::decode(message_data)?,
                });
            }
            2 => {
                bail!("The server should never send Authenticate")
            }
            3 => {
                mumble_message = Some(MumbleMessage::Ping {
                    data: Ping::decode(message_data)?,
                });
            }
            4 => {
                mumble_message = Some(MumbleMessage::Reject {
                    data: Reject::decode(message_data)?,
                });
            }
            5 => {
                mumble_message = Some(MumbleMessage::ServerSync {
                    data: ServerSync::decode(message_data)?,
                });
            }
            6 => {
                mumble_message = Some(MumbleMessage::ChannelRemove {
                    data: ChannelRemove::decode(message_data)?,
                });
            }
            7 => {
                mumble_message = Some(MumbleMessage::ChannelState {
                    data: ChannelState::decode(message_data)?,
                });
            }
            8 => {
                mumble_message = Some(MumbleMessage::UserRemove {
                    data: UserRemove::decode(message_data)?,
                });
            }
            9 => {
                mumble_message = Some(MumbleMessage::UserState {
                    data: UserState::decode(message_data)?,
                });
            }
            10 => {
                mumble_message = Some(MumbleMessage::BanList {
                    data: BanList::decode(message_data)?,
                });
            }
            11 => {
                mumble_message = Some(MumbleMessage::TextMessage {
                    data: TextMessage::decode(message_data)?,
                });
            }
            12 => {
                mumble_message = Some(MumbleMessage::PermissionDenied {
                    data: PermissionDenied::decode(message_data)?,
                });
            }
            13 => {
                mumble_message = Some(MumbleMessage::Acl {
                    data: Acl::decode(message_data)?,
                });
            }
            14 => {
                mumble_message = Some(MumbleMessage::QueryUsers {
                    data: QueryUsers::decode(message_data)?,
                });
            }
            15 => {
                mumble_message = Some(MumbleMessage::CryptSetup {
                    data: CryptSetup::decode(message_data)?,
                });
            }
            16 => {
                mumble_message = Some(MumbleMessage::ContextActionModify {
                    data: ContextActionModify::decode(message_data)?,
                });
            }
            17 => {
                mumble_message = Some(MumbleMessage::ContextAction {
                    data: ContextAction::decode(message_data)?,
                });
            }
            18 => {
                mumble_message = Some(MumbleMessage::UserList {
                    data: UserList::decode(message_data)?,
                });
            }
            19 => {
                mumble_message = Some(MumbleMessage::VoiceTarget {
                    data: VoiceTarget::decode(message_data)?,
                });
            }
            20 => {
                mumble_message = Some(MumbleMessage::PermissionQuery {
                    data: PermissionQuery::decode(message_data)?,
                });
            }
            21 => {
                mumble_message = Some(MumbleMessage::CodecVersion {
                    data: CodecVersion::decode(message_data)?,
                });
            }
            22 => {
                mumble_message = Some(MumbleMessage::UserStats {
                    data: UserStats::decode(message_data)?,
                });
            }
            23 => {
                mumble_message = Some(MumbleMessage::RequestBlob {
                    data: RequestBlob::decode(message_data)?,
                });
            }
            24 => {
                mumble_message = Some(MumbleMessage::ServerConfig {
                    data: ServerConfig::decode(message_data)?,
                });
            }
            25 => {
                mumble_message = Some(MumbleMessage::SuggestConfig {
                    data: SuggestConfig::decode(message_data)?,
                });
            }
            _ => {
                eprintln!("Unknown message type {:?}", message_type);
            }
        }

        src.advance(message_length + 6);
        Ok(mumble_message)
    }
}

impl Encoder<MumbleMessage> for MumbleTcpCodec {
    type Error = anyhow::Error;

    fn encode(&mut self, item: MumbleMessage, dst: &mut BytesMut) -> Result<(), Self::Error> {
        let mut message = BytesMut::new();
        match item {
            MumbleMessage::Version { data } => {
                Version::encode(&data, &mut message)?;
                dst.put_u16(0);
            }
            MumbleMessage::Authenticate { data } => {
                Authenticate::encode(&data, &mut message)?;
                dst.put_u16(2);
            }
            MumbleMessage::Ping { data } => {
                Ping::encode(&data, &mut message)?;
                dst.put_u16(3);
            }
            _ => {
                bail!("Could not encode unknown message")
            }
        }

        dst.put_u32(message.len() as u32);
        dst.extend_from_slice(&message);
        Ok(())
    }
}