//! Binary data conversion utilities. use crate::durandal::err::*; use serde::Serialize; use std::{fmt, num::NonZeroU16, slice::SliceIndex}; /// Returns a byte array from `b` at `i`. pub fn c_data(b: &[u8], i: I) -> ResultS<&>::Output> where I: SliceIndex<[u8]> { ok!(b.get(i), "not enough data") } /// Returns a byte from `b` at `i`. pub fn c_byte(b: &[u8], i: usize) -> ResultS { match b.get(i) { Some(&v) => Ok(v), None => Err(err_msg("not enough data")), } } /// Returns a four-character-code identifier from `b` at `i`. pub fn c_iden(b: &[u8], i: usize) -> ResultS { ok!(o_iden(b, i), "not enough data") } /// Returns a big-endian `u32` from `b` at `i`. pub fn c_u32b(b: &[u8], i: usize) -> ResultS { ok!(o_u32b(b, i), "not enough data") } /// Returns a big-endian `u16` from `b` at `i`. pub fn c_u16b(b: &[u8], i: usize) -> ResultS { ok!(o_u16b(b, i), "not enough data") } /// Returns a big-endian `i32` from `b` at `i`. pub fn c_i32b(b: &[u8], i: usize) -> ResultS { ok!(o_i32b(b, i), "not enough data") } /// Returns a big-endian `i16` from `b` at `i`. pub fn c_i16b(b: &[u8], i: usize) -> ResultS { ok!(o_i16b(b, i), "not enough data") } /// Returns a four-character-code identifier from `b` at `i`. pub fn o_iden(b: &[u8], i: usize) -> Option { if i + 3 < b.len() { Some([b[i], b[i + 1], b[i + 2], b[i + 3]]) } else { None } } /// Returns a big-endian `u32` from `b` at `i`. pub fn o_u32b(b: &[u8], i: usize) -> Option { if i + 3 < b.len() { Some(u32::from_be_bytes([b[i], b[i + 1], b[i + 2], b[i + 3]])) } else { None } } /// Returns a big-endian `u16` from `b` at `i`. pub fn o_u16b(b: &[u8], i: usize) -> Option { if i + 1 < b.len() { Some(u16::from_be_bytes([b[i], b[i + 1]])) } else { None } } /// Returns a big-endian `i32` from `b` at `i`. pub fn o_i32b(b: &[u8], i: usize) -> Option { match o_u32b(b, i) { Some(n) => Some(n as i32), None => None, } } /// Returns a big-endian `i16` from `b` at `i`. pub fn o_i16b(b: &[u8], i: usize) -> Option { match o_u16b(b, i) { Some(n) => Some(n as i16), None => None, } } impl ObjID { /// Creates an `ObjID` from a `u16`. pub fn from_repr(n: u16) -> ObjID { if n == u16::max_value() { ObjID(None) } else { ObjID(NonZeroU16::new(n + 1)) } } /// Returns the `u16` representation of an `ObjID`. pub fn get_repr(&self) -> u16 { match self.0 { None => u16::max_value(), Some(n) => n.get() - 1, } } /// Returns the `Option` representation of an `ObjID`. pub fn get(&self) -> Option { match self.0 { None => None, Some(n) => Some(n.get()), } } } impl fmt::Debug for ObjID { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { None => write!(f, "ObjID(None)"), Some(n) => write!(f, "ObjID({})", n.get()), } } } /// A four-character-code identifier. pub type Ident = [u8; 4]; /// An object identified by a `u16` which may be `u16::max_value()` to /// represent None. #[derive(Serialize)] pub struct ObjID(Option); // EOF