use core::fmt::Debug;
use bson::{doc, RawDocumentBuf};
use tokio::io::{AsyncWrite, AsyncWriteExt};
use crate::wire::{Header, OpCode};
pub(crate) struct Reply {
pub(crate) response_to: i32,
doc: RawDocumentBuf,
pub(crate) payload: Vec<u8>,
}
impl Reply {
pub(crate) fn new(response_to: i32, doc: RawDocumentBuf) -> Reply {
const SINGLE_DOC_KIND: u8 = 0;
let mut payload = Vec::with_capacity(doc.as_bytes().len() + 5);
std::io::Write::write_all(&mut payload, [SINGLE_DOC_KIND].as_slice()).unwrap();
let doc_len = doc.as_bytes().len() as u32;
std::io::Write::write_all(&mut payload, doc_len.to_le_bytes().as_slice()).unwrap();
payload.extend_from_slice(doc.as_bytes());
Reply { response_to, doc, payload }
}
pub(crate) async fn write_to<W: AsyncWrite + Unpin>(&self, stream: &mut W) -> anyhow::Result<()> {
let message_len = Header::LENGTH + self.payload.len();
let header = Header {
length: message_len as i32,
request_id: 0,
response_to: self.response_to,
op_code: OpCode::Message,
};
header.write_to(stream).await?;
stream.write_all(self.payload.as_slice()).await?;
Ok(())
}
}
impl Debug for Reply {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let bson_doc = self.doc
.to_document()
.unwrap_or_else(|_| doc! { "error": "failed to serialize document" });
write!(f, "Reply {{ response_to: {}, payload: {:?} }}", self.response_to, bson_doc)
}
}