use std::str::from_utf8;
use std::fmt::{self, Debug, Display};
use std::ops::Deref;
use std::str::FromStr;
use std::convert::Infallible;
use std::borrow::{Borrow, Cow};
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Default, Clone)]
pub struct MaybeString(pub Vec<u8>);
impl MaybeString {
pub fn from_bytes(bytes: Vec<u8>) -> MaybeString {
MaybeString(bytes)
}
pub fn into_bytes(self) -> Vec<u8> {
self.0
}
pub fn as_maybe_str(&self) -> &MaybeStr {
self
}
pub fn into_lossy_string(self) -> String {
unsafe {
match String::from_utf8_lossy(&self.0) {
Cow::Borrowed(_) => String::from_utf8_unchecked(self.0),
Cow::Owned(string) => string,
}
}
}
pub fn into_string(self) -> Result<String, Vec<u8>> {
match String::from_utf8(self.0) {
Ok(string) => Ok(string),
Err(err) => Err(err.into_bytes()),
}
}
}
impl Deref for MaybeString {
type Target = MaybeStr;
fn deref(&self) -> &MaybeStr {
MaybeStr::from_bytes(self.0.as_slice())
}
}
impl Borrow<MaybeStr> for MaybeString {
fn borrow(&self) -> &MaybeStr {
self.as_ref()
}
}
impl AsRef<MaybeStr> for MaybeString {
fn as_ref(&self) -> &MaybeStr {
self
}
}
impl AsRef<[u8]> for MaybeString {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl Debug for MaybeString {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{:?}", self.as_maybe_str())
}
}
impl Display for MaybeString {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self.as_maybe_str())
}
}
impl From<Vec<u8>> for MaybeString {
fn from(data: Vec<u8>) -> MaybeString {
MaybeString(data)
}
}
impl From<String> for MaybeString {
fn from(data: String) -> MaybeString {
MaybeString(data.into_bytes())
}
}
impl<'b> From<&'b [u8]> for MaybeString {
fn from(data: &[u8]) -> MaybeString {
MaybeString::from(data.to_vec())
}
}
impl<'b> From<&'b str> for MaybeString {
fn from(data: &str) -> MaybeString {
MaybeString::from(data.to_string())
}
}
impl FromStr for MaybeString {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(MaybeString::from(s))
}
}
#[cfg_attr(feature = "serde", derive(Serialize))]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MaybeStr([u8]);
impl MaybeStr {
pub fn from_bytes(bytes: &[u8]) -> &MaybeStr {
unsafe { &*((bytes as *const [u8]) as *const MaybeStr)}
}
pub fn as_bytes(&self) -> &[u8] {
self
}
pub fn to_maybe_string(&self) -> MaybeString {
MaybeString(self.as_bytes().to_owned())
}
pub fn to_lossy_string(&self) -> String {
String::from_utf8_lossy(&self.0).into_owned()
}
pub fn to_string(&self) -> Result<&str, &[u8]> {
match std::str::from_utf8(&self.0) {
Ok(string) => Ok(string),
Err(_) => Err(&self.0),
}
}
}
impl Debug for MaybeStr {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
if let Ok(string) = from_utf8(self.as_bytes()) {
write!(f, "{:?}", string)
} else {
write!(f, "{:02x?}", &self.as_bytes())
}
}
}
impl Display for MaybeStr {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", String::from_utf8_lossy(&self.as_bytes()))
}
}
impl Deref for MaybeStr {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.0
}
}
impl AsRef<[u8]> for MaybeStr {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl ToOwned for MaybeStr {
type Owned = MaybeString;
fn to_owned(&self) -> Self::Owned {
self.to_maybe_string()
}
}
impl<'b> From<&'b [u8]> for &'b MaybeStr {
fn from(data: &[u8]) -> &MaybeStr {
MaybeStr::from_bytes(data)
}
}
impl<'b> From<&'b str> for &'b MaybeStr {
fn from(data: &str) -> &MaybeStr {
MaybeStr::from_bytes(data.as_bytes())
}
}