use crate::{ Error, payload::{Decode, Encode}, }; use std::io::{Read, Seek, SeekFrom}; use crate::Payload; #[derive(Debug, PartialEq)] pub struct TextPayload(pub String); impl> From for TextPayload { fn from(text: T) -> Self { Self(text.into()) } } impl AsRef for TextPayload { fn as_ref(&self) -> &str { &self.0 } } impl Decode for TextPayload { fn decode(mut reader: R, _chunk_len: usize) -> Result { let mut text = Vec::with_capacity(32); let mut buf = [0; 32]; let mut read: usize; loop { read = reader.read(&mut buf).map_err(Error::from)?; // end of stream if read == 0 { break; } let start = buf[..read].iter().position(|&b| b == Payload::START_BYTE); if let Some(start) = start { // 5 4 3 5 4 5 = 6 bytes read // ^ - start byte at idx 2 // seek backwards until start byte is next to read: read - idx = 4 bytes let offset = (read - start) as i64; reader.seek(SeekFrom::Current(-offset)).map_err(Error::from)?; // tell the rest of the loop that we only read up to the start byte read = start as usize; } for &byte in &buf[..read] { text.push(byte); } // we encountered a real payload, so break now if start.is_some() { break; } } let text = if text.len() > 0 { String::from_utf8(text).map_err(Error::from)? } else { String::new() }; Ok(Self(text)) } } impl Encode for TextPayload { fn encode(&self) -> Vec { self.0.as_bytes().to_vec() } }