use std::ops::{
Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
};
use anyhow::{Context, Result};
use bc_envelope::prelude::*;
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Data(Vec<u8>);
impl Data {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn from_bytes(data: impl AsRef<[u8]>) -> Self {
Self(data.as_ref().to_vec())
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
pub fn from_slice(data: &[u8]) -> Self {
Self(data.to_vec())
}
pub fn from_vec(data: Vec<u8>) -> Self {
Self(data)
}
pub fn from_hex(hex: &str) -> Result<Self> {
Ok(Self(hex::decode(hex)?))
}
pub fn concat(a: &[&dyn AsRef<[u8]>]) -> Self {
let mut bytes = Vec::new();
for data in a {
bytes.extend_from_slice(data.as_ref());
}
Self(bytes)
}
}
impl Default for Data {
fn default() -> Self {
Self::new()
}
}
impl Index<usize> for Data {
type Output = u8;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl IndexMut<usize> for Data {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}
impl Index<Range<usize>> for Data {
type Output = [u8];
fn index(&self, range: Range<usize>) -> &Self::Output {
&self.0[range]
}
}
impl IndexMut<Range<usize>> for Data {
fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
&mut self.0[range]
}
}
impl Index<RangeTo<usize>> for Data {
type Output = [u8];
fn index(&self, range: RangeTo<usize>) -> &Self::Output {
&self.0[range]
}
}
impl IndexMut<RangeTo<usize>> for Data {
fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self::Output {
&mut self.0[range]
}
}
impl Index<RangeFrom<usize>> for Data {
type Output = [u8];
fn index(&self, range: RangeFrom<usize>) -> &Self::Output {
&self.0[range]
}
}
impl IndexMut<RangeFrom<usize>> for Data {
fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self::Output {
&mut self.0[range]
}
}
impl Index<RangeFull> for Data {
type Output = [u8];
fn index(&self, range: RangeFull) -> &Self::Output {
&self.0[range]
}
}
impl IndexMut<RangeFull> for Data {
fn index_mut(&mut self, range: RangeFull) -> &mut Self::Output {
&mut self.0[range]
}
}
impl Index<RangeInclusive<usize>> for Data {
type Output = [u8];
fn index(&self, range: RangeInclusive<usize>) -> &Self::Output {
&self.0[range]
}
}
impl IndexMut<RangeInclusive<usize>> for Data {
fn index_mut(&mut self, range: RangeInclusive<usize>) -> &mut Self::Output {
&mut self.0[range]
}
}
impl Index<RangeToInclusive<usize>> for Data {
type Output = [u8];
fn index(&self, range: RangeToInclusive<usize>) -> &Self::Output {
&self.0[range]
}
}
impl IndexMut<RangeToInclusive<usize>> for Data {
fn index_mut(&mut self, range: RangeToInclusive<usize>) -> &mut Self::Output {
&mut self.0[range]
}
}
impl AsRef<[u8]> for Data {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl std::fmt::Debug for Data {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Data<{}>({})", self.len(), hex::encode(self))
}
}
impl AsRef<Data> for Data {
fn as_ref(&self) -> &Data {
self
}
}
impl From<Data> for Vec<u8> {
fn from(data: Data) -> Vec<u8> {
data.to_vec()
}
}
impl From<&Data> for Vec<u8> {
fn from(data: &Data) -> Vec<u8> {
data.to_vec()
}
}
impl From<Vec<u8>> for Data {
fn from(data: Vec<u8>) -> Self {
Self::from_vec(data)
}
}
impl From<&[u8]> for Data {
fn from(data: &[u8]) -> Self {
Self::from_slice(data)
}
}
impl From<Data> for CBOR {
fn from(data: Data) -> Self {
CBOR::to_byte_string(data)
}
}
impl From<&Data> for CBOR {
fn from(data: &Data) -> Self {
CBOR::to_byte_string(data)
}
}
impl TryFrom<CBOR> for Data {
type Error = dcbor::Error;
fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
let bytes = cbor.try_into_byte_string()?;
Ok(Data::from_slice(&bytes))
}
}
impl From<Data> for Envelope {
fn from(value: Data) -> Self {
Envelope::new(CBOR::from(value))
}
}
impl TryFrom<Envelope> for Data {
type Error = anyhow::Error;
fn try_from(envelope: Envelope) -> Result<Self, Self::Error> {
envelope.extract_subject().context("Data")
}
}
#[cfg(test)]
mod tests {
use crate::{test_cbor_roundtrip, test_envelope_roundtrip};
use super::Data;
impl crate::RandomInstance for Data {
fn random_with_size(size: usize) -> Self
where
Self: Sized,
{
bc_rand::random_data(size).into()
}
fn random() -> Self {
Self::random_with_size(32)
}
}
test_cbor_roundtrip!(Data);
test_envelope_roundtrip!(Data);
}