From 3caaadf9bb20b181c84de6f1d8936d8b0b69b4fc Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 12 Sep 2023 05:21:50 +0000 Subject: [PATCH] [IO] Replace the `io::Cursor` re-export with our own `Cursor` --- bitcoin/src/crypto/key.rs | 1 - io/src/lib.rs | 43 ++++++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index 01ff2b13..5352a505 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -752,7 +752,6 @@ mod tests { use super::*; use crate::address::Address; - use crate::io; use crate::network::Network::{Bitcoin, Testnet}; #[test] diff --git a/io/src/lib.rs b/io/src/lib.rs index c25bd3b9..96d07280 100644 --- a/io/src/lib.rs +++ b/io/src/lib.rs @@ -38,10 +38,10 @@ pub mod io { compile_error!("At least one of std or core2 must be enabled"); #[cfg(feature = "std")] - pub use std::io::{Cursor, Error, ErrorKind, Result}; + pub use std::io::{Error, ErrorKind, Result}; #[cfg(not(feature = "std"))] - pub use core2::io::{Cursor, Error, ErrorKind, Result}; + pub use core2::io::{Error, ErrorKind, Result}; /// A generic trait describing an input stream. See [`std::io::Read`] for more info. pub trait Read { @@ -86,11 +86,44 @@ pub mod io { } } - #[cfg(all(feature = "core2", not(feature = "std")))] - impl Read for R { + #[cfg(not(feature = "std"))] + impl Read for &[u8] { #[inline] fn read(&mut self, buf: &mut [u8]) -> Result { - ::read(self, buf) + let cnt = core::cmp::min(self.len(), buf.len()); + buf[..cnt].copy_from_slice(&self[..cnt]); + *self = &self[cnt..]; + Ok(cnt) + } + } + + pub struct Cursor { + inner: T, + pos: u64, + } + impl> Cursor { + #[inline] + pub fn new(inner: T) -> Self { + Cursor { inner, pos: 0 } + } + #[inline] + pub fn position(&self) -> u64 { + self.pos + } + #[inline] + pub fn into_inner(self) -> T { + self.inner + } + } + impl> Read for Cursor { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> Result { + let inner: &[u8] = self.inner.as_ref(); + let start_pos = self.pos.try_into().unwrap_or(inner.len()); + let read = core::cmp::min(inner.len().saturating_sub(start_pos), buf.len()); + buf[..read].copy_from_slice(&inner[start_pos..start_pos + read]); + self.pos = self.pos.saturating_add(read.try_into().unwrap_or(u64::max_value() /* unreachable */)); + Ok(read) } }