// SPDX-License-Identifier: CC0-1.0 //! Bitcoin consensus. //! //! This module defines structures, functions, and traits that are needed to //! conform to Bitcoin consensus. pub mod encode; mod error; #[cfg(feature = "serde")] pub mod serde; use core::fmt; use io::{BufRead, Read}; use crate::consensus; #[rustfmt::skip] // Keep public re-exports separate. #[doc(inline)] pub use self::{ encode::{deserialize, deserialize_partial, serialize, Decodable, Encodable, ReadExt, WriteExt}, error::{Error, FromHexError, DecodeError}, }; pub(crate) use self::error::parse_failed_error; struct IterReader>> { iterator: core::iter::Fuse, buf: Option, error: Option, } impl>> IterReader { pub(crate) fn new(iterator: I) -> Self { IterReader { iterator: iterator.fuse(), buf: None, error: None } } fn decode(mut self) -> Result> { let result = T::consensus_decode(&mut self); match (result, self.error) { (Ok(_), None) if self.iterator.next().is_some() => Err(DecodeError::TooManyBytes), (Ok(value), None) => Ok(value), (Ok(_), Some(error)) => panic!("{} silently ate the error: {:?}", core::any::type_name::(), error), (Err(consensus::encode::Error::Io(io_error)), Some(de_error)) if io_error.kind() == io::ErrorKind::Other && io_error.get_ref().is_none() => Err(DecodeError::Other(de_error)), (Err(consensus_error), None) => Err(DecodeError::Consensus(consensus_error)), (Err(consensus::encode::Error::Io(io_error)), de_error) => panic!("unexpected IO error {:?} returned from {}::consensus_decode(), deserialization error: {:?}", io_error, core::any::type_name::(), de_error), (Err(consensus_error), Some(de_error)) => panic!("{} should've returned `Other` IO error because of deserialization error {:?} but it returned consensus error {:?} instead", core::any::type_name::(), de_error, consensus_error), } } } impl>> Read for IterReader { fn read(&mut self, mut buf: &mut [u8]) -> io::Result { let mut count = 0; if buf.is_empty() { return Ok(0); } if let Some(first) = self.buf.take() { buf[0] = first; buf = &mut buf[1..]; count += 1; } for (dst, src) in buf.iter_mut().zip(&mut self.iterator) { match src { Ok(byte) => *dst = byte, Err(error) => { self.error = Some(error); return Err(io::ErrorKind::Other.into()); } } // bounded by the length of buf count += 1; } Ok(count) } } impl>> BufRead for IterReader { fn fill_buf(&mut self) -> Result<&[u8], io::Error> { // matching on reference rather than using `ref` confuses borrow checker if let Some(ref byte) = self.buf { Ok(core::slice::from_ref(byte)) } else { match self.iterator.next() { Some(Ok(byte)) => { self.buf = Some(byte); Ok(core::slice::from_ref(self.buf.as_ref().expect("we've just filled it"))) } Some(Err(error)) => { self.error = Some(error); Err(io::ErrorKind::Other.into()) } None => Ok(&[]), } } } fn consume(&mut self, len: usize) { debug_assert!(len <= 1); if len > 0 { self.buf = None; } } }