Merge pull request #2 from BeFunctional/edsko/generalize-error

Use `std::error::Error` (not `std::io::Error`)
This commit is contained in:
Edsko de Vries 2023-03-21 15:43:10 +00:00 committed by GitHub
commit 792680d016
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 88 additions and 78 deletions

View file

@ -1,36 +1,37 @@
use std::{ use std::{
io::{Error, ErrorKind, Write}, io::{ErrorKind, Write},
marker::PhantomData, marker::PhantomData,
}; };
use crate::error::Result;
/// Implement `to_haskell` using `bincode` /// Implement `to_haskell` using `bincode`
/// ///
/// The result will be length-prefixed ("bincode-in-Borsh"). /// The result will be length-prefixed ("bincode-in-Borsh").
pub fn bincode_to_haskell<Tag, T, W>( pub fn bincode_to_haskell<Tag, T, W>(t: &T, writer: &mut W, _: PhantomData<Tag>) -> Result<()>
t: &T,
writer: &mut W,
_: PhantomData<Tag>,
) -> Result<(), Error>
where where
T: serde::ser::Serialize, T: serde::ser::Serialize,
W: Write, W: Write,
{ {
match bincode::serialize(t) { match bincode::serialize(t) {
Ok(vec) => borsh::BorshSerialize::serialize(&vec, writer), Ok(vec) => {
Err(e) => Err(Error::new(ErrorKind::InvalidData, e)), borsh::BorshSerialize::serialize(&vec, writer)?;
Ok(())
}
Err(e) => Err(Box::new(std::io::Error::new(ErrorKind::InvalidData, e))),
} }
} }
/// Implement `from_haskell` using `bincode` /// Implement `from_haskell` using `bincode`
/// ///
/// See als `bincode_to_haskell` /// See als `bincode_to_haskell`
pub fn bincode_from_haskell<Tag, T>(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<T, Error> pub fn bincode_from_haskell<Tag, T>(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<T>
where where
T: serde::de::DeserializeOwned, T: serde::de::DeserializeOwned,
{ {
let vec: Vec<u8> = borsh::BorshDeserialize::deserialize(buf)?; let vec: Vec<u8> = borsh::BorshDeserialize::deserialize(buf)?;
match bincode::deserialize(vec.as_ref()) { match bincode::deserialize(vec.as_ref()) {
Ok(x) => Ok(x), Ok(x) => Ok(x),
Err(e) => Err(Error::new(ErrorKind::InvalidData, e)), Err(e) => Err(Box::new(std::io::Error::new(ErrorKind::InvalidData, e))),
} }
} }

View file

@ -4,7 +4,7 @@ use std::{
cmp::Ordering, cmp::Ordering,
fmt::Debug, fmt::Debug,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
io::{Error, Write}, io::Write,
marker::PhantomData, marker::PhantomData,
}; };
@ -100,14 +100,20 @@ impl<Tag, T: Copy> Copy for Haskell<Tag, T> {}
*******************************************************************************/ *******************************************************************************/
impl<Tag, T: ToHaskell<Tag>> BorshSerialize for Haskell<Tag, T> { impl<Tag, T: ToHaskell<Tag>> BorshSerialize for Haskell<Tag, T> {
fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> { fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
self.0.to_haskell(writer, PhantomData) match self.0.to_haskell(writer, PhantomData) {
Ok(_) => Ok(()),
Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, e)),
}
} }
} }
impl<Tag, T: FromHaskell<Tag>> BorshDeserialize for Haskell<Tag, T> { impl<Tag, T: FromHaskell<Tag>> BorshDeserialize for Haskell<Tag, T> {
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> { fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
let tag: PhantomData<Tag> = PhantomData; let tag: PhantomData<Tag> = PhantomData;
T::from_haskell(buf, tag).map(tag_val) match T::from_haskell(buf, tag).map(tag_val) {
Ok(x) => Ok(x),
Err(e) => Err(std::io::Error::new(std::io::ErrorKind::Other, e)),
}
} }
} }

2
haskell-ffi/src/error.rs Normal file
View file

@ -0,0 +1,2 @@
pub type Error = Box<dyn std::error::Error + Send + Sync>;
pub type Result<T> = core::result::Result<T, Error>;

View file

@ -1,9 +1,6 @@
use std::{ use std::{io::ErrorKind, marker::PhantomData};
io::{Error, ErrorKind},
marker::PhantomData,
};
use crate::HaskellSize; use crate::{error::Error, HaskellSize};
/******************************************************************************* /*******************************************************************************
Main class definition Main class definition
@ -23,7 +20,10 @@ pub trait FromHaskell<Tag>: Sized {
let mut slice_mut = slice; let mut slice_mut = slice;
let result = Self::from_haskell(&mut slice_mut, tag)?; let result = Self::from_haskell(&mut slice_mut, tag)?;
if !slice_mut.is_empty() { if !slice_mut.is_empty() {
return Err(Error::new(ErrorKind::InvalidData, ERROR_NOT_ALL_BYTES_READ)); return Err(Box::new(std::io::Error::new(
ErrorKind::InvalidData,
ERROR_NOT_ALL_BYTES_READ,
)));
} }
Ok(result) Ok(result)
} }

View file

@ -7,13 +7,14 @@ use borsh::{BorshDeserialize, BorshSerialize};
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
hash::Hash, hash::Hash,
io::{Error, ErrorKind, Write}, io::{ErrorKind, Write},
marker::PhantomData, marker::PhantomData,
}; };
use crate::{ use crate::{
derive_array_instances, derive_simple_instances, derive_tuple_instances, derive_array_instances, derive_simple_instances, derive_tuple_instances,
deriving_via::{tag_ref, untag_val, Haskell}, deriving_via::{tag_ref, untag_val, Haskell},
error::Result,
from_haskell::FromHaskell, from_haskell::FromHaskell,
map_tuple, map_tuple_ref, map_tuple, map_tuple_ref,
to_haskell::ToHaskell, to_haskell::ToHaskell,
@ -125,14 +126,15 @@ derive_tuple_instances!(
*******************************************************************************/ *******************************************************************************/
impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for Vec<T> { impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for Vec<T> {
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
let tagged: Vec<&Haskell<Tag, T>> = self.iter().map(tag_ref).collect(); let tagged: Vec<&Haskell<Tag, T>> = self.iter().map(tag_ref).collect();
tagged.serialize(writer) tagged.serialize(writer)?;
Ok(())
} }
} }
impl<Tag, T: FromHaskell<Tag>> FromHaskell<Tag> for Vec<T> { impl<Tag, T: FromHaskell<Tag>> FromHaskell<Tag> for Vec<T> {
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self> {
let tagged: Vec<Haskell<Tag, T>> = BorshDeserialize::deserialize(buf)?; let tagged: Vec<Haskell<Tag, T>> = BorshDeserialize::deserialize(buf)?;
Ok(tagged.into_iter().map(untag_val).collect()) Ok(tagged.into_iter().map(untag_val).collect())
} }
@ -147,10 +149,11 @@ where
K: Eq + PartialOrd + Hash + ToHaskell<Tag>, K: Eq + PartialOrd + Hash + ToHaskell<Tag>,
V: ToHaskell<Tag>, V: ToHaskell<Tag>,
{ {
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
let tagged: HashMap<&Haskell<Tag, K>, &Haskell<Tag, V>> = let tagged: HashMap<&Haskell<Tag, K>, &Haskell<Tag, V>> =
self.iter().map(|(k, v)| (tag_ref(k), tag_ref(v))).collect(); self.iter().map(|(k, v)| (tag_ref(k), tag_ref(v))).collect();
tagged.serialize(writer) tagged.serialize(writer)?;
Ok(())
} }
} }
@ -159,7 +162,7 @@ where
K: Eq + Hash + FromHaskell<Tag>, K: Eq + Hash + FromHaskell<Tag>,
V: FromHaskell<Tag>, V: FromHaskell<Tag>,
{ {
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self> {
let tagged: HashMap<Haskell<Tag, K>, Haskell<Tag, V>> = BorshDeserialize::deserialize(buf)?; let tagged: HashMap<Haskell<Tag, K>, Haskell<Tag, V>> = BorshDeserialize::deserialize(buf)?;
Ok(tagged Ok(tagged
.into_iter() .into_iter()
@ -176,9 +179,10 @@ impl<Tag, T> ToHaskell<Tag> for HashSet<T>
where where
T: Eq + PartialOrd + Hash + ToHaskell<Tag>, T: Eq + PartialOrd + Hash + ToHaskell<Tag>,
{ {
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
let tagged: HashSet<&Haskell<Tag, T>> = self.iter().map(tag_ref).collect(); let tagged: HashSet<&Haskell<Tag, T>> = self.iter().map(tag_ref).collect();
tagged.serialize(writer) tagged.serialize(writer)?;
Ok(())
} }
} }
@ -186,7 +190,7 @@ impl<Tag, T> FromHaskell<Tag> for HashSet<T>
where where
T: Eq + Hash + FromHaskell<Tag>, T: Eq + Hash + FromHaskell<Tag>,
{ {
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self> {
let tagged: HashSet<Haskell<Tag, T>> = BorshDeserialize::deserialize(buf)?; let tagged: HashSet<Haskell<Tag, T>> = BorshDeserialize::deserialize(buf)?;
Ok(tagged.into_iter().map(untag_val).collect()) Ok(tagged.into_iter().map(untag_val).collect())
} }
@ -197,14 +201,15 @@ where
*******************************************************************************/ *******************************************************************************/
impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for Option<T> { impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for Option<T> {
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
let tagged: Option<&Haskell<Tag, T>> = self.as_ref().map(tag_ref); let tagged: Option<&Haskell<Tag, T>> = self.as_ref().map(tag_ref);
tagged.serialize(writer) tagged.serialize(writer)?;
Ok(())
} }
} }
impl<Tag, T: FromHaskell<Tag>> FromHaskell<Tag> for Option<T> { impl<Tag, T: FromHaskell<Tag>> FromHaskell<Tag> for Option<T> {
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self> {
let tagged: Option<Haskell<Tag, T>> = BorshDeserialize::deserialize(buf)?; let tagged: Option<Haskell<Tag, T>> = BorshDeserialize::deserialize(buf)?;
Ok(tagged.map(untag_val)) Ok(tagged.map(untag_val))
} }
@ -220,13 +225,14 @@ impl<Tag, T: FromHaskell<Tag>> FromHaskell<Tag> for Option<T> {
the result of some Rust-side operation. the result of some Rust-side operation.
*******************************************************************************/ *******************************************************************************/
impl<Tag, T: ToHaskell<Tag>, E: ToHaskell<Tag>> ToHaskell<Tag> for Result<T, E> { impl<Tag, T: ToHaskell<Tag>, E: ToHaskell<Tag>> ToHaskell<Tag> for core::result::Result<T, E> {
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
let tagged: Result<&Haskell<Tag, T>, &Haskell<Tag, E>> = match self { let tagged: core::result::Result<&Haskell<Tag, T>, &Haskell<Tag, E>> = match self {
Ok(t) => Ok(tag_ref(t)), Ok(t) => Ok(tag_ref(t)),
Err(e) => Err(tag_ref(e)), Err(e) => Err(tag_ref(e)),
}; };
tagged.serialize(writer) tagged.serialize(writer)?;
Ok(())
} }
} }
@ -244,19 +250,22 @@ impl<Tag> HaskellSize<Tag> for bool {
} }
impl<Tag> ToHaskell<Tag> for bool { impl<Tag> ToHaskell<Tag> for bool {
fn to_haskell<W: Write>(&self, writer: &mut W, tag: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W, tag: PhantomData<Tag>) -> Result<()> {
let as_u8: u8 = if *self { 1 } else { 0 }; let as_u8: u8 = if *self { 1 } else { 0 };
as_u8.to_haskell(writer, tag) as_u8.to_haskell(writer, tag)
} }
} }
impl<Tag> FromHaskell<Tag> for bool { impl<Tag> FromHaskell<Tag> for bool {
fn from_haskell(buf: &mut &[u8], tag: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], tag: PhantomData<Tag>) -> Result<Self> {
let as_u8 = u8::from_haskell(buf, tag)?; let as_u8 = u8::from_haskell(buf, tag)?;
match as_u8 { match as_u8 {
0 => Ok(false), 0 => Ok(false),
1 => Ok(true), 1 => Ok(true),
_ => Err(Error::new(ErrorKind::InvalidData, "Invalid bool")), _ => Err(Box::new(std::io::Error::new(
ErrorKind::InvalidData,
"Invalid bool",
))),
} }
} }
} }

View file

@ -6,6 +6,7 @@ mod macros;
pub mod bincode; pub mod bincode;
pub mod deriving_via; pub mod deriving_via;
pub mod error;
pub mod from_haskell; pub mod from_haskell;
pub mod haskell_size; pub mod haskell_size;
pub mod to_haskell; pub mod to_haskell;

View file

@ -119,18 +119,16 @@ macro_rules! fold_types {
macro_rules! derive_simple_instances { macro_rules! derive_simple_instances {
($t:ty) => { ($t:ty) => {
impl<Tag> ToHaskell<Tag> for $t { impl<Tag> ToHaskell<Tag> for $t {
fn to_haskell<W: Write>( fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
&self, self.serialize(writer)?;
writer: &mut W, Ok(())
_: PhantomData<Tag>,
) -> Result<(), Error> {
self.serialize(writer)
} }
} }
impl<Tag> FromHaskell<Tag> for $t { impl<Tag> FromHaskell<Tag> for $t {
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], _tag: PhantomData<Tag>) -> Result<Self> {
<$t>::deserialize(buf) let x = <$t>::deserialize(buf)?;
Ok(x)
} }
} }
}; };
@ -141,18 +139,15 @@ macro_rules! derive_simple_instances {
macro_rules! derive_array_instances { macro_rules! derive_array_instances {
($sz : literal) => { ($sz : literal) => {
impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for [T; $sz] { impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for [T; $sz] {
fn to_haskell<W: Write>( fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
&self,
writer: &mut W,
_: PhantomData<Tag>,
) -> Result<(), Error> {
let tagged: [&Haskell<Tag, T>; $sz] = self.each_ref().map(tag_ref); let tagged: [&Haskell<Tag, T>; $sz] = self.each_ref().map(tag_ref);
tagged.serialize(writer) tagged.serialize(writer)?;
Ok(())
} }
} }
impl<Tag, T: FromHaskell<Tag> + Default + Copy> FromHaskell<Tag> for [T; $sz] { impl<Tag, T: FromHaskell<Tag> + Default + Copy> FromHaskell<Tag> for [T; $sz] {
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self> {
let tagged: [Haskell<Tag, T>; $sz] = BorshDeserialize::deserialize(buf)?; let tagged: [Haskell<Tag, T>; $sz] = BorshDeserialize::deserialize(buf)?;
Ok(tagged.map(untag_val)) Ok(tagged.map(untag_val))
} }
@ -166,14 +161,15 @@ macro_rules! derive_array_instances {
macro_rules! derive_tuple_instances { macro_rules! derive_tuple_instances {
($($ts:ident),*) => { ($($ts:ident),*) => {
impl<Tag, $($ts: ToHaskell<Tag> ),* > ToHaskell<Tag> for ( $($ts ),* ) { impl<Tag, $($ts: ToHaskell<Tag> ),* > ToHaskell<Tag> for ( $($ts ),* ) {
fn to_haskell<W: Write>(&self, writer: &mut W,_: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W,_: PhantomData<Tag>) -> Result<()> {
let tagged: ( $(&Haskell<Tag, $ts> ),* ) = map_tuple_ref!( [ $($ts),* ], self, tag_ref ); let tagged: ( $(&Haskell<Tag, $ts> ),* ) = map_tuple_ref!( [ $($ts),* ], self, tag_ref );
tagged.serialize(writer) tagged.serialize(writer)?;
Ok(())
} }
} }
impl<Tag, $($ts: FromHaskell<Tag> ),* > FromHaskell<Tag> for ( $($ts ),* ) { impl<Tag, $($ts: FromHaskell<Tag> ),* > FromHaskell<Tag> for ( $($ts ),* ) {
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self> {
let tagged: ( $(Haskell<Tag, $ts> ),* ) = BorshDeserialize::deserialize(buf)?; let tagged: ( $(Haskell<Tag, $ts> ),* ) = BorshDeserialize::deserialize(buf)?;
Ok( map_tuple!( [ $($ts),* ], tagged, untag_val ) ) Ok( map_tuple!( [ $($ts),* ], tagged, untag_val ) )
} }

View file

@ -1,10 +1,6 @@
use std::{ use std::{fmt::Display, io::Write, marker::PhantomData};
fmt::Display,
io::{Error, Write},
marker::PhantomData,
};
use crate::HaskellSize; use crate::{error::Result, HaskellSize};
/******************************************************************************* /*******************************************************************************
Main class definition Main class definition
@ -23,9 +19,9 @@ pub trait ToHaskell<Tag> {
/// `solana-sdk-haskell` library can define a `ToHaskell` instance for /// `solana-sdk-haskell` library can define a `ToHaskell` instance for
/// `Keypair`, defined in `solana-sdk`, as long as it uses a tag `Solana` /// `Keypair`, defined in `solana-sdk`, as long as it uses a tag `Solana`
/// defined locally in the `solana-haskell-sdk` package. /// defined locally in the `solana-haskell-sdk` package.
fn to_haskell<W: Write>(&self, writer: &mut W, tag: PhantomData<Tag>) -> Result<(), Error>; fn to_haskell<W: Write>(&self, writer: &mut W, tag: PhantomData<Tag>) -> Result<()>;
fn to_haskell_vec(&self, tag: PhantomData<Tag>) -> Result<Vec<u8>, Error> { fn to_haskell_vec(&self, tag: PhantomData<Tag>) -> Result<Vec<u8>> {
let mut result = Vec::with_capacity(DEFAULT_SERIALIZER_CAPACITY); let mut result = Vec::with_capacity(DEFAULT_SERIALIZER_CAPACITY);
self.to_haskell(&mut result, tag)?; self.to_haskell(&mut result, tag)?;
Ok(result) Ok(result)
@ -33,7 +29,7 @@ pub trait ToHaskell<Tag> {
} }
impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for &T { impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for &T {
fn to_haskell<W: Write>(&self, writer: &mut W, tag: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W, tag: PhantomData<Tag>) -> Result<()> {
(*self).to_haskell(writer, tag) (*self).to_haskell(writer, tag)
} }
} }
@ -95,7 +91,7 @@ pub fn marshall_to_haskell_var<Tag, T>(
/// Wrapper around `marshall_to_haskell_var` that calls `format` for errors /// Wrapper around `marshall_to_haskell_var` that calls `format` for errors
pub fn marshall_result_to_haskell_var<Tag, T, E>( pub fn marshall_result_to_haskell_var<Tag, T, E>(
res: &Result<T, E>, res: &core::result::Result<T, E>,
out: *mut u8, out: *mut u8,
out_len: &mut usize, out_len: &mut usize,
tag: PhantomData<Tag>, tag: PhantomData<Tag>,
@ -103,7 +99,7 @@ pub fn marshall_result_to_haskell_var<Tag, T, E>(
T: ToHaskell<Tag>, T: ToHaskell<Tag>,
E: Display, E: Display,
{ {
let res: Result<&T, String> = match res { let res: core::result::Result<&T, String> = match res {
Ok(t) => Ok(t), Ok(t) => Ok(t),
Err(e) => Err(format!("{}", e)), Err(e) => Err(format!("{}", e)),
}; };

View file

@ -1,10 +1,7 @@
use borsh::{BorshDeserialize, BorshSerialize}; use borsh::{BorshDeserialize, BorshSerialize};
use std::{ use std::{io::Write, marker::PhantomData};
io::{Error, Write},
marker::PhantomData,
};
use crate::{FromHaskell, ToHaskell}; use crate::{error::Result, FromHaskell, ToHaskell};
/// Newtype wrapper for defaulting to `borsh` for `ToHaskell`/`FromHaskell` /// Newtype wrapper for defaulting to `borsh` for `ToHaskell`/`FromHaskell`
/// ///
@ -32,14 +29,16 @@ pub fn unwrap_use_borsh_ref<T>(use_borsh: &UseBorsh<T>) -> &T {
*******************************************************************************/ *******************************************************************************/
impl<Tag, T: BorshSerialize> ToHaskell<Tag> for UseBorsh<T> { impl<Tag, T: BorshSerialize> ToHaskell<Tag> for UseBorsh<T> {
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<(), Error> { fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
unwrap_use_borsh_ref(self).serialize(writer) unwrap_use_borsh_ref(self).serialize(writer)?;
Ok(())
} }
} }
impl<Tag, T: BorshDeserialize> FromHaskell<Tag> for UseBorsh<T> { impl<Tag, T: BorshDeserialize> FromHaskell<Tag> for UseBorsh<T> {
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self, Error> { fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self> {
T::deserialize(buf).map(UseBorsh) let x = T::deserialize(buf).map(UseBorsh)?;
Ok(x)
} }
} }