use crate::{
CStr, Char, Decodable, Encodable, Fmt, FmtArguments, FmtError, FmtResult, FmtWrite, IoError,
IoErrorKind, IoRead, IoResult, IoWrite, NoData, Slice, sf,
};
crate::_use! {basic::from_utf8}
#[cfg(feature = "alloc")]
crate::items! {
use crate::{is, Cow, CString, Box, String, ToOwned, Vec};
impl<W: IoWrite> Encodable<W> for Vec<u8> {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
writer.write(self.as_slice()) } }
impl<R: IoRead> Decodable<R> for Vec<u8> {
type Output = Vec<u8>;
fn decode(reader: &mut R) -> IoResult<Self::Output> {
let mut buf = Vec::new();
reader.read_to_end(&mut buf)?;
Ok(buf) } }
impl<W: IoWrite, T: Encodable<W>> Encodable<W> for Box<T> {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
self.as_ref().encode(writer) } }
impl<R: IoRead, T: Decodable<R>> Decodable<R> for Box<T> {
type Output = Box<T::Output>;
fn decode(reader: &mut R) -> IoResult<Self::Output> {
Ok(Box::new(T::decode(reader)?)) } }
impl<W: IoWrite> Encodable<W> for String {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
writer.write(self.as_bytes()) } }
impl<R: IoRead> Decodable<R> for String {
type Output = String;
fn decode(reader: &mut R) -> IoResult<Self::Output> {
let mut buf = Vec::new();
reader.read_to_end(&mut buf)?;
from_utf8(&buf).map(|s| s.to_owned())
.map_err(|_| IoError::new(IoErrorKind::InvalidData, "Invalid UTF-8"))
}
}
impl<W: IoWrite> Encodable<W> for CString {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
writer.write(self.as_bytes()) } }
impl<R: IoRead> Decodable<R> for CString {
type Output = CString;
fn decode(reader: &mut R) -> IoResult<Self::Output> {
let mut buf = Vec::new();
let mut byte = [0u8; 1];
loop {
reader.read_exact(&mut byte)?;
is![byte[0] == 0, break];
buf.push(byte[0]);
}
CString::new(buf).map_err(|_|
IoError::new(IoErrorKind::InvalidData, "Invalid C string")) } }
impl<W: IoWrite, T: Clone + Encodable<W>> Encodable<W> for Cow<'_, T> {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
self.as_ref().encode(writer) } }
}
#[rustfmt::skip]
#[allow(clippy::io_other_error, reason = "not implemented in core version")]
impl<W: IoWrite> Encodable<W> for FmtArguments<'_> {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
struct InlineFmtAdapter<'a, W: IoWrite> {
writer: &'a mut W,
error: Option<IoError>,
total: usize,
}
impl<W: IoWrite> FmtWrite for InlineFmtAdapter<'_, W> {
fn write_str(&mut self, s: &str) -> FmtResult<()> {
match self.writer.write(s.as_bytes()) {
Ok(n) => { self.total += n; Ok(()) }
Err(e) => { self.error = Some(e); Err(FmtError) }
}
}
}
let mut adapter = InlineFmtAdapter { writer, error: None, total: 0 };
if Fmt::write(&mut adapter, *self).is_ok() { Ok(adapter.total) }
else { Err(adapter.error
.unwrap_or_else(|| IoError::new(IoErrorKind::Other, "Formatting failed"))) }
}
}
impl<W: IoWrite> Encodable<W> for char {
fn encode(&self, w: &mut W) -> IoResult<usize> {
let mut buf = [0; 4];
let s = self.encode_utf8(&mut buf);
w.write(s.as_bytes())
}
}
impl<R: IoRead> Decodable<R> for char {
type Output = char;
fn decode(reader: &mut R) -> IoResult<Self::Output> {
let mut buf = [0u8; 4]; reader.read_exact(&mut buf[..1])?;
let len = Char(buf[0]).len_utf8_unchecked();
reader.read_exact(&mut buf[1..len])?;
let utf8_str = from_utf8(&buf[..len])
.map_err(|_| IoError::new(IoErrorKind::InvalidData, "Invalid UTF-8 sequence"))?;
utf8_str
.chars()
.next()
.ok_or_else(|| IoError::new(IoErrorKind::UnexpectedEof, "Empty UTF-8 sequence"))
}
}
impl<W: IoWrite> Encodable<W> for u8 {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
writer.write(Slice::from_ref(self))
}
}
impl<R: IoRead> Decodable<R> for u8 {
type Output = u8;
fn decode(reader: &mut R) -> IoResult<u8> {
let mut buf = [0u8; size_of::<u8>()];
reader.read_exact(&mut buf)?;
Ok(buf[0])
}
}
impl<W: IoWrite> Encodable<W> for i8 {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
(*self as u8).encode(writer)
}
}
impl<R: IoRead> Decodable<R> for i8 {
type Output = i8;
fn decode(reader: &mut R) -> IoResult<i8> {
let mut buf = [0u8; size_of::<i8>()];
reader.read_exact(&mut buf)?;
Ok(buf[0] as i8)
}
}
impl<W: IoWrite> Encodable<W> for bool {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
u8::from(*self).encode(writer)
}
}
impl<R: IoRead> Decodable<R> for bool {
type Output = bool;
fn decode(reader: &mut R) -> IoResult<Self::Output> {
let mut buf = [0u8; 1];
reader.read_exact(&mut buf)?;
match buf[0] {
0 => Ok(false),
1 => Ok(true),
_ => Err(IoError::new(IoErrorKind::InvalidData, "Invalid boolean value")),
}
}
}
impl<T: Encodable<W> + ?Sized, W: IoWrite> Encodable<W> for &T {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
T::encode(self, writer)
}
}
sf! {
impl<W: IoWrite, const SIZE: usize> Encodable<W> for [u8; SIZE] {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
writer.write(self)
}
}
impl<R: IoRead, const SIZE: usize> Decodable<R> for [u8; SIZE] {
type Output = [u8; SIZE];
fn decode(reader: &mut R) -> IoResult<Self::Output> {
let mut buf = [0u8; SIZE];
reader.read_exact(&mut buf)?;
Ok(buf)
}
}
impl<W: IoWrite> Encodable<W> for str {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
writer.write(self.as_bytes())
}
}
impl<'a> Decodable<&'a mut &[u8]> for &'a str {
type Output = Self;
fn decode(reader: &mut &'a mut &[u8]) -> IoResult<Self::Output> {
let s = from_utf8(reader)
.map_err(|_| IoError::new(IoErrorKind::InvalidData, "Invalid UTF-8"))?;
**reader = &[];
Ok(s)
}
}
impl<W: IoWrite> Encodable<W> for [u8] {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
writer.write(self)
}
}
impl<W: IoWrite> Encodable<W> for CStr {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
writer.write(self.to_bytes_with_nul())
}
}
}
macro_rules! impl_encodable_for_tuple {
($($T:tt)*) => { $crate::paste! {
impl<WRITER, A, $($T,)*> Encodable<WRITER> for (A,$($T,)*)
where
WRITER: IoWrite,
A: Encodable<WRITER>,
$($T: Encodable<WRITER>,)*
{
fn encode(&self, writer: &mut WRITER) -> IoResult<usize> {
let (a, $([<$T:lower>],)*) = self;
let mut total = 0;
total += a.encode(writer)?;
$(
total += [<$T:lower>].encode(writer)?;
)*
Ok(total)
}
}
}};
}
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R S T U V W X Y);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R S T U V W X);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R S T U V W);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R S T U V);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R S T U);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R S T);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R S);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q R);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P Q);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O P);
impl_encodable_for_tuple!(B C D E F G H I J K L M N O);
impl_encodable_for_tuple!(B C D E F G H I J K L M N);
impl_encodable_for_tuple!(B C D E F G H I J K L M);
impl_encodable_for_tuple!(B C D E F G H I J K L);
impl_encodable_for_tuple!(B C D E F G H I J K);
impl_encodable_for_tuple!(B C D E F G H I J);
impl_encodable_for_tuple!(B C D E F G H I);
impl_encodable_for_tuple!(B C D E F G H);
impl_encodable_for_tuple!(B C D E F G);
impl_encodable_for_tuple!(B C D E F);
impl_encodable_for_tuple!(B C D E);
impl_encodable_for_tuple!(B C D);
impl_encodable_for_tuple!(B C);
impl_encodable_for_tuple!(B);
impl_encodable_for_tuple!();
sf! {
impl<T: Encodable<W>, W: IoWrite> Encodable<W> for Option<T> {
fn encode(&self, writer: &mut W) -> IoResult<usize> {
match self { Some(value) => value.encode(writer), None => Ok(0) }
}
}
impl<W: IoWrite> Encodable<W> for NoData {
fn encode(&self, _writer: &mut W) -> IoResult<usize> { Ok(0) }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn option() {
let mut writer = &mut [0u8; 32] as &mut [u8];
None::<Option<u8>>.encode(&mut writer).unwrap();
Some(42u8).encode(&mut writer).unwrap();
}
}