use std::any::{
type_name,
Any,
};
use std::default::Default;
use std::fmt::{
self,
Debug,
};
use std::io::{
Cursor,
Error,
ErrorKind,
Result,
Write,
};
use bytes::{
Buf,
Bytes,
};
use super::Message;
#[allow(clippy::len_without_is_empty)]
pub trait PbBuffer: Any + Clone + Default {
type Reader: PbBufferReader;
fn len(&self) -> usize;
fn into_reader(self) -> Self::Reader;
fn from_reader<R: PbBufferReader>(reader: &mut R) -> Result<Self> {
reader.as_buffer::<Self>()
}
}
pub fn cast_buffer<B1: PbBuffer, B2: PbBuffer>(buf: B1) -> Result<B2> {
let mut buf = Some(buf);
if let Some(buf) = (&mut buf as &mut dyn Any).downcast_mut::<Option<B2>>() {
Ok(buf.take().unwrap())
} else {
Err(Error::new(
ErrorKind::InvalidInput,
format!(
"This reader produces buffers of type {}, not {}",
type_name::<B1>(),
type_name::<B2>()
),
))
}
}
pub trait PbBufferReader: Buf + Sized {
fn as_buffer<B: PbBuffer>(&self) -> Result<B> {
Err(Error::new(
ErrorKind::InvalidInput,
"Taking ownership of the PbBuffer from this reader is not supported",
))
}
fn split(&mut self, at: usize) -> Self;
}
pub trait PbBufferWriter: Write {
fn write_buffer<B: PbBuffer>(&mut self, buf: &B) -> Result<()>;
}
#[derive(Clone, Default, PartialEq)]
pub struct Lazy<B: PbBuffer> {
contents: Option<B>,
}
impl<B: PbBuffer> Lazy<B> {
pub fn new(r: B) -> Self {
Self { contents: Some(r) }
}
pub fn into_buffer(self) -> B {
self.contents.unwrap_or_default()
}
}
impl<B: PbBuffer> Debug for Lazy<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Lazy")
.field("contents", &self.contents.as_ref().map(|_| "_"))
.finish()
}
}
impl<B: PbBuffer + PartialEq> Message for Lazy<B> {
fn compute_size(&self) -> usize {
self.contents.as_ref().map(PbBuffer::len).unwrap_or(0)
}
fn compute_grpc_slices_size(&self) -> usize {
self.contents.as_ref().map(PbBuffer::len).unwrap_or(0)
}
fn serialize<W: PbBufferWriter>(&self, w: &mut W) -> Result<()> {
if let Some(ref contents) = self.contents {
w.write_buffer(contents)?;
}
Ok(())
}
fn deserialize<R: PbBufferReader>(&mut self, r: &mut R) -> Result<()> {
self.contents = Some(B::from_reader(r)?);
Ok(())
}
}
impl<'a> PbBufferReader for Cursor<&'a [u8]> {
fn split(&mut self, at: usize) -> Self {
let pos = self.position() as usize;
self.advance(at);
let new_slice = &self.get_ref()[pos..pos + at];
Self::new(new_slice)
}
}
impl PbBuffer for Bytes {
type Reader = Cursor<Bytes>;
fn len(&self) -> usize {
self.len()
}
fn into_reader(self) -> Cursor<Bytes> {
Cursor::new(self)
}
}
impl PbBufferReader for Cursor<Bytes> {
fn as_buffer<B: PbBuffer>(&self) -> Result<B> {
let bytes = self.get_ref().slice((self.position() as usize)..);
cast_buffer(bytes)
}
fn split(&mut self, at: usize) -> Self {
let pos = self.position() as usize;
self.advance(at);
let new_slice = self.get_ref().slice(pos..(pos + at));
Self::new(new_slice)
}
}
impl<'a> PbBufferWriter for Cursor<&'a mut Vec<u8>> {
#[inline]
fn write_buffer<B: PbBuffer>(&mut self, buf: &B) -> Result<()> {
let mut reader = buf.clone().into_reader();
while reader.has_remaining() {
let n = {
let bytes = reader.bytes();
self.write_all(bytes)?;
bytes.len()
};
reader.advance(n);
}
Ok(())
}
}
impl<'a> PbBufferWriter for Cursor<&'a mut [u8]> {
#[inline]
fn write_buffer<B: PbBuffer>(&mut self, buf: &B) -> Result<()> {
let mut reader = buf.clone().into_reader();
while reader.has_remaining() {
let n = {
let bytes = reader.bytes();
self.write_all(bytes)?;
bytes.len()
};
reader.advance(n);
}
Ok(())
}
}
pub struct CopyWriter<'a, W: Write> {
pub writer: &'a mut W,
}
impl<'a, W: Write + 'a> Write for CopyWriter<'a, W> {
#[inline]
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.writer.write(buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
self.writer.flush()
}
}
impl<'a, W: Write + 'a> PbBufferWriter for CopyWriter<'a, W> {
#[inline]
fn write_buffer<B: PbBuffer>(&mut self, buf: &B) -> Result<()> {
let mut reader = buf.clone().into_reader();
while reader.has_remaining() {
let n = {
let bytes = reader.bytes();
self.write_all(bytes)?;
bytes.len()
};
reader.advance(n);
}
Ok(())
}
}