use crate::{codec::{Codec, DecodeError, EncodeError}, impls::SizeContext};
use crate::buffers::{ EncodeBuffer, DecodeBuffer };
impl Codec<SizeContext> for std::string::String {
fn encode(self, buf: &mut impl EncodeBuffer, ctx: SizeContext) -> Result<(), EncodeError> {
match ctx {
SizeContext::Fixed(usize) => {
let slice = self.as_bytes();
let length = slice.len();
if length > usize {return Err(EncodeError::Encoding)}
buf.push_slice(self.as_bytes())?;
buf.push_slice(vec![0;usize-length].as_slice())
},
SizeContext::U8Len => {
let slice = self.as_bytes();
let length = u8::try_from(slice.len()).or_else(|_| Err(EncodeError::Encoding))?;
buf.push(length)?;
buf.push_slice(self.as_bytes())
},
SizeContext::U16Len(end) => {
let slice = self.as_bytes();
let length = u16::try_from(slice.len()).or_else(|_| Err(EncodeError::Encoding))?;
length.encode(buf, end)?;
buf.push_slice(self.as_bytes())
},
SizeContext::U32Len(end) => {
let slice = self.as_bytes();
let length = u32::try_from(slice.len()).or_else(|_| Err(EncodeError::Encoding))?;
length.encode(buf, end)?;
buf.push_slice(self.as_bytes())
},
SizeContext::NullTerminated => {
buf.push_slice(self.as_bytes())?;
buf.push(0)
},
}
}
fn decode(buf: &mut impl DecodeBuffer, ctx: SizeContext) -> Result<Self, DecodeError> {
match ctx {
SizeContext::Fixed(size) => {
let mut slice = vec![0;size].into_boxed_slice();
buf.read_slice(&mut slice)?;
String::from_utf8(slice.to_vec()).or_else(|_| Err(DecodeError::Invalid))
}
SizeContext::U8Len => {
let len = u8::decode(buf, ())?;
let len = len as usize;
let mut slice = vec![0;len].into_boxed_slice();
buf.read_slice(&mut slice)?;
String::from_utf8(slice.to_vec()).or_else(|_| Err(DecodeError::Invalid))
}
SizeContext::U16Len(end) => {
let len = u16::decode(buf, end)?;
let len = len as usize;
let mut slice = vec![0;len].into_boxed_slice();
buf.read_slice(&mut slice)?;
String::from_utf8(slice.to_vec()).or_else(|_| Err(DecodeError::Invalid))
}
SizeContext::U32Len(end) => {
let len = u32::decode(buf, end)?;
let len = len as usize;
let mut slice = vec![0;len].into_boxed_slice();
buf.read_slice(&mut slice)?;
String::from_utf8(slice.to_vec()).or_else(|_| Err(DecodeError::Invalid))
}
SizeContext::NullTerminated => {
let mut vec = Vec::new();
loop {
let char = u8::decode(buf, ())?;
if char == 0 {break}
vec.push(char);
}
String::from_utf8(vec).or_else(|_| Err(DecodeError::Invalid))
}
}
}
}
impl<T: Copy + Codec<()>> Codec<SizeContext> for Vec<T> {
fn encode(self, buf: & mut impl EncodeBuffer, ctx: SizeContext) -> Result<(), EncodeError> {
match ctx {
SizeContext::Fixed(len) => if len != self.len() {return Err(EncodeError::Encoding)},
SizeContext::U8Len => (self.len() as u8).encode(buf, ())?,
SizeContext::U16Len(endian) => (self.len() as u16).encode(buf, endian)?,
SizeContext::U32Len(endian) => (self.len() as u32).encode(buf, endian)?,
SizeContext::NullTerminated => unimplemented!("Not reasonable"),
};
for i in self {
i.encode(buf, ())?;
}
Ok(())
}
fn decode(buf: &mut impl DecodeBuffer, ctx: SizeContext) -> Result<Self, DecodeError> {
let size = match ctx {
SizeContext::Fixed(len) => len,
SizeContext::U8Len => u8::decode(buf, ())? as usize,
SizeContext::U16Len(endian) => u16::decode(buf, endian)? as usize,
SizeContext::U32Len(endian) => u32::decode(buf, endian)? as usize,
SizeContext::NullTerminated => unimplemented!("Not reasonable"),
};
let mut result = Vec::with_capacity(size);
for _ in 0..size {
result.push(T::decode(buf, ())?);
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{buffers::*, Endian};
#[test]
fn decode_string_null_terminated() {
let mut slice = [b'h', b'e', b'l', b'l', b'o', 0];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::decode(&mut buf, SizeContext::NullTerminated).unwrap();
assert_eq!(string, "hello");
}
#[test]
fn decode_string_fixed() {
let mut slice = [b'h', b'e', b'l', b'l', b'o'];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::decode(&mut buf, SizeContext::Fixed(5)).unwrap();
assert_eq!(string, "hello");
}
#[test]
fn decode_string_u8len() {
let mut slice = [5, b'h', b'e', b'l', b'l', b'o'];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::decode(&mut buf, SizeContext::U8Len).unwrap();
assert_eq!(string, "hello");
}
#[test]
fn decode_string_u16len() {
let mut slice = [5, 0, b'h', b'e', b'l', b'l', b'o'];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::decode(&mut buf, SizeContext::U16Len(Endian::Little)).unwrap();
assert_eq!(string, "hello");
}
#[test]
fn decode_string_u32len() {
let mut slice = [5, 0, 0, 0, b'h', b'e', b'l', b'l', b'o'];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::decode(&mut buf, SizeContext::U32Len(Endian::Little)).unwrap();
assert_eq!(string, "hello");
}
#[test]
fn encode_string_null_terminated() {
let mut slice = [0;6];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::from("hello");
string.encode(&mut buf, SizeContext::NullTerminated).unwrap();
assert_eq!(slice, [b'h', b'e', b'l', b'l', b'o', 0]);
}
#[test]
fn encode_string_fixed() {
let mut slice = [0;5];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::from("hello");
string.encode(&mut buf, SizeContext::Fixed(5)).unwrap();
assert_eq!(slice, [b'h', b'e', b'l', b'l', b'o']);
}
#[test]
fn encode_string_u8len() {
let mut slice = [0;6];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::from("hello");
string.encode(&mut buf, SizeContext::U8Len).unwrap();
assert_eq!(slice, [5, b'h', b'e', b'l', b'l', b'o']);
}
#[test]
fn encode_string_u16len() {
let mut slice = [0;7];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::from("hello");
string.encode(&mut buf, SizeContext::U16Len(Endian::Little)).unwrap();
assert_eq!(slice, [5, 0, b'h', b'e', b'l', b'l', b'o']);
}
#[test]
fn encode_string_u32len() {
let mut slice = [0;9];
let mut buf = StaticBuffer::new(&mut slice);
let string = String::from("hello");
string.encode(&mut buf, SizeContext::U32Len(Endian::Little)).unwrap();
assert_eq!(slice, [5, 0, 0, 0, b'h', b'e', b'l', b'l', b'o']);
}
}