use gbp::CodecError;
use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf;
#[repr(u8)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum GtpContentType {
Plain = 0,
Markdown = 1,
Binary = 2,
AttachmentRef = 3,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GtpMessage {
#[serde(rename = "mid")]
pub message_id: u64,
#[serde(rename = "sid")]
pub sender_id: u32,
#[serde(rename = "ts")]
pub timestamp_ms: u64,
#[serde(rename = "rid")]
pub request_id: u32,
#[serde(rename = "fl")]
pub flags: u8,
#[serde(rename = "ct")]
pub content_type: u8,
#[serde(rename = "len")]
pub content_length: u32,
#[serde(rename = "body")]
pub content: ByteBuf,
}
impl GtpMessage {
pub fn plain(sender_id: u32, message_id: u64, text: &str) -> Self {
let body = text.as_bytes().to_vec();
Self {
message_id,
sender_id,
timestamp_ms: 0,
request_id: 0,
flags: 0x01,
content_type: GtpContentType::Plain as u8,
content_length: body.len() as u32,
content: ByteBuf::from(body),
}
}
pub fn to_cbor(&self) -> Vec<u8> {
let mut buf = Vec::new();
ciborium::into_writer(self, &mut buf).expect("cbor encode");
buf
}
pub fn from_cbor(data: &[u8]) -> Result<Self, CodecError> {
let m: Self = ciborium::from_reader(data).map_err(|e| CodecError::Decode(e.to_string()))?;
if m.content_length as usize != m.content.len() {
return Err(CodecError::PayloadSizeMismatch);
}
Ok(m)
}
pub fn text(&self) -> Option<&str> {
std::str::from_utf8(&self.content).ok()
}
}