use std::borrow::Cow;
use binrw::binrw;
#[binrw]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[brw(big)]
pub struct Bytes {
#[bw(calc = payload.len() as u32)]
size: u32,
#[br(map = Cow::Owned, count = size)]
#[bw(map = |payload| payload.as_ref())]
payload: Cow<'static, [u8]>,
}
impl Bytes {
pub fn new(s: impl Into<Cow<'static, [u8]>>) -> Self {
Self { payload: s.into() }
}
}
impl std::ops::Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.payload.as_ref()
}
}
#[binrw]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[brw(big)]
pub struct MpInt(Bytes);
impl MpInt {
pub fn new(s: impl Into<Cow<'static, [u8]>>) -> Self {
Self(Bytes::new(s))
}
}
impl std::ops::Deref for MpInt {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[binrw]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[brw(big, assert(std::str::from_utf8(&self_0.payload).is_ok()))]
pub struct StringUtf8(Bytes);
impl StringUtf8 {
pub fn new(s: impl Into<String>) -> Self {
Self(Bytes::new(s.into().into_bytes()))
}
}
impl std::ops::Deref for StringUtf8 {
type Target = str;
fn deref(&self) -> &Self::Target {
std::str::from_utf8(self.0.as_ref())
.expect("StringUtf8 was constructed in an unexpected way")
}
}
#[binrw]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[brw(big, assert(self_0.is_ascii()))]
pub struct StringAscii(StringUtf8);
impl StringAscii {
pub fn new(s: impl Into<String>) -> Self {
Self(StringUtf8::new(s))
}
}
impl std::ops::Deref for StringAscii {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[binrw]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[brw(big)]
pub struct NameList(StringAscii);
impl NameList {
pub fn new(names: &[impl std::borrow::Borrow<str>]) -> Self {
Self(StringAscii::new(names.join(",")))
}
pub fn preferred(&self, other: &Self) -> Option<&str> {
self.into_iter()
.find(|&name| other.into_iter().any(|n| name == n))
}
}
impl<'n> IntoIterator for &'n NameList {
type Item = &'n str;
type IntoIter = std::str::Split<'n, char>;
fn into_iter(self) -> Self::IntoIter {
self.0.split(',')
}
}
#[binrw]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[brw(big)]
pub struct Bool(
#[br(map = |n: u8| n > 0)]
#[bw(map = |b| u8::from(*b))]
bool,
);
impl std::ops::Not for Bool {
type Output = Self;
fn not(self) -> Self::Output {
Self(!self.0)
}
}
impl std::ops::Deref for Bool {
type Target = bool;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::convert::From<bool> for Bool {
fn from(value: bool) -> Self {
Self(value)
}
}