sestring/src/payload/text.rs

73 lines
1.8 KiB
Rust

use crate::{
Error,
payload::{Decode, Encode},
};
use std::io::{Read, Seek, SeekFrom};
use crate::Payload;
#[derive(Debug, PartialEq)]
pub struct TextPayload(pub String);
impl<T: Into<String>> From<T> for TextPayload {
fn from(text: T) -> Self {
Self(text.into())
}
}
impl AsRef<str> for TextPayload {
fn as_ref(&self) -> &str {
&self.0
}
}
impl Decode for TextPayload {
fn decode<R: Read + Seek>(mut reader: R, _chunk_len: usize) -> Result<Self, crate::Error> {
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<u8> {
self.0.as_bytes().to_vec()
}
}