use std::{boxed::Box, string::String};
use std::vec;
use std::vec::Vec;
use crate::{codec::{Codec, DecodeError, EncodeError}, impls::StringContext};
use crate::buffers::{ EncodeBuffer, DecodeBuffer };
impl Codec<StringContext> for std::string::String {
fn encode(self, buf: &mut impl EncodeBuffer, ctx: StringContext) -> Result<(), EncodeError> {
match ctx {
StringContext::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())
},
StringContext::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())
},
StringContext::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())
},
StringContext::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())
},
StringContext::NullTerminated => {
buf.push_slice(self.as_bytes())?;
buf.push(0)
},
}
}
fn decode(buf: &mut impl DecodeBuffer, ctx: StringContext) -> Result<Self, DecodeError> {
match ctx {
StringContext::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))
}
StringContext::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))
}
StringContext::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))
}
StringContext::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))
}
StringContext::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))
}
}
}
}
#[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, StringContext::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, StringContext::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, StringContext::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, StringContext::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, StringContext::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, StringContext::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, StringContext::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, StringContext::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, StringContext::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, StringContext::U32Len(Endian::Little)).unwrap();
assert_eq!(slice, [5, 0, 0, 0, b'h', b'e', b'l', b'l', b'o']);
}
}