use bytes::buf::UninitSlice; use bytes::{Buf, BufMut, BytesMut}; /// A specialized buffer to decode gRPC messages from. #[derive(Debug)] pub struct DecodeBuf<'a> { buf: &'a mut BytesMut, len: usize, } /// A specialized buffer to encode gRPC messages into. #[derive(Debug)] pub struct EncodeBuf<'a> { buf: &'a mut BytesMut, } impl<'a> DecodeBuf<'a> { pub(crate) fn new(buf: &'a mut BytesMut, len: usize) -> Self { DecodeBuf { buf, len } } } impl Buf for DecodeBuf<'_> { #[inline] fn remaining(&self) -> usize { self.len } #[inline] fn chunk(&self) -> &[u8] { let ret = self.buf.chunk(); if ret.len() > self.len { &ret[..self.len] } else { ret } } #[inline] fn advance(&mut self, cnt: usize) { assert!(cnt <= self.len); self.buf.advance(cnt); self.len -= cnt; } } impl<'a> EncodeBuf<'a> { pub(crate) fn new(buf: &'a mut BytesMut) -> Self { EncodeBuf { buf } } } impl EncodeBuf<'_> { /// Reserves capacity for at least `additional` more bytes to be inserted /// into the buffer. /// /// More than `additional` bytes may be reserved in order to avoid frequent /// reallocations. A call to `reserve` may result in an allocation. #[inline] pub fn reserve(&mut self, additional: usize) { self.buf.reserve(additional); } } unsafe impl BufMut for EncodeBuf<'_> { #[inline] fn remaining_mut(&self) -> usize { self.buf.remaining_mut() } #[inline] unsafe fn advance_mut(&mut self, cnt: usize) { self.buf.advance_mut(cnt) } #[inline] fn chunk_mut(&mut self) -> &mut UninitSlice { self.buf.chunk_mut() } } #[cfg(test)] mod tests { use super::*; #[test] fn decode_buf() { let mut payload = BytesMut::with_capacity(100); payload.put(&vec![0u8; 50][..]); let mut buf = DecodeBuf::new(&mut payload, 20); assert_eq!(buf.len, 20); assert_eq!(buf.remaining(), 20); assert_eq!(buf.chunk().len(), 20); buf.advance(10); assert_eq!(buf.remaining(), 10); let mut out = [0; 5]; buf.copy_to_slice(&mut out); assert_eq!(buf.remaining(), 5); assert_eq!(buf.chunk().len(), 5); assert_eq!(buf.copy_to_bytes(5).len(), 5); assert!(!buf.has_remaining()); } #[test] fn encode_buf() { let mut bytes = BytesMut::with_capacity(100); let mut buf = EncodeBuf::new(&mut bytes); let initial = buf.remaining_mut(); unsafe { buf.advance_mut(20) }; assert_eq!(buf.remaining_mut(), initial - 20); buf.put_u8(b'a'); assert_eq!(buf.remaining_mut(), initial - 20 - 1); } }