codec_io/
lib.rs

1// Copyright 2017, 2018 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! # Input/Output Trait Definition for Encoding Libraries
16//!
17//! This library defines `Input` and `Output` traits that can be used for
18//! encoding libraries to define their own `Encode` and `Decode` traits.
19
20#![warn(missing_docs)]
21
22#![cfg_attr(not(feature = "std"), no_std)]
23
24extern crate alloc;
25
26/// Trait that allows reading of data into a slice.
27pub trait Input {
28	/// Error type of this input.
29	type Error;
30
31	/// Read the exact number of bytes required to fill the given buffer.
32	///
33	/// Note that this function is similar to `std::io::Read::read_exact` and not
34	/// `std::io::Read::read`.
35	fn read(&mut self, into: &mut [u8]) -> Result<(), Self::Error>;
36
37	/// Read a single byte from the input.
38	fn read_byte(&mut self) -> Result<u8, Self::Error> {
39		let mut buf = [0u8];
40		self.read(&mut buf[..])?;
41		Ok(buf[0])
42	}
43}
44
45/// Error for slice-based input. Only used in `no_std` environments.
46#[cfg(not(feature = "std"))]
47#[derive(PartialEq, Eq, Clone)]
48pub enum SliceInputError {
49	/// Not enough data to fill the buffer.
50	NotEnoughData,
51}
52
53#[cfg(not(feature = "std"))]
54impl<'a> Input for &'a [u8] {
55	type Error = SliceInputError;
56
57	fn read(&mut self, into: &mut [u8]) -> Result<(), SliceInputError> {
58		if into.len() > self.len() {
59			return Err(SliceInputError::NotEnoughData);
60		}
61		let len = into.len();
62		into.copy_from_slice(&self[..len]);
63		*self = &self[len..];
64		Ok(())
65	}
66}
67
68#[cfg(feature = "std")]
69impl<R: std::io::Read> Input for R {
70	type Error = std::io::Error;
71
72	fn read(&mut self, into: &mut [u8]) -> Result<(), std::io::Error> {
73		(self as &mut dyn std::io::Read).read_exact(into)?;
74		Ok(())
75	}
76}
77
78/// Trait that allows writing of data.
79pub trait Output: Sized {
80	/// Write to the output.
81	fn write(&mut self, bytes: &[u8]);
82
83	/// Write a single byte to the output.
84	fn push_byte(&mut self, byte: u8) {
85		self.write(&[byte]);
86	}
87}
88
89#[cfg(not(feature = "std"))]
90impl Output for alloc::vec::Vec<u8> {
91	fn write(&mut self, bytes: &[u8]) {
92		self.extend_from_slice(bytes)
93	}
94}
95
96#[cfg(feature = "std")]
97impl<W: std::io::Write> Output for W {
98	fn write(&mut self, bytes: &[u8]) {
99		(self as &mut dyn std::io::Write).write_all(bytes).expect("Codec outputs are infallible");
100	}
101}