imdl 0.1.16

📦 A 40' shipping container for the internet
Documentation
use crate::common::*;

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub(crate) struct UtMetadata {
  pub(crate) msg_type: u8,
  pub(crate) piece: usize,
  #[serde(
    skip_serializing_if = "Option::is_none",
    default,
    with = "unwrap_or_skip"
  )]
  pub(crate) total_size: Option<usize>,
}

#[derive(Debug, PartialEq)]
pub(crate) enum MsgType {
  Request,
  Data,
  Reject,
}

impl UtMetadata {
  pub(crate) const NAME: &'static str = "ut_metadata";
  pub(crate) const PIECE_LENGTH: usize = 16 * (1 << 10);

  pub(crate) fn request(piece: usize) -> Self {
    Self {
      msg_type: MsgType::Request.into(),
      piece,
      total_size: None,
    }
  }

  #[cfg(test)]
  pub(crate) fn data(piece: usize, total_size: usize) -> Self {
    Self {
      msg_type: MsgType::Data.into(),
      piece,
      total_size: Some(total_size),
    }
  }
}

impl From<MsgType> for u8 {
  fn from(m: MsgType) -> u8 {
    match m {
      MsgType::Request => 0,
      MsgType::Data => 1,
      MsgType::Reject => 2,
    }
  }
}

impl From<u8> for MsgType {
  fn from(x: u8) -> Self {
    match x {
      0 => Self::Request,
      1 => Self::Data,
      _ => MsgType::Reject,
    }
  }
}

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

  #[test]
  fn bencode_extended_metadata_message() {
    let req = UtMetadata {
      msg_type: MsgType::Data.into(),
      piece: 1,
      total_size: None,
    };
    let mut msg = bendy::serde::ser::to_bytes(&req).unwrap();
    let benc = b"d8:msg_typei1e5:piecei1ee";
    assert_eq!(benc, &*msg);
    msg.extend_from_slice(b"piece data goes here...");
    let req2 = bendy::serde::de::from_bytes(&msg).unwrap();
    assert_eq!(req, req2);
  }
}