2018-09-06 09:01:52 -07:00
|
|
|
//! Binary data conversion utilities.
|
|
|
|
|
2018-12-11 00:08:23 -08:00
|
|
|
use crate::durandal::err::*;
|
2019-02-09 11:01:35 -08:00
|
|
|
use std::{fmt,
|
|
|
|
num::NonZeroU16};
|
2018-09-06 09:01:52 -07:00
|
|
|
|
2018-09-11 12:07:42 -07:00
|
|
|
pub trait BinUtil
|
|
|
|
{
|
2019-02-09 21:52:23 -08:00
|
|
|
/// Returns a four-character-code identifier from `self` at `i`.
|
2018-09-11 12:07:42 -07:00
|
|
|
fn c_iden(&self, i: usize) -> ResultS<Ident>;
|
2019-02-09 21:52:23 -08:00
|
|
|
|
|
|
|
/// Returns a big-endian `u32` from `self` at `i`.
|
2018-09-11 12:07:42 -07:00
|
|
|
fn c_u32b(&self, i: usize) -> ResultS<u32>;
|
2019-02-09 21:52:23 -08:00
|
|
|
|
|
|
|
/// Returns a big-endian `u16` from `self` at `i`.
|
2018-09-11 12:07:42 -07:00
|
|
|
fn c_u16b(&self, i: usize) -> ResultS<u16>;
|
|
|
|
|
2019-02-09 21:52:23 -08:00
|
|
|
/// Returns a big-endian `i32` from `self` at `i`.
|
2018-09-11 12:07:42 -07:00
|
|
|
fn c_i32b(&self, i: usize) -> ResultS<i32>
|
2019-02-08 21:53:27 -08:00
|
|
|
{
|
|
|
|
match self.c_u32b(i) {
|
|
|
|
Ok(n) => Ok(n as i32),
|
|
|
|
Err(e) => Err(e),
|
|
|
|
}
|
|
|
|
}
|
2019-02-09 21:52:23 -08:00
|
|
|
|
|
|
|
/// Returns a big-endian `i16` from `self` at `i`.
|
2018-09-11 12:07:42 -07:00
|
|
|
fn c_i16b(&self, i: usize) -> ResultS<i16>
|
2019-02-08 21:53:27 -08:00
|
|
|
{
|
|
|
|
match self.c_u16b(i) {
|
|
|
|
Ok(n) => Ok(n as i16),
|
|
|
|
Err(e) => Err(e),
|
|
|
|
}
|
|
|
|
}
|
2018-09-11 12:07:42 -07:00
|
|
|
|
2019-02-09 21:52:23 -08:00
|
|
|
/// The same as `c_iden`, but returns `Option`.
|
2019-02-08 21:53:27 -08:00
|
|
|
fn o_iden(&self, i: usize) -> Option<Ident>
|
|
|
|
{
|
|
|
|
self.c_iden(i).ok()
|
|
|
|
}
|
2019-02-09 21:52:23 -08:00
|
|
|
|
|
|
|
/// The same as `c_u32b`, but returns `Option`.
|
2019-02-08 21:53:27 -08:00
|
|
|
fn o_u32b(&self, i: usize) -> Option<u32>
|
|
|
|
{
|
|
|
|
self.c_u32b(i).ok()
|
|
|
|
}
|
2019-02-09 21:52:23 -08:00
|
|
|
|
|
|
|
/// The same as `c_u16b`, but returns `Option`.
|
2019-02-08 21:53:27 -08:00
|
|
|
fn o_u16b(&self, i: usize) -> Option<u16>
|
|
|
|
{
|
|
|
|
self.c_u16b(i).ok()
|
|
|
|
}
|
2019-02-09 21:52:23 -08:00
|
|
|
|
|
|
|
/// The same as `c_i32b`, but returns `Option`.
|
2019-02-08 21:53:27 -08:00
|
|
|
fn o_i32b(&self, i: usize) -> Option<i32>
|
|
|
|
{
|
|
|
|
self.c_i32b(i).ok()
|
|
|
|
}
|
2019-02-09 21:52:23 -08:00
|
|
|
|
|
|
|
/// The same as `c_i16b`, but returns `Option`.
|
2019-02-08 21:53:27 -08:00
|
|
|
fn o_i16b(&self, i: usize) -> Option<i16>
|
|
|
|
{
|
|
|
|
self.c_i16b(i).ok()
|
|
|
|
}
|
2018-09-11 12:07:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BinUtil for [u8]
|
|
|
|
{
|
|
|
|
fn c_iden(&self, i: usize) -> ResultS<Ident>
|
|
|
|
{
|
2019-02-05 23:01:47 -08:00
|
|
|
if i + 3 < self.len() {
|
|
|
|
Ok([self[i], self[i + 1], self[i + 2], self[i + 3]])
|
|
|
|
} else {
|
|
|
|
Err(err_msg("not enough data"))
|
|
|
|
}
|
2018-09-11 12:07:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn c_u32b(&self, i: usize) -> ResultS<u32>
|
|
|
|
{
|
2019-02-05 23:01:47 -08:00
|
|
|
if i + 3 < self.len() {
|
2019-02-08 21:53:27 -08:00
|
|
|
Ok(u32::from_be_bytes([self[i],
|
|
|
|
self[i + 1],
|
|
|
|
self[i + 2],
|
|
|
|
self[i + 3]]))
|
2019-02-05 23:01:47 -08:00
|
|
|
} else {
|
|
|
|
Err(err_msg("not enough data"))
|
|
|
|
}
|
2018-09-11 12:07:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn c_u16b(&self, i: usize) -> ResultS<u16>
|
|
|
|
{
|
2019-02-05 23:01:47 -08:00
|
|
|
if i + 1 < self.len() {
|
|
|
|
Ok(u16::from_be_bytes([self[i], self[i + 1]]))
|
|
|
|
} else {
|
|
|
|
Err(err_msg("not enough data"))
|
|
|
|
}
|
2018-09-11 12:07:42 -07:00
|
|
|
}
|
|
|
|
}
|
2018-09-06 09:01:52 -07:00
|
|
|
|
2019-02-09 21:52:23 -08:00
|
|
|
/// A four-character-code identifier.
|
|
|
|
pub type Ident = [u8; 4];
|
2018-09-06 09:01:52 -07:00
|
|
|
|
2019-02-09 21:52:23 -08:00
|
|
|
/// An object identified by a `u16` which may be `u16::max_value()` to
|
|
|
|
/// represent None.
|
2019-02-09 11:01:35 -08:00
|
|
|
pub struct ObjID(Option<NonZeroU16>);
|
|
|
|
|
|
|
|
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()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ObjID
|
|
|
|
{
|
2019-02-09 21:52:23 -08:00
|
|
|
/// Creates an `ObjID` from a `u16`.
|
2019-02-09 11:01:35 -08:00
|
|
|
pub fn from_repr(n: u16) -> ObjID
|
|
|
|
{
|
|
|
|
if n == u16::max_value() {
|
|
|
|
ObjID(None)
|
|
|
|
} else {
|
|
|
|
ObjID(NonZeroU16::new(n + 1))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-09 21:52:23 -08:00
|
|
|
/// Returns the `u16` representation of an `ObjID`.
|
2019-02-09 11:01:35 -08:00
|
|
|
pub fn get_repr(&self) -> u16
|
|
|
|
{
|
|
|
|
match self.0 {
|
|
|
|
None => u16::max_value(),
|
|
|
|
Some(n) => n.get() - 1,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-09 21:52:23 -08:00
|
|
|
/// Returns the `Option` representation of an `ObjID`.
|
2019-02-09 11:01:35 -08:00
|
|
|
pub fn get(&self) -> Option<u16>
|
|
|
|
{
|
|
|
|
match self.0 {
|
|
|
|
None => None,
|
|
|
|
Some(n) => Some(n.get()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-06 09:01:52 -07:00
|
|
|
// EOF
|