Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OwnedBytes and SizedBytes to clvm-utils #499

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 19 additions & 0 deletions crates/clvm-traits/src/from_clvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ impl<N> FromClvm<N> for chia_bls::Signature {
mod tests {
use clvmr::{serde::node_from_bytes, Allocator, NodePtr};

use crate::{OwnedAtom, SizedAtom};

use super::*;

fn decode<T>(a: &mut Allocator, hex: &str) -> Result<T, FromClvmError>
Expand Down Expand Up @@ -286,6 +288,23 @@ mod tests {
assert_eq!(decode(a, "80"), Ok("".to_string()));
}

#[test]
fn test_owned_atom() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "80"), Ok(OwnedAtom::new(Vec::new())));
assert_eq!(
decode(a, "8568656c6c6f"),
Ok(OwnedAtom::new(b"hello".to_vec()))
);
}

#[test]
fn test_sized_atom() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "80"), Ok(SizedAtom::new([])));
assert_eq!(decode(a, "8568656c6c6f"), Ok(SizedAtom::new(*b"hello")));
}

#[cfg(feature = "chia-bls")]
#[test]
fn test_public_key() {
Expand Down
22 changes: 22 additions & 0 deletions crates/clvm-traits/src/to_clvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ mod tests {
use clvmr::{serde::node_to_bytes, Allocator, NodePtr};
use hex::ToHex;

use crate::{OwnedAtom, SizedAtom};

use super::*;

fn encode<T>(a: &mut Allocator, value: T) -> Result<String, ToClvmError>
Expand Down Expand Up @@ -267,6 +269,26 @@ mod tests {
assert_eq!(encode(a, "".to_string()), Ok("80".to_owned()));
}

#[test]
fn test_owned_atom() {
let a = &mut Allocator::new();
assert_eq!(encode(a, OwnedAtom::new(Vec::new())), Ok("80".to_owned()));
assert_eq!(
encode(a, OwnedAtom::new(b"hello".to_vec())),
Ok("8568656c6c6f".to_owned())
);
}

#[test]
fn test_sized_atom() {
let a = &mut Allocator::new();
assert_eq!(encode(a, SizedAtom::new([])), Ok("80".to_owned()));
assert_eq!(
encode(a, SizedAtom::new(*b"hello")),
Ok("8568656c6c6f".to_owned())
);
}

#[cfg(feature = "chia-bls")]
#[test]
fn test_public_key() {
Expand Down
114 changes: 114 additions & 0 deletions crates/clvm-traits/src/wrappers.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ops::Deref;

use crate::{ClvmDecoder, ClvmEncoder, FromClvm, FromClvmError, ToClvm, ToClvmError};

/// A wrapper for an intermediate CLVM value. This is required to
Expand All @@ -17,3 +19,115 @@ impl<N> ToClvm<N> for Raw<N> {
Ok(encoder.clone_node(&self.0))
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct OwnedAtom(Vec<u8>);

impl OwnedAtom {
pub fn new(data: Vec<u8>) -> Self {
Self(data)
}

pub fn into_inner(self) -> Vec<u8> {
self.0
}
}

impl AsRef<[u8]> for OwnedAtom {
fn as_ref(&self) -> &[u8] {
&self.0
}
}

impl From<Vec<u8>> for OwnedAtom {
fn from(data: Vec<u8>) -> Self {
Self(data)
}
}

impl From<OwnedAtom> for Vec<u8> {
fn from(atom: OwnedAtom) -> Self {
atom.0
}
}

impl Deref for OwnedAtom {
type Target = [u8];

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<N> ToClvm<N> for OwnedAtom {
fn to_clvm(&self, encoder: &mut impl ClvmEncoder<Node = N>) -> Result<N, ToClvmError> {
encoder.encode_atom(self)
}
}

impl<N> FromClvm<N> for OwnedAtom {
fn from_clvm(decoder: &impl ClvmDecoder<Node = N>, node: N) -> Result<Self, FromClvmError> {
decoder
.decode_atom(&node)
.map(|atom| Self::new(atom.as_ref().to_vec()))
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SizedAtom<const LEN: usize>([u8; LEN]);

impl<const LEN: usize> SizedAtom<LEN> {
pub fn new(data: [u8; LEN]) -> Self {
Self(data)
}

pub fn as_bytes(self) -> [u8; LEN] {
self.0
}
}

impl<const LEN: usize> AsRef<[u8]> for SizedAtom<LEN> {
fn as_ref(&self) -> &[u8] {
&self.0
}
}

impl<const LEN: usize> Deref for SizedAtom<LEN> {
type Target = [u8];

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<const LEN: usize> From<[u8; LEN]> for SizedAtom<LEN> {
fn from(data: [u8; LEN]) -> Self {
Self(data)
}
}

impl<const LEN: usize> From<SizedAtom<LEN>> for [u8; LEN] {
fn from(atom: SizedAtom<LEN>) -> Self {
atom.0
}
}

impl<N, const LEN: usize> ToClvm<N> for SizedAtom<LEN> {
fn to_clvm(&self, encoder: &mut impl ClvmEncoder<Node = N>) -> Result<N, ToClvmError> {
encoder.encode_atom(self)
}
}

impl<N, const LEN: usize> FromClvm<N> for SizedAtom<LEN> {
fn from_clvm(decoder: &impl ClvmDecoder<Node = N>, node: N) -> Result<Self, FromClvmError> {
let atom = decoder.decode_atom(&node)?;
let bytes = atom.as_ref();

Ok(Self::new(bytes.try_into().map_err(|_| {
FromClvmError::WrongAtomLength {
expected: LEN,
found: bytes.len(),
}
})?))
}
}