From ecf547f1bca98545378e55c7e55aa0ef3cf4e66a Mon Sep 17 00:00:00 2001 From: Jun Luo <4catcode@gmail.com> Date: Thu, 12 Sep 2024 12:24:44 +0800 Subject: [PATCH] Rust: add support for no_std env --- lib/xdrgen/generators/rust.rb | 24 +- lib/xdrgen/generators/rust/src/types.rs | 155 ++++++++---- .../block_comments.x/MyXDR.rs | 167 +++++++----- .../generator_spec_rust/const.x/MyXDR.rs | 163 ++++++++---- .../generator_spec_rust/enum.x/MyXDR.rs | 179 ++++++++----- .../generator_spec_rust/nesting.x/MyXDR.rs | 179 ++++++++----- .../generator_spec_rust/optional.x/MyXDR.rs | 167 +++++++----- .../generator_spec_rust/struct.x/MyXDR.rs | 167 +++++++----- .../generator_spec_rust/test.x/MyXDR.rs | 239 +++++++++++------- .../generator_spec_rust/union.x/MyXDR.rs | 179 ++++++++----- .../block_comments.x/MyXDR.rs | 167 +++++++----- .../const.x/MyXDR.rs | 163 ++++++++---- .../enum.x/MyXDR.rs | 179 ++++++++----- .../nesting.x/MyXDR.rs | 179 ++++++++----- .../optional.x/MyXDR.rs | 167 +++++++----- .../struct.x/MyXDR.rs | 167 +++++++----- .../test.x/MyXDR.rs | 239 +++++++++++------- .../union.x/MyXDR.rs | 179 ++++++++----- .../block_comments.x/MyXDR.rs | 167 +++++++----- .../const.x/MyXDR.rs | 163 ++++++++---- .../enum.x/MyXDR.rs | 179 ++++++++----- .../nesting.x/MyXDR.rs | 179 ++++++++----- .../optional.x/MyXDR.rs | 167 +++++++----- .../struct.x/MyXDR.rs | 167 +++++++----- .../test.x/MyXDR.rs | 239 +++++++++++------- .../union.x/MyXDR.rs | 179 ++++++++----- 26 files changed, 2887 insertions(+), 1612 deletions(-) diff --git a/lib/xdrgen/generators/rust.rb b/lib/xdrgen/generators/rust.rb index 8a4d36a37..ac6a8a718 100644 --- a/lib/xdrgen/generators/rust.rb +++ b/lib/xdrgen/generators/rust.rb @@ -175,7 +175,7 @@ def render_enum_of_all_types(out, types) pub const VARIANTS: [TypeVariant; #{types.count}] = [ #{types.map { |t| "TypeVariant::#{t}," }.join("\n")} ]; pub const VARIANTS_STR: [&'static str; #{types.count}] = [ #{types.map { |t| "\"#{t}\"," }.join("\n")} ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -190,7 +190,7 @@ def render_enum_of_all_types(out, types) Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -234,7 +234,7 @@ def render_enum_of_all_types(out, types) } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -318,7 +318,7 @@ def render_enum_of_all_types(out, types) } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { @@ -407,7 +407,7 @@ def render_struct(out, struct) out.puts "" out.puts <<-EOS.strip_heredoc impl ReadXdr for #{name struct} { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -420,7 +420,7 @@ def render_struct(out, struct) } impl WriteXdr for #{name struct} { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { #{struct.members.map do |m| @@ -517,7 +517,7 @@ def render_enum(out, enum) } impl ReadXdr for #{name enum} { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -528,7 +528,7 @@ def render_enum(out, enum) } impl WriteXdr for #{name enum} { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -656,7 +656,7 @@ def render_union(out, union) impl Union<#{discriminant_type}> for #{name union} {} impl ReadXdr for #{name union} { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: #{discriminant_type} = <#{discriminant_type} as ReadXdr>::read_xdr(r)?; @@ -678,7 +678,7 @@ def render_union(out, union) } impl WriteXdr for #{name union} { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -816,7 +816,7 @@ def render_typedef(out, typedef) } impl ReadXdr for #{name typedef} { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = #{reference_to_call(typedef, typedef.type)}::read_xdr(r)?; @@ -827,7 +827,7 @@ def render_typedef(out, typedef) } impl WriteXdr for #{name typedef} { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } diff --git a/lib/xdrgen/generators/rust/src/types.rs b/lib/xdrgen/generators/rust/src/types.rs index 13a36c004..4f70c060d 100644 --- a/lib/xdrgen/generators/rust/src/types.rs +++ b/lib/xdrgen/generators/rust/src/types.rs @@ -25,6 +25,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -33,14 +34,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -56,6 +60,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -72,13 +78,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -105,6 +132,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -157,6 +186,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -190,7 +222,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -207,7 +239,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -238,13 +270,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -297,6 +329,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -323,6 +364,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -396,7 +449,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -431,7 +484,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -471,7 +524,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -495,7 +548,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -544,7 +597,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -568,10 +621,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -593,13 +646,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -611,7 +664,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -622,7 +675,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -634,7 +687,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -645,7 +698,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -657,7 +710,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -668,7 +721,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -680,7 +733,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -691,35 +744,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -730,7 +783,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -740,7 +793,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -757,7 +810,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -772,35 +825,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -819,7 +872,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -833,7 +886,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -848,7 +901,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1207,7 +1260,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1234,7 +1287,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1254,7 +1307,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1274,7 +1327,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1647,7 +1700,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1674,7 +1727,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2050,7 +2103,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2077,7 +2130,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2123,7 +2176,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2143,10 +2196,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2255,7 +2306,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; diff --git a/spec/output/generator_spec_rust/block_comments.x/MyXDR.rs b/spec/output/generator_spec_rust/block_comments.x/MyXDR.rs index 6bb6392dc..0f509ea49 100644 --- a/spec/output/generator_spec_rust/block_comments.x/MyXDR.rs +++ b/spec/output/generator_spec_rust/block_comments.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2856,7 +2907,7 @@ impl From for i32 { } impl ReadXdr for AccountFlags { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2867,7 +2918,7 @@ impl ReadXdr for AccountFlags { } impl WriteXdr for AccountFlags { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2955,7 +3006,7 @@ impl Type { pub const VARIANTS: [TypeVariant; 1] = [ TypeVariant::AccountFlags, ]; pub const VARIANTS_STR: [&'static str; 1] = [ "AccountFlags", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2970,7 +3021,7 @@ impl Type { Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3014,7 +3065,7 @@ impl Type { } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3098,7 +3149,7 @@ impl Variants for Type { } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust/const.x/MyXDR.rs b/spec/output/generator_spec_rust/const.x/MyXDR.rs index 966b54a40..d4d8e38ab 100644 --- a/spec/output/generator_spec_rust/const.x/MyXDR.rs +++ b/spec/output/generator_spec_rust/const.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2890,7 +2941,7 @@ TypeVariant::TestArray2, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "TestArray", "TestArray2", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2906,7 +2957,7 @@ TypeVariant::TestArray2 => r.with_limited_depth(|r| Ok(Self::TestArray2(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2953,7 +3004,7 @@ TypeVariant::TestArray2 => Box::new(ReadXdrIter::<_, TestArray2>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3042,7 +3093,7 @@ Self::TestArray2(_) => TypeVariant::TestArray2, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust/enum.x/MyXDR.rs b/spec/output/generator_spec_rust/enum.x/MyXDR.rs index 9968bbd13..cfc1b5e62 100644 --- a/spec/output/generator_spec_rust/enum.x/MyXDR.rs +++ b/spec/output/generator_spec_rust/enum.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2940,7 +2991,7 @@ Self::FbaMessage => "FbaMessage", } impl ReadXdr for MessageType { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2951,7 +3002,7 @@ Self::FbaMessage => "FbaMessage", } impl WriteXdr for MessageType { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3049,7 +3100,7 @@ Self::Blue => "Blue", } impl ReadXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3060,7 +3111,7 @@ Self::Blue => "Blue", } impl WriteXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3158,7 +3209,7 @@ Self::Blue2 => "Blue2", } impl ReadXdr for Color2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3169,7 +3220,7 @@ Self::Blue2 => "Blue2", } impl WriteXdr for Color2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3267,7 +3318,7 @@ Self::R3 => "R3", } impl ReadXdr for Color3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3278,7 +3329,7 @@ Self::R3 => "R3", } impl WriteXdr for Color3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3393,7 +3444,7 @@ TypeVariant::Color3, ]; "Color2", "Color3", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3411,7 +3462,7 @@ TypeVariant::Color3 => r.with_limited_depth(|r| Ok(Self::Color3(Box::new(Color3: Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3464,7 +3515,7 @@ TypeVariant::Color3 => Box::new(ReadXdrIter::<_, Color3>::new(dec, r.limits.clon } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3563,7 +3614,7 @@ Self::Color3(_) => TypeVariant::Color3, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust/nesting.x/MyXDR.rs b/spec/output/generator_spec_rust/nesting.x/MyXDR.rs index 4cdff6d8b..038bb9c08 100644 --- a/spec/output/generator_spec_rust/nesting.x/MyXDR.rs +++ b/spec/output/generator_spec_rust/nesting.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2867,7 +2918,7 @@ Self::Offer => "Offer", } impl ReadXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2878,7 +2929,7 @@ Self::Offer => "Offer", } impl WriteXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2912,7 +2963,7 @@ pub struct MyUnionOne { } impl ReadXdr for MyUnionOne { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2923,7 +2974,7 @@ impl ReadXdr for MyUnionOne { } impl WriteXdr for MyUnionOne { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -2951,7 +3002,7 @@ pub struct MyUnionTwo { } impl ReadXdr for MyUnionTwo { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2963,7 +3014,7 @@ foo: i32::read_xdr(r)?, } impl WriteXdr for MyUnionTwo { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -3066,7 +3117,7 @@ Self::Offer => UnionKey::Offer, impl Union for MyUnion {} impl ReadXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: UnionKey = ::read_xdr(r)?; @@ -3084,7 +3135,7 @@ UnionKey::Offer => Self::Offer, } impl WriteXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3214,7 +3265,7 @@ TypeVariant::MyUnionTwo, ]; "MyUnionOne", "MyUnionTwo", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3233,7 +3284,7 @@ TypeVariant::MyUnionTwo => r.with_limited_depth(|r| Ok(Self::MyUnionTwo(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3289,7 +3340,7 @@ TypeVariant::MyUnionTwo => Box::new(ReadXdrIter::<_, MyUnionTwo>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3393,7 +3444,7 @@ Self::MyUnionTwo(_) => TypeVariant::MyUnionTwo, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust/optional.x/MyXDR.rs b/spec/output/generator_spec_rust/optional.x/MyXDR.rs index b9454b181..bd6ef6b10 100644 --- a/spec/output/generator_spec_rust/optional.x/MyXDR.rs +++ b/spec/output/generator_spec_rust/optional.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2808,7 +2859,7 @@ pub struct HasOptions { } impl ReadXdr for HasOptions { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2821,7 +2872,7 @@ third_option: Option::::read_xdr(r)?, } impl WriteXdr for HasOptions { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.first_option.write_xdr(w)?; @@ -2920,7 +2971,7 @@ TypeVariant::HasOptions, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "Arr", "HasOptions", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2936,7 +2987,7 @@ TypeVariant::HasOptions => r.with_limited_depth(|r| Ok(Self::HasOptions(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2983,7 +3034,7 @@ TypeVariant::HasOptions => Box::new(ReadXdrIter::<_, HasOptions>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3072,7 +3123,7 @@ Self::HasOptions(_) => TypeVariant::HasOptions, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust/struct.x/MyXDR.rs b/spec/output/generator_spec_rust/struct.x/MyXDR.rs index 696a6f49a..0f788ddfb 100644 --- a/spec/output/generator_spec_rust/struct.x/MyXDR.rs +++ b/spec/output/generator_spec_rust/struct.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2812,7 +2863,7 @@ pub struct MyStruct { } impl ReadXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2827,7 +2878,7 @@ max_string: StringM::<100>::read_xdr(r)?, } impl WriteXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -2928,7 +2979,7 @@ TypeVariant::MyStruct, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "Int64", "MyStruct", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2944,7 +2995,7 @@ TypeVariant::MyStruct => r.with_limited_depth(|r| Ok(Self::MyStruct(Box::new(MyS Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2991,7 +3042,7 @@ TypeVariant::MyStruct => Box::new(ReadXdrIter::<_, MyStruct>::new(dec, r.limits. } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3080,7 +3131,7 @@ Self::MyStruct(_) => TypeVariant::MyStruct, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust/test.x/MyXDR.rs b/spec/output/generator_spec_rust/test.x/MyXDR.rs index 5d234038f..2a35f2a19 100644 --- a/spec/output/generator_spec_rust/test.x/MyXDR.rs +++ b/spec/output/generator_spec_rust/test.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2872,7 +2923,7 @@ impl AsRef<[u8; 64]> for Uint512 { } impl ReadXdr for Uint512 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[u8; 64]>::read_xdr(r)?; @@ -2883,7 +2934,7 @@ impl ReadXdr for Uint512 { } impl WriteXdr for Uint512 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -2962,7 +3013,7 @@ impl AsRef> for Uint513 { } impl ReadXdr for Uint513 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = BytesM::<64>::read_xdr(r)?; @@ -2973,7 +3024,7 @@ impl ReadXdr for Uint513 { } impl WriteXdr for Uint513 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3064,7 +3115,7 @@ impl AsRef for Uint514 { } impl ReadXdr for Uint514 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = BytesM::read_xdr(r)?; @@ -3075,7 +3126,7 @@ impl ReadXdr for Uint514 { } impl WriteXdr for Uint514 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3166,7 +3217,7 @@ impl AsRef> for Str { } impl ReadXdr for Str { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = StringM::<64>::read_xdr(r)?; @@ -3177,7 +3228,7 @@ impl ReadXdr for Str { } impl WriteXdr for Str { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3268,7 +3319,7 @@ impl AsRef for Str2 { } impl ReadXdr for Str2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = StringM::read_xdr(r)?; @@ -3279,7 +3330,7 @@ impl ReadXdr for Str2 { } impl WriteXdr for Str2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3428,7 +3479,7 @@ impl AsRef<[u8; 32]> for Hash { } impl ReadXdr for Hash { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[u8; 32]>::read_xdr(r)?; @@ -3439,7 +3490,7 @@ impl ReadXdr for Hash { } impl WriteXdr for Hash { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3517,7 +3568,7 @@ impl AsRef<[Hash; 12]> for Hashes1 { } impl ReadXdr for Hashes1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[Hash; 12]>::read_xdr(r)?; @@ -3528,7 +3579,7 @@ impl ReadXdr for Hashes1 { } impl WriteXdr for Hashes1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3607,7 +3658,7 @@ impl AsRef> for Hashes2 { } impl ReadXdr for Hashes2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = VecM::::read_xdr(r)?; @@ -3618,7 +3669,7 @@ impl ReadXdr for Hashes2 { } impl WriteXdr for Hashes2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3709,7 +3760,7 @@ impl AsRef> for Hashes3 { } impl ReadXdr for Hashes3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = VecM::::read_xdr(r)?; @@ -3720,7 +3771,7 @@ impl ReadXdr for Hashes3 { } impl WriteXdr for Hashes3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3810,7 +3861,7 @@ impl AsRef> for OptHash1 { } impl ReadXdr for OptHash1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = Option::::read_xdr(r)?; @@ -3821,7 +3872,7 @@ impl ReadXdr for OptHash1 { } impl WriteXdr for OptHash1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3862,7 +3913,7 @@ impl AsRef> for OptHash2 { } impl ReadXdr for OptHash2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = Option::::read_xdr(r)?; @@ -3873,7 +3924,7 @@ impl ReadXdr for OptHash2 { } impl WriteXdr for OptHash2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3941,7 +3992,7 @@ pub struct MyStruct { } impl ReadXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -3958,7 +4009,7 @@ field7: bool::read_xdr(r)?, } impl WriteXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.field1.write_xdr(w)?; @@ -3991,7 +4042,7 @@ pub struct LotsOfMyStructs { } impl ReadXdr for LotsOfMyStructs { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4002,7 +4053,7 @@ impl ReadXdr for LotsOfMyStructs { } impl WriteXdr for LotsOfMyStructs { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.members.write_xdr(w)?; @@ -4029,7 +4080,7 @@ pub struct HasStuff { } impl ReadXdr for HasStuff { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4040,7 +4091,7 @@ impl ReadXdr for HasStuff { } impl WriteXdr for HasStuff { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.data.write_xdr(w)?; @@ -4138,7 +4189,7 @@ Self::Green => "Green", } impl ReadXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -4149,7 +4200,7 @@ Self::Green => "Green", } impl WriteXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -4257,7 +4308,7 @@ Self::B2 => "B2", } impl ReadXdr for NesterNestedEnum { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -4268,7 +4319,7 @@ Self::B2 => "B2", } impl WriteXdr for NesterNestedEnum { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -4294,7 +4345,7 @@ pub struct NesterNestedStruct { } impl ReadXdr for NesterNestedStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4305,7 +4356,7 @@ impl ReadXdr for NesterNestedStruct { } impl WriteXdr for NesterNestedStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.blah.write_xdr(w)?; @@ -4387,7 +4438,7 @@ impl Variants for NesterNestedUnion { impl Union for NesterNestedUnion {} impl ReadXdr for NesterNestedUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: Color = ::read_xdr(r)?; @@ -4403,7 +4454,7 @@ impl ReadXdr for NesterNestedUnion { } impl WriteXdr for NesterNestedUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -4452,7 +4503,7 @@ pub struct Nester { } impl ReadXdr for Nester { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4465,7 +4516,7 @@ nested_union: NesterNestedUnion::read_xdr(r)?, } impl WriteXdr for Nester { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.nested_enum.write_xdr(w)?; @@ -4753,7 +4804,7 @@ TypeVariant::NesterNestedUnion, ]; "NesterNestedStruct", "NesterNestedUnion", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -4790,7 +4841,7 @@ TypeVariant::NesterNestedUnion => r.with_limited_depth(|r| Ok(Self::NesterNested Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -4900,7 +4951,7 @@ TypeVariant::NesterNestedUnion => Box::new(ReadXdrIter::<_, NesterNestedUnion>:: } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -5094,7 +5145,7 @@ Self::NesterNestedUnion(_) => TypeVariant::NesterNestedUnion, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust/union.x/MyXDR.rs b/spec/output/generator_spec_rust/union.x/MyXDR.rs index ad02b2966..a277e7408 100644 --- a/spec/output/generator_spec_rust/union.x/MyXDR.rs +++ b/spec/output/generator_spec_rust/union.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2877,7 +2928,7 @@ Self::Multi => "Multi", } impl ReadXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2888,7 +2939,7 @@ Self::Multi => "Multi", } impl WriteXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2978,7 +3029,7 @@ Self::Multi(_) => UnionKey::Multi, impl Union for MyUnion {} impl ReadXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: UnionKey = ::read_xdr(r)?; @@ -2995,7 +3046,7 @@ UnionKey::Multi => Self::Multi(VecM::::read_xdr(r)?), } impl WriteXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3089,7 +3140,7 @@ Self::V1(_) => 1, impl Union for IntUnion {} impl ReadXdr for IntUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: i32 = ::read_xdr(r)?; @@ -3106,7 +3157,7 @@ Self::V1(_) => 1, } impl WriteXdr for IntUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3155,7 +3206,7 @@ impl AsRef for IntUnion2 { } impl ReadXdr for IntUnion2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = IntUnion::read_xdr(r)?; @@ -3166,7 +3217,7 @@ impl ReadXdr for IntUnion2 { } impl WriteXdr for IntUnion2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3296,7 +3347,7 @@ TypeVariant::IntUnion2, ]; "IntUnion", "IntUnion2", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3316,7 +3367,7 @@ TypeVariant::IntUnion2 => r.with_limited_depth(|r| Ok(Self::IntUnion2(Box::new(I Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3375,7 +3426,7 @@ TypeVariant::IntUnion2 => Box::new(ReadXdrIter::<_, IntUnion2>::new(dec, r.limit } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3484,7 +3535,7 @@ Self::IntUnion2(_) => TypeVariant::IntUnion2, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_jsonschema_impls/block_comments.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_jsonschema_impls/block_comments.x/MyXDR.rs index 6bb6392dc..0f509ea49 100644 --- a/spec/output/generator_spec_rust_custom_jsonschema_impls/block_comments.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_jsonschema_impls/block_comments.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2856,7 +2907,7 @@ impl From for i32 { } impl ReadXdr for AccountFlags { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2867,7 +2918,7 @@ impl ReadXdr for AccountFlags { } impl WriteXdr for AccountFlags { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2955,7 +3006,7 @@ impl Type { pub const VARIANTS: [TypeVariant; 1] = [ TypeVariant::AccountFlags, ]; pub const VARIANTS_STR: [&'static str; 1] = [ "AccountFlags", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2970,7 +3021,7 @@ impl Type { Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3014,7 +3065,7 @@ impl Type { } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3098,7 +3149,7 @@ impl Variants for Type { } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_jsonschema_impls/const.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_jsonschema_impls/const.x/MyXDR.rs index 966b54a40..d4d8e38ab 100644 --- a/spec/output/generator_spec_rust_custom_jsonschema_impls/const.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_jsonschema_impls/const.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2890,7 +2941,7 @@ TypeVariant::TestArray2, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "TestArray", "TestArray2", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2906,7 +2957,7 @@ TypeVariant::TestArray2 => r.with_limited_depth(|r| Ok(Self::TestArray2(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2953,7 +3004,7 @@ TypeVariant::TestArray2 => Box::new(ReadXdrIter::<_, TestArray2>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3042,7 +3093,7 @@ Self::TestArray2(_) => TypeVariant::TestArray2, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_jsonschema_impls/enum.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_jsonschema_impls/enum.x/MyXDR.rs index 62d418406..7db523c78 100644 --- a/spec/output/generator_spec_rust_custom_jsonschema_impls/enum.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_jsonschema_impls/enum.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2940,7 +2991,7 @@ Self::FbaMessage => "FbaMessage", } impl ReadXdr for MessageType { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2951,7 +3002,7 @@ Self::FbaMessage => "FbaMessage", } impl WriteXdr for MessageType { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3049,7 +3100,7 @@ Self::Blue => "Blue", } impl ReadXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3060,7 +3111,7 @@ Self::Blue => "Blue", } impl WriteXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3157,7 +3208,7 @@ Self::Blue2 => "Blue2", } impl ReadXdr for Color2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3168,7 +3219,7 @@ Self::Blue2 => "Blue2", } impl WriteXdr for Color2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3266,7 +3317,7 @@ Self::R3 => "R3", } impl ReadXdr for Color3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3277,7 +3328,7 @@ Self::R3 => "R3", } impl WriteXdr for Color3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3392,7 +3443,7 @@ TypeVariant::Color3, ]; "Color2", "Color3", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3410,7 +3461,7 @@ TypeVariant::Color3 => r.with_limited_depth(|r| Ok(Self::Color3(Box::new(Color3: Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3463,7 +3514,7 @@ TypeVariant::Color3 => Box::new(ReadXdrIter::<_, Color3>::new(dec, r.limits.clon } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3562,7 +3613,7 @@ Self::Color3(_) => TypeVariant::Color3, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_jsonschema_impls/nesting.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_jsonschema_impls/nesting.x/MyXDR.rs index 81767aed3..af26cbeca 100644 --- a/spec/output/generator_spec_rust_custom_jsonschema_impls/nesting.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_jsonschema_impls/nesting.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2866,7 +2917,7 @@ Self::Offer => "Offer", } impl ReadXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2877,7 +2928,7 @@ Self::Offer => "Offer", } impl WriteXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2911,7 +2962,7 @@ pub struct MyUnionOne { } impl ReadXdr for MyUnionOne { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2922,7 +2973,7 @@ impl ReadXdr for MyUnionOne { } impl WriteXdr for MyUnionOne { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -2950,7 +3001,7 @@ pub struct MyUnionTwo { } impl ReadXdr for MyUnionTwo { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2962,7 +3013,7 @@ foo: i32::read_xdr(r)?, } impl WriteXdr for MyUnionTwo { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -3064,7 +3115,7 @@ Self::Offer => UnionKey::Offer, impl Union for MyUnion {} impl ReadXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: UnionKey = ::read_xdr(r)?; @@ -3082,7 +3133,7 @@ UnionKey::Offer => Self::Offer, } impl WriteXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3212,7 +3263,7 @@ TypeVariant::MyUnionTwo, ]; "MyUnionOne", "MyUnionTwo", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3231,7 +3282,7 @@ TypeVariant::MyUnionTwo => r.with_limited_depth(|r| Ok(Self::MyUnionTwo(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3287,7 +3338,7 @@ TypeVariant::MyUnionTwo => Box::new(ReadXdrIter::<_, MyUnionTwo>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3391,7 +3442,7 @@ Self::MyUnionTwo(_) => TypeVariant::MyUnionTwo, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_jsonschema_impls/optional.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_jsonschema_impls/optional.x/MyXDR.rs index 0848b0a4a..2a13253f0 100644 --- a/spec/output/generator_spec_rust_custom_jsonschema_impls/optional.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_jsonschema_impls/optional.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2807,7 +2858,7 @@ pub struct HasOptions { } impl ReadXdr for HasOptions { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2820,7 +2871,7 @@ third_option: Option::::read_xdr(r)?, } impl WriteXdr for HasOptions { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.first_option.write_xdr(w)?; @@ -2919,7 +2970,7 @@ TypeVariant::HasOptions, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "Arr", "HasOptions", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2935,7 +2986,7 @@ TypeVariant::HasOptions => r.with_limited_depth(|r| Ok(Self::HasOptions(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2982,7 +3033,7 @@ TypeVariant::HasOptions => Box::new(ReadXdrIter::<_, HasOptions>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3071,7 +3122,7 @@ Self::HasOptions(_) => TypeVariant::HasOptions, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_jsonschema_impls/struct.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_jsonschema_impls/struct.x/MyXDR.rs index e43738634..327c024bf 100644 --- a/spec/output/generator_spec_rust_custom_jsonschema_impls/struct.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_jsonschema_impls/struct.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2811,7 +2862,7 @@ pub struct MyStruct { } impl ReadXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2826,7 +2877,7 @@ max_string: StringM::<100>::read_xdr(r)?, } impl WriteXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -2927,7 +2978,7 @@ TypeVariant::MyStruct, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "Int64", "MyStruct", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2943,7 +2994,7 @@ TypeVariant::MyStruct => r.with_limited_depth(|r| Ok(Self::MyStruct(Box::new(MyS Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2990,7 +3041,7 @@ TypeVariant::MyStruct => Box::new(ReadXdrIter::<_, MyStruct>::new(dec, r.limits. } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3079,7 +3130,7 @@ Self::MyStruct(_) => TypeVariant::MyStruct, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_jsonschema_impls/test.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_jsonschema_impls/test.x/MyXDR.rs index c16a6f4f9..5164b451e 100644 --- a/spec/output/generator_spec_rust_custom_jsonschema_impls/test.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_jsonschema_impls/test.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2872,7 +2923,7 @@ impl AsRef<[u8; 64]> for Uint512 { } impl ReadXdr for Uint512 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[u8; 64]>::read_xdr(r)?; @@ -2883,7 +2934,7 @@ impl ReadXdr for Uint512 { } impl WriteXdr for Uint512 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -2962,7 +3013,7 @@ impl AsRef> for Uint513 { } impl ReadXdr for Uint513 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = BytesM::<64>::read_xdr(r)?; @@ -2973,7 +3024,7 @@ impl ReadXdr for Uint513 { } impl WriteXdr for Uint513 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3064,7 +3115,7 @@ impl AsRef for Uint514 { } impl ReadXdr for Uint514 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = BytesM::read_xdr(r)?; @@ -3075,7 +3126,7 @@ impl ReadXdr for Uint514 { } impl WriteXdr for Uint514 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3166,7 +3217,7 @@ impl AsRef> for Str { } impl ReadXdr for Str { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = StringM::<64>::read_xdr(r)?; @@ -3177,7 +3228,7 @@ impl ReadXdr for Str { } impl WriteXdr for Str { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3268,7 +3319,7 @@ impl AsRef for Str2 { } impl ReadXdr for Str2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = StringM::read_xdr(r)?; @@ -3279,7 +3330,7 @@ impl ReadXdr for Str2 { } impl WriteXdr for Str2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3428,7 +3479,7 @@ impl AsRef<[u8; 32]> for Hash { } impl ReadXdr for Hash { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[u8; 32]>::read_xdr(r)?; @@ -3439,7 +3490,7 @@ impl ReadXdr for Hash { } impl WriteXdr for Hash { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3517,7 +3568,7 @@ impl AsRef<[Hash; 12]> for Hashes1 { } impl ReadXdr for Hashes1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[Hash; 12]>::read_xdr(r)?; @@ -3528,7 +3579,7 @@ impl ReadXdr for Hashes1 { } impl WriteXdr for Hashes1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3607,7 +3658,7 @@ impl AsRef> for Hashes2 { } impl ReadXdr for Hashes2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = VecM::::read_xdr(r)?; @@ -3618,7 +3669,7 @@ impl ReadXdr for Hashes2 { } impl WriteXdr for Hashes2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3709,7 +3760,7 @@ impl AsRef> for Hashes3 { } impl ReadXdr for Hashes3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = VecM::::read_xdr(r)?; @@ -3720,7 +3771,7 @@ impl ReadXdr for Hashes3 { } impl WriteXdr for Hashes3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3810,7 +3861,7 @@ impl AsRef> for OptHash1 { } impl ReadXdr for OptHash1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = Option::::read_xdr(r)?; @@ -3821,7 +3872,7 @@ impl ReadXdr for OptHash1 { } impl WriteXdr for OptHash1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3862,7 +3913,7 @@ impl AsRef> for OptHash2 { } impl ReadXdr for OptHash2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = Option::::read_xdr(r)?; @@ -3873,7 +3924,7 @@ impl ReadXdr for OptHash2 { } impl WriteXdr for OptHash2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3940,7 +3991,7 @@ pub struct MyStruct { } impl ReadXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -3957,7 +4008,7 @@ field7: bool::read_xdr(r)?, } impl WriteXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.field1.write_xdr(w)?; @@ -3989,7 +4040,7 @@ pub struct LotsOfMyStructs { } impl ReadXdr for LotsOfMyStructs { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4000,7 +4051,7 @@ impl ReadXdr for LotsOfMyStructs { } impl WriteXdr for LotsOfMyStructs { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.members.write_xdr(w)?; @@ -4027,7 +4078,7 @@ pub struct HasStuff { } impl ReadXdr for HasStuff { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4038,7 +4089,7 @@ impl ReadXdr for HasStuff { } impl WriteXdr for HasStuff { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.data.write_xdr(w)?; @@ -4136,7 +4187,7 @@ Self::Green => "Green", } impl ReadXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -4147,7 +4198,7 @@ Self::Green => "Green", } impl WriteXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -4255,7 +4306,7 @@ Self::B2 => "B2", } impl ReadXdr for NesterNestedEnum { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -4266,7 +4317,7 @@ Self::B2 => "B2", } impl WriteXdr for NesterNestedEnum { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -4292,7 +4343,7 @@ pub struct NesterNestedStruct { } impl ReadXdr for NesterNestedStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4303,7 +4354,7 @@ impl ReadXdr for NesterNestedStruct { } impl WriteXdr for NesterNestedStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.blah.write_xdr(w)?; @@ -4385,7 +4436,7 @@ impl Variants for NesterNestedUnion { impl Union for NesterNestedUnion {} impl ReadXdr for NesterNestedUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: Color = ::read_xdr(r)?; @@ -4401,7 +4452,7 @@ impl ReadXdr for NesterNestedUnion { } impl WriteXdr for NesterNestedUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -4450,7 +4501,7 @@ pub struct Nester { } impl ReadXdr for Nester { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4463,7 +4514,7 @@ nested_union: NesterNestedUnion::read_xdr(r)?, } impl WriteXdr for Nester { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.nested_enum.write_xdr(w)?; @@ -4751,7 +4802,7 @@ TypeVariant::NesterNestedUnion, ]; "NesterNestedStruct", "NesterNestedUnion", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -4788,7 +4839,7 @@ TypeVariant::NesterNestedUnion => r.with_limited_depth(|r| Ok(Self::NesterNested Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -4898,7 +4949,7 @@ TypeVariant::NesterNestedUnion => Box::new(ReadXdrIter::<_, NesterNestedUnion>:: } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -5092,7 +5143,7 @@ Self::NesterNestedUnion(_) => TypeVariant::NesterNestedUnion, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_jsonschema_impls/union.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_jsonschema_impls/union.x/MyXDR.rs index d0b2a427a..04fa7cfcc 100644 --- a/spec/output/generator_spec_rust_custom_jsonschema_impls/union.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_jsonschema_impls/union.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2876,7 +2927,7 @@ Self::Multi => "Multi", } impl ReadXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2887,7 +2938,7 @@ Self::Multi => "Multi", } impl WriteXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2976,7 +3027,7 @@ Self::Multi(_) => UnionKey::Multi, impl Union for MyUnion {} impl ReadXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: UnionKey = ::read_xdr(r)?; @@ -2993,7 +3044,7 @@ UnionKey::Multi => Self::Multi(VecM::::read_xdr(r)?), } impl WriteXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3087,7 +3138,7 @@ Self::V1(_) => 1, impl Union for IntUnion {} impl ReadXdr for IntUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: i32 = ::read_xdr(r)?; @@ -3104,7 +3155,7 @@ Self::V1(_) => 1, } impl WriteXdr for IntUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3153,7 +3204,7 @@ impl AsRef for IntUnion2 { } impl ReadXdr for IntUnion2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = IntUnion::read_xdr(r)?; @@ -3164,7 +3215,7 @@ impl ReadXdr for IntUnion2 { } impl WriteXdr for IntUnion2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3294,7 +3345,7 @@ TypeVariant::IntUnion2, ]; "IntUnion", "IntUnion2", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3314,7 +3365,7 @@ TypeVariant::IntUnion2 => r.with_limited_depth(|r| Ok(Self::IntUnion2(Box::new(I Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3373,7 +3424,7 @@ TypeVariant::IntUnion2 => Box::new(ReadXdrIter::<_, IntUnion2>::new(dec, r.limit } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3482,7 +3533,7 @@ Self::IntUnion2(_) => TypeVariant::IntUnion2, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_str_impls/block_comments.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_str_impls/block_comments.x/MyXDR.rs index 6bb6392dc..0f509ea49 100644 --- a/spec/output/generator_spec_rust_custom_str_impls/block_comments.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_str_impls/block_comments.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2856,7 +2907,7 @@ impl From for i32 { } impl ReadXdr for AccountFlags { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2867,7 +2918,7 @@ impl ReadXdr for AccountFlags { } impl WriteXdr for AccountFlags { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2955,7 +3006,7 @@ impl Type { pub const VARIANTS: [TypeVariant; 1] = [ TypeVariant::AccountFlags, ]; pub const VARIANTS_STR: [&'static str; 1] = [ "AccountFlags", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2970,7 +3021,7 @@ impl Type { Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3014,7 +3065,7 @@ impl Type { } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3098,7 +3149,7 @@ impl Variants for Type { } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_str_impls/const.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_str_impls/const.x/MyXDR.rs index 966b54a40..d4d8e38ab 100644 --- a/spec/output/generator_spec_rust_custom_str_impls/const.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_str_impls/const.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2890,7 +2941,7 @@ TypeVariant::TestArray2, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "TestArray", "TestArray2", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2906,7 +2957,7 @@ TypeVariant::TestArray2 => r.with_limited_depth(|r| Ok(Self::TestArray2(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2953,7 +3004,7 @@ TypeVariant::TestArray2 => Box::new(ReadXdrIter::<_, TestArray2>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3042,7 +3093,7 @@ Self::TestArray2(_) => TypeVariant::TestArray2, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_str_impls/enum.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_str_impls/enum.x/MyXDR.rs index 3a63ac95d..e890eb80d 100644 --- a/spec/output/generator_spec_rust_custom_str_impls/enum.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_str_impls/enum.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2940,7 +2991,7 @@ Self::FbaMessage => "FbaMessage", } impl ReadXdr for MessageType { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2951,7 +3002,7 @@ Self::FbaMessage => "FbaMessage", } impl WriteXdr for MessageType { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3049,7 +3100,7 @@ Self::Blue => "Blue", } impl ReadXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3060,7 +3111,7 @@ Self::Blue => "Blue", } impl WriteXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3158,7 +3209,7 @@ Self::Blue2 => "Blue2", } impl ReadXdr for Color2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3169,7 +3220,7 @@ Self::Blue2 => "Blue2", } impl WriteXdr for Color2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3267,7 +3318,7 @@ Self::R3 => "R3", } impl ReadXdr for Color3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -3278,7 +3329,7 @@ Self::R3 => "R3", } impl WriteXdr for Color3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -3393,7 +3444,7 @@ TypeVariant::Color3, ]; "Color2", "Color3", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3411,7 +3462,7 @@ TypeVariant::Color3 => r.with_limited_depth(|r| Ok(Self::Color3(Box::new(Color3: Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3464,7 +3515,7 @@ TypeVariant::Color3 => Box::new(ReadXdrIter::<_, Color3>::new(dec, r.limits.clon } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3563,7 +3614,7 @@ Self::Color3(_) => TypeVariant::Color3, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_str_impls/nesting.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_str_impls/nesting.x/MyXDR.rs index fd6a7b54f..58cb1b478 100644 --- a/spec/output/generator_spec_rust_custom_str_impls/nesting.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_str_impls/nesting.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2867,7 +2918,7 @@ Self::Offer => "Offer", } impl ReadXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2878,7 +2929,7 @@ Self::Offer => "Offer", } impl WriteXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2912,7 +2963,7 @@ pub struct MyUnionOne { } impl ReadXdr for MyUnionOne { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2923,7 +2974,7 @@ impl ReadXdr for MyUnionOne { } impl WriteXdr for MyUnionOne { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -2951,7 +3002,7 @@ pub struct MyUnionTwo { } impl ReadXdr for MyUnionTwo { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2963,7 +3014,7 @@ foo: i32::read_xdr(r)?, } impl WriteXdr for MyUnionTwo { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -3066,7 +3117,7 @@ Self::Offer => UnionKey::Offer, impl Union for MyUnion {} impl ReadXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: UnionKey = ::read_xdr(r)?; @@ -3084,7 +3135,7 @@ UnionKey::Offer => Self::Offer, } impl WriteXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3214,7 +3265,7 @@ TypeVariant::MyUnionTwo, ]; "MyUnionOne", "MyUnionTwo", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3233,7 +3284,7 @@ TypeVariant::MyUnionTwo => r.with_limited_depth(|r| Ok(Self::MyUnionTwo(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3289,7 +3340,7 @@ TypeVariant::MyUnionTwo => Box::new(ReadXdrIter::<_, MyUnionTwo>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3393,7 +3444,7 @@ Self::MyUnionTwo(_) => TypeVariant::MyUnionTwo, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_str_impls/optional.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_str_impls/optional.x/MyXDR.rs index d4fed65d3..9ac7c5c6d 100644 --- a/spec/output/generator_spec_rust_custom_str_impls/optional.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_str_impls/optional.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2808,7 +2859,7 @@ pub struct HasOptions { } impl ReadXdr for HasOptions { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2821,7 +2872,7 @@ third_option: Option::::read_xdr(r)?, } impl WriteXdr for HasOptions { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.first_option.write_xdr(w)?; @@ -2920,7 +2971,7 @@ TypeVariant::HasOptions, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "Arr", "HasOptions", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2936,7 +2987,7 @@ TypeVariant::HasOptions => r.with_limited_depth(|r| Ok(Self::HasOptions(Box::new Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2983,7 +3034,7 @@ TypeVariant::HasOptions => Box::new(ReadXdrIter::<_, HasOptions>::new(dec, r.lim } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3072,7 +3123,7 @@ Self::HasOptions(_) => TypeVariant::HasOptions, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_str_impls/struct.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_str_impls/struct.x/MyXDR.rs index 882f72e13..932215fdf 100644 --- a/spec/output/generator_spec_rust_custom_str_impls/struct.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_str_impls/struct.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2812,7 +2863,7 @@ pub struct MyStruct { } impl ReadXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -2827,7 +2878,7 @@ max_string: StringM::<100>::read_xdr(r)?, } impl WriteXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.some_int.write_xdr(w)?; @@ -2928,7 +2979,7 @@ TypeVariant::MyStruct, ]; pub const VARIANTS_STR: [&'static str; 2] = [ "Int64", "MyStruct", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -2944,7 +2995,7 @@ TypeVariant::MyStruct => r.with_limited_depth(|r| Ok(Self::MyStruct(Box::new(MyS Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -2991,7 +3042,7 @@ TypeVariant::MyStruct => Box::new(ReadXdrIter::<_, MyStruct>::new(dec, r.limits. } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3080,7 +3131,7 @@ Self::MyStruct(_) => TypeVariant::MyStruct, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_str_impls/test.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_str_impls/test.x/MyXDR.rs index 52d6e3d11..69abdac69 100644 --- a/spec/output/generator_spec_rust_custom_str_impls/test.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_str_impls/test.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2872,7 +2923,7 @@ impl AsRef<[u8; 64]> for Uint512 { } impl ReadXdr for Uint512 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[u8; 64]>::read_xdr(r)?; @@ -2883,7 +2934,7 @@ impl ReadXdr for Uint512 { } impl WriteXdr for Uint512 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -2962,7 +3013,7 @@ impl AsRef> for Uint513 { } impl ReadXdr for Uint513 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = BytesM::<64>::read_xdr(r)?; @@ -2973,7 +3024,7 @@ impl ReadXdr for Uint513 { } impl WriteXdr for Uint513 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3064,7 +3115,7 @@ impl AsRef for Uint514 { } impl ReadXdr for Uint514 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = BytesM::read_xdr(r)?; @@ -3075,7 +3126,7 @@ impl ReadXdr for Uint514 { } impl WriteXdr for Uint514 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3166,7 +3217,7 @@ impl AsRef> for Str { } impl ReadXdr for Str { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = StringM::<64>::read_xdr(r)?; @@ -3177,7 +3228,7 @@ impl ReadXdr for Str { } impl WriteXdr for Str { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3268,7 +3319,7 @@ impl AsRef for Str2 { } impl ReadXdr for Str2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = StringM::read_xdr(r)?; @@ -3279,7 +3330,7 @@ impl ReadXdr for Str2 { } impl WriteXdr for Str2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3428,7 +3479,7 @@ impl AsRef<[u8; 32]> for Hash { } impl ReadXdr for Hash { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[u8; 32]>::read_xdr(r)?; @@ -3439,7 +3490,7 @@ impl ReadXdr for Hash { } impl WriteXdr for Hash { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3517,7 +3568,7 @@ impl AsRef<[Hash; 12]> for Hashes1 { } impl ReadXdr for Hashes1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = <[Hash; 12]>::read_xdr(r)?; @@ -3528,7 +3579,7 @@ impl ReadXdr for Hashes1 { } impl WriteXdr for Hashes1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3607,7 +3658,7 @@ impl AsRef> for Hashes2 { } impl ReadXdr for Hashes2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = VecM::::read_xdr(r)?; @@ -3618,7 +3669,7 @@ impl ReadXdr for Hashes2 { } impl WriteXdr for Hashes2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3709,7 +3760,7 @@ impl AsRef> for Hashes3 { } impl ReadXdr for Hashes3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = VecM::::read_xdr(r)?; @@ -3720,7 +3771,7 @@ impl ReadXdr for Hashes3 { } impl WriteXdr for Hashes3 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3810,7 +3861,7 @@ impl AsRef> for OptHash1 { } impl ReadXdr for OptHash1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = Option::::read_xdr(r)?; @@ -3821,7 +3872,7 @@ impl ReadXdr for OptHash1 { } impl WriteXdr for OptHash1 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3862,7 +3913,7 @@ impl AsRef> for OptHash2 { } impl ReadXdr for OptHash2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = Option::::read_xdr(r)?; @@ -3873,7 +3924,7 @@ impl ReadXdr for OptHash2 { } impl WriteXdr for OptHash2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3941,7 +3992,7 @@ pub struct MyStruct { } impl ReadXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -3958,7 +4009,7 @@ field7: bool::read_xdr(r)?, } impl WriteXdr for MyStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.field1.write_xdr(w)?; @@ -3991,7 +4042,7 @@ pub struct LotsOfMyStructs { } impl ReadXdr for LotsOfMyStructs { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4002,7 +4053,7 @@ impl ReadXdr for LotsOfMyStructs { } impl WriteXdr for LotsOfMyStructs { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.members.write_xdr(w)?; @@ -4029,7 +4080,7 @@ pub struct HasStuff { } impl ReadXdr for HasStuff { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4040,7 +4091,7 @@ impl ReadXdr for HasStuff { } impl WriteXdr for HasStuff { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.data.write_xdr(w)?; @@ -4138,7 +4189,7 @@ Self::Green => "Green", } impl ReadXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -4149,7 +4200,7 @@ Self::Green => "Green", } impl WriteXdr for Color { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -4257,7 +4308,7 @@ Self::B2 => "B2", } impl ReadXdr for NesterNestedEnum { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -4268,7 +4319,7 @@ Self::B2 => "B2", } impl WriteXdr for NesterNestedEnum { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -4294,7 +4345,7 @@ pub struct NesterNestedStruct { } impl ReadXdr for NesterNestedStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4305,7 +4356,7 @@ impl ReadXdr for NesterNestedStruct { } impl WriteXdr for NesterNestedStruct { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.blah.write_xdr(w)?; @@ -4387,7 +4438,7 @@ impl Variants for NesterNestedUnion { impl Union for NesterNestedUnion {} impl ReadXdr for NesterNestedUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: Color = ::read_xdr(r)?; @@ -4403,7 +4454,7 @@ impl ReadXdr for NesterNestedUnion { } impl WriteXdr for NesterNestedUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -4452,7 +4503,7 @@ pub struct Nester { } impl ReadXdr for Nester { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { Ok(Self{ @@ -4465,7 +4516,7 @@ nested_union: NesterNestedUnion::read_xdr(r)?, } impl WriteXdr for Nester { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.nested_enum.write_xdr(w)?; @@ -4753,7 +4804,7 @@ TypeVariant::NesterNestedUnion, ]; "NesterNestedStruct", "NesterNestedUnion", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -4790,7 +4841,7 @@ TypeVariant::NesterNestedUnion => r.with_limited_depth(|r| Ok(Self::NesterNested Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -4900,7 +4951,7 @@ TypeVariant::NesterNestedUnion => Box::new(ReadXdrIter::<_, NesterNestedUnion>:: } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -5094,7 +5145,7 @@ Self::NesterNestedUnion(_) => TypeVariant::NesterNestedUnion, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self { diff --git a/spec/output/generator_spec_rust_custom_str_impls/union.x/MyXDR.rs b/spec/output/generator_spec_rust_custom_str_impls/union.x/MyXDR.rs index 946a36cc9..3ac492b1c 100644 --- a/spec/output/generator_spec_rust_custom_str_impls/union.x/MyXDR.rs +++ b/spec/output/generator_spec_rust_custom_str_impls/union.x/MyXDR.rs @@ -35,6 +35,7 @@ use alloc::{ borrow::ToOwned, boxed::Box, string::{FromUtf8Error, String}, + vec, vec::Vec, }; #[cfg(feature = "std")] @@ -43,14 +44,17 @@ use std::string::FromUtf8Error; #[cfg(feature = "arbitrary")] use arbitrary::Arbitrary; -// TODO: Add support for read/write xdr fns when std not available. - #[cfg(feature = "std")] use std::{ error, io, io::{BufRead, BufReader, Cursor, Read, Write}, }; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io::{Error as _, ErrorType, Read, Write}; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use embedded_io_cursor::Cursor; + /// Error contains all errors returned by functions in this crate. It can be /// compared via `PartialEq`, however any contained IO errors will only be /// compared on their `ErrorKind`. @@ -66,6 +70,8 @@ pub enum Error { InvalidHex, #[cfg(feature = "std")] Io(io::Error), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Io(embedded_io::ErrorKind), DepthLimitExceeded, #[cfg(feature = "serde_json")] Json(serde_json::Error), @@ -82,13 +88,34 @@ impl PartialEq for Error { // case for comparing errors outputted by the XDR library is for // error case testing, and a lack of the ability to compare has a // detrimental affect on failure testing, so this is a tradeoff. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(), _ => core::mem::discriminant(self) == core::mem::discriminant(other), } } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl embedded_io::Error for Error { + fn kind(&self) -> embedded_io::ErrorKind { + match self { + Self::Io(e) => *e, + _ => embedded_io::ErrorKind::Other, + } + } +} + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl From> for Error { + fn from(value: embedded_io::ReadExactError) -> Self { + match value { + embedded_io::ReadExactError::UnexpectedEof => Error::Io(embedded_io::ErrorKind::Other), + embedded_io::ReadExactError::Other(e) => e + } + } +} + #[cfg(feature = "std")] impl error::Error for Error { #[must_use] @@ -115,6 +142,8 @@ impl fmt::Display for Error { Error::InvalidHex => write!(f, "hex invalid"), #[cfg(feature = "std")] Error::Io(e) => write!(f, "{e}"), + #[cfg(all(not(feature = "std"), feature = "alloc"))] + Error::Io(_) => write!(f, "io error"), Error::DepthLimitExceeded => write!(f, "depth limit exceeded"), #[cfg(feature = "serde_json")] Error::Json(e) => write!(f, "{e}"), @@ -167,6 +196,9 @@ impl From for () { #[allow(dead_code)] type Result = core::result::Result; +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl ErrorType for Limited { type Error = Error; } + /// Name defines types that assign a static name to their value, such as the /// name given to an identifier in an XDR enum, or the name given to the case in /// a union. @@ -200,7 +232,7 @@ where /// `Limits` contains the limits that a limited reader or writer will be /// constrained to. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Limits { /// Defines the maximum depth for recursive calls in `Read/WriteXdr` to @@ -217,7 +249,7 @@ pub struct Limits { pub len: usize, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limits { #[must_use] pub fn none() -> Self { @@ -248,13 +280,13 @@ impl Limits { /// /// Intended for use with readers and writers and limiting their reads and /// writes. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] pub struct Limited { pub inner: L, pub(crate) limits: Limits, } -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] impl Limited { /// Constructs a new `Limited`. /// @@ -307,6 +339,15 @@ impl Read for Limited { } } + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Read for Limited { + /// Forwards the read operation to the wrapped object. + fn read(&mut self, buf: &mut [u8]) -> core::result::Result { + self.inner.read(buf).map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] impl BufRead for Limited { /// Forwards the read operation to the wrapped object. @@ -333,6 +374,18 @@ impl Write for Limited { } } +#[cfg(all(not(feature = "std"), feature = "alloc"))] +impl Write for Limited { + /// Forwards the write operation to the wrapped object. + fn write(&mut self, buf: &[u8]) -> core::result::Result { + self.inner.write(buf).map_err(|e| Error::Io(e.kind())) + } + + fn flush(&mut self) -> core::result::Result<(), Self::Error> { + self.inner.flush().map_err(|e| Error::Io(e.kind())) + } +} + #[cfg(feature = "std")] pub struct ReadXdrIter { reader: Limited>, @@ -406,7 +459,7 @@ where /// /// Use [`ReadXdR: Read_xdr_to_end`] when the intent is for all bytes in the /// read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result; /// Construct the type from the XDR bytes base64 encoded. @@ -441,7 +494,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_to_end(r: &mut Limited) -> Result { let s = Self::read_xdr(r)?; // Check that any further reads, such as this read of one byte, read no @@ -481,7 +534,7 @@ where /// /// Use [`ReadXdR: Read_xdr_into_to_end`] when the intent is for all bytes /// in the read implementation to be consumed by the read. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into(&mut self, r: &mut Limited) -> Result<()> { *self = Self::read_xdr(r)?; Ok(()) @@ -505,7 +558,7 @@ where /// /// All implementations should continue if the read implementation returns /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted). - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr_into_to_end(&mut self, r: &mut Limited) -> Result<()> { Self::read_xdr_into(self, r)?; // Check that any further reads, such as this read of one byte, read no @@ -554,7 +607,7 @@ where /// /// An error is returned if the bytes are not completely consumed by the /// deserialization. - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn from_xdr(bytes: impl AsRef<[u8]>, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(&mut cursor)?; @@ -578,10 +631,10 @@ where } pub trait WriteXdr { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()>; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn to_xdr(&self, limits: Limits) -> Result> { let mut cursor = Limited::new(Cursor::new(vec![]), limits); self.write_xdr(&mut cursor)?; @@ -603,13 +656,13 @@ pub trait WriteXdr { /// `Pad_len` returns the number of bytes to pad an XDR value of the given /// length to make the final serialized size a multiple of 4. -#[cfg(feature = "std")] +#[cfg(feature = "alloc")] fn pad_len(len: usize) -> usize { (4 - (len % 4)) % 4 } impl ReadXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -621,7 +674,7 @@ impl ReadXdr for i32 { } impl WriteXdr for i32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -632,7 +685,7 @@ impl WriteXdr for i32 { } impl ReadXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 4]; r.with_limited_depth(|r| { @@ -644,7 +697,7 @@ impl ReadXdr for u32 { } impl WriteXdr for u32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 4] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -655,7 +708,7 @@ impl WriteXdr for u32 { } impl ReadXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -667,7 +720,7 @@ impl ReadXdr for i64 { } impl WriteXdr for i64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -678,7 +731,7 @@ impl WriteXdr for i64 { } impl ReadXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { let mut b = [0u8; 8]; r.with_limited_depth(|r| { @@ -690,7 +743,7 @@ impl ReadXdr for u64 { } impl WriteXdr for u64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { let b: [u8; 8] = self.to_be_bytes(); w.with_limited_depth(|w| { @@ -701,35 +754,35 @@ impl WriteXdr for u64 { } impl ReadXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f32 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { todo!() } } impl WriteXdr for f64 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { todo!() } } impl ReadXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -740,7 +793,7 @@ impl ReadXdr for bool { } impl WriteXdr for bool { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i = u32::from(*self); // true = 1, false = 0 @@ -750,7 +803,7 @@ impl WriteXdr for bool { } impl ReadXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = u32::read_xdr(r)?; @@ -767,7 +820,7 @@ impl ReadXdr for Option { } impl WriteXdr for Option { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { if let Some(t) = self { @@ -782,35 +835,35 @@ impl WriteXdr for Option { } impl ReadXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| Ok(Box::new(T::read_xdr(r)?))) } } impl WriteXdr for Box { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| T::write_xdr(self, w)) } } impl ReadXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(_r: &mut Limited) -> Result { Ok(()) } } impl WriteXdr for () { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, _w: &mut Limited) -> Result<()> { Ok(()) } } impl ReadXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { r.consume_len(N)?; @@ -829,7 +882,7 @@ impl ReadXdr for [u8; N] { } impl WriteXdr for [u8; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { w.consume_len(N)?; @@ -843,7 +896,7 @@ impl WriteXdr for [u8; N] { } impl ReadXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let mut vec = Vec::with_capacity(N); @@ -858,7 +911,7 @@ impl ReadXdr for [T; N] { } impl WriteXdr for [T; N] { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { for t in self { @@ -1217,7 +1270,7 @@ impl<'a, const MAX: u32> TryFrom<&'a VecM> for &'a str { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1244,7 +1297,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1264,7 +1317,7 @@ impl WriteXdr for VecM { } impl ReadXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len = u32::read_xdr(r)?; @@ -1284,7 +1337,7 @@ impl ReadXdr for VecM { } impl WriteXdr for VecM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -1657,7 +1710,7 @@ impl<'a, const MAX: u32> TryFrom<&'a BytesM> for &'a str { } impl ReadXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -1684,7 +1737,7 @@ impl ReadXdr for BytesM { } impl WriteXdr for BytesM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2060,7 +2113,7 @@ impl<'a, const MAX: u32> TryFrom<&'a StringM> for &'a str { } impl ReadXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let len: u32 = u32::read_xdr(r)?; @@ -2087,7 +2140,7 @@ impl ReadXdr for StringM { } impl WriteXdr for StringM { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?; @@ -2133,7 +2186,7 @@ impl ReadXdr for Frame where T: ReadXdr, { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { // Read the frame header value that contains 1 flag-bit and a 33-bit length. // - The 1 flag bit is 0 when there are more frames for the same record. @@ -2153,10 +2206,8 @@ where } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod tests { - use std::io::Cursor; - use super::*; #[test] @@ -2265,7 +2316,7 @@ mod tests { } } -#[cfg(all(test, feature = "std"))] +#[cfg(all(test, feature = "alloc"))] mod test { use super::*; @@ -2877,7 +2928,7 @@ Self::Multi => "Multi", } impl ReadXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let e = i32::read_xdr(r)?; @@ -2888,7 +2939,7 @@ Self::Multi => "Multi", } impl WriteXdr for UnionKey { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { let i: i32 = (*self).into(); @@ -2978,7 +3029,7 @@ Self::Multi(_) => UnionKey::Multi, impl Union for MyUnion {} impl ReadXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: UnionKey = ::read_xdr(r)?; @@ -2995,7 +3046,7 @@ UnionKey::Multi => Self::Multi(VecM::::read_xdr(r)?), } impl WriteXdr for MyUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3089,7 +3140,7 @@ Self::V1(_) => 1, impl Union for IntUnion {} impl ReadXdr for IntUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let dv: i32 = ::read_xdr(r)?; @@ -3106,7 +3157,7 @@ Self::V1(_) => 1, } impl WriteXdr for IntUnion { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w| { self.discriminant().write_xdr(w)?; @@ -3155,7 +3206,7 @@ impl AsRef for IntUnion2 { } impl ReadXdr for IntUnion2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn read_xdr(r: &mut Limited) -> Result { r.with_limited_depth(|r| { let i = IntUnion::read_xdr(r)?; @@ -3166,7 +3217,7 @@ impl ReadXdr for IntUnion2 { } impl WriteXdr for IntUnion2 { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] fn write_xdr(&self, w: &mut Limited) -> Result<()> { w.with_limited_depth(|w|{ self.0.write_xdr(w) }) } @@ -3296,7 +3347,7 @@ TypeVariant::IntUnion2, ]; "IntUnion", "IntUnion2", ]; - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] pub fn read_xdr(v: TypeVariant, r: &mut Limited) -> Result { match v { @@ -3316,7 +3367,7 @@ TypeVariant::IntUnion2 => r.with_limited_depth(|r| Ok(Self::IntUnion2(Box::new(I Ok(t) } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn read_xdr_to_end(v: TypeVariant, r: &mut Limited) -> Result { let s = Self::read_xdr(v, r)?; // Check that any further reads, such as this read of one byte, read no @@ -3375,7 +3426,7 @@ TypeVariant::IntUnion2 => Box::new(ReadXdrIter::<_, IntUnion2>::new(dec, r.limit } } - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] pub fn from_xdr>(v: TypeVariant, bytes: B, limits: Limits) -> Result { let mut cursor = Limited::new(Cursor::new(bytes.as_ref()), limits); let t = Self::read_xdr_to_end(v, &mut cursor)?; @@ -3484,7 +3535,7 @@ Self::IntUnion2(_) => TypeVariant::IntUnion2, } impl WriteXdr for Type { - #[cfg(feature = "std")] + #[cfg(feature = "alloc")] #[allow(clippy::too_many_lines)] fn write_xdr(&self, w: &mut Limited) -> Result<()> { match self {