From 75cb654068dc751c1cfb52f8742a074927a55e26 Mon Sep 17 00:00:00 2001 From: parazyd Date: Thu, 24 Aug 2023 13:22:37 +0200 Subject: [PATCH] serial: Introduce full async serialization support. Unfortunately this duplicates the code, but it is beneficial for perf. --- Cargo.lock | 2 + src/serial/Cargo.toml | 4 +- src/serial/src/async_lib.rs | 656 ++++++++++++++++++++++++++++ src/serial/src/async_serial.rs | 143 ------ src/serial/src/lib.rs | 6 +- src/serial/src/types.rs | 3 - src/serial/src/types/bridgetree.rs | 190 +++++++- src/serial/src/types/collections.rs | 155 ++++++- src/serial/src/types/hash.rs | 35 +- src/serial/src/types/pasta.rs | 123 +++++- src/serial/src/types/semver.rs | 103 ++++- src/serial/src/types/url.rs | 38 +- src/serial/src/types/x25519.rs | 40 -- 13 files changed, 1239 insertions(+), 259 deletions(-) create mode 100644 src/serial/src/async_lib.rs delete mode 100644 src/serial/src/async_serial.rs delete mode 100644 src/serial/src/types/x25519.rs diff --git a/Cargo.lock b/Cargo.lock index f88c08716..1447598bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1526,6 +1526,7 @@ dependencies = [ "darkfi-derive-internal", "proc-macro-crate", "proc-macro2", + "quote", "syn 2.0.29", ] @@ -1595,6 +1596,7 @@ dependencies = [ name = "darkfi-serial" version = "0.4.1" dependencies = [ + "async-trait", "blake3", "bridgetree", "darkfi-derive", diff --git a/src/serial/Cargo.toml b/src/serial/Cargo.toml index f012dac65..cdeebbef2 100644 --- a/src/serial/Cargo.toml +++ b/src/serial/Cargo.toml @@ -11,6 +11,7 @@ edition = "2021" [dependencies] darkfi-derive = {version = "0.4.1", path = "./derive", optional = true} futures-lite = {version = "1.13.0", optional = true} +async-trait = {version = "0.1.73", optional = true} # Supported types for encoding blake3 = {version = "1.4.1", optional = true} @@ -23,7 +24,8 @@ url = {version = "2.4.0", optional = true} default = ["derive", "semver"] derive = ["darkfi-derive"] -async = ["futures-lite"] +async = ["futures-lite", "async-trait", "darkfi-derive/async"] + collections = [] crypto = ["collections", "hash", "bridgetree", "pasta_curves"] hash = ["blake3"] diff --git a/src/serial/src/async_lib.rs b/src/serial/src/async_lib.rs new file mode 100644 index 000000000..6c433465f --- /dev/null +++ b/src/serial/src/async_lib.rs @@ -0,0 +1,656 @@ +/* This file is part of DarkFi (https://dark.fi) + * + * Copyright (C) 2020-2023 Dyne.org foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +use std::{ + collections::VecDeque, + io::{Error, ErrorKind, Result}, +}; + +use async_trait::async_trait; +use futures_lite::{ + io::Cursor, AsyncRead, AsyncReadExt as FutAsyncReadExt, AsyncWrite, + AsyncWriteExt as FutAsyncWriteExt, +}; + +use crate::{endian, VarInt}; + +/// Data which can asynchronously be encoded in a consensus-consistent way. +#[async_trait] +pub trait AsyncEncodable { + /// Asynchronously encode an object with a well-defined format. + /// Should only ever error if the underlying `AsyncWrite` errors. + /// Returns the number of bytes written on success. + async fn encode_async(&self, w: &mut W) -> Result; +} + +/// Data which can asynchronously be decoded in a consensus-consistent way. +#[async_trait] +pub trait AsyncDecodable: Sized { + async fn decode_async(d: &mut D) -> Result; +} + +/// Asynchronously encode an object into a vector. +pub async fn serialize_async(data: &T) -> Vec { + let mut encoder = Vec::new(); + let len = data.encode_async(&mut encoder).await.unwrap(); + assert_eq!(len, encoder.len()); + encoder +} + +/// Asynchronously deserialize an object from a vector, but do not error if the +/// entire vector is not consumed. +pub async fn deserialize_async_partial(data: &[u8]) -> Result<(T, usize)> { + let mut decoder = Cursor::new(data); + let rv = AsyncDecodable::decode_async(&mut decoder).await?; + let consumed = decoder.position() as usize; + + Ok((rv, consumed)) +} + +/// Asynchronously deserialize an object from a vector. +/// Will error if said deserialization doesn't consume the entire vector. +pub async fn deserialize_async(data: &[u8]) -> Result { + let (rv, consumed) = deserialize_async_partial(data).await?; + + // Fail if data is not consumed entirely. + if consumed != data.len() { + return Err(Error::new(ErrorKind::Other, "Data not consumed fully on deserialization")) + } + + Ok(rv) +} + +/// Extensions of `AsyncWrite` to encode data as per Bitcoin consensus. +#[async_trait] +pub trait AsyncWriteExt { + /// Output a 128-bit unsigned int + async fn write_u128_async(&mut self, v: u128) -> Result<()>; + /// Output a 64-bit unsigned int + async fn write_u64_async(&mut self, v: u64) -> Result<()>; + /// Output a 32-bit unsigned int + async fn write_u32_async(&mut self, v: u32) -> Result<()>; + /// Output a 16-bit unsigned int + async fn write_u16_async(&mut self, v: u16) -> Result<()>; + /// Output an 8-bit unsigned int + async fn write_u8_async(&mut self, v: u8) -> Result<()>; + + /// Output a 128-bit signed int + async fn write_i128_async(&mut self, v: i128) -> Result<()>; + /// Output a 64-bit signed int + async fn write_i64_async(&mut self, v: i64) -> Result<()>; + /// Ouptut a 32-bit signed int + async fn write_i32_async(&mut self, v: i32) -> Result<()>; + /// Output a 16-bit signed int + async fn write_i16_async(&mut self, v: i16) -> Result<()>; + /// Output an 8-bit signed int + async fn write_i8_async(&mut self, v: i8) -> Result<()>; + + /// Output a 64-bit floating point int + async fn write_f64_async(&mut self, v: f64) -> Result<()>; + /// Output a 32-bit floating point int + async fn write_f32_async(&mut self, v: f32) -> Result<()>; + + /// Output a boolean + async fn write_bool_async(&mut self, v: bool) -> Result<()>; + + /// Output a byte slice + async fn write_slice_async(&mut self, v: &[u8]) -> Result<()>; +} + +/// Extensions of `AsyncRead` to decode data as per Bitcoin consensus. +#[async_trait] +pub trait AsyncReadExt { + /// Read a 128-bit unsigned int + async fn read_u128_async(&mut self) -> Result; + /// Read a 64-bit unsigned int + async fn read_u64_async(&mut self) -> Result; + /// Read a 32-bit unsigned int + async fn read_u32_async(&mut self) -> Result; + /// Read a 16-bit unsigned int + async fn read_u16_async(&mut self) -> Result; + /// Read an 8-bit unsigned int + async fn read_u8_async(&mut self) -> Result; + + /// Read a 128-bit signed int + async fn read_i128_async(&mut self) -> Result; + /// Read a 64-bit signed int + async fn read_i64_async(&mut self) -> Result; + /// Ouptut a 32-bit signed int + async fn read_i32_async(&mut self) -> Result; + /// Read a 16-bit signed int + async fn read_i16_async(&mut self) -> Result; + /// Read an 8-bit signed int + async fn read_i8_async(&mut self) -> Result; + + /// Read a 64-bit floating point int + async fn read_f64_async(&mut self) -> Result; + /// Read a 32-bit floating point int + async fn read_f32_async(&mut self) -> Result; + + /// Read a boolean + async fn read_bool_async(&mut self) -> Result; + + /// Read a byte slice + async fn read_slice_async(&mut self, slice: &mut [u8]) -> Result<()>; +} + +#[async_trait] +impl AsyncWriteExt for W { + #[inline] + async fn write_u128_async(&mut self, v: u128) -> Result<()> { + self.write_all(&endian::u128_to_array_le(v)).await + } + + #[inline] + async fn write_u64_async(&mut self, v: u64) -> Result<()> { + self.write_all(&endian::u64_to_array_le(v)).await + } + + #[inline] + async fn write_u32_async(&mut self, v: u32) -> Result<()> { + self.write_all(&endian::u32_to_array_le(v)).await + } + + #[inline] + async fn write_u16_async(&mut self, v: u16) -> Result<()> { + self.write_all(&endian::u16_to_array_le(v)).await + } + + #[inline] + async fn write_u8_async(&mut self, v: u8) -> Result<()> { + self.write_all(&[v]).await + } + + #[inline] + async fn write_i128_async(&mut self, v: i128) -> Result<()> { + self.write_all(&endian::i128_to_array_le(v)).await + } + + #[inline] + async fn write_i64_async(&mut self, v: i64) -> Result<()> { + self.write_all(&endian::i64_to_array_le(v)).await + } + + #[inline] + async fn write_i32_async(&mut self, v: i32) -> Result<()> { + self.write_all(&endian::i32_to_array_le(v)).await + } + + #[inline] + async fn write_i16_async(&mut self, v: i16) -> Result<()> { + self.write_all(&endian::i16_to_array_le(v)).await + } + + #[inline] + async fn write_i8_async(&mut self, v: i8) -> Result<()> { + self.write_all(&[v as u8]).await + } + + #[inline] + async fn write_f64_async(&mut self, v: f64) -> Result<()> { + self.write_all(&endian::f64_to_array_le(v)).await + } + + #[inline] + async fn write_f32_async(&mut self, v: f32) -> Result<()> { + self.write_all(&endian::f32_to_array_le(v)).await + } + + #[inline] + async fn write_bool_async(&mut self, v: bool) -> Result<()> { + self.write_all(&[v as u8]).await + } + + #[inline] + async fn write_slice_async(&mut self, v: &[u8]) -> Result<()> { + self.write_all(v).await + } +} + +#[async_trait] +impl AsyncReadExt for R { + #[inline] + async fn read_u128_async(&mut self) -> Result { + let mut val = [0; 16]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_u128_le(&val)) + } + + #[inline] + async fn read_u64_async(&mut self) -> Result { + let mut val = [0; 8]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_u64_le(&val)) + } + + #[inline] + async fn read_u32_async(&mut self) -> Result { + let mut val = [0; 4]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_u32_le(&val)) + } + + #[inline] + async fn read_u16_async(&mut self) -> Result { + let mut val = [0; 2]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_u16_le(&val)) + } + + #[inline] + async fn read_u8_async(&mut self) -> Result { + let mut val = [0; 1]; + self.read_exact(&mut val[..]).await?; + Ok(val[0]) + } + + #[inline] + async fn read_i128_async(&mut self) -> Result { + let mut val = [0; 16]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_i128_le(&val)) + } + + #[inline] + async fn read_i64_async(&mut self) -> Result { + let mut val = [0; 8]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_i64_le(&val)) + } + + #[inline] + async fn read_i32_async(&mut self) -> Result { + let mut val = [0; 4]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_i32_le(&val)) + } + + #[inline] + async fn read_i16_async(&mut self) -> Result { + let mut val = [0; 2]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_i16_le(&val)) + } + + #[inline] + async fn read_i8_async(&mut self) -> Result { + let mut val = [0; 1]; + self.read_exact(&mut val[..]).await?; + Ok(val[0] as i8) + } + + #[inline] + async fn read_f64_async(&mut self) -> Result { + let mut val = [0; 8]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_f64_le(&val)) + } + + #[inline] + async fn read_f32_async(&mut self) -> Result { + let mut val = [0; 4]; + self.read_exact(&mut val[..]).await?; + Ok(endian::slice_to_f32_le(&val)) + } + + #[inline] + async fn read_bool_async(&mut self) -> Result { + AsyncReadExt::read_i8_async(self).await.map(|bit| bit != 0) + } + + #[inline] + async fn read_slice_async(&mut self, slice: &mut [u8]) -> Result<()> { + self.read_exact(slice).await + } +} + +macro_rules! impl_int_encodable { + ($ty:ident, $meth_dec:ident, $meth_enc:ident) => { + #[async_trait] + impl AsyncDecodable for $ty { + #[inline] + async fn decode_async(d: &mut D) -> Result { + AsyncReadExt::$meth_dec(d).await.map($ty::from_le) + } + } + + #[async_trait] + impl AsyncEncodable for $ty { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + s.$meth_enc(self.to_le()).await?; + Ok(core::mem::size_of::<$ty>()) + } + } + }; +} + +impl_int_encodable!(u8, read_u8_async, write_u8_async); +impl_int_encodable!(u16, read_u16_async, write_u16_async); +impl_int_encodable!(u32, read_u32_async, write_u32_async); +impl_int_encodable!(u64, read_u64_async, write_u64_async); +impl_int_encodable!(u128, read_u128_async, write_u128_async); + +impl_int_encodable!(i8, read_i8_async, write_i8_async); +impl_int_encodable!(i16, read_i16_async, write_i16_async); +impl_int_encodable!(i32, read_i32_async, write_i32_async); +impl_int_encodable!(i64, read_i64_async, write_i64_async); +impl_int_encodable!(i128, read_i128_async, write_i128_async); + +macro_rules! tuple_encode { + ($($x:ident),*) => ( + #[async_trait] + impl<$($x: AsyncEncodable + Sync),*> AsyncEncodable for ($($x),*) { + #[inline] + #[allow(non_snake_case)] + async fn encode_async(&self, s: &mut S) -> Result { + let &($(ref $x),*) = self; + let mut len = 0; + $(len += $x.encode_async(s).await?;)* + Ok(len) + } + } + + #[async_trait] + impl<$($x: AsyncDecodable + Send),*> AsyncDecodable for ($($x),*) { + #[inline] + #[allow(non_snake_case)] + async fn decode_async(d: &mut D) -> Result { + Ok(($({let $x = AsyncDecodable::decode_async(d).await?; $x }),*)) + } + } + ) +} + +tuple_encode!(T0, T1); +tuple_encode!(T0, T1, T2); +tuple_encode!(T0, T1, T2, T3); +tuple_encode!(T0, T1, T2, T3, T4); +tuple_encode!(T0, T1, T2, T3, T4, T5); +tuple_encode!(T0, T1, T2, T3, T4, T5, T6); +tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7); + +/// Asynchronously encode a dynamic set of arguments to a buffer. +#[macro_export] +macro_rules! encode_payload_async { + ($buf:expr, $($args:expr),*) => {{ $( $args.encode_async($buf).await?;)* }} +} + +#[async_trait] +impl AsyncEncodable for VarInt { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + match self.0 { + 0..=0xFC => { + (self.0 as u8).encode_async(s).await?; + Ok(1) + } + + 0xFD..=0xFFFF => { + s.write_u8_async(0xFD).await?; + (self.0 as u16).encode_async(s).await?; + Ok(3) + } + + 0x10000..=0xFFFFFFFF => { + s.write_u8_async(0xFE).await?; + (self.0 as u32).encode_async(s).await?; + Ok(5) + } + + _ => { + s.write_u8_async(0xFF).await?; + self.0.encode_async(s).await?; + Ok(9) + } + } + } +} + +#[async_trait] +impl AsyncDecodable for VarInt { + #[inline] + async fn decode_async(d: &mut D) -> Result { + let n = AsyncReadExt::read_u8_async(d).await?; + match n { + 0xFF => { + let x = AsyncReadExt::read_u64_async(d).await?; + if x < 0x100000000 { + return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt")) + } + Ok(VarInt(x)) + } + + 0xFE => { + let x = AsyncReadExt::read_u32_async(d).await?; + if x < 0x10000 { + return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt")) + } + Ok(VarInt(x as u64)) + } + + 0xFD => { + let x = AsyncReadExt::read_u16_async(d).await?; + if x < 0xFD { + return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt")) + } + Ok(VarInt(x as u64)) + } + + n => Ok(VarInt(n as u64)), + } + } +} + +// Implementations for some primitive types +#[async_trait] +impl AsyncEncodable for usize { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + s.write_u64_async(*self as u64).await?; + Ok(8) + } +} + +#[async_trait] +impl AsyncDecodable for usize { + #[inline] + async fn decode_async(d: &mut D) -> Result { + Ok(AsyncReadExt::read_u64_async(d).await? as usize) + } +} + +#[async_trait] +impl AsyncEncodable for f64 { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + s.write_f64_async(*self).await?; + Ok(core::mem::size_of::()) + } +} + +#[async_trait] +impl AsyncDecodable for f64 { + #[inline] + async fn decode_async(d: &mut D) -> Result { + AsyncReadExt::read_f64_async(d).await + } +} + +#[async_trait] +impl AsyncEncodable for f32 { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + s.write_f32_async(*self).await?; + Ok(core::mem::size_of::()) + } +} + +#[async_trait] +impl AsyncDecodable for f32 { + #[inline] + async fn decode_async(d: &mut D) -> Result { + AsyncReadExt::read_f32_async(d).await + } +} + +#[async_trait] +impl AsyncEncodable for bool { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + s.write_bool_async(*self).await?; + Ok(1) + } +} + +#[async_trait] +impl AsyncDecodable for bool { + #[inline] + async fn decode_async(d: &mut D) -> Result { + AsyncReadExt::read_bool_async(d).await + } +} + +#[async_trait] +impl AsyncEncodable for Vec { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).encode_async(s).await?; + for val in self { + len += val.encode_async(s).await?; + } + Ok(len) + } +} + +#[async_trait] +impl AsyncDecodable for Vec { + #[inline] + async fn decode_async(d: &mut D) -> Result { + let len = VarInt::decode_async(d).await?.0; + let mut ret = Vec::with_capacity(len as usize); + for _ in 0..len { + ret.push(AsyncDecodable::decode_async(d).await?); + } + Ok(ret) + } +} + +#[async_trait] +impl AsyncEncodable for VecDeque { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).encode_async(s).await?; + for val in self { + len += val.encode_async(s).await?; + } + Ok(len) + } +} + +#[async_trait] +impl AsyncDecodable for VecDeque { + #[inline] + async fn decode_async(d: &mut D) -> Result { + let len = VarInt::decode_async(d).await?.0; + let mut ret = VecDeque::with_capacity(len as usize); + for _ in 0..len { + ret.push_back(AsyncDecodable::decode_async(d).await?); + } + Ok(ret) + } +} + +#[async_trait] +impl AsyncEncodable for Option { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + if let Some(v) = self { + len += true.encode_async(s).await?; + len += v.encode_async(s).await?; + } else { + len += false.encode_async(s).await?; + } + Ok(len) + } +} + +#[async_trait] +impl AsyncDecodable for Option { + async fn decode_async(d: &mut D) -> Result { + let valid: bool = AsyncDecodable::decode_async(d).await?; + let val = if valid { Some(AsyncDecodable::decode_async(d).await?) } else { None }; + Ok(val) + } +} + +#[async_trait] +impl AsyncEncodable for [u8; N] { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + s.write_slice_async(&self[..]).await?; + Ok(self.len()) + } +} + +#[async_trait] +impl AsyncDecodable for [u8; N] { + #[inline] + async fn decode_async(d: &mut D) -> Result { + let mut ret = [0; N]; + d.read_slice_async(&mut ret).await?; + Ok(ret) + } +} + +#[async_trait] +impl AsyncEncodable for String { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + let b = self.as_bytes(); + let b_len = b.len(); + let vi_len = VarInt(b_len as u64).encode_async(s).await?; + s.write_slice_async(b).await?; + Ok(vi_len + b_len) + } +} + +#[async_trait] +impl AsyncEncodable for &str { + #[inline] + async fn encode_async(&self, s: &mut S) -> Result { + let b = self.as_bytes(); + let b_len = b.len(); + let vi_len = VarInt(b_len as u64).encode_async(s).await?; + s.write_slice_async(b).await?; + Ok(vi_len + b_len) + } +} + +#[async_trait] +impl AsyncDecodable for String { + #[inline] + async fn decode_async(d: &mut D) -> Result { + match String::from_utf8(AsyncDecodable::decode_async(d).await?) { + Ok(v) => Ok(v), + Err(_) => Err(Error::new(ErrorKind::Other, "Invalid UTF-8 for string")), + } + } +} diff --git a/src/serial/src/async_serial.rs b/src/serial/src/async_serial.rs deleted file mode 100644 index 2ee2f4c53..000000000 --- a/src/serial/src/async_serial.rs +++ /dev/null @@ -1,143 +0,0 @@ -/* This file is part of DarkFi (https://dark.fi) - * - * Copyright (C) 2020-2023 Dyne.org foundation - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -use std::io::{Error, ErrorKind}; - -use futures_lite::{ - AsyncRead, AsyncReadExt as AsyncReadExtFut, AsyncWrite, AsyncWriteExt as AsyncWriteExtFut, -}; - -use super::{endian, VarInt}; - -pub struct AsyncReadExt; -pub struct AsyncWriteExt; - -macro_rules! async_decoder_fn { - ($name:ident, $val_type:ty, $readfn:ident, $byte_len:expr) => { - #[inline] - pub async fn $name(stream: &mut R) -> Result<$val_type, Error> { - assert_eq!(core::mem::size_of::<$val_type>(), $byte_len); - let mut val = [0; $byte_len]; - stream.read_exact(&mut val[..]).await?; - Ok(endian::$readfn(&val)) - } - }; -} - -macro_rules! async_encoder_fn { - ($name:ident, $val_type:ty, $writefn:ident) => { - #[inline] - pub async fn $name( - stream: &mut W, - v: $val_type, - ) -> Result<(), Error> { - stream.write_all(&endian::$writefn(v)).await - } - }; -} - -#[allow(dead_code)] -impl AsyncReadExt { - async_decoder_fn!(read_u128, u128, slice_to_u128_le, 16); - async_decoder_fn!(read_u64, u64, slice_to_u64_le, 8); - async_decoder_fn!(read_u32, u32, slice_to_u32_le, 4); - async_decoder_fn!(read_u16, u16, slice_to_u16_le, 2); - - pub async fn read_u8(stream: &mut R) -> Result { - let mut slice = [0u8; 1]; - stream.read_exact(&mut slice).await?; - Ok(slice[0]) - } -} - -#[allow(dead_code)] -impl AsyncWriteExt { - async_encoder_fn!(write_u128, u128, u128_to_array_le); - async_encoder_fn!(write_u64, u64, u64_to_array_le); - async_encoder_fn!(write_u32, u32, u32_to_array_le); - async_encoder_fn!(write_u16, u16, u16_to_array_le); - - pub async fn write_u8(stream: &mut W, v: u8) -> Result<(), Error> { - stream.write_all(&[v]).await - } -} - -impl VarInt { - #[inline] - pub async fn encode_async( - &self, - stream: &mut W, - ) -> Result { - match self.0 { - 0..=0xFC => { - AsyncWriteExt::write_u8(stream, self.0 as u8).await?; - Ok(1) - } - - 0xFD..=0xFFFF => { - AsyncWriteExt::write_u8(stream, 0xFD).await?; - AsyncWriteExt::write_u16(stream, self.0 as u16).await?; - Ok(3) - } - - 0x10000..=0xFFFFFFFF => { - AsyncWriteExt::write_u8(stream, 0xFE).await?; - AsyncWriteExt::write_u32(stream, self.0 as u32).await?; - Ok(5) - } - - _ => { - AsyncWriteExt::write_u8(stream, 0xFF).await?; - AsyncWriteExt::write_u64(stream, self.0).await?; - Ok(9) - } - } - } - - #[inline] - pub async fn decode_async(stream: &mut R) -> Result { - let n = AsyncReadExt::read_u8(stream).await?; - match n { - 0xFF => { - let x = AsyncReadExt::read_u64(stream).await?; - if x < 0x100000000 { - return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt")) - } - Ok(VarInt(x)) - } - - 0xFE => { - let x = AsyncReadExt::read_u32(stream).await?; - if x < 0x10000 { - return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt")) - } - Ok(VarInt(x as u64)) - } - - 0xFD => { - let x = AsyncReadExt::read_u16(stream).await?; - if x < 0xFD { - return Err(Error::new(ErrorKind::Other, "Non-minimal VarInt")) - } - Ok(VarInt(x as u64)) - } - - n => Ok(VarInt(n as u64)), - } - } -} diff --git a/src/serial/src/lib.rs b/src/serial/src/lib.rs index 349b9f364..bdd80ec01 100644 --- a/src/serial/src/lib.rs +++ b/src/serial/src/lib.rs @@ -25,7 +25,11 @@ use std::{ pub use darkfi_derive::{SerialDecodable, SerialEncodable}; #[cfg(feature = "async")] -mod async_serial; +mod async_lib; +#[cfg(feature = "async")] +pub use async_lib::{ + deserialize_async, deserialize_async_partial, serialize_async, AsyncDecodable, AsyncEncodable, +}; mod endian; mod types; diff --git a/src/serial/src/types.rs b/src/serial/src/types.rs index 560f5aa32..3f2ddde62 100644 --- a/src/serial/src/types.rs +++ b/src/serial/src/types.rs @@ -33,8 +33,5 @@ mod pasta; #[cfg(feature = "url")] mod url; -#[cfg(feature = "x25519-dalek")] -mod x25519; - #[cfg(feature = "semver")] mod semver; diff --git a/src/serial/src/types/bridgetree.rs b/src/serial/src/types/bridgetree.rs index cef790802..fc5864076 100644 --- a/src/serial/src/types/bridgetree.rs +++ b/src/serial/src/types/bridgetree.rs @@ -17,25 +17,49 @@ */ use core::fmt::Debug; -use std::io::{Error, ErrorKind, Read, Write}; +use std::io::{Error, ErrorKind, Read, Result, Write}; + +#[cfg(feature = "async")] +use crate::{AsyncDecodable, AsyncEncodable}; +#[cfg(feature = "async")] +use async_trait::async_trait; +#[cfg(feature = "async")] +use futures_lite::{AsyncRead, AsyncWrite}; use crate::{Decodable, Encodable}; impl Encodable for bridgetree::Position { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { u64::from(*self).encode(&mut s) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for bridgetree::Position { + async fn encode_async(&self, s: &mut S) -> Result { + u64::from(*self).encode_async(s).await + } +} + impl Decodable for bridgetree::Position { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let dec: u64 = Decodable::decode(&mut d)?; Ok(Self::try_from(dec).unwrap()) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for bridgetree::Position { + async fn decode_async(d: &mut D) -> Result { + let dec: u64 = AsyncDecodable::decode_async(d).await?; + Ok(Self::try_from(dec).unwrap()) + } +} + impl Encodable for bridgetree::Address { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += u8::from(self.level()).encode(&mut s)?; len += self.index().encode(&mut s)?; @@ -43,16 +67,37 @@ impl Encodable for bridgetree::Address { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for bridgetree::Address { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += u8::from(self.level()).encode_async(s).await?; + len += self.index().encode_async(s).await?; + Ok(len) + } +} + impl Decodable for bridgetree::Address { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let level: u8 = Decodable::decode(&mut d)?; let index = Decodable::decode(&mut d)?; Ok(Self::from_parts(level.into(), index)) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for bridgetree::Address { + async fn decode_async(d: &mut D) -> Result { + let level: u8 = AsyncDecodable::decode_async(d).await?; + let index = AsyncDecodable::decode_async(d).await?; + Ok(Self::from_parts(level.into(), index)) + } +} + impl Encodable for bridgetree::NonEmptyFrontier { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += self.position().encode(&mut s)?; len += self.leaf().encode(&mut s)?; @@ -61,8 +106,22 @@ impl Encodable for bridgetree::NonEmptyFrontier { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable + for bridgetree::NonEmptyFrontier +{ + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.position().encode_async(s).await?; + len += self.leaf().encode_async(s).await?; + len += self.ommers().to_vec().encode_async(s).await?; + Ok(len) + } +} + impl Decodable for bridgetree::NonEmptyFrontier { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let position = Decodable::decode(&mut d)?; let leaf = Decodable::decode(&mut d)?; let ommers = Decodable::decode(&mut d)?; @@ -74,8 +133,23 @@ impl Decodable for bridgetree::NonEmptyFrontier { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for bridgetree::NonEmptyFrontier { + async fn decode_async(d: &mut D) -> Result { + let position = AsyncDecodable::decode_async(d).await?; + let leaf = AsyncDecodable::decode_async(d).await?; + let ommers = AsyncDecodable::decode_async(d).await?; + + match Self::from_parts(position, leaf, ommers) { + Ok(v) => Ok(v), + Err(_) => Err(Error::new(ErrorKind::Other, "FrontierError")), + } + } +} + impl Encodable for bridgetree::MerkleBridge { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += self.prior_position().encode(&mut s)?; len += self.tracking().encode(&mut s)?; @@ -85,8 +159,21 @@ impl Encodable for bridgetree::MerkleBridge { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for bridgetree::MerkleBridge { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.prior_position().encode_async(s).await?; + len += self.tracking().encode_async(s).await?; + len += self.ommers().encode_async(s).await?; + len += self.frontier().encode_async(s).await?; + Ok(len) + } +} + impl Decodable for bridgetree::MerkleBridge { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let prior_position = Decodable::decode(&mut d)?; let tracking = Decodable::decode(&mut d)?; let ommers = Decodable::decode(&mut d)?; @@ -95,8 +182,20 @@ impl Decodable for bridgetree::MerkleBridge { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for bridgetree::MerkleBridge { + async fn decode_async(d: &mut D) -> Result { + let prior_position = AsyncDecodable::decode_async(d).await?; + let tracking = AsyncDecodable::decode_async(d).await?; + let ommers = AsyncDecodable::decode_async(d).await?; + let frontier = AsyncDecodable::decode_async(d).await?; + Ok(Self::from_parts(prior_position, tracking, ommers, frontier)) + } +} + impl Encodable for bridgetree::Checkpoint { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += self.id().encode(&mut s)?; len += self.bridges_len().encode(&mut s)?; @@ -106,8 +205,21 @@ impl Encodable for bridgetree::Checkpoint { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for bridgetree::Checkpoint { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.id().encode_async(s).await?; + len += self.bridges_len().encode_async(s).await?; + len += self.marked().encode_async(s).await?; + len += self.forgotten().encode_async(s).await?; + Ok(len) + } +} + impl Decodable for bridgetree::Checkpoint { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let id = Decodable::decode(&mut d)?; let bridges_len = Decodable::decode(&mut d)?; let marked = Decodable::decode(&mut d)?; @@ -116,10 +228,22 @@ impl Decodable for bridgetree::Checkpoint { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for bridgetree::Checkpoint { + async fn decode_async(d: &mut D) -> Result { + let id = AsyncDecodable::decode_async(d).await?; + let bridges_len = AsyncDecodable::decode_async(d).await?; + let marked = AsyncDecodable::decode_async(d).await?; + let forgotten = AsyncDecodable::decode_async(d).await?; + Ok(Self::from_parts(id, bridges_len, marked, forgotten)) + } +} + impl Encodable for bridgetree::BridgeTree { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += self.prior_bridges().to_vec().encode(&mut s)?; len += self.current_bridge().encode(&mut s)?; @@ -130,13 +254,32 @@ impl Encodabl } } +#[cfg(feature = "async")] +#[async_trait] +impl< + H: AsyncEncodable + Sync + Send + Ord + Clone, + C: AsyncEncodable + Sync + Debug, + const DEPTH: u8, + > AsyncEncodable for bridgetree::BridgeTree +{ + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.prior_bridges().to_vec().encode_async(s).await?; + len += self.current_bridge().encode_async(s).await?; + len += self.marked_indices().encode_async(s).await?; + len += self.checkpoints().encode_async(s).await?; + len += self.max_checkpoints().encode_async(s).await?; + Ok(len) + } +} + impl< H: Decodable + Clone + Ord + bridgetree::Hashable, C: Decodable + Clone + Ord + Eq + Debug, const DEPTH: u8, > Decodable for bridgetree::BridgeTree { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let prior_bridges = Decodable::decode(&mut d)?; let current_bridge = Decodable::decode(&mut d)?; let saved = Decodable::decode(&mut d)?; @@ -149,6 +292,27 @@ impl< } } +#[cfg(feature = "async")] +#[async_trait] +impl< + H: AsyncDecodable + Send + Clone + Ord + bridgetree::Hashable, + C: AsyncDecodable + Send + Clone + Ord + Eq + Debug, + const DEPTH: u8, + > AsyncDecodable for bridgetree::BridgeTree +{ + async fn decode_async(d: &mut D) -> Result { + let prior_bridges = AsyncDecodable::decode_async(d).await?; + let current_bridge = AsyncDecodable::decode_async(d).await?; + let saved = AsyncDecodable::decode_async(d).await?; + let checkpoints = AsyncDecodable::decode_async(d).await?; + let max_checkpoints = AsyncDecodable::decode_async(d).await?; + match Self::from_parts(prior_bridges, current_bridge, saved, checkpoints, max_checkpoints) { + Ok(v) => Ok(v), + Err(_) => Err(Error::new(ErrorKind::Other, "BridgeTreeError")), + } + } +} + #[cfg(test)] mod tests { use crate::{deserialize, serialize, SerialDecodable, SerialEncodable}; diff --git a/src/serial/src/types/collections.rs b/src/serial/src/types/collections.rs index d591d7ea4..9962f77d0 100644 --- a/src/serial/src/types/collections.rs +++ b/src/serial/src/types/collections.rs @@ -19,13 +19,20 @@ //! Serialization of collections use std::{ collections::{BTreeMap, BTreeSet, HashMap, HashSet}, - io::{Error, Read, Write}, + io::{Read, Result, Write}, }; +#[cfg(feature = "async")] +use crate::{AsyncDecodable, AsyncEncodable}; +#[cfg(feature = "async")] +use async_trait::async_trait; +#[cfg(feature = "async")] +use futures_lite::{AsyncRead, AsyncWrite}; + use crate::{Decodable, Encodable, VarInt}; impl Encodable for HashSet { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += VarInt(self.len() as u64).encode(&mut s)?; for c in self.iter() { @@ -35,8 +42,21 @@ impl Encodable for HashSet { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for HashSet { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).encode_async(s).await?; + for c in self.iter() { + len += c.encode_async(s).await?; + } + Ok(len) + } +} + impl Decodable for HashSet { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let len = VarInt::decode(&mut d)?.0; let mut ret = HashSet::new(); for _ in 0..len { @@ -47,8 +67,22 @@ impl Decodable for HashSet { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for HashSet { + async fn decode_async(d: &mut D) -> Result { + let len = VarInt::decode_async(d).await?.0; + let mut ret = HashSet::new(); + for _ in 0..len { + let entry: T = AsyncDecodable::decode_async(d).await?; + ret.insert(entry); + } + Ok(ret) + } +} + impl Encodable for BTreeMap { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += VarInt(self.len() as u64).encode(&mut s)?; for c in self.iter() { @@ -59,8 +93,22 @@ impl Encodable for BTreeMap { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for BTreeMap { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).encode_async(s).await?; + for c in self.iter() { + len += c.0.encode_async(s).await?; + len += c.1.encode_async(s).await?; + } + Ok(len) + } +} + impl Decodable for BTreeMap { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let len = VarInt::decode(&mut d)?.0; let mut ret = BTreeMap::new(); for _ in 0..len { @@ -72,8 +120,25 @@ impl Decodable for BTreeMap { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable + for BTreeMap +{ + async fn decode_async(d: &mut D) -> Result { + let len = VarInt::decode_async(d).await?.0; + let mut ret = BTreeMap::new(); + for _ in 0..len { + let key: T = AsyncDecodable::decode_async(d).await?; + let entry: U = AsyncDecodable::decode_async(d).await?; + ret.insert(key, entry); + } + Ok(ret) + } +} + impl Encodable for BTreeSet { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += VarInt(self.len() as u64).encode(&mut s)?; for c in self.iter() { @@ -83,8 +148,21 @@ impl Encodable for BTreeSet { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for BTreeSet { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).encode_async(s).await?; + for c in self.iter() { + len += c.encode_async(s).await?; + } + Ok(len) + } +} + impl Decodable for BTreeSet { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let len = VarInt::decode(&mut d)?.0; let mut ret = BTreeSet::new(); for _ in 0..len { @@ -95,8 +173,48 @@ impl Decodable for BTreeSet { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for BTreeSet { + async fn decode_async(d: &mut D) -> Result { + let len = VarInt::decode_async(d).await?.0; + let mut ret = BTreeSet::new(); + for _ in 0..len { + let key: T = AsyncDecodable::decode_async(d).await?; + ret.insert(key); + } + Ok(ret) + } +} + +impl Encodable for HashMap { + fn encode(&self, mut s: S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).encode(&mut s)?; + for c in self.iter() { + len += c.0.encode(&mut s)?; + len += c.1.encode(&mut s)?; + } + Ok(len) + } +} + +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for HashMap { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += VarInt(self.len() as u64).encode_async(s).await?; + for c in self.iter() { + len += c.0.encode_async(s).await?; + len += c.1.encode_async(s).await?; + } + Ok(len) + } +} + impl Decodable for HashMap { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let len = VarInt::decode(&mut d)?.0; let mut ret = HashMap::new(); for _ in 0..len { @@ -108,14 +226,19 @@ impl Decodable for } } -impl Encodable for HashMap { - fn encode(&self, mut s: S) -> Result { - let mut len = 0; - len += VarInt(self.len() as u64).encode(&mut s)?; - for c in self.iter() { - len += c.0.encode(&mut s)?; - len += c.1.encode(&mut s)?; +#[cfg(feature = "async")] +#[async_trait] +impl + AsyncDecodable for HashMap +{ + async fn decode_async(d: &mut D) -> Result { + let len = VarInt::decode_async(d).await?.0; + let mut ret = HashMap::new(); + for _ in 0..len { + let key: T = AsyncDecodable::decode_async(d).await?; + let entry: U = AsyncDecodable::decode_async(d).await?; + ret.insert(key, entry); } - Ok(len) + Ok(ret) } } diff --git a/src/serial/src/types/hash.rs b/src/serial/src/types/hash.rs index 7250f01eb..e1c4696cc 100644 --- a/src/serial/src/types/hash.rs +++ b/src/serial/src/types/hash.rs @@ -16,23 +16,52 @@ * along with this program. If not, see . */ -use std::io::{Error, Read, Write}; +use std::io::{Read, Result, Write}; + +#[cfg(feature = "async")] +use crate::{ + async_lib::{AsyncReadExt, AsyncWriteExt}, + AsyncDecodable, AsyncEncodable, +}; +#[cfg(feature = "async")] +use async_trait::async_trait; +#[cfg(feature = "async")] +use futures_lite::{AsyncRead, AsyncWrite}; use crate::{Decodable, Encodable, ReadExt, WriteExt}; #[cfg(feature = "blake3")] impl Encodable for blake3::Hash { - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { s.write_slice(self.as_bytes())?; Ok(32) } } +#[cfg(all(feature = "blake3", feature = "async"))] +#[async_trait] +impl AsyncEncodable for blake3::Hash { + async fn encode_async(&self, s: &mut S) -> Result { + s.write_slice_async(self.as_bytes()).await?; + Ok(blake3::OUT_LEN) + } +} + #[cfg(feature = "blake3")] impl Decodable for blake3::Hash { - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let mut bytes = [0u8; 32]; d.read_slice(&mut bytes)?; Ok(bytes.into()) } } + +#[cfg(all(feature = "blake3", feature = "async"))] +#[async_trait] +impl AsyncDecodable for blake3::Hash { + async fn decode_async(d: &mut D) -> Result { + let mut bytes = [0u8; blake3::OUT_LEN]; + d.read_slice_async(&mut bytes).await?; + Ok(bytes.into()) + } +} diff --git a/src/serial/src/types/pasta.rs b/src/serial/src/types/pasta.rs index c1bfa1d46..8eab541c9 100644 --- a/src/serial/src/types/pasta.rs +++ b/src/serial/src/types/pasta.rs @@ -17,7 +17,17 @@ */ //! Implementations for pasta curves -use std::io::{Error, ErrorKind, Read, Write}; +use std::io::{Error, ErrorKind, Read, Result, Write}; + +#[cfg(feature = "async")] +use crate::{ + async_lib::{AsyncReadExt, AsyncWriteExt}, + AsyncDecodable, AsyncEncodable, +}; +#[cfg(feature = "async")] +use async_trait::async_trait; +#[cfg(feature = "async")] +use futures_lite::{AsyncRead, AsyncWrite}; use pasta_curves::{ group::{ff::PrimeField, GroupEncoding}, @@ -27,16 +37,23 @@ use pasta_curves::{ use crate::{Decodable, Encodable, ReadExt, WriteExt}; impl Encodable for Fp { - #[inline] - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { s.write_slice(&self.to_repr())?; Ok(32) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for Fp { + async fn encode_async(&self, s: &mut S) -> Result { + s.write_slice_async(&self.to_repr()).await?; + Ok(32) + } +} + impl Decodable for Fp { - #[inline] - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let mut bytes = [0u8; 32]; d.read_slice(&mut bytes)?; match Self::from_repr(bytes).into() { @@ -45,18 +62,37 @@ impl Decodable for Fp { } } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for Fp { + async fn decode_async(d: &mut D) -> Result { + let mut bytes = [0u8; 32]; + d.read_slice_async(&mut bytes).await?; + match Self::from_repr(bytes).into() { + Some(v) => Ok(v), + None => Err(Error::new(ErrorKind::Other, "Noncanonical bytes for pallas::Base")), + } + } +} impl Encodable for Fq { - #[inline] - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { s.write_slice(&self.to_repr())?; Ok(32) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for Fq { + async fn encode_async(&self, s: &mut S) -> Result { + s.write_slice_async(&self.to_repr()).await?; + Ok(32) + } +} + impl Decodable for Fq { - #[inline] - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let mut bytes = [0u8; 32]; d.read_slice(&mut bytes)?; match Self::from_repr(bytes).into() { @@ -66,17 +102,37 @@ impl Decodable for Fq { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for Fq { + async fn decode_async(d: &mut D) -> Result { + let mut bytes = [0u8; 32]; + d.read_slice_async(&mut bytes).await?; + match Self::from_repr(bytes).into() { + Some(v) => Ok(v), + None => Err(Error::new(ErrorKind::Other, "Noncanonical bytes for pallas::Scalar")), + } + } +} + impl Encodable for Ep { - #[inline] - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { s.write_slice(&self.to_bytes())?; Ok(32) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for Ep { + async fn encode_async(&self, s: &mut S) -> Result { + s.write_slice_async(&self.to_bytes()).await?; + Ok(32) + } +} + impl Decodable for Ep { - #[inline] - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let mut bytes = [0u8; 32]; d.read_slice(&mut bytes)?; match Self::from_bytes(&bytes).into() { @@ -86,17 +142,37 @@ impl Decodable for Ep { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for Ep { + async fn decode_async(d: &mut D) -> Result { + let mut bytes = [0u8; 32]; + d.read_slice_async(&mut bytes).await?; + match Self::from_bytes(&bytes).into() { + Some(v) => Ok(v), + None => Err(Error::new(ErrorKind::Other, "Noncanonical bytes for pallas::Point")), + } + } +} + impl Encodable for Eq { - #[inline] - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { s.write_slice(&self.to_bytes())?; Ok(32) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for Eq { + async fn encode_async(&self, s: &mut S) -> Result { + s.write_slice_async(&self.to_bytes()).await?; + Ok(32) + } +} + impl Decodable for Eq { - #[inline] - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let mut bytes = [0u8; 32]; d.read_slice(&mut bytes)?; match Self::from_bytes(&bytes).into() { @@ -105,3 +181,16 @@ impl Decodable for Eq { } } } + +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for Eq { + async fn decode_async(d: &mut D) -> Result { + let mut bytes = [0u8; 32]; + d.read_slice_async(&mut bytes).await?; + match Self::from_bytes(&bytes).into() { + Some(v) => Ok(v), + None => Err(Error::new(ErrorKind::Other, "Noncanonical bytes for vesta::Point")), + } + } +} diff --git a/src/serial/src/types/semver.rs b/src/serial/src/types/semver.rs index a074a6ee6..238fd054b 100644 --- a/src/serial/src/types/semver.rs +++ b/src/serial/src/types/semver.rs @@ -16,51 +16,99 @@ * along with this program. If not, see . */ -use std::io::{Error, ErrorKind, Read, Write}; +use std::io::{Error, ErrorKind, Read, Result, Write}; + +#[cfg(feature = "async")] +use crate::{AsyncDecodable, AsyncEncodable}; +#[cfg(feature = "async")] +use async_trait::async_trait; +#[cfg(feature = "async")] +use futures_lite::{AsyncRead, AsyncWrite}; use crate::{Decodable, Encodable}; impl Encodable for semver::Prerelease { - #[inline] - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { self.as_str().encode(&mut s) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for semver::Prerelease { + async fn encode_async(&self, s: &mut S) -> Result { + self.as_str().encode_async(s).await + } +} + impl Decodable for semver::Prerelease { - #[inline] - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let s: String = Decodable::decode(&mut d)?; match Self::new(&s) { Ok(v) => Ok(v), - Err(_e) => Err(Error::new(ErrorKind::Other, "Failed parsing semver Prerelase")), + Err(_) => Err(Error::new(ErrorKind::Other, "Failed deserializing semver::Prerelase")), + } + } +} + +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for semver::Prerelease { + async fn decode_async(d: &mut D) -> Result { + let s: String = AsyncDecodable::decode_async(d).await?; + + match Self::new(&s) { + Ok(v) => Ok(v), + Err(_) => Err(Error::new(ErrorKind::Other, "Failed deserializing semver::Prerelease")), } } } impl Encodable for semver::BuildMetadata { - #[inline] - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { self.as_str().encode(&mut s) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for semver::BuildMetadata { + async fn encode_async(&self, s: &mut S) -> Result { + self.as_str().encode_async(s).await + } +} + impl Decodable for semver::BuildMetadata { - #[inline] - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let s: String = Decodable::decode(&mut d)?; match Self::new(&s) { Ok(v) => Ok(v), - Err(_e) => Err(Error::new(ErrorKind::Other, "Failed parsing semver BuildMetadata")), + Err(_) => { + Err(Error::new(ErrorKind::Other, "Failed deserializing semver::BuildMetadata")) + } + } + } +} + +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for semver::BuildMetadata { + async fn decode_async(d: &mut D) -> Result { + let s: String = AsyncDecodable::decode_async(d).await?; + + match Self::new(&s) { + Ok(v) => Ok(v), + Err(_) => { + Err(Error::new(ErrorKind::Other, "Failed deserializing semver::BuildMetadata")) + } } } } impl Encodable for semver::Version { - #[inline] - fn encode(&self, mut s: S) -> Result { + fn encode(&self, mut s: S) -> Result { let mut len = 0; len += self.major.encode(&mut s)?; len += self.minor.encode(&mut s)?; @@ -71,9 +119,22 @@ impl Encodable for semver::Version { } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for semver::Version { + async fn encode_async(&self, s: &mut S) -> Result { + let mut len = 0; + len += self.major.encode_async(s).await?; + len += self.minor.encode_async(s).await?; + len += self.patch.encode_async(s).await?; + len += self.pre.encode_async(s).await?; + len += self.build.encode_async(s).await?; + Ok(len) + } +} + impl Decodable for semver::Version { - #[inline] - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let major: u64 = Decodable::decode(&mut d)?; let minor: u64 = Decodable::decode(&mut d)?; let patch: u64 = Decodable::decode(&mut d)?; @@ -82,6 +143,18 @@ impl Decodable for semver::Version { Ok(Self { major, minor, patch, pre, build }) } } +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for semver::Version { + async fn decode_async(d: &mut D) -> Result { + let major: u64 = AsyncDecodable::decode_async(d).await?; + let minor: u64 = AsyncDecodable::decode_async(d).await?; + let patch: u64 = AsyncDecodable::decode_async(d).await?; + let pre: semver::Prerelease = AsyncDecodable::decode_async(d).await?; + let build: semver::BuildMetadata = AsyncDecodable::decode_async(d).await?; + Ok(Self { major, minor, patch, pre, build }) + } +} #[cfg(test)] mod tests { diff --git a/src/serial/src/types/url.rs b/src/serial/src/types/url.rs index 0e7b4c6e2..8f7bfa694 100644 --- a/src/serial/src/types/url.rs +++ b/src/serial/src/types/url.rs @@ -16,22 +16,34 @@ * along with this program. If not, see . */ -use std::io::{Error, ErrorKind, Read, Write}; - +use std::io::{Error, ErrorKind, Read, Result, Write}; use url::Url; +#[cfg(feature = "async")] +use crate::{AsyncDecodable, AsyncEncodable}; +#[cfg(feature = "async")] +use async_trait::async_trait; +#[cfg(feature = "async")] +use futures_lite::{AsyncRead, AsyncWrite}; + use crate::{Decodable, Encodable}; impl Encodable for Url { - #[inline] - fn encode(&self, s: S) -> Result { - self.as_str().to_string().encode(s) + fn encode(&self, s: S) -> Result { + self.as_str().encode(s) + } +} + +#[cfg(feature = "async")] +#[async_trait] +impl AsyncEncodable for Url { + async fn encode_async(&self, s: &mut S) -> Result { + self.as_str().encode_async(s).await } } impl Decodable for Url { - #[inline] - fn decode(mut d: D) -> Result { + fn decode(mut d: D) -> Result { let s: String = Decodable::decode(&mut d)?; match Url::parse(&s) { Ok(v) => Ok(v), @@ -39,3 +51,15 @@ impl Decodable for Url { } } } + +#[cfg(feature = "async")] +#[async_trait] +impl AsyncDecodable for Url { + async fn decode_async(d: &mut D) -> Result { + let s: String = AsyncDecodable::decode_async(d).await?; + match Url::parse(&s) { + Ok(v) => Ok(v), + Err(e) => Err(Error::new(ErrorKind::Other, e)), + } + } +} diff --git a/src/serial/src/types/x25519.rs b/src/serial/src/types/x25519.rs deleted file mode 100644 index eb708ab2b..000000000 --- a/src/serial/src/types/x25519.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* This file is part of DarkFi (https://dark.fi) - * - * Copyright (C) 2020-2023 Dyne.org foundation - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -use std::io::{Error, Read, Write}; - -use x25519_dalek::PublicKey as X25519PublicKey; - -use crate::{Decodable, Encodable, ReadExt, WriteExt}; - -impl Encodable for X25519PublicKey { - #[inline] - fn encode(&self, mut s: S) -> Result { - s.write_slice(self.as_bytes())?; - Ok(32) - } -} - -impl Decodable for X25519PublicKey { - #[inline] - fn decode(mut d: D) -> Result { - let mut bytes = [0u8; 32]; - d.read_slice(&mut bytes)?; - Ok(Self::from(bytes)) - } -}