use std::ops::Deref;
use binrw::binrw;
#[binrw]
#[derive(Default, Clone, PartialEq, Eq)]
#[brw(big)]
pub struct Bytes {
#[bw(calc = payload.len() as u32)]
size: u32,
#[br(count = size)]
payload: Vec<u8>,
}
impl Bytes {
pub fn new(s: impl Into<Vec<u8>>) -> Self {
Self { payload: s.into() }
}
pub fn into_vec(self) -> Vec<u8> {
self.payload
}
}
impl std::fmt::Debug for Bytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Bytes").field(&self.payload).finish()
}
}
impl std::ops::Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.payload.as_ref()
}
}
impl std::ops::DerefMut for Bytes {
fn deref_mut(&mut self) -> &mut Self::Target {
self.payload.as_mut()
}
}
impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
&self.payload
}
}
impl<T: Into<Vec<u8>>> From<T> for Bytes {
fn from(value: T) -> Self {
Self::new(value)
}
}
#[binrw]
#[derive(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()))
}
pub fn as_str(&self) -> &str {
self
}
pub fn into_string(self) -> String {
String::from_utf8(self.0.into_vec())
.expect("StringUtf8 was constructed in an unexpected way")
}
}
impl std::fmt::Debug for StringUtf8 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("StringUtf8").field(&self.deref()).finish()
}
}
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")
}
}
impl std::ops::DerefMut for StringUtf8 {
fn deref_mut(&mut self) -> &mut Self::Target {
std::str::from_utf8_mut(self.0.as_mut())
.expect("StringUtf8 was constructed in an unexpected way")
}
}
impl<T: Into<String>> From<T> for StringUtf8 {
fn from(value: T) -> Self {
Self::new(value)
}
}
#[binrw]
#[derive(Default, Clone, PartialEq, Eq)]
#[brw(big, assert(self_0.is_ascii()))]
pub struct StringAscii(StringUtf8);
impl StringAscii {
pub fn new(s: impl AsRef<str>) -> Self {
Self(StringUtf8::new(
s.as_ref()
.chars()
.filter(char::is_ascii)
.collect::<String>(),
))
}
pub fn as_str(&self) -> &str {
self
}
pub fn into_string(self) -> String {
self.0.into_string()
}
}
impl std::fmt::Debug for StringAscii {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("StringAscii").field(&self.deref()).finish()
}
}
impl std::ops::Deref for StringAscii {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for StringAscii {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: AsRef<str>> From<T> for StringAscii {
fn from(value: T) -> Self {
Self::new(value)
}
}