doc everything
parent
6e4c7512e8
commit
1d6aa0c14e
|
@ -22,16 +22,16 @@ macro_rules! _durandal_read_impl {
|
|||
|
||||
// little endian
|
||||
(LE $b:ident $nam:ident u16 $n:expr) => {
|
||||
_durandal_read_impl!($b u16::from_le_bytes $nam 2 $n);
|
||||
_durandal_read_impl!($b u16::from_le_bytes, $nam 2 $n);
|
||||
};
|
||||
(LE $b:ident $nam:ident i16 $n:expr) => {
|
||||
_durandal_read_impl!($b i16::from_le_bytes $nam 2 $n);
|
||||
_durandal_read_impl!($b i16::from_le_bytes, $nam 2 $n);
|
||||
};
|
||||
(LE $b:ident $nam:ident u32 $n:expr) => {
|
||||
_durandal_read_impl!($b u32::from_le_bytes $nam 4 $n);
|
||||
_durandal_read_impl!($b u32::from_le_bytes, $nam 4 $n);
|
||||
};
|
||||
(LE $b:ident $nam:ident i32 $n:expr) => {
|
||||
_durandal_read_impl!($b i32::from_le_bytes $nam 4 $n);
|
||||
_durandal_read_impl!($b i32::from_le_bytes, $nam 4 $n);
|
||||
};
|
||||
|
||||
// either endianness
|
||||
|
@ -87,6 +87,8 @@ macro_rules! _durandal_read_impl {
|
|||
|
||||
/// Reads structured data from a byte slice.
|
||||
///
|
||||
/// # Syntax
|
||||
///
|
||||
/// First start by specifying the endianness, size and source using the syntax
|
||||
/// `endian, size in source =>` where:
|
||||
///
|
||||
|
@ -126,14 +128,41 @@ macro_rules! _durandal_read_impl {
|
|||
/// - `place` is either an integer literal which must be representable as
|
||||
/// `usize`, or a range, which may only be used when `type` is a function
|
||||
/// name.
|
||||
#[macro_export]
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This macro will not panic unless any index expression used exceeds `size`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate maraiah;
|
||||
/// # use maraiah::durandal::err::*;
|
||||
/// # fn main() -> ResultS<()>
|
||||
/// # {
|
||||
/// let buffer = &[4, 0, 2, 0, 0, 0, 6];
|
||||
///
|
||||
/// read_data! {
|
||||
/// 7, LE in buffer =>
|
||||
/// four = u16[0];
|
||||
/// two = u32[2];
|
||||
/// six = u8 [6];
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(four, 4_u16);
|
||||
/// assert_eq!(two, 2_u32);
|
||||
/// assert_eq!(six, 6_u8);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! read_data {
|
||||
(
|
||||
$sz:expr , $ty:ident in $b:ident =>
|
||||
$( $nam:ident = $t:ident [ $n:expr ] $( $ex:ident )* ; )*
|
||||
) => {
|
||||
if $b.len() < $sz {
|
||||
bail!("not enough data");
|
||||
return Err(err_msg("not enough data"));
|
||||
}
|
||||
|
||||
$($crate::_durandal_read_impl!($ty $b $nam $($ex)* $t $n);)*
|
||||
|
@ -141,32 +170,91 @@ macro_rules! read_data {
|
|||
}
|
||||
|
||||
/// Casts a `u32` to a `usize`. For future compatibility.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::usize_from_u32;
|
||||
///
|
||||
/// assert_eq!(usize_from_u32(777u32), 777usize);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub const fn usize_from_u32(n: u32) -> usize {n as usize}
|
||||
|
||||
/// Creates an `Ident` from a slice.
|
||||
///
|
||||
/// `b` must be at least 4 bytes, or a panic will occur.
|
||||
pub fn ident(b: &[u8]) -> Ident {Ident([b[0], b[1], b[2], b[3]])}
|
||||
/// # Panics
|
||||
///
|
||||
/// A panic will occur if `b.len()` is less than 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::{Ident, ident};
|
||||
///
|
||||
/// assert_eq!(ident(b"POLY"), Ident([b'P', b'O', b'L', b'Y']));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub const fn ident(b: &[u8]) -> Ident {Ident([b[0], b[1], b[2], b[3]])}
|
||||
|
||||
/// Applies `u32::from_be_bytes` to a slice.
|
||||
///
|
||||
/// `b` must be at least 4 bytes, or a panic will occur.
|
||||
/// # Panics
|
||||
///
|
||||
/// A panic will occur if `b.len()` is less than 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::u32b;
|
||||
///
|
||||
/// assert_eq!(u32b(&[0x00, 0x0B, 0xDE, 0x31]), 777_777u32);
|
||||
/// ```
|
||||
pub fn u32b(b: &[u8]) -> u32 {u32::from_be_bytes([b[0], b[1], b[2], b[3]])}
|
||||
|
||||
/// Applies `u16::from_be_bytes` to a slice.
|
||||
///
|
||||
/// `b` must be at least 2 bytes, or a panic will occur.
|
||||
/// # Panics
|
||||
///
|
||||
/// A panic will occur if `b.len()` is less than 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::u16b;
|
||||
///
|
||||
/// assert_eq!(u16b(&[0x1E, 0x61]), 7_777u16);
|
||||
/// ```
|
||||
pub fn u16b(b: &[u8]) -> u16 {u16::from_be_bytes([b[0], b[1]])}
|
||||
|
||||
/// Applies `i32::from_be_bytes` to a slice.
|
||||
///
|
||||
/// `b` must be at least 4 bytes, or a panic will occur.
|
||||
/// # Panics
|
||||
///
|
||||
/// A panic will occur if `b.len()` is less than 4.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::i32b;
|
||||
///
|
||||
/// assert_eq!(i32b(&[0xFF, 0x89, 0x52, 0x0F]), -7_777_777i32);
|
||||
/// ```
|
||||
pub fn i32b(b: &[u8]) -> i32 {i32::from_be_bytes([b[0], b[1], b[2], b[3]])}
|
||||
|
||||
/// Applies `i16::from_be_bytes` to a slice.
|
||||
///
|
||||
/// `b` must be at least 2 bytes, or a panic will occur.
|
||||
/// # Panics
|
||||
///
|
||||
/// A panic will occur if `b.len()` is less than 2.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::i16b;
|
||||
///
|
||||
/// assert_eq!(i16b(&[0xE1, 0x9F]), -7_777i16);
|
||||
/// ```
|
||||
pub fn i16b(b: &[u8]) -> i16 {i16::from_be_bytes([b[0], b[1]])}
|
||||
|
||||
/// Applies a read function over a slice.
|
||||
|
@ -175,6 +263,26 @@ pub fn i16b(b: &[u8]) -> i16 {i16::from_be_bytes([b[0], b[1]])}
|
|||
/// iteration will pass a slice of `b` to `read` for it to read from, and then
|
||||
/// increments the slice index by the second return value. When there is no
|
||||
/// data left in `b`, the function returns.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// A panic will occur if the `read` function returns a disjoint index or
|
||||
/// otherwise panics (by an out of bounds index to `b` or otherwise.)
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Execution will return the result of `read` if `read` returns an error.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::{err::*, bin::{rd_array, u16b}};
|
||||
///
|
||||
/// fn read_a_u16(b: &[u8]) -> ResultS<(u16, usize)> {Ok((u16b(b), 2))}
|
||||
///
|
||||
/// let inp = &[0x1E, 0x61, 0x03, 0x09];
|
||||
/// assert_eq!(rd_array(inp, read_a_u16).unwrap(), vec![7_777u16, 777u16]);
|
||||
/// ```
|
||||
pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
|
||||
where T: Sized,
|
||||
F: Fn(&[u8]) -> ResultS<(T, usize)>
|
||||
|
@ -198,6 +306,15 @@ pub fn rd_array<T, F>(b: &[u8], read: F) -> ResultS<Vec<T>>
|
|||
/// reads a 32-bit big endian offset from `b`, and then passes a slice of `b`
|
||||
/// to `read` starting at that offset. When all offsets have been read, the
|
||||
/// function returns.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// A panic will occur if the `read` function returns a disjoint index or
|
||||
/// otherwise panics (by an out of bounds index to `b` or otherwise.)
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Execution will return the result of `read` if `read` returns an error.
|
||||
pub fn rd_ofstable<T, F>(b: &[u8],
|
||||
mut p: usize,
|
||||
num: usize,
|
||||
|
@ -225,6 +342,14 @@ pub fn rd_ofstable<T, F>(b: &[u8],
|
|||
impl OptU16
|
||||
{
|
||||
/// Creates an `OptU16` representing `None`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::OptU16;
|
||||
///
|
||||
/// assert_eq!(OptU16::none(), OptU16::from_repr(u16::max_value()));
|
||||
/// ```
|
||||
pub const fn none() -> Self {OptU16(None)}
|
||||
|
||||
/// Creates an `OptU16` from a `u16`.
|
||||
|
@ -238,6 +363,18 @@ impl OptU16
|
|||
}
|
||||
|
||||
/// Returns the `u16` representation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::OptU16;
|
||||
///
|
||||
/// let u16max = u16::max_value();
|
||||
///
|
||||
/// assert_eq!(OptU16::from_repr(500u16).get_repr(), 500u16);
|
||||
/// assert_eq!(OptU16::from_repr(u16max).get_repr(), u16max);
|
||||
/// assert_eq!(OptU16::from_repr(0u16).get_repr(), 0u16);
|
||||
/// ```
|
||||
pub fn get_repr(&self) -> u16
|
||||
{
|
||||
match self.0 {
|
||||
|
@ -247,6 +384,16 @@ impl OptU16
|
|||
}
|
||||
|
||||
/// Returns the `Option` representation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::OptU16;
|
||||
///
|
||||
/// assert_eq!(OptU16::from_repr(500u16).get(), Some(500u16));
|
||||
/// assert_eq!(OptU16::from_repr(u16::max_value()).get(), None);
|
||||
/// assert_eq!(OptU16::from_repr(0u16).get(), Some(0u16));
|
||||
/// ```
|
||||
pub fn get(&self) -> Option<u16>
|
||||
{
|
||||
match self.0 {
|
||||
|
@ -276,12 +423,22 @@ impl fmt::Debug for Ident
|
|||
}
|
||||
|
||||
/// A four-character-code identifier.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::bin::Ident;
|
||||
///
|
||||
/// assert_eq!(Ident(*b"POLY").0, *b"POLY");
|
||||
/// ```
|
||||
#[derive(Clone, Copy, Default, PartialEq)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct Ident(pub [u8; 4]);
|
||||
|
||||
/// An object identified by a `u16` which may be `u16::max_value()` to
|
||||
/// represent a nulled value.
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Copy, Default, PartialEq)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct OptU16(Option<NonZeroU16>);
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -8,6 +8,29 @@
|
|||
///
|
||||
/// This will generate an `enum E` as well as a function `E::from_repr` which
|
||||
/// will return `Result<E, ReprError>`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::{c_enum, durandal::err::ReprError};
|
||||
///
|
||||
/// c_enum! {
|
||||
/// #[derive(Debug, PartialEq)]
|
||||
/// enum MyEnum: u16
|
||||
/// {
|
||||
/// 0 => Zero,
|
||||
/// 1 => One,
|
||||
/// 2 => Two,
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(MyEnum::from_repr(0), Ok(MyEnum::Zero));
|
||||
/// assert_eq!(MyEnum::from_repr(1), Ok(MyEnum::One));
|
||||
/// assert_eq!(MyEnum::from_repr(2), Ok(MyEnum::Two));
|
||||
/// assert_eq!(MyEnum::from_repr(3), Err(ReprError::new(3)));
|
||||
/// assert_eq!(MyEnum::from_repr(4), Err(ReprError::new(4)));
|
||||
/// assert_eq!(MyEnum::from_repr(5), Err(ReprError::new(5)));
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! c_enum
|
||||
{
|
||||
|
|
|
@ -19,6 +19,14 @@ fn crc_init() -> [u32; 256]
|
|||
}
|
||||
|
||||
/// Creates a CRC-32 of all bytes in `b` with the starting sum `s`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::crc::crc32;
|
||||
///
|
||||
/// assert_eq!(crc32(b"Lorem ipsum dolor sit amet", !0), 0x5F29_D461);
|
||||
/// ```
|
||||
pub fn crc32(b: &[u8], s: u32) -> u32
|
||||
{
|
||||
let t = crc_init();
|
||||
|
@ -26,10 +34,4 @@ pub fn crc32(b: &[u8], s: u32) -> u32
|
|||
.fold(s, |a, &o| a >> 8 ^ t[usize::from(a as u8 ^ o)])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn crc32_lorem_ipsum()
|
||||
{
|
||||
assert_eq!(crc32(b"Lorem ipsum dolor sit amet", !0), 0x5F29_D461);
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -29,10 +29,29 @@ macro_rules! bail {
|
|||
}
|
||||
|
||||
/// Returns an `Error` with a static string.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::err::err_msg;
|
||||
///
|
||||
/// assert_eq!(format!("{}", err_msg("oh no not things")), "oh no not things");
|
||||
/// ```
|
||||
pub fn err_msg(msg: &'static str) -> Error {Error::from(ErrMsg(msg))}
|
||||
|
||||
impl ReprError
|
||||
{
|
||||
/// Creates a new `ReprError`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::err::ReprError;
|
||||
///
|
||||
/// let err = ReprError::new(7);
|
||||
///
|
||||
/// assert_eq!(format!("{}", err), "representation error (got 7)");
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn new<T>(n: T) -> Self where T: Into<i64> {Self(n.into())}
|
||||
}
|
||||
|
|
|
@ -63,8 +63,11 @@ macro_rules! fixed_ref_op_assign {
|
|||
|
||||
macro_rules! define_fixed_types {
|
||||
(
|
||||
$($(#[$outer:meta])*
|
||||
struct $t:ident ($ti:ident, $bytes:expr) : $tu:ident, $frac_bits:expr;)*
|
||||
$(
|
||||
$(#[$outer:meta])*
|
||||
struct $t:ident ( $ti:ident, $bytes:expr ) :
|
||||
$tu:ident, $frac_bits:expr; $test:ident
|
||||
)*
|
||||
) => {$(
|
||||
$(#[$outer])*
|
||||
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, serde::Serialize)]
|
||||
|
@ -230,6 +233,43 @@ macro_rules! define_fixed_types {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod $test {
|
||||
use super::$t;
|
||||
|
||||
#[test]
|
||||
fn basic_ops()
|
||||
{
|
||||
let one = $t::one();
|
||||
let two = 2 << $t::frac_bits();
|
||||
let twelve = 12 << $t::frac_bits();
|
||||
|
||||
assert_eq!(($t::from(1) + $t::from(1)).to_bits(), two);
|
||||
assert_eq!(($t::from(2) - $t::from(1)).to_bits(), one);
|
||||
assert_eq!(($t::from(6) * $t::from(2)).to_bits(), twelve);
|
||||
assert_eq!(($t::from(6) * 2) .to_bits(), twelve);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fractions()
|
||||
{
|
||||
let three_pt_5 = 3 << $t::frac_bits() | $t::one() / 2;
|
||||
let one_pt_2 = 1 << $t::frac_bits() | $t::one() / 5;
|
||||
let two_pt_4 = one_pt_2 * 2;
|
||||
|
||||
assert_eq!(($t::from(7) / $t::from(2)) .to_bits(), three_pt_5);
|
||||
assert_eq!(($t::from(7) / 2) .to_bits(), three_pt_5);
|
||||
assert_eq!(($t::from_bits(one_pt_2) * 2).to_bits(), two_pt_4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn printing()
|
||||
{
|
||||
assert_eq!(format!("{}", $t::from(6)), "6.0");
|
||||
assert_eq!(format!("{:2.3}", $t::from(7) / 2), " 3.500");
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$ti> for $t
|
||||
{
|
||||
#[inline]
|
||||
|
@ -388,42 +428,17 @@ define_fixed_types! {
|
|||
///
|
||||
/// The format of this type is `0.9s`, but because of the implementation,
|
||||
/// the real format is `7.9s`.
|
||||
struct Angle(i16, 2) : u16, 9;
|
||||
struct Angle(i16, 2) : u16, 9; angle_tests
|
||||
|
||||
/// A fixed point type representing a world unit.
|
||||
///
|
||||
/// The format of this type is `5.10s`. This has caused eternal suffering.
|
||||
struct Unit(i16, 2) : u16, 10;
|
||||
struct Unit(i16, 2) : u16, 10; unit_tests
|
||||
|
||||
/// A generic fixed point type.
|
||||
///
|
||||
/// The format of this type is `15.16s`.
|
||||
struct Fixed(i32, 4) : u32, 16;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixed_basic_ops()
|
||||
{
|
||||
let one = Fixed::one();
|
||||
let two = 2 << Fixed::frac_bits();
|
||||
let twelve = 12 << Fixed::frac_bits();
|
||||
|
||||
assert_eq!((Fixed::from(1) + Fixed::from(1)).to_bits(), two);
|
||||
assert_eq!((Fixed::from(2) - Fixed::from(1)).to_bits(), one);
|
||||
assert_eq!((Fixed::from(6) * Fixed::from(2)).to_bits(), twelve);
|
||||
assert_eq!((Fixed::from(6) * 2) .to_bits(), twelve);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixed_fractions()
|
||||
{
|
||||
let three_pt_5 = 3 << Fixed::frac_bits() | Fixed::one() / 2;
|
||||
let one_pt_2 = 1 << Fixed::frac_bits() | Fixed::one() / 5;
|
||||
let two_pt_4 = 157_286;
|
||||
|
||||
assert_eq!((Fixed::from(7) / Fixed::from(2)).to_bits(), three_pt_5);
|
||||
assert_eq!((Fixed::from(7) / 2) .to_bits(), three_pt_5);
|
||||
assert_eq!((Fixed::from_bits(one_pt_2) * 2) .to_bits(), two_pt_4);
|
||||
struct Fixed(i32, 4) : u32, 16; fixed_tests
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -431,13 +446,4 @@ fn fixed_fractions()
|
|||
#[allow(unused_must_use)]
|
||||
fn fixed_overflow() {Fixed::from(i16::max_value() as i32) + Fixed::from(1);}
|
||||
|
||||
#[test]
|
||||
fn fixed_printing()
|
||||
{
|
||||
assert_eq!(format!("{}", Fixed::from(6)), "6.0");
|
||||
assert_eq!(format!("{}", Fixed::from(7) / 2), "3.5");
|
||||
assert_eq!(format!("{:7.7}", Fixed::from_bits(0xDEAD_BEEF)),
|
||||
" -8531.7458343");
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -4,17 +4,31 @@ use crate::durandal::err::*;
|
|||
use std::io;
|
||||
|
||||
/// Creates a RGB8 color from a R5G5B5 format color.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::image::{Color8, r5g5b5_to_rgb8};
|
||||
///
|
||||
/// assert_eq!(r5g5b5_to_rgb8(0x2345), Color8::new(64, 208, 40));
|
||||
/// ```
|
||||
pub fn r5g5b5_to_rgb8(rgb: u16) -> Color8
|
||||
{
|
||||
let r = rgb >> 10 & 0x1f;
|
||||
let g = rgb >> 5 & 0x1f;
|
||||
let b = rgb & 0x1f;
|
||||
Color8::new((r << 3 | r >> 2) as u8,
|
||||
(g << 3 | g >> 2) as u8,
|
||||
(b << 3 | b >> 2) as u8)
|
||||
let r = (rgb >> 10) as u8 & 0x1f;
|
||||
let g = (rgb >> 5) as u8 & 0x1f;
|
||||
let b = rgb as u8 & 0x1f;
|
||||
Color8::new(r << 3, g << 3, b << 3)
|
||||
}
|
||||
|
||||
/// Creates a RGB16 color from a R5G5B5 format color.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::image::{Color16, r5g5b5_to_rgb16};
|
||||
///
|
||||
/// assert_eq!(r5g5b5_to_rgb16(0x2345), Color16::new(0x4000, 0xD000, 0x2800));
|
||||
/// ```
|
||||
pub fn r5g5b5_to_rgb16(rgb: u16) -> Color16
|
||||
{
|
||||
let r = rgb >> 10 & 0x1f;
|
||||
|
@ -24,14 +38,27 @@ pub fn r5g5b5_to_rgb16(rgb: u16) -> Color16
|
|||
}
|
||||
|
||||
/// Creates a RGB16 color from a RGB8 format color.
|
||||
pub fn rgb8_to_rgb16(r: u8, g: u8, b: u8) -> Color16
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::image;
|
||||
///
|
||||
/// let inpl = image::r5g5b5_to_rgb8(0x2345);
|
||||
/// let inph = image::r5g5b5_to_rgb16(0x2345);
|
||||
///
|
||||
/// assert_eq!(inph, image::rgb8_to_rgb16(inpl));
|
||||
/// ```
|
||||
pub fn rgb8_to_rgb16(cr: Color8) -> Color16
|
||||
{
|
||||
Color16::new(u16::from(r) << 8,
|
||||
u16::from(g) << 8,
|
||||
u16::from(b) << 8)
|
||||
Color16::new(cr.r(), cr.g(), cr.b())
|
||||
}
|
||||
|
||||
/// Writes a PPM file from an image.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Errors if `out` cannot be written to.
|
||||
pub fn write_ppm(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
|
||||
{
|
||||
write!(out, "P3\n{} {}\n{}\n", im.w(), im.h(), u16::max_value())?;
|
||||
|
@ -49,6 +76,10 @@ pub fn write_ppm(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
|
|||
}
|
||||
|
||||
/// Writes a TGA file from an image.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Errors if `out` cannot be written to.
|
||||
pub fn write_tga(out: &mut impl io::Write, im: &impl Image) -> ResultS<()>
|
||||
{
|
||||
// id len, color map type, image type
|
||||
|
|
|
@ -4,6 +4,10 @@ use crate::durandal::err::*;
|
|||
use std::io;
|
||||
|
||||
/// Writes a WAVE file from a sound.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Errors if `out` cannot be written to.
|
||||
pub fn write_wav(out: &mut impl io::Write, snd: &impl Sound) -> ResultS<()>
|
||||
{
|
||||
let smp_rate = u32::from(snd.rate());
|
||||
|
|
|
@ -2,30 +2,15 @@
|
|||
|
||||
use crate::durandal::err::*;
|
||||
|
||||
/// Dumps a slice of memory as text to stderr.
|
||||
pub fn dump_mem(b: &[u8])
|
||||
{
|
||||
let mut p = 0;
|
||||
|
||||
for &c in b {
|
||||
if p + 3 > 79 {
|
||||
eprintln!("");
|
||||
p = 0;
|
||||
}
|
||||
|
||||
if c.is_ascii_graphic() {
|
||||
eprint!(" {} ", c as char);
|
||||
} else {
|
||||
eprint!("{:02X} ", c);
|
||||
}
|
||||
|
||||
p += 3;
|
||||
}
|
||||
|
||||
eprintln!("");
|
||||
}
|
||||
|
||||
/// Formats a binary size string for any given number.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::text::to_binsize;
|
||||
///
|
||||
/// assert_eq!(to_binsize(5000), "5kB".to_string());
|
||||
/// ```
|
||||
pub fn to_binsize(n: u64) -> String
|
||||
{
|
||||
const NAMES: [&str; 4] = ["kB", "MB", "GB", "TB"];
|
||||
|
@ -70,6 +55,16 @@ pub fn fuck_string(s: &[u8]) -> Vec<u8>
|
|||
}
|
||||
|
||||
/// Reads a Pascal-style byte string with bounds checking.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::text::pascal_str;
|
||||
///
|
||||
/// assert_eq!(pascal_str(b"\x0bhello world"), b"hello world"[..].into());
|
||||
/// assert_eq!(pascal_str(b"\x0chello world"), None);
|
||||
/// assert_eq!(pascal_str(&[]), None);
|
||||
/// ```
|
||||
pub fn pascal_str(b: &[u8]) -> Option<&[u8]>
|
||||
{
|
||||
let s = usize::from(*b.get(0)?);
|
||||
|
@ -77,6 +72,15 @@ pub fn pascal_str(b: &[u8]) -> Option<&[u8]>
|
|||
}
|
||||
|
||||
/// Converts input from Mac Roman to a Unicode string.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::text::mac_roman_conv;
|
||||
///
|
||||
/// assert_eq!(mac_roman_conv(b"p\x8cth"), "påth");
|
||||
/// assert_eq!(mac_roman_conv(b"I\xd5ve"), "I’ve");
|
||||
/// ```
|
||||
pub fn mac_roman_conv(s: &[u8]) -> String
|
||||
{
|
||||
let mut v = String::with_capacity(s.len());
|
||||
|
@ -93,6 +97,14 @@ pub fn mac_roman_conv(s: &[u8]) -> String
|
|||
}
|
||||
|
||||
/// Converts a C-style string from Mac Roman to Unicode.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use maraiah::durandal::text::mac_roman_cstr;
|
||||
///
|
||||
/// assert_eq!(mac_roman_cstr(b"I\xd5ve awaken\0ed").unwrap(), "I’ve awaken");
|
||||
/// ```
|
||||
pub fn mac_roman_cstr(s: &[u8]) -> ResultS<String>
|
||||
{
|
||||
if let Some(s) = s.split(|&n| n == 0).nth(0) {
|
||||
|
@ -143,17 +155,5 @@ fn to_binsize_integrals()
|
|||
assert_eq!(to_binsize(1000 * 1000 * 1000 * 1000 * 7), "7TB");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mac_roman_conv_basic_marathon_stuff()
|
||||
{
|
||||
assert_eq!(mac_roman_conv(b"p\x8cth"), "påth");
|
||||
assert_eq!(mac_roman_conv(b"I\xd5ve"), "I’ve");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mac_roman_cstr_tests()
|
||||
{
|
||||
assert_eq!(mac_roman_cstr(b"I\xd5ve awaken\0ed").unwrap(), "I’ve awaken");
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -2,28 +2,48 @@
|
|||
|
||||
use crate::durandal::image::Color;
|
||||
|
||||
/// An image possibly cached into a native driver's memory.
|
||||
pub trait CacheImage
|
||||
{
|
||||
/// The width of the image.
|
||||
fn w(&self) -> Coord;
|
||||
|
||||
/// The width of the image.
|
||||
fn h(&self) -> Coord;
|
||||
}
|
||||
|
||||
/// A native vector drawing area.
|
||||
pub trait DrawArea
|
||||
{
|
||||
/// The native `CacheImage` type for this `DrawArea`.
|
||||
type NativeImage: CacheImage;
|
||||
|
||||
/// The width of the entire area.
|
||||
fn w(&self) -> Coord;
|
||||
|
||||
/// The height of the entire area.
|
||||
fn h(&self) -> Coord;
|
||||
|
||||
/// Fills the entire screen with `cr`.
|
||||
fn clear(&self, cr: impl Color);
|
||||
|
||||
/// Draws a rectangle `rect` of color `cr`.
|
||||
fn rect(&self, rect: Rect, cr: impl Color);
|
||||
|
||||
/// Draws the Unicode `text` at `pos` stroked with color `cr`.
|
||||
fn text(&self, pos: Point, text: &str, cr: impl Color);
|
||||
|
||||
/// Draws `im` at `pos`, starting from the top left column.
|
||||
fn image(&self, pos: Point, im: &Self::NativeImage);
|
||||
}
|
||||
|
||||
/// A type capable of representing any coordinate on any axis.
|
||||
pub type Coord = i32;
|
||||
|
||||
/// A 2-dimensional point.
|
||||
pub type Point = (Coord, Coord);
|
||||
|
||||
/// A 2-dimensional rectangle.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Rect
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue