use std::ffi::{CStr, CString};
use std::io::{Read, Write};
use crate::{SpError, SpRead, SpWrite};
impl SpRead for String {
fn inner_from_bytes<R: Read + ?Sized> (
src: &mut R,
is_input_le: bool,
_count: Option<usize>,
) -> Result<Self, crate::SpError>
where
Self: Sized {
let num_bytes = <u64>::inner_from_bytes(src, is_input_le, None)?;
let vec = <Vec<u8>>::inner_from_bytes(src, is_input_le, Some(num_bytes as _))?;
let val = match String::from_utf8(vec) {
Ok(s) => s,
Err(_e) => {
return Err(SpError::InvalidBytes);
}
};
Ok(val)
}
fn from_bytes<R: Read + ?Sized>(src: &mut R) -> Result<Self, crate::SpError>
where
Self: Sized {
Self::inner_from_bytes(src, true, None)
}
}
impl SpWrite for String {
fn inner_to_bytes<W: Write + ?Sized>(
&self,
_is_output_le: bool,
dst: &mut W,
) -> Result<usize, crate::SpError> {
self.as_str().inner_to_bytes(true, dst)
}
fn to_bytes<W: Write + ?Sized>(&self, dst: &mut W) -> Result<usize, crate::SpError> {
self.inner_to_bytes(true, dst)
}
}
impl SpWrite for &str {
fn inner_to_bytes<W: Write + ?Sized>(
&self,
is_output_le: bool,
dst: &mut W,
) -> Result<usize, crate::SpError> {
let total_sz = (self.len() as u64).inner_to_bytes(is_output_le, dst)?;
match dst.write(self.as_bytes()) {
Ok(v) => Ok(total_sz + v),
Err(_) => Err(SpError::NotEnoughSpace),
}
}
fn to_bytes<W: Write + ?Sized>(&self, dst: &mut W) -> Result<usize, crate::SpError> {
self.inner_to_bytes(true, dst)
}
}
impl SpRead for CString {
fn inner_from_bytes<R: Read + ?Sized> (
src: &mut R,
is_input_le: bool,
_count: Option<usize>,
) -> Result<Self, crate::SpError>
where
Self: Sized {
let mut vec = Vec::new();
loop {
let val = <u8>::inner_from_bytes(src, is_input_le, None)?;
vec.push(val);
if val == 0 {
break;
}
}
Ok(
unsafe {
CString::from_vec_unchecked(vec)
}
)
}
fn from_bytes<R: Read + ?Sized>(src: &mut R) -> Result<Self, crate::SpError>
where
Self: Sized {
Self::inner_from_bytes(src, true, None)
}
}
impl SpWrite for CString {
fn inner_to_bytes<W: Write + ?Sized>(
&self,
_is_output_le: bool,
dst: &mut W,
) -> Result<usize, crate::SpError> {
self.as_c_str().inner_to_bytes(true, dst)
}
fn to_bytes<W: Write + ?Sized>(&self, dst: &mut W) -> Result<usize, crate::SpError> {
self.inner_to_bytes(true, dst)
}
}
impl SpWrite for &CStr {
fn inner_to_bytes<W: Write + ?Sized>(
&self,
_is_output_le: bool,
dst: &mut W,
) -> Result<usize, crate::SpError> {
let contents = self.to_bytes_with_nul();
match dst.write(contents) {
Ok(v) => Ok(v),
Err(_) => Err(SpError::NotEnoughSpace),
}
}
fn to_bytes<'a, W: Write + ?Sized>(&self, dst: &'a mut W) -> Result<usize, crate::SpError> {
self.inner_to_bytes(true, dst)
}
}