use crate::value::Value;
use crate::value::list::List;
use crate::value::meta::Meta;
use crate::value::print::Print;
use crate::value::tracer::Tracer;
use bstr::ByteSlice;
use serde::Deserialize;
use serde::Serialize;
use unicode_segmentation::UnicodeSegmentation;
#[derive(Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Bytes {
#[serde(default, skip_serializing_if = "Tracer::is_empty")]
pub(crate) tracer: Tracer,
#[serde(default, skip_serializing_if = "Meta::is_empty")]
pub(crate) meta: Meta,
#[serde(with = "crate::serde::bytes_as_base64")]
pub(crate) data: Vec<u8>,
}
impl core::fmt::Debug for Bytes {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Bytes")
.field("tracer", &self.tracer)
.field("meta", &self.meta)
.field("data", &String::from_utf8_lossy(&self.data))
.finish()
}
}
impl core::fmt::Display for Bytes {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(&String::from_utf8_lossy(&self.clone().print_syntax()))
}
}
impl From<Vec<u8>> for Bytes {
fn from(value: Vec<u8>) -> Self {
Self {
data: value,
..Default::default()
}
}
}
impl Bytes {
pub(crate) fn trace<T: Into<Tracer>>(&mut self, tracer: T) {
self.tracer.trace(tracer);
}
pub(crate) fn tracer(&self) -> &Tracer {
&self.tracer
}
pub fn as_bytes(&self) -> &[u8] {
&self.data
}
pub fn as_chars(&self) -> List {
self.data
.chars()
.map(String::from)
.map(Value::from)
.collect()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn contains(self, needle: &[u8]) -> bool {
match (self.is_empty(), needle.is_empty()) {
(false, false) => self.data.windows(needle.len()).any(|w| w == needle),
(true, false) => false,
(_, true) => true,
}
}
pub fn join(self) -> Vec<u8> {
self.data
}
pub fn clear(mut self) -> Self {
self.data = Vec::default();
self
}
pub fn trim(mut self) -> Self {
let trim = self.data.trim();
if self.data.len() != trim.len() {
self.data = trim.to_vec();
}
self
}
pub fn first(mut self) -> Bytes {
self.data = str::from_utf8(&self.data)
.unwrap_or_default()
.graphemes(true)
.next()
.map(|v| v.as_bytes().to_vec())
.unwrap_or_default();
self
}
pub fn last(mut self) -> Bytes {
self.data = str::from_utf8(&self.data)
.unwrap_or_default()
.graphemes(true)
.next_back()
.map(|v| v.as_bytes().to_vec())
.unwrap_or_default();
self
}
pub fn rest(mut self) -> Bytes {
self.data = str::from_utf8(&self.data)
.unwrap_or_default()
.graphemes(true)
.skip(1)
.collect::<String>()
.into_bytes();
self
}
pub(crate) fn fold(&mut self, mut value: Self) {
match value.meta.get(b"internal-insert") {
Some(b"prepend") => {
value.data.append(&mut self.data);
self.data = value.data;
}
Some(b"append") => {
self.data.append(&mut value.data);
}
_ => {
*self = value;
}
}
}
}