use alloc::boxed::Box;
use alloc::vec::Vec;
use core::borrow::{Borrow, BorrowMut};
use core::convert::TryFrom;
use core::fmt::{self, Display, Formatter};
use core::ops::Range;
use amplify::num::error::OverflowError;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct ByteStr {
len: u16,
#[doc(hidden)]
pub bytes: Box<[u8; u16::MAX as usize]>,
}
impl Default for ByteStr {
fn default() -> ByteStr { ByteStr { len: 0, bytes: Box::new([0u8; u16::MAX as usize]) } }
}
impl AsRef<[u8]> for ByteStr {
#[inline]
fn as_ref(&self) -> &[u8] { &self.bytes[..self.len as usize] }
}
impl AsMut<[u8]> for ByteStr {
#[inline]
fn as_mut(&mut self) -> &mut [u8] { &mut self.bytes[..self.len as usize] }
}
impl Borrow<[u8]> for ByteStr {
#[inline]
fn borrow(&self) -> &[u8] { &self.bytes[..self.len as usize] }
}
impl BorrowMut<[u8]> for ByteStr {
#[inline]
fn borrow_mut(&mut self) -> &mut [u8] { &mut self.bytes[..self.len as usize] }
}
impl Extend<u8> for ByteStr {
fn extend<T: IntoIterator<Item = u8>>(&mut self, iter: T) {
let mut pos = self.len();
let iter = iter.into_iter();
for byte in iter {
assert!(pos < u16::MAX);
self.bytes[pos as usize] = byte;
pos += 1;
}
self.len = pos;
}
}
impl TryFrom<&[u8]> for ByteStr {
type Error = OverflowError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
let len = slice.as_ref().len();
if len > u16::MAX as usize {
return Err(OverflowError { max: u16::MAX as usize + 1, value: len });
}
let mut bytes = [0u8; u16::MAX as usize];
bytes[0..len].copy_from_slice(slice.as_ref());
Ok(ByteStr { len: len as u16, bytes: Box::new(bytes) })
}
}
impl ByteStr {
#[inline]
pub fn with(slice: impl AsRef<[u8]>) -> ByteStr {
ByteStr::try_from(slice.as_ref())
.expect("internal error: ByteStr::with requires slice <= u16::MAX + 1")
}
#[inline]
pub fn len(&self) -> u16 { self.len }
#[inline]
pub fn is_empty(&self) -> bool { self.len == 0 }
#[inline]
pub fn adjust_len(&mut self, new_len: u16) { self.len = new_len }
pub fn fill(&mut self, range: Range<u16>, val: u8) {
let start = range.start;
let end = range.end;
self.adjust_len(end);
self.bytes[start as usize..end as usize].fill(val);
}
#[inline]
pub fn to_vec(&self) -> Vec<u8> { self.as_ref().to_vec() }
}
#[cfg(feature = "std")]
impl Display for ByteStr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
use std::fmt::Write;
use amplify::hex::ToHex;
let vec = Vec::from(&self.bytes[..self.len as usize]);
if f.alternate() {
for (line, slice) in self.as_ref().chunks(16).enumerate() {
write!(f, "\x1B[0;35m{:>1$x}0 | \x1B[0m", line, f.width().unwrap_or(1) - 1)?;
for (pos, byte) in slice.iter().enumerate() {
write!(f, "{:02x} ", byte)?;
if pos == 7 {
f.write_char(' ')?;
}
}
if slice.len() < 8 {
f.write_char(' ')?;
}
write!(
f,
"{:1$}\x1B[0;35m|\x1B[0m ",
' ',
16usize.saturating_sub(slice.len()) * 3 + 1
)?;
for byte in slice {
f.write_str(&if byte.is_ascii_control()
|| byte.is_ascii_whitespace()
|| !byte.is_ascii()
{
s!("\x1B[0;35m·\x1B[0m")
} else {
String::from(char::from(*byte))
})?;
}
f.write_char('\n')?;
}
Ok(())
} else if let Ok(s) = String::from_utf8(vec) {
f.write_str("\"")?;
f.write_str(&s)?;
f.write_str("\"")
} else {
f.write_str(&self.as_ref().to_hex())
}
}
}
#[cfg(not(feature = "std"))]
impl Display for ByteStr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{:#04X?}", &self.bytes[0usize..self.len as usize])
}
}
#[cfg(feature = "strict_encoding")]
mod _strict_encoding {
use std::convert::TryFrom;
use std::io::{Read, Write};
use std::ops::Deref;
use strict_encoding::{StrictDecode, StrictEncode};
use super::ByteStr;
impl StrictEncode for ByteStr {
fn strict_encode<E: Write>(&self, e: E) -> Result<usize, strict_encoding::Error> {
self.as_ref().strict_encode(e)
}
}
impl StrictDecode for ByteStr {
fn strict_decode<D: Read>(d: D) -> Result<Self, strict_encoding::Error> {
let data = Vec::<u8>::strict_decode(d)?;
Ok(ByteStr::try_from(data.deref()).expect("strict encoding can't read more than 67 kb"))
}
}
}
#[cfg(feature = "serde")]
mod _serde {
use std::convert::TryFrom;
use std::ops::Deref;
use serde_crate::de::Error;
use serde_crate::{Deserialize, Deserializer, Serialize, Serializer};
use super::ByteStr;
impl Serialize for ByteStr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.as_ref().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for ByteStr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let vec = Vec::<u8>::deserialize(deserializer)?;
ByteStr::try_from(vec.deref())
.map_err(|_| D::Error::invalid_length(vec.len(), &"max u16::MAX bytes"))
}
}
}