use super::{bytes_as_mut_slice, bytes_as_slice, check_for_extra_bytes};
use crate::{ReadDataError, ReadableElement, ViewDataError, ViewElement, ViewMutElement};
use py_literal::Value as PyValue;
use std::error::Error;
use std::fmt;
use std::io;
use std::mem;
#[derive(Debug)]
struct ParseBoolError {
bad_value: u8,
}
impl Error for ParseBoolError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
}
impl fmt::Display for ParseBoolError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "error parsing value {:#04x} as a bool", self.bad_value)
}
}
impl From<ParseBoolError> for ReadDataError {
fn from(err: ParseBoolError) -> ReadDataError {
ReadDataError::ParseData(Box::new(err))
}
}
impl From<ParseBoolError> for ViewDataError {
fn from(err: ParseBoolError) -> ViewDataError {
ViewDataError::InvalidData(Box::new(err))
}
}
fn check_valid_for_bool(bytes: &[u8]) -> Result<(), ParseBoolError> {
for &byte in bytes {
if byte > 1 {
return Err(ParseBoolError { bad_value: byte });
}
}
Ok(())
}
impl ReadableElement for bool {
fn read_to_end_exact_vec<R: io::Read>(
mut reader: R,
type_desc: &PyValue,
len: usize,
) -> Result<Vec<Self>, ReadDataError> {
match *type_desc {
PyValue::String(ref s) if s == "|b1" => {
let mut bytes: Vec<u8> = vec![0; len];
reader.read_exact(&mut bytes)?;
check_for_extra_bytes(&mut reader)?;
check_valid_for_bool(&bytes)?;
{
let ptr: *mut u8 = bytes.as_mut_ptr();
let len: usize = bytes.len();
let cap: usize = bytes.capacity();
mem::forget(bytes);
Ok(unsafe { Vec::from_raw_parts(ptr.cast::<bool>(), len, cap) })
}
}
ref other => Err(ReadDataError::WrongDescriptor(other.clone())),
}
}
}
impl_writable_element_always_valid_cast!(bool, "|b1", "|b1");
impl ViewElement for bool {
fn bytes_as_slice<'a>(
bytes: &'a [u8],
type_desc: &PyValue,
len: usize,
) -> Result<&'a [Self], ViewDataError> {
match *type_desc {
PyValue::String(ref s) if s == "|b1" => {
check_valid_for_bool(bytes)?;
unsafe { bytes_as_slice(bytes, len) }
}
ref other => Err(ViewDataError::WrongDescriptor(other.clone())),
}
}
}
impl ViewMutElement for bool {
fn bytes_as_mut_slice<'a>(
bytes: &'a mut [u8],
type_desc: &PyValue,
len: usize,
) -> Result<&'a mut [Self], ViewDataError> {
match *type_desc {
PyValue::String(ref s) if s == "|b1" => {
check_valid_for_bool(bytes)?;
unsafe { bytes_as_mut_slice(bytes, len) }
}
ref other => Err(ViewDataError::WrongDescriptor(other.clone())),
}
}
}