Merge pull request #2 from BeFunctional/edsko/generalize-error
Use `std::error::Error` (not `std::io::Error`)
This commit is contained in:
commit
792680d016
9 changed files with 88 additions and 78 deletions
|
@ -1,36 +1,37 @@
|
|||
use std::{
|
||||
io::{Error, ErrorKind, Write},
|
||||
io::{ErrorKind, Write},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use crate::error::Result;
|
||||
|
||||
/// Implement `to_haskell` using `bincode`
|
||||
///
|
||||
/// The result will be length-prefixed ("bincode-in-Borsh").
|
||||
pub fn bincode_to_haskell<Tag, T, W>(
|
||||
t: &T,
|
||||
writer: &mut W,
|
||||
_: PhantomData<Tag>,
|
||||
) -> Result<(), Error>
|
||||
pub fn bincode_to_haskell<Tag, T, W>(t: &T, writer: &mut W, _: PhantomData<Tag>) -> Result<()>
|
||||
where
|
||||
T: serde::ser::Serialize,
|
||||
W: Write,
|
||||
{
|
||||
match bincode::serialize(t) {
|
||||
Ok(vec) => borsh::BorshSerialize::serialize(&vec, writer),
|
||||
Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
|
||||
Ok(vec) => {
|
||||
borsh::BorshSerialize::serialize(&vec, writer)?;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(Box::new(std::io::Error::new(ErrorKind::InvalidData, e))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement `from_haskell` using `bincode`
|
||||
///
|
||||
/// 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
|
||||
T: serde::de::DeserializeOwned,
|
||||
{
|
||||
let vec: Vec<u8> = borsh::BorshDeserialize::deserialize(buf)?;
|
||||
match bincode::deserialize(vec.as_ref()) {
|
||||
Ok(x) => Ok(x),
|
||||
Err(e) => Err(Error::new(ErrorKind::InvalidData, e)),
|
||||
Err(e) => Err(Box::new(std::io::Error::new(ErrorKind::InvalidData, e))),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::{
|
|||
cmp::Ordering,
|
||||
fmt::Debug,
|
||||
hash::{Hash, Hasher},
|
||||
io::{Error, Write},
|
||||
io::Write,
|
||||
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> {
|
||||
fn serialize<W: Write>(&self, writer: &mut W) -> Result<(), Error> {
|
||||
self.0.to_haskell(writer, PhantomData)
|
||||
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
|
||||
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> {
|
||||
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
|
||||
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
2
haskell-ffi/src/error.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
|
@ -1,9 +1,6 @@
|
|||
use std::{
|
||||
io::{Error, ErrorKind},
|
||||
marker::PhantomData,
|
||||
};
|
||||
use std::{io::ErrorKind, marker::PhantomData};
|
||||
|
||||
use crate::HaskellSize;
|
||||
use crate::{error::Error, HaskellSize};
|
||||
|
||||
/*******************************************************************************
|
||||
Main class definition
|
||||
|
@ -23,7 +20,10 @@ pub trait FromHaskell<Tag>: Sized {
|
|||
let mut slice_mut = slice;
|
||||
let result = Self::from_haskell(&mut slice_mut, tag)?;
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -7,13 +7,14 @@ use borsh::{BorshDeserialize, BorshSerialize};
|
|||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
hash::Hash,
|
||||
io::{Error, ErrorKind, Write},
|
||||
io::{ErrorKind, Write},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
derive_array_instances, derive_simple_instances, derive_tuple_instances,
|
||||
deriving_via::{tag_ref, untag_val, Haskell},
|
||||
error::Result,
|
||||
from_haskell::FromHaskell,
|
||||
map_tuple, map_tuple_ref,
|
||||
to_haskell::ToHaskell,
|
||||
|
@ -125,14 +126,15 @@ derive_tuple_instances!(
|
|||
*******************************************************************************/
|
||||
|
||||
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();
|
||||
tagged.serialize(writer)
|
||||
tagged.serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
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)?;
|
||||
Ok(tagged.into_iter().map(untag_val).collect())
|
||||
}
|
||||
|
@ -147,10 +149,11 @@ where
|
|||
K: Eq + PartialOrd + Hash + 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>> =
|
||||
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>,
|
||||
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)?;
|
||||
Ok(tagged
|
||||
.into_iter()
|
||||
|
@ -176,9 +179,10 @@ impl<Tag, T> ToHaskell<Tag> for HashSet<T>
|
|||
where
|
||||
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();
|
||||
tagged.serialize(writer)
|
||||
tagged.serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,7 +190,7 @@ impl<Tag, T> FromHaskell<Tag> for HashSet<T>
|
|||
where
|
||||
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)?;
|
||||
Ok(tagged.into_iter().map(untag_val).collect())
|
||||
}
|
||||
|
@ -197,14 +201,15 @@ where
|
|||
*******************************************************************************/
|
||||
|
||||
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);
|
||||
tagged.serialize(writer)
|
||||
tagged.serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
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)?;
|
||||
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.
|
||||
*******************************************************************************/
|
||||
|
||||
impl<Tag, T: ToHaskell<Tag>, E: ToHaskell<Tag>> ToHaskell<Tag> for Result<T, E> {
|
||||
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<(), Error> {
|
||||
let tagged: Result<&Haskell<Tag, T>, &Haskell<Tag, E>> = match self {
|
||||
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<()> {
|
||||
let tagged: core::result::Result<&Haskell<Tag, T>, &Haskell<Tag, E>> = match self {
|
||||
Ok(t) => Ok(tag_ref(t)),
|
||||
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 {
|
||||
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 };
|
||||
as_u8.to_haskell(writer, tag)
|
||||
}
|
||||
}
|
||||
|
||||
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)?;
|
||||
match as_u8 {
|
||||
0 => Ok(false),
|
||||
1 => Ok(true),
|
||||
_ => Err(Error::new(ErrorKind::InvalidData, "Invalid bool")),
|
||||
_ => Err(Box::new(std::io::Error::new(
|
||||
ErrorKind::InvalidData,
|
||||
"Invalid bool",
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ mod macros;
|
|||
|
||||
pub mod bincode;
|
||||
pub mod deriving_via;
|
||||
pub mod error;
|
||||
pub mod from_haskell;
|
||||
pub mod haskell_size;
|
||||
pub mod to_haskell;
|
||||
|
|
|
@ -119,18 +119,16 @@ macro_rules! fold_types {
|
|||
macro_rules! derive_simple_instances {
|
||||
($t:ty) => {
|
||||
impl<Tag> ToHaskell<Tag> for $t {
|
||||
fn to_haskell<W: Write>(
|
||||
&self,
|
||||
writer: &mut W,
|
||||
_: PhantomData<Tag>,
|
||||
) -> Result<(), Error> {
|
||||
self.serialize(writer)
|
||||
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
|
||||
self.serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Tag> FromHaskell<Tag> for $t {
|
||||
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<Tag>) -> Result<Self, Error> {
|
||||
<$t>::deserialize(buf)
|
||||
fn from_haskell(buf: &mut &[u8], _tag: PhantomData<Tag>) -> Result<Self> {
|
||||
let x = <$t>::deserialize(buf)?;
|
||||
Ok(x)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -141,18 +139,15 @@ macro_rules! derive_simple_instances {
|
|||
macro_rules! derive_array_instances {
|
||||
($sz : literal) => {
|
||||
impl<Tag, T: ToHaskell<Tag>> ToHaskell<Tag> for [T; $sz] {
|
||||
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, 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] {
|
||||
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)?;
|
||||
Ok(tagged.map(untag_val))
|
||||
}
|
||||
|
@ -166,14 +161,15 @@ macro_rules! derive_array_instances {
|
|||
macro_rules! derive_tuple_instances {
|
||||
($($ts:ident),*) => {
|
||||
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 );
|
||||
tagged.serialize(writer)
|
||||
tagged.serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
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)?;
|
||||
Ok( map_tuple!( [ $($ts),* ], tagged, untag_val ) )
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
use std::{
|
||||
fmt::Display,
|
||||
io::{Error, Write},
|
||||
marker::PhantomData,
|
||||
};
|
||||
use std::{fmt::Display, io::Write, marker::PhantomData};
|
||||
|
||||
use crate::HaskellSize;
|
||||
use crate::{error::Result, HaskellSize};
|
||||
|
||||
/*******************************************************************************
|
||||
Main class definition
|
||||
|
@ -23,9 +19,9 @@ pub trait ToHaskell<Tag> {
|
|||
/// `solana-sdk-haskell` library can define a `ToHaskell` instance for
|
||||
/// `Keypair`, defined in `solana-sdk`, as long as it uses a tag `Solana`
|
||||
/// 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);
|
||||
self.to_haskell(&mut result, tag)?;
|
||||
Ok(result)
|
||||
|
@ -33,7 +29,7 @@ pub trait ToHaskell<Tag> {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +91,7 @@ pub fn marshall_to_haskell_var<Tag, T>(
|
|||
|
||||
/// Wrapper around `marshall_to_haskell_var` that calls `format` for errors
|
||||
pub fn marshall_result_to_haskell_var<Tag, T, E>(
|
||||
res: &Result<T, E>,
|
||||
res: &core::result::Result<T, E>,
|
||||
out: *mut u8,
|
||||
out_len: &mut usize,
|
||||
tag: PhantomData<Tag>,
|
||||
|
@ -103,7 +99,7 @@ pub fn marshall_result_to_haskell_var<Tag, T, E>(
|
|||
T: ToHaskell<Tag>,
|
||||
E: Display,
|
||||
{
|
||||
let res: Result<&T, String> = match res {
|
||||
let res: core::result::Result<&T, String> = match res {
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(format!("{}", e)),
|
||||
};
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use std::{
|
||||
io::{Error, Write},
|
||||
marker::PhantomData,
|
||||
};
|
||||
use std::{io::Write, marker::PhantomData};
|
||||
|
||||
use crate::{FromHaskell, ToHaskell};
|
||||
use crate::{error::Result, FromHaskell, ToHaskell};
|
||||
|
||||
/// 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> {
|
||||
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<(), Error> {
|
||||
unwrap_use_borsh_ref(self).serialize(writer)
|
||||
fn to_haskell<W: Write>(&self, writer: &mut W, _: PhantomData<Tag>) -> Result<()> {
|
||||
unwrap_use_borsh_ref(self).serialize(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Tag, T: BorshDeserialize> FromHaskell<Tag> for UseBorsh<T> {
|
||||
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self, Error> {
|
||||
T::deserialize(buf).map(UseBorsh)
|
||||
fn from_haskell(buf: &mut &[u8], _: PhantomData<Tag>) -> Result<Self> {
|
||||
let x = T::deserialize(buf).map(UseBorsh)?;
|
||||
Ok(x)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue