bytecodec-0.4.15/.cargo_vcs_info.json0000644000000001120000000000000130550ustar { "git": { "sha1": "6f71222f535118571160bd2695e323bec78fd158" } } bytecodec-0.4.15/.github/actions-rs/grcov.yml000064400000000000000000000000550000000000000171160ustar 00000000000000ignore-not-existing: true ignore: - "../*" bytecodec-0.4.15/.github/workflows/ci.yml000064400000000000000000000061010000000000000163420ustar 00000000000000# Based on https://github.com/actions-rs/meta/blob/master/recipes/quickstart.md name: CI on: [push, pull_request] jobs: check: name: Check runs-on: ubuntu-latest strategy: matrix: toolchain: [stable, beta, nightly] steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install ${{ matrix.toolchain }} toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true - name: Run cargo check uses: actions-rs/cargo@v1 with: command: check args: --all-features --all test: name: Test Suite runs-on: ubuntu-latest strategy: matrix: toolchain: [stable, beta, nightly] steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install ${{ matrix.toolchain }} toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true - name: Run cargo test uses: actions-rs/cargo@v1 with: command: test args: --all-features --all lints: name: Lints runs-on: ubuntu-latest strategy: matrix: toolchain: [stable, beta, nightly] steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install ${{ matrix.toolchain }} toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.toolchain }} override: true components: rustfmt, clippy - name: Run cargo fmt uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check - name: Run cargo clippy uses: actions-rs/cargo@v1 with: command: clippy args: --all-features --all -- -D warnings grcov: name: Coverage runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install toolchain uses: actions-rs/toolchain@v1 with: toolchain: nightly override: true - name: Execute tests uses: actions-rs/cargo@v1 with: command: test args: --all --all-features env: CARGO_INCREMENTAL: 0 RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" RUSTDOCFLAGS: "-Cpanic=abort" - name: Gather coverage data id: coverage uses: actions-rs/grcov@v0.1 - name: Coveralls upload uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel: true path-to-lcov: ${{ steps.coverage.outputs.report }} grcov_finalize: runs-on: ubuntu-latest needs: grcov steps: - name: Coveralls finalization uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true bytecodec-0.4.15/.gitignore000064400000000000000000000000400000000000000136130ustar 00000000000000 /target/ **/*.rs.bk Cargo.lock bytecodec-0.4.15/Cargo.toml0000644000000027230000000000000110650ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "bytecodec" version = "0.4.15" authors = ["Takeru Ohta "] description = "A tiny framework for implementing encoders/decoders of byte-oriented protocols" homepage = "https://github.com/sile/bytecodec" readme = "README.md" categories = ["encoding"] license = "MIT" repository = "https://github.com/sile/bytecodec" [package.metadata.docs.rs] all-features = true [dependencies.bincode] version = "1" optional = true [dependencies.byteorder] version = "1" [dependencies.pin-project] version = "1" optional = true [dependencies.serde] version = "1" optional = true [dependencies.serde_json] version = "1" optional = true [dependencies.tokio] version = "1.0" features = ["io-util"] optional = true [dependencies.trackable] version = "0.2" [features] bincode_codec = ["serde", "bincode"] json_codec = ["serde", "serde_json"] tokio-async = ["tokio", "pin-project"] [badges.coveralls] repository = "sile/bytecodec" bytecodec-0.4.15/Cargo.toml.orig000064400000000000000000000016010000000000000145160ustar 00000000000000[package] name = "bytecodec" version = "0.4.15" authors = ["Takeru Ohta "] description = "A tiny framework for implementing encoders/decoders of byte-oriented protocols" homepage = "https://github.com/sile/bytecodec" repository = "https://github.com/sile/bytecodec" readme = "README.md" license = "MIT" categories = ["encoding"] edition = "2018" [badges] coveralls = {repository = "sile/bytecodec"} [dependencies] bincode = { version = "1", optional = true } byteorder = "1" serde = { version = "1", optional = true } serde_json = { version = "1", optional = true } trackable = "0.2" tokio = { version = "1.0", features = ["io-util"], optional = true } pin-project = { version = "1", optional = true } [features] bincode_codec = ["serde", "bincode"] json_codec = ["serde", "serde_json"] tokio-async = ["tokio", "pin-project"] [package.metadata.docs.rs] all-features = true bytecodec-0.4.15/LICENSE000064400000000000000000000021050000000000000126340ustar 00000000000000The MIT License Copyright (c) 2018 Takeru Ohta Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. bytecodec-0.4.15/README.md000064400000000000000000000041610000000000000131120ustar 00000000000000bytecodec ========= [![bytecodec](https://img.shields.io/crates/v/bytecodec.svg)](https://crates.io/crates/bytecodec) [![Documentation](https://docs.rs/bytecodec/badge.svg)](https://docs.rs/bytecodec) [![Actions Status](https://github.com/sile/bytecodec/workflows/CI/badge.svg)](https://github.com/sile/bytecodec/actions) [![Coverage Status](https://coveralls.io/repos/github/sile/bytecodec/badge.svg?branch=main)](https://coveralls.io/github/sile/bytecodec?branch=main) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) A tiny Rust framework for implementing encoders/decoders of byte-oriented protocols. [Documentation](https://docs.rs/bytecodec) Features -------- - Suited for byte-oriented protocols - Incremental encoding/decoding: - `Encode` and `Decode` traits support incremental encoding and decoding - The number of bytes consumed in an execution of `encode/decode` methods can be completely controlled by the caller - This property makes it easy to implement, for example, multi-stream multiplexing, transmittin rate control and asynchronous I/O - Composable: - By combining multiple encoders (or decoders), it is easy to build a more complex encoder (or decoder) - See the examples of `EncodeExt` and `DecodeExt` traits - Reduced number of memory copies: - In design, only two memory copies are required - Considering in the decode process, one is the copy from the actual stream (e.g., TCP socket) to the decoding buffer, the other one is the copy to construct the item from the buffer. - Supports some [serde] implemention crates: - Currently [serde_json] and [bincode] are supported (as optional featuers) - See `json_codec` and `bincode_codec` modules - Easily adapt to synchronous I/O, asynchronous I/O, UDP, etc - Trackable errors: - By using [trackable] crate, the location where an error occurred can be easily specified - See `EncodeExt::map_err` and `DecodeExt::map_err` methods [bincode]: https://crates.io/crates/bincode [serde]: https://crates.io/crates/serde [serde_json]: https://crates.io/crates/serde_json [trackable]: https://crates.io/crates/trackable bytecodec-0.4.15/src/bincode_codec.rs000064400000000000000000000101770000000000000155340ustar 00000000000000//! `#[cfg(feature = "bincode_codec")]` Bincode encoder and decoder that use [bincode] internally. //! //! [bincode]: https://crates.io/crates/bincode use crate::monolithic::{MonolithicDecode, MonolithicDecoder, MonolithicEncode, MonolithicEncoder}; use crate::{ByteCount, Decode, Encode, Eos, ErrorKind, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Write}; use std::marker::PhantomData; use trackable::error::ErrorKindExt; /// Bincode decoder. /// /// Note that this decodes items monolithically /// so very large items may impair real-time property of the system. #[derive(Debug)] pub struct BincodeDecoder(MonolithicDecoder>) where T: for<'de> Deserialize<'de>; impl BincodeDecoder where T: for<'de> Deserialize<'de>, { /// Makes a new `BincodeDecoder` instance. pub fn new() -> Self { BincodeDecoder(MonolithicDecoder::new(MonolithicBincodeDecoder::new())) } } impl Decode for BincodeDecoder where T: for<'de> Deserialize<'de>, { type Item = T; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl Default for BincodeDecoder where T: for<'de> Deserialize<'de>, { fn default() -> Self { Self::new() } } #[derive(Debug)] struct MonolithicBincodeDecoder(PhantomData) where T: for<'de> Deserialize<'de>; impl MonolithicBincodeDecoder where T: for<'de> Deserialize<'de>, { fn new() -> Self { MonolithicBincodeDecoder(PhantomData) } } impl MonolithicDecode for MonolithicBincodeDecoder where T: for<'de> Deserialize<'de>, { type Item = T; fn monolithic_decode(&self, reader: R) -> Result { track!( bincode::deserialize_from(reader).map_err(|e| ErrorKind::InvalidInput.cause(e).into()) ) } } /// Bincode encoder. /// /// Note that this encodes items monolithically /// so very large items may impair real-time property of the system. #[derive(Debug)] pub struct BincodeEncoder(MonolithicEncoder>); impl BincodeEncoder where T: Serialize, { /// Makes a new `BincodeEncoder` instance. pub fn new() -> Self { BincodeEncoder(MonolithicEncoder::new(MonolithicBincodeEncoder::new())) } } impl Encode for BincodeEncoder where T: Serialize, { type Item = T; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding(item)) } fn is_idle(&self) -> bool { self.0.is_idle() } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } } impl Default for BincodeEncoder where T: Serialize, { fn default() -> Self { Self::new() } } #[derive(Debug)] struct MonolithicBincodeEncoder(PhantomData); impl MonolithicBincodeEncoder { fn new() -> Self { MonolithicBincodeEncoder(PhantomData) } } impl MonolithicEncode for MonolithicBincodeEncoder where T: Serialize, { type Item = T; fn monolithic_encode(&self, item: &Self::Item, writer: W) -> Result<()> { track!(bincode::serialize_into(writer, item) .map_err(|e| ErrorKind::InvalidInput.cause(e).into())) } } #[cfg(test)] mod test { use super::*; use crate::io::{IoDecodeExt, IoEncodeExt}; use crate::EncodeExt; #[test] fn bincode_works() { let item = (1, Some(2), 3); let mut buf = Vec::new(); let mut encoder = BincodeEncoder::with_item(item).unwrap(); encoder.encode_all(&mut buf).unwrap(); let mut decoder = BincodeDecoder::<(u8, Option, u32)>::new(); let decoded = decoder.decode_exact(&buf[..]).unwrap(); assert_eq!(decoded, item); } } bytecodec-0.4.15/src/byte_count.rs000064400000000000000000000105760000000000000151520ustar 00000000000000use std::cmp; /// Number of bytes of interest. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum ByteCount { Finite(u64), Infinite, Unknown, } impl ByteCount { /// Returns `true` if this is `ByteCount::Finite(_)`, otherwise `false`. pub fn is_finite(&self) -> bool { matches!(self, ByteCount::Finite(_)) } /// Returns `true` if this is `ByteCount::Infinite`, otherwise `false`. pub fn is_infinite(&self) -> bool { *self == ByteCount::Infinite } /// Returns `true` if this is `ByteCount::Unknown`, otherwise `false`. pub fn is_unknow(&self) -> bool { *self == ByteCount::Unknown } /// Tries to convert this `ByteCount` to an `u64` value. /// /// If it is not a `ByteCount::Finite(_)`,`None` will be returned. pub fn to_u64(self) -> Option { if let ByteCount::Finite(n) = self { Some(n) } else { None } } /// Adds two `ByteCount` instances for decoding (i.e., `Decode::requiring_bytes` method). /// /// # Rule /// /// ```text /// Finite(a) + Finite(b) = Finite(a + b) /// Infinite + _ = Infinite /// _ + Infinite = Infinite /// Unknown + Unknown = Unknown /// Finite(0) + Unknown = Unknown /// Unknown + Finite(0) = Unknown /// Finite(a) + Unknown = Finite(a) /// Unknown + Finite(b) = Finite(b) /// ``` pub fn add_for_decoding(self, other: Self) -> Self { match (self, other) { (ByteCount::Finite(a), ByteCount::Finite(b)) => ByteCount::Finite(a + b), (ByteCount::Infinite, _) => ByteCount::Infinite, (_, ByteCount::Infinite) => ByteCount::Infinite, (ByteCount::Unknown, ByteCount::Unknown) => ByteCount::Unknown, (ByteCount::Finite(0), ByteCount::Unknown) => ByteCount::Unknown, (ByteCount::Unknown, ByteCount::Finite(0)) => ByteCount::Unknown, (ByteCount::Finite(a), ByteCount::Unknown) => ByteCount::Finite(a), (ByteCount::Unknown, ByteCount::Finite(b)) => ByteCount::Finite(b), } } /// Adds two `ByteCount` instances for encoding (i.e., `Encode::requiring_bytes` method). /// /// # Rule /// /// ```text /// Finite(a) + Finite(b) = Finite(a + b) /// Infinite + _ = Infinite /// _ + Infinite = Infinite /// Unknown + _ = Unknown /// _ + Unknown = Unknown /// ``` pub fn add_for_encoding(self, other: Self) -> Self { match (self, other) { (ByteCount::Finite(a), ByteCount::Finite(b)) => ByteCount::Finite(a + b), (ByteCount::Infinite, _) => ByteCount::Infinite, (_, ByteCount::Infinite) => ByteCount::Infinite, (_, ByteCount::Unknown) => ByteCount::Unknown, (ByteCount::Unknown, _) => ByteCount::Unknown, } } } impl PartialOrd for ByteCount { fn partial_cmp(&self, other: &Self) -> Option { match (*self, *other) { (ByteCount::Finite(l), ByteCount::Finite(r)) => Some(l.cmp(&r)), (ByteCount::Unknown, _) | (_, ByteCount::Unknown) => None, (ByteCount::Infinite, ByteCount::Infinite) => Some(cmp::Ordering::Equal), (ByteCount::Infinite, _) => Some(cmp::Ordering::Greater), (_, ByteCount::Infinite) => Some(cmp::Ordering::Less), } } } impl Default for ByteCount { /// Returns `ByteCount::Unknown` as the default value. fn default() -> Self { ByteCount::Unknown } } #[cfg(test)] mod test { use super::*; #[test] fn it_works() { assert_eq!(ByteCount::default(), ByteCount::Unknown); assert!(ByteCount::Finite(0).is_finite()); assert!(ByteCount::Infinite.is_infinite()); assert!(ByteCount::Unknown.is_unknow()); assert_eq!(ByteCount::Finite(3).to_u64(), Some(3)); assert_eq!(ByteCount::Infinite.to_u64(), None); assert_eq!(ByteCount::Unknown.to_u64(), None); assert!(ByteCount::Finite(1) < ByteCount::Finite(2)); assert!(ByteCount::Finite(9) < ByteCount::Infinite); assert!(!(ByteCount::Infinite < ByteCount::Unknown)); assert!(!(ByteCount::Unknown < ByteCount::Infinite)); assert!(!(ByteCount::Unknown < ByteCount::Unknown)); assert!(!(ByteCount::Unknown < ByteCount::Unknown)); } } bytecodec-0.4.15/src/bytes.rs000064400000000000000000000332340000000000000141210ustar 00000000000000//! Encoders and decoders for reading/writing byte sequences. use crate::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode}; use std::cmp; use std::mem; use trackable::error::ErrorKindExt; /// `BytesEncoder` writes the given bytes into an output byte sequence. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt}; /// use bytecodec::bytes::BytesEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = BytesEncoder::with_item(b"foo").unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert!(encoder.is_idle()); /// assert_eq!(output, b"foo"); /// ``` #[derive(Debug)] pub struct BytesEncoder> { bytes: Option, offset: usize, } impl BytesEncoder { /// Makes a new `BytesEncoder` instance. pub fn new() -> Self { Self::default() } } impl Default for BytesEncoder { fn default() -> Self { BytesEncoder { bytes: None, offset: 0, } } } impl> Encode for BytesEncoder { type Item = B; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let mut size = 0; let drop_item = if let Some(ref b) = self.bytes { size = cmp::min(buf.len(), b.as_ref().len() - self.offset); (&mut buf[..size]).copy_from_slice(&b.as_ref()[self.offset..][..size]); self.offset += size; if self.offset == b.as_ref().len() { true } else { track_assert!(!eos.is_reached(), ErrorKind::UnexpectedEos; buf.len(), size, self.offset, b.as_ref().len()); false } } else { false }; if drop_item { self.bytes = None; } Ok(size) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track_assert!(self.is_idle(), ErrorKind::EncoderFull); self.bytes = Some(item); self.offset = 0; Ok(()) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.exact_requiring_bytes()) } fn is_idle(&self) -> bool { self.bytes.is_none() } } impl> SizedEncode for BytesEncoder { fn exact_requiring_bytes(&self) -> u64 { self.bytes .as_ref() .map_or(0, |b| b.as_ref().len() - self.offset) as u64 } } /// A variant of `BytesDecoder` for copyable bytes types. /// /// Unlike `BytesDecoder`, this has no restriction on decoding count. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, Eos}; /// use bytecodec::bytes::CopyableBytesDecoder; /// /// let mut decoder = CopyableBytesDecoder::new([0; 3]); /// let mut input = b"foobar"; /// /// // Decodes first item /// assert_eq!(decoder.requiring_bytes().to_u64(), Some(3)); /// decoder.decode(&input[0..3], Eos::new(false)).unwrap(); /// assert_eq!(decoder.is_idle(), true); /// assert_eq!(decoder.finish_decoding().unwrap(), *b"foo"); /// /// // Decodes second item /// assert_eq!(decoder.requiring_bytes().to_u64(), Some(3)); /// decoder.decode(&input[3..5], Eos::new(false)).unwrap(); /// assert_eq!(decoder.is_idle(), false); /// assert_eq!(decoder.requiring_bytes().to_u64(), Some(1)); /// /// decoder.decode(&input[5..], Eos::new(true)).unwrap(); /// assert_eq!(decoder.is_idle(), true); /// assert_eq!(decoder.finish_decoding().unwrap(), *b"bar"); /// ``` #[derive(Debug, Default)] pub struct CopyableBytesDecoder { bytes: B, offset: usize, } impl CopyableBytesDecoder { /// Makes a new `CopyableBytesDecoder` instance. pub fn new(bytes: B) -> Self { CopyableBytesDecoder { bytes, offset: 0 } } /// Returns a reference to the inner bytes. pub fn inner_ref(&self) -> &B { &self.bytes } /// Returns a mutable reference to the inner bytes. pub fn inner_mut(&mut self) -> &mut B { &mut self.bytes } /// Takes ownership of this instance and returns the inner bytes. pub fn into_inner(self) -> B { self.bytes } } impl + AsMut<[u8]> + Copy> Decode for CopyableBytesDecoder { type Item = B; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let size = cmp::min(buf.len(), self.bytes.as_ref().len() - self.offset); (&mut self.bytes.as_mut()[self.offset..][..size]).copy_from_slice(&buf[..size]); self.offset += size; if self.offset != self.bytes.as_mut().len() { track_assert!(!eos.is_reached(), ErrorKind::UnexpectedEos; self.offset, self.bytes.as_ref().len()); } Ok(size) } fn finish_decoding(&mut self) -> Result { track_assert_eq!( self.offset, self.bytes.as_ref().len(), ErrorKind::IncompleteDecoding ); self.offset = 0; Ok(self.bytes) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite((self.bytes.as_ref().len() - self.offset) as u64) } fn is_idle(&self) -> bool { self.offset == self.bytes.as_ref().len() } } /// `BytesDecoder` copies bytes from an input sequence to a slice. /// /// This is a oneshot decoder (i.e., it decodes only one item). /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::bytes::BytesDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = BytesDecoder::new([0; 3]); /// assert_eq!(decoder.requiring_bytes().to_u64(), Some(3)); /// /// let item = decoder.decode_exact(b"foobar".as_ref()).unwrap(); /// assert_eq!(item.as_ref(), b"foo"); /// assert_eq!(decoder.requiring_bytes().to_u64(), Some(0)); // no more items are decoded /// ``` #[derive(Debug)] pub struct BytesDecoder> { bytes: Option, offset: usize, } impl + AsMut<[u8]>> BytesDecoder { /// Makes a new `BytesDecoder` instance for filling the given byte slice. pub fn new(bytes: B) -> Self { BytesDecoder { bytes: Some(bytes), offset: 0, } } /// Sets the byte slice to be filled. pub fn set_bytes(&mut self, bytes: B) { self.bytes = Some(bytes); self.offset = 0; } fn exact_requiring_bytes(&self) -> u64 { self.bytes .as_ref() .map_or(0, |b| b.as_ref().len() - self.offset) as u64 } fn buf_len(&self) -> usize { self.bytes.as_ref().map_or(0, |b| b.as_ref().len()) } } impl Default for BytesDecoder { fn default() -> Self { BytesDecoder { bytes: None, offset: 0, } } } impl + AsMut<[u8]>> Decode for BytesDecoder { type Item = B; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let size = { let bytes = track_assert_some!(self.bytes.as_mut(), ErrorKind::DecoderTerminated); let size = cmp::min(buf.len(), bytes.as_ref().len() - self.offset); (&mut bytes.as_mut()[self.offset..][..size]).copy_from_slice(&buf[..size]); self.offset += size; size }; if self.exact_requiring_bytes() != 0 { track_assert!(!eos.is_reached(), ErrorKind::UnexpectedEos; self.offset, self.buf_len()); } Ok(size) } fn finish_decoding(&mut self) -> Result { track_assert_eq!( self.exact_requiring_bytes(), 0, ErrorKind::IncompleteDecoding ); let bytes = track_assert_some!(self.bytes.take(), ErrorKind::DecoderTerminated); Ok(bytes) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.exact_requiring_bytes()) } fn is_idle(&self) -> bool { self.exact_requiring_bytes() == 0 } } /// `RemainingBytesDecoder` reads all the bytes from a input sequence until it reaches EOS. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, Eos}; /// use bytecodec::bytes::RemainingBytesDecoder; /// /// let mut decoder = RemainingBytesDecoder::new(); /// assert_eq!(decoder.requiring_bytes().to_u64(), None); /// /// let size = decoder.decode(b"foo", Eos::new(false)).unwrap(); /// assert_eq!(size, 3); /// assert_eq!(decoder.is_idle(), false); /// /// let size = decoder.decode(b"bar", Eos::new(true)).unwrap(); /// assert_eq!(size, 3); /// assert_eq!(decoder.is_idle(), true); /// assert_eq!(decoder.finish_decoding().unwrap(), b"foobar"); /// ``` #[derive(Debug, Default)] pub struct RemainingBytesDecoder { buf: Vec, eos: bool, } impl RemainingBytesDecoder { /// Makes a new `RemainingBytesDecoder` instance. pub fn new() -> Self { Self::default() } } impl Decode for RemainingBytesDecoder { type Item = Vec; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { if self.eos { return Ok(0); } if let Some(remaining) = eos.remaining_bytes().to_u64() { self.buf.reserve_exact(buf.len() + remaining as usize); } self.buf.extend_from_slice(buf); self.eos = eos.is_reached(); Ok(buf.len()) } fn finish_decoding(&mut self) -> Result { track_assert!(self.eos, ErrorKind::IncompleteDecoding); self.eos = false; let bytes = mem::take(&mut self.buf); Ok(bytes) } fn requiring_bytes(&self) -> ByteCount { if self.eos { ByteCount::Finite(0) } else { ByteCount::Infinite } } fn is_idle(&self) -> bool { self.eos } } #[derive(Debug)] struct Utf8Bytes(T); impl> AsRef<[u8]> for Utf8Bytes { fn as_ref(&self) -> &[u8] { self.0.as_ref().as_bytes() } } /// `Utf8Encoder` writes the given Rust string into an output byte sequence. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt}; /// use bytecodec::bytes::Utf8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = Utf8Encoder::with_item("foo").unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert!(encoder.is_idle()); /// assert_eq!(output, b"foo"); /// ``` #[derive(Debug)] pub struct Utf8Encoder(BytesEncoder>); impl Utf8Encoder { /// Makes a new `Utf8Encoder` instance. pub fn new() -> Self { Utf8Encoder(BytesEncoder::new()) } } impl Default for Utf8Encoder { fn default() -> Self { Self::new() } } impl> Encode for Utf8Encoder { type Item = S; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding(Utf8Bytes(item))) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl> SizedEncode for Utf8Encoder { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } /// `Utf8Decoder` decodes Rust strings from a input byte sequence. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, Eos}; /// use bytecodec::bytes::Utf8Decoder; /// /// let mut decoder = Utf8Decoder::new(); /// /// decoder.decode(b"foo", Eos::new(true)).unwrap(); /// assert_eq!(decoder.finish_decoding().unwrap(), "foo"); /// ``` #[derive(Debug, Default)] pub struct Utf8Decoder(D); impl Utf8Decoder { /// Makes a new `Utf8Decoder` that uses `RemainingBytesDecoder` as the internal bytes decoder. pub fn new() -> Self { Utf8Decoder(RemainingBytesDecoder::new()) } } impl Utf8Decoder where D: Decode>, { /// Makes a new `Utf8Decoder` with the given bytes decoder. pub fn with_bytes_decoder(bytes_decoder: D) -> Self { Utf8Decoder(bytes_decoder) } /// Returns a reference to the inner bytes decoder. pub fn inner_ref(&self) -> &D { &self.0 } /// Returns a mutable reference to the inner bytes decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.0 } /// Takes ownership of this instance and returns the inner bytes decoder. pub fn into_inner(self) -> D { self.0 } } impl Decode for Utf8Decoder where D: Decode>, { type Item = String; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { let b = track!(self.0.finish_decoding())?; let s = track!(String::from_utf8(b).map_err(|e| ErrorKind::InvalidInput.cause(e)))?; Ok(s) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } #[cfg(test)] mod test { use super::*; use crate::io::{IoDecodeExt, IoEncodeExt}; use crate::{Encode, EncodeExt, ErrorKind}; #[test] fn bytes_decoder_works() { let mut decoder = BytesDecoder::new([0; 3]); assert_eq!(decoder.requiring_bytes().to_u64(), Some(3)); let mut input = b"foobar".as_ref(); let item = decoder.decode_exact(&mut input).unwrap(); assert_eq!(item.as_ref(), b"foo"); assert_eq!(decoder.requiring_bytes().to_u64(), Some(0)); assert_eq!( decoder.decode_exact(&mut input).err().map(|e| *e.kind()), Some(ErrorKind::DecoderTerminated) ); } #[test] fn utf8_encoder_works() { let mut buf = Vec::new(); let mut encoder = Utf8Encoder::with_item("foo").unwrap(); encoder.encode_all(&mut buf).unwrap(); assert!(encoder.is_idle()); assert_eq!(buf, b"foo"); } } bytecodec-0.4.15/src/combinator.rs000064400000000000000000001307370000000000000151360ustar 00000000000000//! Encoders and decoders for combination. //! //! These are mainly created via the methods provided by `EncodeExt` or `DecodeExt` traits. use crate::bytes::BytesEncoder; use crate::marker::Never; use crate::{ByteCount, Decode, Encode, EncodeExt, Eos, Error, ErrorKind, Result, SizedEncode}; use std::cmp; use std::fmt; use std::iter; use std::marker::PhantomData; use std::mem; /// Combinator for converting decoded items to other values. /// /// This is created by calling `DecodeExt::map` method. #[derive(Debug)] pub struct Map { inner: D, map: F, _item: PhantomData, } impl Map { /// Returns a reference to the inner decoder. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of this instance and returns the inner decoder. pub fn into_inner(self) -> D { self.inner } pub(crate) fn new(inner: D, map: F) -> Self where F: Fn(D::Item) -> T, { Map { inner, map, _item: PhantomData, } } } impl Decode for Map where D: Decode, F: Fn(D::Item) -> T, { type Item = T; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { self.inner.decode(buf, eos) } fn finish_decoding(&mut self) -> Result { let item = self.inner.finish_decoding()?; Ok((self.map)(item)) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } /// Combinator for modifying encoding/decoding errors. /// /// This is created by calling `{DecodeExt, EncodeExt}::map_err` method. #[derive(Debug)] pub struct MapErr { inner: C, map_err: F, _error: PhantomData, } impl MapErr { /// Returns a reference to the inner encoder or decoder. pub fn inner_ref(&self) -> &C { &self.inner } /// Returns a mutable reference to the inner encoder or decoder. pub fn inner_mut(&mut self) -> &mut C { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder or decoder. pub fn into_inner(self) -> C { self.inner } pub(crate) fn new(inner: C, map_err: F) -> Self where F: Fn(Error) -> E, Error: From, { MapErr { inner, map_err, _error: PhantomData, } } } impl Decode for MapErr where D: Decode, F: Fn(Error) -> E, Error: From, { type Item = D::Item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { self.inner .decode(buf, eos) .map_err(|e| (self.map_err)(e).into()) } fn finish_decoding(&mut self) -> Result { self.inner .finish_decoding() .map_err(|e| (self.map_err)(e).into()) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } impl Encode for MapErr where C: Encode, F: Fn(Error) -> E, Error: From, { type Item = C::Item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { self.inner .encode(buf, eos) .map_err(|e| (self.map_err)(e).into()) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { self.inner .start_encoding(item) .map_err(|e| (self.map_err)(e).into()) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } impl SizedEncode for MapErr where C: SizedEncode, F: Fn(Error) -> E, Error: From, { fn exact_requiring_bytes(&self) -> u64 { self.inner.exact_requiring_bytes() } } /// Combinator for conditional decoding. /// /// If the first item is successfully decoded, /// it will start decoding the second item by using the decoder returned by `f` function. /// /// This is created by calling `DecodeExt::and_then` method. #[derive(Debug)] pub struct AndThen { inner0: D0, inner1: Option, and_then: F, } impl AndThen { pub(crate) fn new(inner0: D0, and_then: F) -> Self where F: Fn(D0::Item) -> D1, { AndThen { inner0, inner1: None, and_then, } } } impl Decode for AndThen where D0: Decode, D1: Decode, F: Fn(D0::Item) -> D1, { type Item = D1::Item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let mut offset = 0; if self.inner1.is_none() { bytecodec_try_decode!(self.inner0, offset, buf, eos); let item = track!(self.inner0.finish_decoding())?; self.inner1 = Some((self.and_then)(item)); } let inner1 = self.inner1.as_mut().expect("Never fails"); bytecodec_try_decode!(inner1, offset, buf, eos); Ok(offset) } fn finish_decoding(&mut self) -> Result { let mut d = track_assert_some!(self.inner1.take(), ErrorKind::IncompleteDecoding); track!(d.finish_decoding()) } fn requiring_bytes(&self) -> ByteCount { if let Some(ref d) = self.inner1 { d.requiring_bytes() } else { self.inner0.requiring_bytes() } } fn is_idle(&self) -> bool { self.inner1.as_ref().map_or(false, Decode::is_idle) } } /// Combinator for converting items into ones that /// suited to the inner encoder by calling the given function. /// /// This is created by calling `EncodeExt::map_from` method. #[derive(Debug)] pub struct MapFrom { inner: E, _item: PhantomData, from: F, } impl MapFrom { /// Returns a reference to the inner encoder. pub fn inner_ref(&self) -> &E { &self.inner } /// Returns a mutable reference to the inner encoder. pub fn inner_mut(&mut self) -> &mut E { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder. pub fn into_inner(self) -> E { self.inner } pub(crate) fn new(inner: E, from: F) -> Self { MapFrom { inner, _item: PhantomData, from, } } } impl Encode for MapFrom where E: Encode, F: Fn(T) -> E::Item, { type Item = T; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { self.inner.encode(buf, eos) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { self.inner.start_encoding((self.from)(item)) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } impl SizedEncode for MapFrom where E: SizedEncode, F: Fn(T) -> E::Item, { fn exact_requiring_bytes(&self) -> u64 { self.inner.exact_requiring_bytes() } } /// Combinator that tries to convert items into ones that /// suited to the inner encoder by calling the given function. /// /// This is created by calling `EncodeExt::try_map_from` method. #[derive(Debug)] pub struct TryMapFrom { inner: C, try_from: F, _phantom: PhantomData<(T, E)>, } impl TryMapFrom { /// Returns a reference to the inner encoder. pub fn inner_ref(&self) -> &C { &self.inner } /// Returns a mutable reference to the inner encoder. pub fn inner_mut(&mut self) -> &mut C { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder. pub fn into_inner(self) -> C { self.inner } pub(crate) fn new(inner: C, try_from: F) -> Self { TryMapFrom { inner, try_from, _phantom: PhantomData, } } } impl Encode for TryMapFrom where C: Encode, F: Fn(T) -> std::result::Result, Error: From, { type Item = T; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { self.inner.encode(buf, eos) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { let item = track!((self.try_from)(item).map_err(Error::from))?; self.inner.start_encoding(item) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } impl SizedEncode for TryMapFrom where C: SizedEncode, F: Fn(T) -> std::result::Result, Error: From, { fn exact_requiring_bytes(&self) -> u64 { self.inner.exact_requiring_bytes() } } /// Combinator for repeating encoding of `E::Item`. /// /// This is created by calling `EncodeExt::repeat` method. #[derive(Debug)] pub struct Repeat { inner: E, items: Option, } impl Repeat { /// Returns a reference to the inner encoder. pub fn inner_ref(&self) -> &E { &self.inner } /// Returns a mutable reference to the inner encoder. pub fn inner_mut(&mut self) -> &mut E { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder. pub fn into_inner(self) -> E { self.inner } pub(crate) fn new(inner: E) -> Self { Repeat { inner, items: None } } } impl Encode for Repeat where E: Encode, I: Iterator, { type Item = I; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let mut offset = 0; loop { while self.inner.is_idle() { if let Some(item) = self.items.as_mut().and_then(Iterator::next) { track!(self.inner.start_encoding(item))?; } else { self.items = None; return Ok(offset); } } let size = track!(self.inner.encode(&mut buf[offset..], eos))?; offset += size; if size == 0 { return Ok(offset); } } } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track_assert!(self.is_idle(), ErrorKind::EncoderFull); self.items = Some(item); Ok(()) } fn requiring_bytes(&self) -> ByteCount { if self.is_idle() { ByteCount::Finite(0) } else { ByteCount::Unknown } } fn is_idle(&self) -> bool { self.items.is_none() } } impl Default for Repeat { fn default() -> Self { Self::new(E::default()) } } /// Combinator for representing optional decoders. /// /// This is created by calling `DecodeExt::omit` method. #[derive(Debug, Default)] pub struct Omittable { inner: D, do_omit: bool, } impl Omittable { /// Returns a reference to the inner decoder. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of this instance and returns the inner decoder. pub fn into_inner(self) -> D { self.inner } /// If `true` is specified, the decoder will consume no bytes and /// return `Ok((0, None))` when `decode` method is called. pub fn do_omit(&mut self, b: bool) { self.do_omit = b; } /// Returns `true` if the decoder will omit to decode items, otherwise `false`. pub fn will_omit(&self) -> bool { self.do_omit } pub(crate) fn new(inner: D, do_omit: bool) -> Self { Omittable { inner, do_omit } } } impl Decode for Omittable { type Item = Option; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { if self.do_omit { Ok(0) } else { track!(self.inner.decode(buf, eos)) } } fn finish_decoding(&mut self) -> Result { if self.do_omit { Ok(None) } else { track!(self.inner.finish_decoding()).map(Some) } } fn requiring_bytes(&self) -> ByteCount { if self.do_omit { ByteCount::Finite(0) } else { self.inner.requiring_bytes() } } fn is_idle(&self) -> bool { self.do_omit || self.inner.is_idle() } } /// Combinator for representing an optional encoder. #[derive(Debug, Default)] pub struct Optional(E); impl Optional { /// Returns a reference to the inner encoder. pub fn inner_ref(&self) -> &E { &self.0 } /// Returns a mutable reference to the inner encoder. pub fn inner_mut(&mut self) -> &mut E { &mut self.0 } /// Takes ownership of this instance and returns the inner encoder. pub fn into_inner(self) -> E { self.0 } pub(crate) fn new(inner: E) -> Self { Optional(inner) } } impl Encode for Optional { type Item = Option; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { if let Some(item) = item { track!(self.0.start_encoding(item))?; } Ok(()) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl SizedEncode for Optional { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } /// Combinator for collecting decoded items. /// /// `Collect` decodes all items until it reaches EOS /// and returns the collected items as the single decoded item. /// /// This is created by calling `DecodeExt::collect` method. #[derive(Debug, Default)] pub struct Collect { inner: D, items: T, eos: bool, } impl Collect { /// Returns a reference to the inner decoder. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of this instance and returns the inner decoder. pub fn into_inner(self) -> D { self.inner } pub(crate) fn new(inner: D) -> Self { Collect { inner, items: T::default(), eos: false, } } } impl Decode for Collect where D: Decode, T: Extend, { type Item = T; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { if self.eos { return Ok(0); } let mut offset = 0; while offset < buf.len() { bytecodec_try_decode!(self.inner, offset, buf, eos); let item = track!(self.inner.finish_decoding())?; self.items.extend(iter::once(item)); } if eos.is_reached() { self.eos = true; } Ok(offset) } fn finish_decoding(&mut self) -> Result { track_assert!(self.eos, ErrorKind::IncompleteDecoding); self.eos = false; let items = mem::take(&mut self.items); Ok(items) } fn requiring_bytes(&self) -> ByteCount { if self.eos { ByteCount::Finite(0) } else { self.inner.requiring_bytes() } } fn is_idle(&self) -> bool { self.eos } } /// Combinator for consuming the specified number of bytes exactly. /// /// This is created by calling `{DecodeExt, EncodeExt}::length` method. #[derive(Debug, Default)] pub struct Length { inner: C, expected_bytes: u64, remaining_bytes: u64, } impl Length { pub(crate) fn new(inner: C, expected_bytes: u64) -> Self { Length { inner, expected_bytes, remaining_bytes: expected_bytes, } } /// Returns the number of bytes expected to be consumed for decoding an item. pub fn expected_bytes(&self) -> u64 { self.expected_bytes } /// Sets the number of bytes expected to be consumed for decoding an item. /// /// # Errors /// /// If it is in the middle of decoding an item, it willl return an `ErrorKind::IncompleteDecoding` error. pub fn set_expected_bytes(&mut self, bytes: u64) -> Result<()> { track_assert_eq!( self.remaining_bytes, self.expected_bytes, ErrorKind::IncompleteDecoding, "An item is being decoded" ); self.expected_bytes = bytes; self.remaining_bytes = bytes; Ok(()) } /// Returns the number of remaining bytes required to decode the next item. pub fn remaining_bytes(&self) -> u64 { self.remaining_bytes } /// Returns a reference to the inner encoder or decoder. pub fn inner_ref(&self) -> &C { &self.inner } /// Returns a mutable reference to the inner encoder or decoder. pub fn inner_mut(&mut self) -> &mut C { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder or decoder. pub fn into_inner(self) -> C { self.inner } } impl Decode for Length { type Item = D::Item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let limit = cmp::min(buf.len() as u64, self.remaining_bytes) as usize; let required = self.remaining_bytes - limit as u64; let expected_eos = Eos::with_remaining_bytes(ByteCount::Finite(required)); if let Some(mut remaining) = eos.remaining_bytes().to_u64() { remaining += buf.len() as u64; track_assert!(remaining >= required, ErrorKind::UnexpectedEos; remaining, required); } let size = track!(self.inner.decode(&buf[..limit], expected_eos))?; self.remaining_bytes -= size as u64; Ok(size) } fn finish_decoding(&mut self) -> Result { track_assert_eq!(self.remaining_bytes, 0, ErrorKind::IncompleteDecoding); self.remaining_bytes = self.expected_bytes; track!(self.inner.finish_decoding()) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.remaining_bytes) } fn is_idle(&self) -> bool { self.inner.is_idle() } } impl Encode for Length { type Item = E::Item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { if (buf.len() as u64) < self.remaining_bytes { track_assert!(!eos.is_reached(), ErrorKind::UnexpectedEos); } let (limit, eos) = if (buf.len() as u64) < self.remaining_bytes { (buf.len(), eos) } else { (self.remaining_bytes as usize, Eos::new(true)) }; let size = track!(self.inner.encode(&mut buf[..limit], eos))?; self.remaining_bytes -= size as u64; if self.inner.is_idle() { track_assert_eq!( self.remaining_bytes, 0, ErrorKind::InvalidInput, "Too small item" ); } Ok(size) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track_assert_eq!( self.remaining_bytes, self.expected_bytes, ErrorKind::EncoderFull ); self.remaining_bytes = self.expected_bytes; track!(self.inner.start_encoding(item)) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(self.remaining_bytes) } fn is_idle(&self) -> bool { self.remaining_bytes == 0 } } impl SizedEncode for Length { fn exact_requiring_bytes(&self) -> u64 { self.remaining_bytes } } /// Combinator for decoding the specified number of items and collecting the result. /// /// This is created by calling `DecodeExt::collectn` method. #[derive(Debug, Default)] pub struct CollectN { inner: D, remaining_items: usize, items: T, } impl CollectN { /// Returns the number of remaining items expected to be decoded. pub fn remaining_items(&self) -> usize { self.remaining_items } /// Sets the number of remaining items expected to be decoded. pub fn set_remaining_items(&mut self, n: usize) { self.remaining_items = n; } /// Returns a reference to the inner decoder. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of this instance and returns the inner decoder. pub fn into_inner(self) -> D { self.inner } pub(crate) fn new(inner: D, count: usize) -> Self { CollectN { inner, remaining_items: count, items: T::default(), } } } impl Decode for CollectN where D: Decode, T: Default + Extend, { type Item = T; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let mut offset = 0; while self.remaining_items != 0 && offset < buf.len() { bytecodec_try_decode!(self.inner, offset, buf, eos); let item = track!(self.inner.finish_decoding())?; self.items.extend(iter::once(item)); self.remaining_items -= 1; } if self.remaining_items != 0 { track_assert!(!eos.is_reached(), ErrorKind::UnexpectedEos); } Ok(offset) } fn finish_decoding(&mut self) -> Result { track_assert_eq!(self.remaining_items, 0, ErrorKind::IncompleteDecoding); let items = mem::take(&mut self.items); Ok(items) } fn requiring_bytes(&self) -> ByteCount { if self.remaining_items == 0 { ByteCount::Finite(0) } else { self.inner.requiring_bytes() } } fn is_idle(&self) -> bool { self.remaining_items == 0 } } /// Combinator which tries to convert decoded values by calling the specified function. /// /// This is created by calling `DecodeExt::try_map` method. #[derive(Debug)] pub struct TryMap { inner: D, try_map: F, _phantom: PhantomData<(T, E)>, } impl TryMap { /// Returns a reference to the inner decoder. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of this instance and returns the inner decoder. pub fn into_inner(self) -> D { self.inner } pub(crate) fn new(inner: D, try_map: F) -> Self { TryMap { inner, try_map, _phantom: PhantomData, } } } impl Decode for TryMap where D: Decode, F: Fn(D::Item) -> std::result::Result, Error: From, { type Item = T; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.inner.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { let item = track!(self.inner.finish_decoding())?; track!((self.try_map)(item).map_err(Error::from)) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } /// Combinator that will fail if the number of consumed bytes exceeds the specified size. /// /// This is created by calling `{DecodeExt, EncodeExt}::max_bytes` method. /// /// Note that `MaxBytes` assumes the inner decoder will consume all the bytes in the target stream. #[derive(Debug, Default)] pub struct MaxBytes { inner: C, consumed_bytes: u64, max_bytes: u64, } impl MaxBytes { pub(crate) fn new(inner: C, max_bytes: u64) -> Self { MaxBytes { inner, consumed_bytes: 0, max_bytes, } } /// Returns the number of bytes consumed for encoding/decoding the current item. pub fn consumed_bytes(&self) -> u64 { self.consumed_bytes } /// Returns the maximum number of bytes that can be consumed for encoding/decoding an item. pub fn max_bytes(&self) -> u64 { self.max_bytes } /// Sets the maximum number of bytes that can be consumed for encoding/decoding an item. /// /// # Error /// /// If `n` is smaller than `self.consumed_bytes()`, an `ErrorKind::InvalidInput` error will be returned. pub fn set_max_bytes(&mut self, n: u64) -> Result<()> { track_assert!( self.consumed_bytes <= n, ErrorKind::InvalidInput; self.consumed_bytes, n ); self.max_bytes = n; Ok(()) } /// Returns a reference to the inner encoder or decoder. pub fn inner_ref(&self) -> &C { &self.inner } /// Returns a mutable reference to the inner encoder or decoder. pub fn inner_mut(&mut self) -> &mut C { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder or decoder. pub fn into_inner(self) -> C { self.inner } } impl Decode for MaxBytes { type Item = D::Item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { match eos.remaining_bytes() { ByteCount::Infinite => { track_panic!(ErrorKind::InvalidInput, "Max bytes limit exceeded"; self.consumed_bytes, self.max_bytes) } ByteCount::Unknown => { let consumable_bytes = self.max_bytes - self.consumed_bytes; track_assert!((buf.len() as u64) <= consumable_bytes, ErrorKind::InvalidInput, "Max bytes limit exceeded"; buf.len(), self.consumed_bytes, self.max_bytes); } ByteCount::Finite(remaining_bytes) => { let consumable_bytes = self.max_bytes - self.consumed_bytes; track_assert!((buf.len() as u64) + remaining_bytes <= consumable_bytes, ErrorKind::InvalidInput, "Max bytes limit exceeded"; buf.len(), remaining_bytes, self.consumed_bytes, self.max_bytes) } } let size = track!(self.inner.decode(buf, eos))?; self.consumed_bytes += size as u64; Ok(size) } fn finish_decoding(&mut self) -> Result { self.consumed_bytes = 0; track!(self.inner.finish_decoding()) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } impl Encode for MaxBytes { type Item = E::Item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let size = track!(self.inner.encode(buf, eos))?; self.consumed_bytes += size as u64; track_assert!(self.consumed_bytes <= self.max_bytes, ErrorKind::InvalidInput, "Max bytes limit exceeded"; self.consumed_bytes, self.max_bytes); if self.is_idle() { self.consumed_bytes = 0; } Ok(size) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.inner.start_encoding(item)) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } impl SizedEncode for MaxBytes { fn exact_requiring_bytes(&self) -> u64 { self.inner.exact_requiring_bytes() } } /// Combinator for pre-encoding items when `start_encoding` method is called. /// /// This is created by calling `EncodeExt::pre_encode` method. #[derive(Debug, Default)] pub struct PreEncode { inner: E, pre_encoded: BytesEncoder>, } impl PreEncode { /// Returns a reference to the inner encoder. pub fn inner_ref(&self) -> &E { &self.inner } /// Returns a mutable reference to the inner encoder. pub fn inner_mut(&mut self) -> &mut E { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder. pub fn into_inner(self) -> E { self.inner } pub(crate) fn new(inner: E) -> Self { PreEncode { inner, pre_encoded: BytesEncoder::new(), } } } impl Encode for PreEncode { type Item = E::Item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.pre_encoded.encode(buf, eos)) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { let buf = track!(self.inner.encode_into_bytes(item))?; track!(self.pre_encoded.start_encoding(buf))?; Ok(()) } fn requiring_bytes(&self) -> ByteCount { self.pre_encoded.requiring_bytes() } fn is_idle(&self) -> bool { self.pre_encoded.is_idle() } } impl SizedEncode for PreEncode { fn exact_requiring_bytes(&self) -> u64 { self.pre_encoded.exact_requiring_bytes() } } /// Combinator for slicing an input/output byte sequence by the specified number of bytes. /// /// This is created by calling `{DecodeExt, EncodeExt}::slice`. #[derive(Debug, Default)] pub struct Slice { inner: T, consumable_bytes: u64, } impl Slice { pub(crate) fn new(inner: T) -> Self { Slice { inner, consumable_bytes: 0, } } /// Returns the number of remaining bytes consumable in this slice. /// /// The inner decoder or encoder will be suspended if the consumable bytes reaches to `0`. pub fn consumable_bytes(&self) -> u64 { self.consumable_bytes } /// Set the number of remaining bytes consumable in this slice. pub fn set_consumable_bytes(&mut self, n: u64) { self.consumable_bytes = n; } /// Returns `true` if the encoder or decoder cannot consume any more bytes, otherwise `false`. /// /// To resume its works, it is needed to reset the value of consumable bytes /// by calling `set_consumable_bytes` method. pub fn is_suspended(&self) -> bool { self.consumable_bytes == 0 } /// Returns a reference to the inner encoder or decoder. pub fn inner_ref(&self) -> &T { &self.inner } /// Returns a mutable reference to the inner encoder or decoder. pub fn inner_mut(&mut self) -> &mut T { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder or decoder. pub fn into_inner(self) -> T { self.inner } } impl Decode for Slice { type Item = D::Item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let limit = cmp::min(buf.len() as u64, self.consumable_bytes) as usize; let eos = eos.back((buf.len() - limit) as u64); let size = track!(self.inner.decode(&buf[..limit], eos))?; self.consumable_bytes -= size as u64; Ok(size) } fn finish_decoding(&mut self) -> Result { track!(self.inner.finish_decoding()) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } impl Encode for Slice { type Item = E::Item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let limit = cmp::min(buf.len() as u64, self.consumable_bytes) as usize; let eos = eos.back((buf.len() - limit) as u64); let size = track!(self.inner.encode(&mut buf[..limit], eos))?; self.consumable_bytes -= size as u64; Ok(size) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.inner.start_encoding(item)) } fn is_idle(&self) -> bool { self.inner.is_idle() } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } } impl SizedEncode for Slice { fn exact_requiring_bytes(&self) -> u64 { self.inner.exact_requiring_bytes() } } /// Combinator for representing encoders that accepts only one additional item. /// /// This is created by calling `EncodeExt::last`. #[derive(Debug, Default)] pub struct Last { inner: E, item: Option, } impl Last { /// Returns a reference to the inner encoder. pub fn inner_ref(&self) -> &E { &self.inner } /// Returns a mutable reference to the inner encoder. pub fn inner_mut(&mut self) -> &mut E { &mut self.inner } /// Takes ownership of this instance and returns the inner encoder. pub fn into_inner(self) -> E { self.inner } pub(crate) fn new(inner: E, item: E::Item) -> Self { Last { inner, item: Some(item), } } } impl Encode for Last { type Item = Never; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { if self.inner.is_idle() { if let Some(item) = self.item.take() { track!(self.inner.start_encoding(item))?; } } track!(self.inner.encode(buf, eos)) } fn start_encoding(&mut self, _item: Self::Item) -> Result<()> { unreachable!() } fn is_idle(&self) -> bool { self.item.is_none() && self.inner.is_idle() } fn requiring_bytes(&self) -> ByteCount { if self.item.is_some() { ByteCount::Unknown } else { self.inner.requiring_bytes() } } } impl SizedEncode for Last { fn exact_requiring_bytes(&self) -> u64 { self.inner.exact_requiring_bytes() } } /// Combinator that enables to peek decoded items before calling `finish_decoding` method. /// /// This is created by calling `DecodeExt::peekable` method. pub struct Peekable { inner: D, item: Option, } impl Peekable { /// Returns a reference to the last item decoded (but not `finish_decoding` called yet) by the decoder. pub fn peek(&self) -> Option<&D::Item> { self.item.as_ref() } /// Returns a mutable reference to the last item decoded (but not `finish_decoding` called yet) by the decoder. pub fn peek_mut(&mut self) -> Option<&mut D::Item> { self.item.as_mut() } /// Returns a reference to the inner decoder. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of this instance and returns the inner decoder. pub fn into_inner(self) -> D { self.inner } pub(crate) fn new(inner: D) -> Self { Peekable { inner, item: None } } } impl fmt::Debug for Peekable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Peekable {{ inner: {:?}, item.is_some(): {:?} }}", self.inner, self.item.is_some() ) } } impl Default for Peekable { fn default() -> Self { Peekable { inner: D::default(), item: None, } } } impl Decode for Peekable { type Item = D::Item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { if self.item.is_none() { let size = track!(self.inner.decode(buf, eos))?; if self.inner.is_idle() { self.item = Some(track!(self.inner.finish_decoding())?); } Ok(size) } else { Ok(0) } } fn finish_decoding(&mut self) -> Result { let item = track_assert_some!(self.item.take(), ErrorKind::IncompleteDecoding); Ok(item) } fn requiring_bytes(&self) -> ByteCount { if self.item.is_some() { ByteCount::Finite(0) } else { self.inner.requiring_bytes() } } fn is_idle(&self) -> bool { self.item.is_some() } } /// Combinator for ignoring EOS if there is no item being decoded. /// /// This is created by calling `DecodeExt::maybe_eos`. #[derive(Debug, Default)] pub struct MaybeEos { inner: D, started: bool, } impl MaybeEos { /// Returns a reference to the inner decoder. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of this instance and returns the inner decoder. pub fn into_inner(self) -> D { self.inner } pub(crate) fn new(inner: D) -> Self { MaybeEos { inner, started: false, } } } impl Decode for MaybeEos { type Item = D::Item; fn decode(&mut self, buf: &[u8], mut eos: Eos) -> Result { if !self.started && buf.is_empty() && eos.is_reached() { eos = Eos::new(false); } let size = track!(self.inner.decode(buf, eos))?; if size != 0 { self.started = true; } Ok(size) } fn finish_decoding(&mut self) -> Result { self.started = false; track!(self.inner.finish_decoding()) } fn requiring_bytes(&self) -> ByteCount { self.inner.requiring_bytes() } fn is_idle(&self) -> bool { self.inner.is_idle() } } #[cfg(test)] mod test { use crate::bytes::{Utf8Decoder, Utf8Encoder}; use crate::fixnum::{U16beDecoder, U8Decoder, U8Encoder}; use crate::io::{IoDecodeExt, IoEncodeExt}; use crate::tuple::TupleDecoder; use crate::{Decode, DecodeExt, Encode, EncodeExt, Eos, ErrorKind}; #[test] fn collect_works() { let mut decoder = U8Decoder::new().collect::>(); let item = track_try_unwrap!(decoder.decode_exact(b"foo".as_ref())); assert_eq!(item, vec![b'f', b'o', b'o']); } #[test] fn collectn_works() { let mut decoder = U8Decoder::new().collectn::>(2); let item = track_try_unwrap!(decoder.decode_exact(b"foo".as_ref())); assert_eq!(item, vec![b'f', b'o']); let mut decoder = U8Decoder::new().collectn::>(4); assert_eq!( decoder .decode_exact(b"foo".as_ref()) .err() .map(|e| *e.kind()), Some(ErrorKind::UnexpectedEos) ); } #[test] fn decoder_length_works() { // length=3 let mut decoder = Utf8Decoder::new().length(3); let mut input = b"foobarba".as_ref(); let item = track_try_unwrap!(decoder.decode_exact(&mut input)); assert_eq!(item, "foo"); let item = track_try_unwrap!(decoder.decode_exact(&mut input)); assert_eq!(item, "bar"); let error = decoder.decode_exact(&mut input).err().unwrap(); assert_eq!(*error.kind(), ErrorKind::UnexpectedEos); // length=0 let mut decoder = Utf8Decoder::new().length(0); assert!(!decoder.is_idle()); assert!(decoder.finish_decoding().is_err()); let input = b"foobarba"; assert_eq!(decoder.decode(input, Eos::new(false)).ok(), Some(0)); assert!(decoder.is_idle()); assert!(decoder.finish_decoding().is_ok()); } #[test] fn encoder_length_works() { let mut output = Vec::new(); let mut encoder = Utf8Encoder::new().length(3); encoder.start_encoding("hey").unwrap(); // OK track_try_unwrap!(encoder.encode_all(&mut output)); assert_eq!(output, b"hey"); let mut output = Vec::new(); let mut encoder = Utf8Encoder::new().length(3); encoder.start_encoding("hello").unwrap(); // Error (too long) let error = encoder.encode_all(&mut output).err().expect("too long"); assert_eq!(*error.kind(), ErrorKind::UnexpectedEos); let mut output = Vec::new(); let mut encoder = Utf8Encoder::new().length(3); encoder.start_encoding("hi").unwrap(); // Error (too short) let error = encoder.encode_all(&mut output).err().expect("too short"); assert_eq!(*error.kind(), ErrorKind::InvalidInput); } #[test] fn repeat_works() { let mut output = Vec::new(); let mut encoder = U8Encoder::new().repeat(); encoder.start_encoding(0..4).unwrap(); track_try_unwrap!(encoder.encode_all(&mut output)); assert_eq!(output, [0, 1, 2, 3]); } #[test] fn decoder_max_bytes_works() { let mut decoder = Utf8Decoder::new().max_bytes(3); assert!(decoder.decode_from_bytes(b"12").is_ok()); assert!(decoder.decode_from_bytes(b"123").is_ok()); assert!(decoder.decode_from_bytes(b"1234").is_err()); } #[test] fn encoder_max_bytes_works() { let mut encoder = Utf8Encoder::new().max_bytes(3); let mut output = Vec::new(); encoder.start_encoding("foo").unwrap(); // OK encoder.encode_all(&mut output).unwrap(); assert_eq!(output, b"foo"); let mut output = Vec::new(); encoder.start_encoding("hello").unwrap(); // Error let error = encoder.encode_all(&mut output).err().unwrap(); assert_eq!(*error.kind(), ErrorKind::InvalidInput); } #[test] fn decoder_slice_works() { let mut decoder0 = Utf8Decoder::new().length(3).slice(); let mut decoder1 = Utf8Decoder::new().length(3).slice(); let eos = Eos::new(true); let input = b"fboaor"; let mut offset = 0; for _ in 0..3 { decoder0.set_consumable_bytes(1); offset += track_try_unwrap!(decoder0.decode(&input[offset..], eos)); decoder1.set_consumable_bytes(1); offset += track_try_unwrap!(decoder1.decode(&input[offset..], eos)); } assert_eq!(offset, input.len()); assert_eq!(decoder0.finish_decoding().ok(), Some("foo".to_owned())); assert_eq!(decoder1.finish_decoding().ok(), Some("bar".to_owned())); } #[test] fn encoder_slice_works() { let mut encoder = Utf8Encoder::new().slice(); encoder.start_encoding("foobarbazqux").unwrap(); let eos = Eos::new(true); let mut output = [0; 12]; let mut offset = 0; encoder.set_consumable_bytes(3); offset += track_try_unwrap!(encoder.encode(&mut output[offset..], eos)); assert_eq!(offset, 3); assert!(!encoder.is_idle()); offset += track_try_unwrap!(encoder.encode(&mut output[offset..], eos)); assert_eq!(offset, 3); assert_eq!(encoder.is_suspended(), true); encoder.set_consumable_bytes(3); offset += track_try_unwrap!(encoder.encode(&mut output[offset..], eos)); assert_eq!(offset, 6); encoder.set_consumable_bytes(6); offset += track_try_unwrap!(encoder.encode(&mut output[offset..], eos)); assert_eq!(offset, 12); assert!(encoder.is_idle()); assert_eq!(output.as_ref(), b"foobarbazqux"); } #[test] fn and_then_works() { let mut decoder = U8Decoder::new().and_then(|len| Utf8Decoder::new().length(u64::from(len))); track_try_unwrap!(decoder.decode(b"\x03foo", Eos::new(false))); assert_eq!(track_try_unwrap!(decoder.finish_decoding()), "foo"); } #[test] fn maybe_eos_works() { let mut decoder = U16beDecoder::new(); assert!(decoder.decode(&[][..], Eos::new(true)).is_err()); let mut decoder = U16beDecoder::new().maybe_eos(); assert!(decoder.decode(&[][..], Eos::new(true)).is_ok()); let mut decoder = U16beDecoder::new().maybe_eos(); assert!(decoder.decode(&[1][..], Eos::new(false)).is_ok()); assert!(decoder.decode(&[][..], Eos::new(true)).is_err()); } #[test] fn peekable_works() { let mut decoder = TupleDecoder::new((U8Decoder::new(), U8Decoder::new(), U8Decoder::new())).peekable(); let size = decoder.decode(b"foo", Eos::new(false)).unwrap(); assert_eq!(size, 3); assert_eq!(decoder.peek(), Some(&(b'f', b'o', b'o'))); assert_eq!(decoder.finish_decoding().unwrap(), (b'f', b'o', b'o')); assert_eq!(decoder.peek(), None); } } bytecodec-0.4.15/src/decode.rs000064400000000000000000000437530000000000000142250ustar 00000000000000use crate::combinator::{ AndThen, Collect, CollectN, Length, Map, MapErr, MaxBytes, MaybeEos, Omittable, Peekable, Slice, TryMap, }; use crate::tuple::TupleDecoder; use crate::{ByteCount, Eos, Error, ErrorKind, Result}; /// This trait allows for decoding items from a byte sequence incrementally. pub trait Decode { /// The type of items to be decoded. type Item; /// Consumes the given buffer (a part of a byte sequence), and proceeds the decoding process. /// /// It returns the number of bytes consumed from the input buffer. /// /// If an item is completely decoded, the next invocation of `is_idle` method will return `true`. /// And if `is_idle` method returns `true`, `decode` method should consume no bytes. /// /// The decoder must consume as many bytes in the buffer as possible. /// If an item is not yet decoded but the number of consumed bytes in the last `decode` invocation /// is smaller than the length of `buf`, it means the decoder has been suspended its work in any reasons. /// In that case the decoder may require some instructions from clients to resume the work, /// but its concrete method is beyond the scope of this trait. /// /// # Errors /// /// The following errors may be returned by the decoder: /// - `ErrorKind::DecoderTerminated`: /// - If all decodable items have been decoded, /// the decoder must return this kind of error when `decode` method is called. /// - `ErrorKind::UnexpectedEos`: /// - The invocation of `eos.is_reached()` returns `true` despite of /// the decoder requires more bytes to decode the next item. /// - `ErrorKind::InvalidInput`: /// - Decoded items have invalid values /// - Invalid parameters were given to decoders /// - `ErrorKind::InconsistentState`: /// - The state of the decoder bocame inconsistent /// - This means the implementation contains a bug /// - `ErrorKind::Other`: /// - Other errors fn decode(&mut self, buf: &[u8], eos: Eos) -> Result; /// Finishes the current decoding process and returns the decoded item. /// /// # Errors /// /// The following errors may be returned by the decoder: /// - `ErrorKind::IncompleteDecoding`: /// - The decoding process has not been completed /// - `ErrorKind::DecoderTerminated`: /// - The decoder has terminated (i.e., cannot decode any more items) /// - `ErrorKind::InconsistentState`: /// - The state of the decoder bocame inconsistent /// - This means the implementation contains a bug /// - `ErrorKind::Other`: /// - Other errors fn finish_decoding(&mut self) -> Result; /// Returns the lower bound of the number of bytes needed to decode the next item. /// /// If the decoder does not know the value, it will return `ByteCount::Unknown` /// (e.g., null-terminated strings have no pre-estimable length). /// /// If the decoder returns `ByteCount::Finite(0)`, it means one of the followings: /// - (a) There is an already decoded item /// - The next invocation of `decode()` will return it without consuming any bytes /// - (b) There are no decodable items /// - All decodable items have been decoded, and the decoder cannot do any further works /// - In this case, the next invocation of `decode` method will fail. fn requiring_bytes(&self) -> ByteCount; /// Returns `true` if there are no items to be decoded by the decoder /// at the next invocation of `decode` method, otherwise `false`. /// /// Typically, `true` means the decoder already has a decoded item and /// it is waiting for `finish_decoding` to be called. /// /// The default implementation returns the result of `self.requiring_bytes() == ByteCount::Finite(0)`. fn is_idle(&self) -> bool { self.requiring_bytes() == ByteCount::Finite(0) } } impl<'a, D: ?Sized + Decode> Decode for &'a mut D { type Item = D::Item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { (**self).decode(buf, eos) } fn finish_decoding(&mut self) -> Result { (**self).finish_decoding() } fn requiring_bytes(&self) -> ByteCount { (**self).requiring_bytes() } fn is_idle(&self) -> bool { (**self).is_idle() } } impl Decode for Box { type Item = D::Item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { (**self).decode(buf, eos) } fn finish_decoding(&mut self) -> Result { (**self).finish_decoding() } fn requiring_bytes(&self) -> ByteCount { (**self).requiring_bytes() } fn is_idle(&self) -> bool { (**self).is_idle() } } /// An extension of `Decode` trait. pub trait DecodeExt: Decode + Sized { /// Creates a decoder that converts decoded values by calling the given function. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt}; /// use bytecodec::fixnum::U8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U8Decoder::new().map(|b| b * 2); /// let item = decoder.decode_exact([10].as_ref()).unwrap(); /// assert_eq!(item, 20); /// ``` fn map(self, f: F) -> Map where F: Fn(Self::Item) -> T, { Map::new(self, f) } /// Creates a decoder that tries to convert decoded values by calling the given function. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt, ErrorKind, Result}; /// use bytecodec::fixnum::U8Decoder; /// use bytecodec::io::IoDecodeExt; /// use trackable::{track, track_assert, track_assert_ne, track_panic}; /// /// let mut decoder = U8Decoder::new().try_map(|b| -> Result<_> { /// track_assert_ne!(b, 0, ErrorKind::InvalidInput); /// Ok(b * 2) /// }); /// /// let error = decoder.decode_exact([0].as_ref()).err().unwrap(); /// assert_eq!(*error.kind(), ErrorKind::InvalidInput); /// /// let item = decoder.decode_exact([4].as_ref()).unwrap(); /// assert_eq!(item, 8); /// ``` fn try_map(self, f: F) -> TryMap where F: Fn(Self::Item) -> std::result::Result, Error: From, { TryMap::new(self, f) } /// Creates a decoder for modifying decoding errors produced by `self`. /// /// # Examples /// /// The following code shows the idiomatic way to track decoding errors: /// /// ``` /// use bytecodec::{Decode, DecodeExt}; /// use bytecodec::fixnum::U16beDecoder; /// use bytecodec::io::IoDecodeExt; /// use trackable::track; /// /// let mut decoder = /// U16beDecoder::new().map_err(|e| track!(e, "oops!")); /// // or `track_err!(U16beDecoder::new(), "oops!")` /// /// let input = [0]; // Insufficient bytes /// let error = track!(decoder.decode_exact(input.as_ref())).err().unwrap(); /// /// assert_eq!(error.to_string(), "\ /// UnexpectedEos (cause; assertion failed: `!eos.is_reached()`; \ /// self.offset=1, self.bytes.as_ref().len()=2) /// HISTORY: /// [0] at src/bytes.rs:152 /// [1] at src/fixnum.rs:200 /// [2] at src/decode.rs:10 -- oops! /// [3] at src/io.rs:45 /// [4] at src/decode.rs:14\n"); /// ``` fn map_err(self, f: F) -> MapErr where F: Fn(Error) -> E, Error: From, { MapErr::new(self, f) } /// Creates a decoder that enables conditional decoding. /// /// If the first item is successfully decoded, /// it will start decoding the second item by using the decoder returned by `f` function. /// /// # Examples /// /// Decodes a length-prefixed string: /// /// ``` /// use bytecodec::{Decode, DecodeExt}; /// use bytecodec::bytes::Utf8Decoder; /// use bytecodec::fixnum::U8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U8Decoder::new().and_then(|len| Utf8Decoder::new().length(len as u64)); /// let item = decoder.decode_exact(b"\x03foobar".as_ref()).unwrap(); /// assert_eq!(item, "foo"); /// ``` fn and_then(self, f: F) -> AndThen where F: Fn(Self::Item) -> D, D: Decode, { AndThen::new(self, f) } /// Creates a decoder for collecting decoded items. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt}; /// use bytecodec::fixnum::U8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U8Decoder::new().collect::>(); /// let item = decoder.decode_exact(b"foo".as_ref()).unwrap(); /// assert_eq!(item, vec![b'f', b'o', b'o']); /// ``` fn collect(self) -> Collect where T: Extend + Default, { Collect::new(self) } /// Creates a decoder that decodes `n` items by using `self` and collecting the result. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt}; /// use bytecodec::fixnum::U8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U8Decoder::new().collectn::>(2); /// let item = decoder.decode_exact(b"foo".as_ref()).unwrap(); /// assert_eq!(item, vec![b'f', b'o']); /// ``` fn collectn(self, n: usize) -> CollectN where T: Extend + Default, { CollectN::new(self, n) } /// Creates a decoder that consumes the specified number of bytes exactly. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt, ErrorKind}; /// use bytecodec::bytes::Utf8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = Utf8Decoder::new().length(3); /// let mut input = &b"foobarba"[..]; /// /// let item = decoder.decode_exact(&mut input).unwrap(); /// assert_eq!(item, "foo"); /// /// let item = decoder.decode_exact(&mut input).unwrap(); /// assert_eq!(item, "bar"); /// /// let error = decoder.decode_exact(&mut input).err().unwrap(); /// assert_eq!(*error.kind(), ErrorKind::UnexpectedEos); /// ``` fn length(self, expected_bytes: u64) -> Length { Length::new(self, expected_bytes) } /// Creates a decoder that will omit decoding items if `do_omit = true` is specified. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt}; /// use bytecodec::fixnum::U8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut input = &b"foo"[..]; /// /// let mut decoder = U8Decoder::new().omit(true); /// let item = decoder.decode_exact(&mut input).unwrap(); /// assert_eq!(item, None); /// /// let mut decoder = U8Decoder::new().omit(false); /// let item = decoder.decode_exact(&mut input).unwrap(); /// assert_eq!(item, Some(b'f')); /// ``` fn omit(self, do_omit: bool) -> Omittable { Omittable::new(self, do_omit) } /// Creates a decoder that will fail if the number of consumed bytes exceeds `bytes`. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt, ErrorKind}; /// use bytecodec::bytes::Utf8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = Utf8Decoder::new().max_bytes(3); /// /// let item = decoder.decode_exact(b"foo".as_ref()).unwrap(); /// assert_eq!(item, "foo"); // OK /// /// let error = decoder.decode_exact(b"hello".as_ref()).err(); /// assert_eq!(error.map(|e| *e.kind()), Some(ErrorKind::InvalidInput)); // Error /// ``` fn max_bytes(self, bytes: u64) -> MaxBytes { MaxBytes::new(self, bytes) } /// Takes two decoders and creates a new decoder that decodes both items in sequence. /// /// This is equivalent to call `TupleDecoder::new((self, other))`. fn chain(self, other: T) -> TupleDecoder<(Self, T)> { TupleDecoder::new((self, other)) } /// Creates a decoder that makes it possible to slice the input byte sequence in arbitrary units. /// /// Slicing an input byte sequence makes it easier to demultiplex multiple sequences from it. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt, Eos}; /// use bytecodec::bytes::Utf8Decoder; /// /// let mut decoder0 = Utf8Decoder::new().length(3).slice(); /// let mut decoder1 = Utf8Decoder::new().length(3).slice(); /// /// let eos = Eos::new(true); /// let input = b"fboaor"; /// let mut offset = 0; /// /// for _ in 0..3 { /// decoder0.set_consumable_bytes(1); /// offset += decoder0.decode(&input[offset..], eos).unwrap(); /// /// decoder1.set_consumable_bytes(1); /// offset += decoder1.decode(&input[offset..], eos).unwrap(); /// } /// /// assert_eq!(offset, input.len()); /// assert_eq!(decoder0.finish_decoding().unwrap(), "foo"); /// assert_eq!(decoder1.finish_decoding().unwrap(), "bar"); /// ``` fn slice(self) -> Slice { Slice::new(self) } /// Creates a decoder that enables to peek decoded items before calling `finish_decoding` method. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt, Eos}; /// use bytecodec::fixnum::U8Decoder; /// use bytecodec::tuple::TupleDecoder; /// /// let mut decoder = TupleDecoder::new(( /// U8Decoder::new(), /// U8Decoder::new(), /// U8Decoder::new(), /// )).peekable(); /// let size = decoder.decode(b"foo", Eos::new(false)).unwrap(); /// assert_eq!(size, 3); /// assert_eq!(decoder.peek(), Some(&(b'f', b'o', b'o'))); /// assert_eq!(decoder.finish_decoding().unwrap(), (b'f', b'o', b'o')); /// assert_eq!(decoder.peek(), None); /// ``` fn peekable(self) -> Peekable { Peekable::new(self) } /// Creates a decoder that ignores EOS if there is no item being decoded. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, DecodeExt, Eos}; /// use bytecodec::fixnum::U16beDecoder; /// /// let mut decoder = U16beDecoder::new(); /// assert!(decoder.decode(&[][..], Eos::new(true)).is_err()); // UnexpectedEos /// /// let mut decoder = U16beDecoder::new().maybe_eos(); /// assert!(decoder.decode(&[][..], Eos::new(true)).is_ok()); // EOS is ignored /// /// let mut decoder = U16beDecoder::new().maybe_eos(); /// assert!(decoder.decode(&[1][..], Eos::new(true)).is_err()); // UnexpectedEos /// ``` fn maybe_eos(self) -> MaybeEos { MaybeEos::new(self) } /// Decodes an item by consuming the whole part of the given bytes. /// /// # Examples /// /// ``` /// use bytecodec::DecodeExt; /// use bytecodec::fixnum::U16beDecoder; /// /// let mut decoder = U16beDecoder::new(); /// assert_eq!( /// decoder.decode_from_bytes(&[0x12, 0x34][..]).unwrap(), /// 0x1234 /// ); /// ``` fn decode_from_bytes(&mut self, buf: &[u8]) -> Result { let size = track!(self.decode(buf, Eos::new(true)))?; track_assert_eq!(size, buf.len(), ErrorKind::InvalidInput; self.is_idle()); track!(self.finish_decoding()) } } impl DecodeExt for T {} /// This trait allows for decoding tagged items from a byte sequence incrementally. pub trait TaggedDecode: Decode { /// The type of tags prefixed to the items to be decoded. type Tag; /// Prepares to start decoding an item tagged by `tag`. /// /// # Errors /// /// The following errors may be returned by the decoder: /// - `ErrorKind::InvalidInput`: /// - Unexpected tag was passed /// - `ErrorKind::IncompleteDecoding`: /// - The previous decoding process has not been completed /// - `ErrorKind::DecoderTerminated`: /// - The decoder has terminated (i.e., cannot decode any more items) /// - `ErrorKind::Other`: /// - Other errors has occurred fn start_decoding(&mut self, tag: Self::Tag) -> Result<()>; } impl<'a, D: ?Sized + TaggedDecode> TaggedDecode for &'a mut D { type Tag = D::Tag; fn start_decoding(&mut self, tag: Self::Tag) -> Result<()> { (**self).start_decoding(tag) } } impl TaggedDecode for Box { type Tag = D::Tag; fn start_decoding(&mut self, tag: Self::Tag) -> Result<()> { (**self).start_decoding(tag) } } /// This trait allows for decoding known-tagged or unknown-tagged items from a byte sequence incrementally. pub trait TryTaggedDecode: Decode { /// The type of tags prefixed to the items to be decoded. type Tag; /// Tries to prepare to start decoding an item tagged by `tag`. /// /// If the given tag is unknown, it will return `Ok(false)`. /// /// # Errors /// /// The following errors may be returned by the decoder: /// - `ErrorKind::IncompleteDecoding`: /// - The previous decoding process has not been completed /// - `ErrorKind::DecoderTerminated`: /// - The decoder has terminated (i.e., cannot decode any more items) /// - `ErrorKind::Other`: /// - Other errors has occurred fn try_start_decoding(&mut self, tag: Self::Tag) -> Result; } impl<'a, D: ?Sized + TryTaggedDecode> TryTaggedDecode for &'a mut D { type Tag = D::Tag; fn try_start_decoding(&mut self, tag: Self::Tag) -> Result { (**self).try_start_decoding(tag) } } impl TryTaggedDecode for Box { type Tag = D::Tag; fn try_start_decoding(&mut self, tag: Self::Tag) -> Result { (**self).try_start_decoding(tag) } } #[cfg(test)] mod test { use super::*; use crate::fixnum::U16beDecoder; #[test] fn decode_from_bytes_works() { let mut decoder = U16beDecoder::new(); assert_eq!( decoder.decode_from_bytes(&[0x12, 0x34][..]).unwrap(), 0x1234 ); } } bytecodec-0.4.15/src/encode.rs000064400000000000000000000370110000000000000142250ustar 00000000000000use crate::combinator::{ Last, Length, MapErr, MapFrom, MaxBytes, Optional, PreEncode, Repeat, Slice, TryMapFrom, }; use crate::io::IoEncodeExt; use crate::tuple::TupleEncoder; use crate::{ByteCount, Eos, Error, ErrorKind, Result}; /// This trait allows for encoding items into a byte sequence incrementally. pub trait Encode { /// The type of items to be encoded. type Item; /// Encodes the items in the encoder and writes the encoded bytes to the given buffer. /// /// It returns the number of bytes written to the given buffer. /// /// If the encoded bytes are larger than the length of `buf`, /// the encoder must consume as many bytes in the buffer as possible. /// /// The completion of the encoding can be detected by using `is_idle` method. /// /// If `self.is_idle()` returns `false` but the number of written bytes in the last `encode` invocation /// is smaller than the length of `buf`, it means the encoder has been suspended its work in any reasons. /// In that case the encoder may require some instructions from clients to resume the work, /// but its concrete method is beyond the scope of this trait. /// /// The encoded bytes that could not be written to the given buffer is held by /// the encoder until the next invocation of the `encode` method. /// /// # Errors /// /// Encoders return the following kinds of errors as necessary: /// - `ErrorKind::InvalidInput`: /// - An item that the encoder could not encode was passed /// - `ErrorKind::UnexpectedEos`: /// - The output byte stream has reached the end in the middle of an encoding process /// - `ErrorKind::InconsistentState`: /// - The state of the encoder bocame inconsistent /// - This means the implementation contains a bug /// - `ErrorKind::Other`: /// - Other errors has occurred fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result; /// Tries to start encoding the given item. /// /// If the encoder has no items to be encoded and the passed item is valid, it must accept the item. /// /// # Errors /// /// - `ErrorKind::EncoderFull`: /// - The encoder currently cannot accept any more items /// - `ErrorKind::InvalidInput`: /// - An invalid item was passed /// - `ErrorKind::InconsistentState`: /// - The state of the encoder bocame inconsistent /// - This means the implementation contains a bug /// - `ErrorKind::Other`: /// - Other errors has occurred fn start_encoding(&mut self, item: Self::Item) -> Result<()>; /// Returns the number of bytes required to encode all the items in the encoder. /// /// If there are no items to be encoded, the encoder must return `ByteCount::Finite(0)`. fn requiring_bytes(&self) -> ByteCount; /// Returns `true` if there are no items to be encoded in the encoder, otherwise `false`. /// /// The default implementation returns the result of `self.requiring_bytes() == ByteCount::Finite(0)`. fn is_idle(&self) -> bool { self.requiring_bytes() == ByteCount::Finite(0) } } impl<'a, E: ?Sized + Encode> Encode for &'a mut E { type Item = E::Item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { (**self).encode(buf, eos) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { (**self).start_encoding(item) } fn requiring_bytes(&self) -> ByteCount { (**self).requiring_bytes() } fn is_idle(&self) -> bool { (**self).is_idle() } } impl Encode for Box { type Item = E::Item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { (**self).encode(buf, eos) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { (**self).start_encoding(item) } fn requiring_bytes(&self) -> ByteCount { (**self).requiring_bytes() } fn is_idle(&self) -> bool { (**self).is_idle() } } /// This trait indicates that the encoder always knows the exact bytes required to encode remaining items. pub trait SizedEncode: Encode { /// Returns the exact number of bytes required to encode all the items remaining in the encoder. fn exact_requiring_bytes(&self) -> u64; } impl<'a, E: ?Sized + SizedEncode> SizedEncode for &'a mut E { fn exact_requiring_bytes(&self) -> u64 { (**self).exact_requiring_bytes() } } impl SizedEncode for Box { fn exact_requiring_bytes(&self) -> u64 { (**self).exact_requiring_bytes() } } /// An extension of `Encode` trait. pub trait EncodeExt: Encode + Sized { /// Creates a new encoder instance that has the given initial item. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt}; /// use bytecodec::fixnum::U8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U8Encoder::with_item(7).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [7]); /// assert!(encoder.is_idle()); /// ``` fn with_item(item: Self::Item) -> Result where Self: Default, { let mut this = Self::default(); track!(this.start_encoding(item))?; Ok(this) } /// Creates an encoder for modifying encoding errors produced by `self`. /// /// # Examples /// /// The following code shows the idiomatic way to track encoding errors: /// /// ``` /// use bytecodec::{Encode, EncodeExt, Eos}; /// use bytecodec::fixnum::U8Encoder; /// use trackable::track; /// /// let encoder = U8Encoder::with_item(7).unwrap(); /// let mut encoder = encoder.map_err(|e| track!(e, "oops!")); // or track_err!(encoder, "oops!") /// let error = track!(encoder.encode(&mut [][..], Eos::new(true))).err().unwrap(); /// /// assert_eq!(error.to_string(), "\ /// UnexpectedEos (cause; assertion failed: `!eos.is_reached()`; \ /// buf.len()=0, size=0, self.offset=0, b.as_ref().len()=1) /// HISTORY: /// [0] at src/bytes.rs:53 /// [1] at src/fixnum.rs:116 /// [2] at src/encode.rs:9 -- oops! /// [3] at src/encode.rs:10\n"); /// ``` fn map_err(self, f: F) -> MapErr where F: Fn(Error) -> E, Error: From, { MapErr::new(self, f) } /// Creates an encoder that converts items into ones that /// suited to the `self` encoder by calling the given function. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt}; /// use bytecodec::fixnum::U8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U8Encoder::new().map_from(|s: String| s.len() as u8); /// let item = "Hello World!".to_owned(); /// encoder.start_encoding(item).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [12]); /// ``` fn map_from(self, f: F) -> MapFrom where F: Fn(T) -> Self::Item, { MapFrom::new(self, f) } /// Creates an encoder that tries to convert items into ones that /// suited to the `self` encoder by calling the given function. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt, ErrorKind, Result}; /// use bytecodec::fixnum::U8Encoder; /// use bytecodec::io::IoEncodeExt; /// use trackable::{track, track_assert, track_panic}; /// /// let mut output = Vec::new(); /// let mut encoder = U8Encoder::new().try_map_from(|s: String| -> Result<_> { /// track_assert!(s.len() <= 0xFF, ErrorKind::InvalidInput); /// Ok(s.len() as u8) /// }); /// let item = "Hello World!".to_owned(); /// encoder.start_encoding(item).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [12]); /// ``` fn try_map_from(self, f: F) -> TryMapFrom where F: Fn(T) -> std::result::Result, Error: From, { TryMapFrom::new(self, f) } /// Creates an encoder that represents an optional encoder. /// /// It takes `Option` items. /// If `Some(_)` is passed as an argument for `start_encoding` method, it will be encoded as ordinally. /// On the other hand, if `None` is passed, it will be ignored completely. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt}; /// use bytecodec::fixnum::U8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U8Encoder::new().optional(); /// /// encoder.start_encoding(None).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// /// encoder.start_encoding(Some(9)).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// /// assert_eq!(output, [9]); /// ``` fn optional(self) -> Optional { Optional::new(self) } /// Creates an encoder that will fail if the number of encoded bytes of an item exceeds `n`. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt, ErrorKind}; /// use bytecodec::bytes::Utf8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = Utf8Encoder::new().max_bytes(3); /// /// encoder.start_encoding("foo").unwrap(); // OK /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, b"foo"); /// /// encoder.start_encoding("hello").unwrap(); // Error /// let error = encoder.encode_all(&mut output).err().unwrap(); /// assert_eq!(*error.kind(), ErrorKind::InvalidInput); /// ``` fn max_bytes(self, n: u64) -> MaxBytes { MaxBytes::new(self, n) } /// Creates an encoder that required to encode each item exactly at the specified number of bytes. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt, ErrorKind}; /// use bytecodec::bytes::Utf8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = Utf8Encoder::new().length(3); /// encoder.start_encoding("hey").unwrap(); // OK /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, b"hey"); /// /// let mut encoder = Utf8Encoder::new().length(3); /// encoder.start_encoding("hello").unwrap(); // Error (too long) /// let error = encoder.encode_all(&mut output).err().unwrap(); /// assert_eq!(*error.kind(), ErrorKind::UnexpectedEos); /// /// let mut encoder = Utf8Encoder::new().length(3); /// encoder.start_encoding("hi").unwrap(); // Error (too short) /// let error = encoder.encode_all(&mut output).err().unwrap(); /// assert_eq!(*error.kind(), ErrorKind::InvalidInput); /// ``` fn length(self, n: u64) -> Length { Length::new(self, n) } /// Takes two encoders and creates a new encoder that encodes both items in sequence. /// /// This is equivalent to call `TupleEncoder::new((self, other))`. fn chain(self, other: T) -> TupleEncoder<(Self, T)> { TupleEncoder::new((self, other)) } /// Creates an encoder that repeats encoding of `Self::Item`. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt, ErrorKind}; /// use bytecodec::fixnum::U8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U8Encoder::new().repeat(); /// encoder.start_encoding(0..4).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0, 1, 2, 3]); /// ``` fn repeat(self) -> Repeat where I: Iterator, { Repeat::new(self) } /// Creates an encoder that pre-encodes items when `start_encoding` method is called. /// /// Although the number of memory copies increases, /// pre-encoding will enable to acquire the exact size of encoded items. /// /// # Examples /// /// ```ignore /// use bytecodec::{Encode, EncodeExt, ExactBytesEncode}; /// use bytecodec::fixnum::U8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = /// U8Encoder::new() /// .repeat() /// .pre_encode() /// .with_prefix(U8Encoder::new(), |body| body.exact_requiring_bytes() as u8); /// /// encoder.start_encoding(0..3).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [3, 0, 1, 2]); /// ``` fn pre_encode(self) -> PreEncode { PreEncode::new(self) } /// Creates an encoder that makes it possible to slice the encoded byte sequence in arbitrary units. /// /// Slicing encoded byte sequences makes it easier to multiplex them into a single sequence. /// /// # Examples /// /// ``` /// use bytecodec::{Encode, EncodeExt, Eos}; /// use bytecodec::bytes::Utf8Encoder; /// /// let mut encoder = Utf8Encoder::new().slice(); /// encoder.start_encoding("foobarbaz").unwrap(); /// /// let eos = Eos::new(true); /// let mut output = [0; 9]; /// let mut offset = 0; /// /// encoder.set_consumable_bytes(3); /// offset += encoder.encode(&mut output[offset..], eos).unwrap(); /// assert_eq!(offset, 3); /// assert_eq!(encoder.is_idle(), false); /// assert_eq!(encoder.consumable_bytes(), 0); /// /// offset += encoder.encode(&mut output[offset..], eos).unwrap(); /// assert_eq!(offset, 3); /// /// encoder.set_consumable_bytes(6); /// offset += encoder.encode(&mut output[offset..], eos).unwrap(); /// assert_eq!(offset, 9); /// assert_eq!(encoder.is_idle(), true); /// assert_eq!(output.as_ref(), b"foobarbaz"); /// ``` fn slice(self) -> Slice { Slice::new(self) } /// Creates an encoder that cannot accept any more items except the given one. fn last(self, item: Self::Item) -> Last { Last::new(self, item) } /// Encodes the given item and returns the resulting bytes. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U16beEncoder; /// /// let mut encoder = U16beEncoder::new(); /// assert_eq!(encoder.encode_into_bytes(0x1234).unwrap(), [0x12, 0x34]); /// ``` fn encode_into_bytes(&mut self, item: Self::Item) -> Result> { track!(self.start_encoding(item))?; match self.requiring_bytes() { ByteCount::Finite(size) => { track_assert!(size <= std::usize::MAX as u64, ErrorKind::Other; size); let mut buf = vec![0; size as usize]; track!(self.encode(&mut buf, Eos::new(true)))?; track_assert!(self.is_idle(), ErrorKind::InconsistentState); Ok(buf) } ByteCount::Unknown => { let mut buf = Vec::new(); track!(self.encode_all(&mut buf))?; Ok(buf) } ByteCount::Infinite => track_panic!(ErrorKind::InvalidInput), } } } impl EncodeExt for T {} #[cfg(test)] mod test { use super::*; use crate::fixnum::U16beEncoder; #[test] fn encode_into_bytes_works() { let mut encoder = U16beEncoder::new(); assert_eq!(encoder.encode_into_bytes(0x1234).unwrap(), [0x12, 0x34]); } } bytecodec-0.4.15/src/eos.rs000064400000000000000000000032140000000000000135540ustar 00000000000000use crate::ByteCount; /// `Eos` contains information on the distance to the end of a stream. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd)] pub struct Eos(ByteCount); impl Eos { /// Makes a new `Eos` instance. pub fn new(is_eos_reached: bool) -> Self { if is_eos_reached { Eos(ByteCount::Finite(0)) } else { Eos(ByteCount::Unknown) } } /// Makes a new `Eos` instance that /// has the given information about the number of remaining bytes in a stream. pub fn with_remaining_bytes(n: ByteCount) -> Self { Eos(n) } /// Returns `true` if the target stream has reached to the end, otherwise `false`. pub fn is_reached(&self) -> bool { self.0 == ByteCount::Finite(0) } /// Returns the information about the number of bytes remaining in the target stream. pub fn remaining_bytes(&self) -> ByteCount { self.0 } /// Returns a new `Eos` instance that has moved backward from /// the end of the target stream by the specified number of bytes. /// /// # Examples /// /// ``` /// use bytecodec::{ByteCount, Eos}; /// /// let eos = Eos::new(true); /// assert_eq!(eos.is_reached(), true); /// assert_eq!(eos.remaining_bytes(), ByteCount::Finite(0)); /// /// let eos = eos.back(5); /// assert_eq!(eos.is_reached(), false); /// assert_eq!(eos.remaining_bytes(), ByteCount::Finite(5)); /// ``` pub fn back(&self, bytes: u64) -> Self { if let ByteCount::Finite(n) = self.0 { Eos(ByteCount::Finite(n + bytes)) } else { *self } } } bytecodec-0.4.15/src/error.rs000064400000000000000000000030520000000000000141170ustar 00000000000000use trackable::error::{ErrorKind as TrackableErrorKind, ErrorKindExt}; use trackable::error::{Failure, TrackableError}; /// This crate specific `Error` type. #[derive(Debug, Clone, TrackableError)] pub struct Error(TrackableError); impl From for Error { fn from(f: Failure) -> Self { ErrorKind::Other.takes_over(f).into() } } impl From for Error { fn from(f: std::io::Error) -> Self { let kind = if f.kind() == std::io::ErrorKind::UnexpectedEof { ErrorKind::UnexpectedEos } else { ErrorKind::Other }; kind.cause(f).into() } } /// Possible error kinds. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ErrorKind { /// Input is invalid. /// /// Usually it indicates there is a problem outside of the encoder/decoder. InvalidInput, /// Inconsistent state of the encoder/decoder. /// /// Usually it indicates there is a bug in the encoder/decoder. InconsistentState, /// Unexpected EOS. /// /// A target stream has reached EOS despite there are some items to be encoded/decoded. UnexpectedEos, /// Encoder is full. /// /// The encoder cannot accept more items because it has some items to be encoded currently. EncoderFull, /// Decoder has terminated. /// /// The decoder cannot decode any more items. DecoderTerminated, /// A decoding process terminated incompletely. IncompleteDecoding, /// Other errors. Other, } impl TrackableErrorKind for ErrorKind {} bytecodec-0.4.15/src/fixnum.rs000064400000000000000000001335220000000000000143020ustar 00000000000000//! Encoders and decoders for numbers which have fixed length binary representation. use crate::bytes::{BytesEncoder, CopyableBytesDecoder}; use crate::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode}; use byteorder::{BigEndian, ByteOrder, LittleEndian}; macro_rules! impl_decode { ($ty:ty, $item:ty) => { impl Decode for $ty { type Item = $item; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()).map(Self::decode_item) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } }; } macro_rules! impl_encode { ($ty:ty, $item:ty) => { impl Encode for $ty { type Item = $item; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { let mut b = Default::default(); track!(Self::encode_item(item, &mut b))?; track!(self.0.start_encoding(b)) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl SizedEncode for $ty { fn exact_requiring_bytes(&self) -> u64 { self.0.exact_requiring_bytes() } } }; } /// Decoder which decodes `u8` values. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U8Decoder::new(); /// let item = decoder.decode_exact([7].as_ref()).unwrap(); /// assert_eq!(item, 7); /// ``` #[derive(Debug, Default)] pub struct U8Decoder(CopyableBytesDecoder<[u8; 1]>); impl U8Decoder { /// Makes a new `U8Decoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 1]) -> u8 { b[0] } } impl_decode!(U8Decoder, u8); /// Encoder which encodes `u8` values. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U8Encoder::with_item(7).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [7]); /// ``` #[derive(Debug, Default)] pub struct U8Encoder(BytesEncoder<[u8; 1]>); impl U8Encoder { /// Makes a new `U8Encoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: u8, b: &mut [u8; 1]) -> Result<()> { b[0] = n; Ok(()) } } impl_encode!(U8Encoder, u8); /// Decoder which decodes `i8` values. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::I8Decoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = I8Decoder::new(); /// let item = decoder.decode_exact([255].as_ref()).unwrap(); /// assert_eq!(item, -1); /// ``` #[derive(Debug, Default)] pub struct I8Decoder(CopyableBytesDecoder<[u8; 1]>); impl I8Decoder { /// Makes a new `I8Decoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 1]) -> i8 { b[0] as i8 } } impl_decode!(I8Decoder, i8); /// Encoder which encodes `i8` values. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::I8Encoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = I8Encoder::with_item(-1).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [255]); /// ``` #[derive(Debug, Default)] pub struct I8Encoder(BytesEncoder<[u8; 1]>); impl I8Encoder { /// Makes a new `I8Encoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: i8, b: &mut [u8; 1]) -> Result<()> { b[0] = n as u8; Ok(()) } } impl_encode!(I8Encoder, i8); /// Decoder which decodes `u16` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U16beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U16beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02].as_ref()).unwrap(); /// assert_eq!(item, 0x0102u16); /// ``` #[derive(Debug, Default)] pub struct U16beDecoder(CopyableBytesDecoder<[u8; 2]>); impl U16beDecoder { /// Makes a new `U16beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 2]) -> u16 { BigEndian::read_u16(&b) } } impl_decode!(U16beDecoder, u16); /// Decoder which decodes `u16` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U16leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U16leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02].as_ref()).unwrap(); /// assert_eq!(item, 0x0201u16); /// ``` #[derive(Debug, Default)] pub struct U16leDecoder(CopyableBytesDecoder<[u8; 2]>); impl U16leDecoder { /// Makes a new `U16leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 2]) -> u16 { LittleEndian::read_u16(&b) } } impl_decode!(U16leDecoder, u16); /// Encoder which encodes `u16` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U16beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U16beEncoder::with_item(0x0102).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x01, 0x02]); /// ``` #[derive(Debug, Default)] pub struct U16beEncoder(BytesEncoder<[u8; 2]>); impl U16beEncoder { /// Makes a new `U16beEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: u16, b: &mut [u8; 2]) -> Result<()> { BigEndian::write_u16(b, n); Ok(()) } } impl_encode!(U16beEncoder, u16); /// Encoder which encodes `u16` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U16leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U16leEncoder::with_item(0x0102).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x02, 0x01]); /// ``` #[derive(Debug, Default)] pub struct U16leEncoder(BytesEncoder<[u8; 2]>); impl U16leEncoder { /// Makes a new `U16leEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: u16, b: &mut [u8; 2]) -> Result<()> { LittleEndian::write_u16(b, n); Ok(()) } } impl_encode!(U16leEncoder, u16); /// Decoder which decodes `i16` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::I16beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = I16beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02].as_ref()).unwrap(); /// assert_eq!(item, 0x0102i16); /// ``` #[derive(Debug, Default)] pub struct I16beDecoder(CopyableBytesDecoder<[u8; 2]>); impl I16beDecoder { /// Makes a new `I16beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 2]) -> i16 { BigEndian::read_i16(&b) } } impl_decode!(I16beDecoder, i16); /// Decoder which decodes `i16` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::I16leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = I16leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02].as_ref()).unwrap(); /// assert_eq!(item, 0x0201i16); /// ``` #[derive(Debug, Default)] pub struct I16leDecoder(CopyableBytesDecoder<[u8; 2]>); impl I16leDecoder { /// Makes a new `I16leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 2]) -> i16 { LittleEndian::read_i16(&b) } } impl_decode!(I16leDecoder, i16); /// Encoder which encodes `i16` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::I16beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = I16beEncoder::with_item(-2).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0xFF, 0xFE]); /// ``` #[derive(Debug, Default)] pub struct I16beEncoder(BytesEncoder<[u8; 2]>); impl I16beEncoder { /// Makes a new `I16beEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: i16, b: &mut [u8; 2]) -> Result<()> { BigEndian::write_i16(b, n); Ok(()) } } impl_encode!(I16beEncoder, i16); /// Encoder which encodes `i16` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::I16leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = I16leEncoder::with_item(-2).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0xFE, 0xFF]); /// ``` #[derive(Debug, Default)] pub struct I16leEncoder(BytesEncoder<[u8; 2]>); impl I16leEncoder { /// Makes a new `I16leEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: i16, b: &mut [u8; 2]) -> Result<()> { LittleEndian::write_i16(b, n); Ok(()) } } impl_encode!(I16leEncoder, i16); /// Decoder which decodes unsigned 24-bit integers by big-endian byte order. /// /// The type of decoded values is `u32`, but the most significant 8-bits always be `0`. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U24beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U24beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03].as_ref()).unwrap(); /// assert_eq!(item, 0x0001_0203u32); /// ``` #[derive(Debug, Default)] pub struct U24beDecoder(CopyableBytesDecoder<[u8; 3]>); impl U24beDecoder { /// Makes a new `U24beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 3]) -> u32 { BigEndian::read_u24(&b) } } impl_decode!(U24beDecoder, u32); /// Decoder which decodes unsigned 24-bit integers by little-endian byte order. /// /// The type of decoded values is `u32`, but the most significant 8-bits always be `0`. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U24leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U24leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03].as_ref()).unwrap(); /// assert_eq!(item, 0x0003_0201u32); /// ``` #[derive(Debug, Default)] pub struct U24leDecoder(CopyableBytesDecoder<[u8; 3]>); impl U24leDecoder { /// Makes a new `U24leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 3]) -> u32 { LittleEndian::read_u24(&b) } } impl_decode!(U24leDecoder, u32); /// Encoder which encodes unsigned 24-bit integers by big-endian byte order. /// /// Although the type of items is `u32`, the most significant 8-bits must be `0`. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U24beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U24beEncoder::with_item(0x0001_0203).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x01, 0x02, 0x03]); /// ``` #[derive(Debug, Default)] pub struct U24beEncoder(BytesEncoder<[u8; 3]>); impl U24beEncoder { /// Makes a new `U24beEncoder` instance. pub fn new() -> Self { Self::default() } fn encode_item(n: u32, b: &mut [u8; 3]) -> Result<()> { track_assert!(n <= 0xFF_FFFF, ErrorKind::InvalidInput); BigEndian::write_u24(b, n); Ok(()) } } impl_encode!(U24beEncoder, u32); /// Encoder which encodes unsigned 24-bit integers by little-endian byte order. /// /// Although the type of items is `u32`, the most significant 8-bits must be `0`. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U24leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U24leEncoder::with_item(0x0001_0203).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x03, 0x02, 0x01]); /// ``` #[derive(Debug, Default)] pub struct U24leEncoder(BytesEncoder<[u8; 3]>); impl U24leEncoder { /// Makes a new `U24leEncoder` instance. pub fn new() -> Self { Self::default() } fn encode_item(n: u32, b: &mut [u8; 3]) -> Result<()> { track_assert!(n <= 0xFF_FFFF, ErrorKind::InvalidInput); LittleEndian::write_u24(b, n); Ok(()) } } impl_encode!(U24leEncoder, u32); /// Decoder which decodes `u32` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U32beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U32beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04].as_ref()).unwrap(); /// assert_eq!(item, 0x0102_0304u32); /// ``` #[derive(Debug, Default)] pub struct U32beDecoder(CopyableBytesDecoder<[u8; 4]>); impl U32beDecoder { /// Makes a new `U32beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 4]) -> u32 { BigEndian::read_u32(&b) } } impl_decode!(U32beDecoder, u32); /// Decoder which decodes `u32` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U32leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U32leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04].as_ref()).unwrap(); /// assert_eq!(item, 0x0403_0201u32); /// ``` #[derive(Debug, Default)] pub struct U32leDecoder(CopyableBytesDecoder<[u8; 4]>); impl U32leDecoder { /// Makes a new `U32leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 4]) -> u32 { LittleEndian::read_u32(&b) } } impl_decode!(U32leDecoder, u32); /// Encoder which encodes `u32` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U32beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U32beEncoder::with_item(0x0102_0304).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x01, 0x02, 0x03, 0x04]); /// ``` #[derive(Debug, Default)] pub struct U32beEncoder(BytesEncoder<[u8; 4]>); impl U32beEncoder { /// Makes a new `U32beEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: u32, b: &mut [u8; 4]) -> Result<()> { BigEndian::write_u32(b, n); Ok(()) } } impl_encode!(U32beEncoder, u32); /// Encoder which encodes `u32` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U32leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U32leEncoder::with_item(0x0102_0304).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x04, 0x03, 0x02, 0x01]); /// ``` #[derive(Debug, Default)] pub struct U32leEncoder(BytesEncoder<[u8; 4]>); impl U32leEncoder { /// Makes a new `U32leEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: u32, b: &mut [u8; 4]) -> Result<()> { LittleEndian::write_u32(b, n); Ok(()) } } impl_encode!(U32leEncoder, u32); /// Decoder which decodes `i32` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::I32beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = I32beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04].as_ref()).unwrap(); /// assert_eq!(item, 0x0102_0304i32); /// ``` #[derive(Debug, Default)] pub struct I32beDecoder(CopyableBytesDecoder<[u8; 4]>); impl I32beDecoder { /// Makes a new `I32beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 4]) -> i32 { BigEndian::read_i32(&b) } } impl_decode!(I32beDecoder, i32); /// Decoder which decodes `i32` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::I32leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = I32leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04].as_ref()).unwrap(); /// assert_eq!(item, 0x0403_0201i32); /// ``` #[derive(Debug, Default)] pub struct I32leDecoder(CopyableBytesDecoder<[u8; 4]>); impl I32leDecoder { /// Makes a new `I32leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 4]) -> i32 { LittleEndian::read_i32(&b) } } impl_decode!(I32leDecoder, i32); /// Encoder which encodes `i32` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::I32beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = I32beEncoder::with_item(-2).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0xFF, 0xFF, 0xFF, 0xFE]); /// ``` #[derive(Debug, Default)] pub struct I32beEncoder(BytesEncoder<[u8; 4]>); impl I32beEncoder { /// Makes a new `I32beEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: i32, b: &mut [u8; 4]) -> Result<()> { BigEndian::write_i32(b, n); Ok(()) } } impl_encode!(I32beEncoder, i32); /// Encoder which encodes `i32` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::I32leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = I32leEncoder::with_item(-2).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0xFE, 0xFF, 0xFF, 0xFF]); /// ``` #[derive(Debug, Default)] pub struct I32leEncoder(BytesEncoder<[u8; 4]>); impl I32leEncoder { /// Makes a new `I32leEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: i32, b: &mut [u8; 4]) -> Result<()> { LittleEndian::write_i32(b, n); Ok(()) } } impl_encode!(I32leEncoder, i32); /// Decoder which decodes unsigned 40-bit integers by big-endian byte order. /// /// The type of decoded values is `u64`, but the most significant 24-bits always be `0`. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U40beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U40beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05].as_ref()).unwrap(); /// assert_eq!(item, 0x0000_0001_0203_0405u64); /// ``` #[derive(Debug, Default)] pub struct U40beDecoder(CopyableBytesDecoder<[u8; 5]>); impl U40beDecoder { /// Makes a new `U40beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 5]) -> u64 { BigEndian::read_uint(&b, b.len()) } } impl_decode!(U40beDecoder, u64); /// Decoder which decodes unsigned 40-bit integers by little-endian byte order. /// /// The type of decoded values is `u64`, but the most significant 24-bits always be `0`. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U40leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U40leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05].as_ref()).unwrap(); /// assert_eq!(item, 0x0000_0005_0403_0201u64); /// ``` #[derive(Debug, Default)] pub struct U40leDecoder(CopyableBytesDecoder<[u8; 5]>); impl U40leDecoder { /// Makes a new `U40leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 5]) -> u64 { LittleEndian::read_uint(&b, b.len()) } } impl_decode!(U40leDecoder, u64); /// Encoder which encodes unsigned 40-bit integers by big-endian byte order. /// /// Although the type of items is `u64`, the most significant 24-bits must be `0`. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U40beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U40beEncoder::with_item(0x0000_0001_0203_0405).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x01, 0x02, 0x03, 0x04, 0x05]); /// ``` #[derive(Debug, Default)] pub struct U40beEncoder(BytesEncoder<[u8; 5]>); impl U40beEncoder { /// Makes a new `U40beEncoder` instance. pub fn new() -> Self { Self::default() } fn encode_item(n: u64, b: &mut [u8; 5]) -> Result<()> { track_assert!(n <= 0xFF_FFFF_FFFF, ErrorKind::InvalidInput); let len = b.len(); BigEndian::write_uint(b, n, len); Ok(()) } } impl_encode!(U40beEncoder, u64); /// Encoder which encodes unsigned 40-bit integers by little-endian byte order. /// /// Although the type of items is `u64`, the most significant 24-bits must be `0`. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U40leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U40leEncoder::with_item(0x0000_0001_0203_0405).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x05, 0x04, 0x03, 0x02, 0x01]); /// ``` #[derive(Debug, Default)] pub struct U40leEncoder(BytesEncoder<[u8; 5]>); impl U40leEncoder { /// Makes a new `U40leEncoder` instance. pub fn new() -> Self { Self::default() } fn encode_item(n: u64, b: &mut [u8; 5]) -> Result<()> { track_assert!(n <= 0xFF_FFFF_FFFF, ErrorKind::InvalidInput); let len = b.len(); LittleEndian::write_uint(b, n, len); Ok(()) } } impl_encode!(U40leEncoder, u64); /// Decoder which decodes unsigned 48-bit integers by big-endian byte order. /// /// The type of decoded values is `u64`, but the most significant 16-bits always be `0`. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U48beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U48beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05, 0x06].as_ref()).unwrap(); /// assert_eq!(item, 0x0000_0102_0304_0506u64); /// ``` #[derive(Debug, Default)] pub struct U48beDecoder(CopyableBytesDecoder<[u8; 6]>); impl U48beDecoder { /// Makes a new `U48beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 6]) -> u64 { BigEndian::read_uint(&b, b.len()) } } impl_decode!(U48beDecoder, u64); /// Decoder which decodes unsigned 48-bit integers by little-endian byte order. /// /// The type of decoded values is `u64`, but the most significant 16-bits always be `0`. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U48leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U48leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05, 0x06].as_ref()).unwrap(); /// assert_eq!(item, 0x0000_0605_0403_0201u64); /// ``` #[derive(Debug, Default)] pub struct U48leDecoder(CopyableBytesDecoder<[u8; 6]>); impl U48leDecoder { /// Makes a new `U48leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 6]) -> u64 { LittleEndian::read_uint(&b, b.len()) } } impl_decode!(U48leDecoder, u64); /// Encoder which encodes unsigned 48-bit integers by big-endian byte order. /// /// Although the type of items is `u64`, the most significant 16-bits must be `0`. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U48beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U48beEncoder::with_item(0x0000_0102_0304_0506).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); /// ``` #[derive(Debug, Default)] pub struct U48beEncoder(BytesEncoder<[u8; 6]>); impl U48beEncoder { /// Makes a new `U48beEncoder` integers. pub fn new() -> Self { Self::default() } fn encode_item(n: u64, b: &mut [u8; 6]) -> Result<()> { track_assert!(n <= 0xFFFF_FFFF_FFFF, ErrorKind::InvalidInput); let len = b.len(); BigEndian::write_uint(b, n, len); Ok(()) } } impl_encode!(U48beEncoder, u64); /// Encoder which encodes unsigned 48-bit integers by little-endian byte order. /// /// Although the type of items is `u64`, the most significant 16-bits must be `0`. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U48leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U48leEncoder::with_item(0x0000_0102_0304_0506).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x06, 0x05, 0x04, 0x03, 0x02, 0x01]); /// ``` #[derive(Debug, Default)] pub struct U48leEncoder(BytesEncoder<[u8; 6]>); impl U48leEncoder { /// Makes a new `U48leEncoder` instance. pub fn new() -> Self { Self::default() } fn encode_item(n: u64, b: &mut [u8; 6]) -> Result<()> { track_assert!(n <= 0xFFFF_FFFF_FFFF, ErrorKind::InvalidInput); let len = b.len(); LittleEndian::write_uint(b, n, len); Ok(()) } } impl_encode!(U48leEncoder, u64); /// Decoder which decodes unsigned 56-bit integers by big-endian byte order. /// /// The type of decoded values is `u64`, but the most significant 8-bits always be `0`. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U56beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U56beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07].as_ref()).unwrap(); /// assert_eq!(item, 0x0001_0203_0405_0607u64); /// ``` #[derive(Debug, Default)] pub struct U56beDecoder(CopyableBytesDecoder<[u8; 7]>); impl U56beDecoder { /// Makes a new `U56beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 7]) -> u64 { BigEndian::read_uint(&b, b.len()) } } impl_decode!(U56beDecoder, u64); /// Decoder which decodes unsigned 56-bit integers by little-endian byte order. /// /// The type of decoded values is `u64`, but the most significant 8-bits always be `0`. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U56leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U56leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07].as_ref()).unwrap(); /// assert_eq!(item, 0x0007_0605_0403_0201u64); /// ``` #[derive(Debug, Default)] pub struct U56leDecoder(CopyableBytesDecoder<[u8; 7]>); impl U56leDecoder { /// Makes a new `U56leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 7]) -> u64 { LittleEndian::read_uint(&b, b.len()) } } impl_decode!(U56leDecoder, u64); /// Encoder which encodes unsigned 56-bit integers by big-endian byte order. /// /// Although the type of items is `u64`, the most significant 8-bits must be `0`. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U56beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U56beEncoder::with_item(0x0001_0203_0405_0607).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]); /// ``` #[derive(Debug, Default)] pub struct U56beEncoder(BytesEncoder<[u8; 7]>); impl U56beEncoder { /// Makes a new `U56beEncoder` instance. pub fn new() -> Self { Self::default() } fn encode_item(n: u64, b: &mut [u8; 7]) -> Result<()> { track_assert!(n <= 0xFF_FFFF_FFFF_FFFF, ErrorKind::InvalidInput); let len = b.len(); BigEndian::write_uint(b, n, len); Ok(()) } } impl_encode!(U56beEncoder, u64); /// Encoder which encodes unsigned 56-bit integers by little-endian byte order. /// /// Although the type of items is `u64`, the most significant 8-bits must be `0`. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U56leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U56leEncoder::with_item(0x0001_0203_0405_0607).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]); /// ``` #[derive(Debug, Default)] pub struct U56leEncoder(BytesEncoder<[u8; 7]>); impl U56leEncoder { /// Makes a new `U56leEncoder` instance. pub fn new() -> Self { Self::default() } fn encode_item(n: u64, b: &mut [u8; 7]) -> Result<()> { track_assert!(n <= 0xFF_FFFF_FFFF_FFFF, ErrorKind::InvalidInput); let len = b.len(); LittleEndian::write_uint(b, n, len); Ok(()) } } impl_encode!(U56leEncoder, u64); /// Decoder which decodes `u64` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U64beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U64beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08].as_ref()).unwrap(); /// assert_eq!(item, 0x0102_0304_0506_0708u64); /// ``` #[derive(Debug, Default)] pub struct U64beDecoder(CopyableBytesDecoder<[u8; 8]>); impl U64beDecoder { /// Makes a new `U64beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 8]) -> u64 { BigEndian::read_u64(&b) } } impl_decode!(U64beDecoder, u64); /// Decoder which decodes `u64` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::U64leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = U64leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08].as_ref()).unwrap(); /// assert_eq!(item, 0x0807_0605_0403_0201u64); /// ``` #[derive(Debug, Default)] pub struct U64leDecoder(CopyableBytesDecoder<[u8; 8]>); impl U64leDecoder { /// Makes a new `U64leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 8]) -> u64 { LittleEndian::read_u64(&b) } } impl_decode!(U64leDecoder, u64); /// Encoder which encodes `u64` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U64beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U64beEncoder::with_item(0x0102_0304_0506_0708).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]); /// ``` #[derive(Debug, Default)] pub struct U64beEncoder(BytesEncoder<[u8; 8]>); impl U64beEncoder { /// Makes a new `U64beEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: u64, b: &mut [u8; 8]) -> Result<()> { BigEndian::write_u64(b, n); Ok(()) } } impl_encode!(U64beEncoder, u64); /// Encoder which encodes `u64` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::U64leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = U64leEncoder::with_item(0x0102_0304_0506_0708).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]); /// ``` #[derive(Debug, Default)] pub struct U64leEncoder(BytesEncoder<[u8; 8]>); impl U64leEncoder { /// Makes a new `U64leEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: u64, b: &mut [u8; 8]) -> Result<()> { LittleEndian::write_u64(b, n); Ok(()) } } impl_encode!(U64leEncoder, u64); /// Decoder which decodes `i64` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::I64beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = I64beDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08].as_ref()).unwrap(); /// assert_eq!(item, 0x0102_0304_0506_0708i64); /// ``` #[derive(Debug, Default)] pub struct I64beDecoder(CopyableBytesDecoder<[u8; 8]>); impl I64beDecoder { /// Makes a new `I64beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 8]) -> i64 { BigEndian::read_i64(&b) } } impl_decode!(I64beDecoder, i64); /// Decoder which decodes `i64` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::I64leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = I64leDecoder::new(); /// let item = decoder.decode_exact([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08].as_ref()).unwrap(); /// assert_eq!(item, 0x0807_0605_0403_0201i64); /// ``` #[derive(Debug, Default)] pub struct I64leDecoder(CopyableBytesDecoder<[u8; 8]>); impl I64leDecoder { /// Makes a new `I64leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 8]) -> i64 { LittleEndian::read_i64(&b) } } impl_decode!(I64leDecoder, i64); /// Encoder which encodes `i64` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::I64beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = I64beEncoder::with_item(-2).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE]); /// ``` #[derive(Debug, Default)] pub struct I64beEncoder(BytesEncoder<[u8; 8]>); impl I64beEncoder { /// Makes a new `I64beEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: i64, b: &mut [u8; 8]) -> Result<()> { BigEndian::write_i64(b, n); Ok(()) } } impl_encode!(I64beEncoder, i64); /// Encoder which encodes `i64` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::I64leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = I64leEncoder::with_item(-2).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]); /// ``` #[derive(Debug, Default)] pub struct I64leEncoder(BytesEncoder<[u8; 8]>); impl I64leEncoder { /// Makes a new `I64leEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: i64, b: &mut [u8; 8]) -> Result<()> { LittleEndian::write_i64(b, n); Ok(()) } } impl_encode!(I64leEncoder, i64); /// Decoder which decodes `f32` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::F32beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = F32beDecoder::new(); /// let item = decoder.decode_exact([66, 246, 204, 205].as_ref()).unwrap(); /// assert_eq!(item, 123.4); /// ``` #[derive(Debug, Default)] pub struct F32beDecoder(CopyableBytesDecoder<[u8; 4]>); impl F32beDecoder { /// Makes a new `F32beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 4]) -> f32 { BigEndian::read_f32(&b) } } impl_decode!(F32beDecoder, f32); /// Decoder which decodes `f32` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::F32leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = F32leDecoder::new(); /// let item = decoder.decode_exact([205, 204, 246, 66].as_ref()).unwrap(); /// assert_eq!(item, 123.4); /// ``` #[derive(Debug, Default)] pub struct F32leDecoder(CopyableBytesDecoder<[u8; 4]>); impl F32leDecoder { /// Makes a new `F32leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 4]) -> f32 { LittleEndian::read_f32(&b) } } impl_decode!(F32leDecoder, f32); /// Encoder which encodes `f32` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::F32beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = F32beEncoder::with_item(123.4).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [66, 246, 204, 205]); /// ``` #[derive(Debug, Default)] pub struct F32beEncoder(BytesEncoder<[u8; 4]>); impl F32beEncoder { /// Makes a new `F32beEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: f32, b: &mut [u8; 4]) -> Result<()> { BigEndian::write_f32(b, n); Ok(()) } } impl_encode!(F32beEncoder, f32); /// Encoder which encodes `f32` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::F32leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = F32leEncoder::with_item(123.4).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [205, 204, 246, 66]); /// ``` #[derive(Debug, Default)] pub struct F32leEncoder(BytesEncoder<[u8; 4]>); impl F32leEncoder { /// Makes a new `F32leEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: f32, b: &mut [u8; 4]) -> Result<()> { LittleEndian::write_f32(b, n); Ok(()) } } impl_encode!(F32leEncoder, f32); /// Decoder which decodes `f64` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::F64beDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = F64beDecoder::new(); /// let item = decoder.decode_exact([64, 94, 221, 47, 26, 159, 190, 119].as_ref()).unwrap(); /// assert_eq!(item, 123.456); /// ``` #[derive(Debug, Default)] pub struct F64beDecoder(CopyableBytesDecoder<[u8; 8]>); impl F64beDecoder { /// Makes a new `F64beDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 8]) -> f64 { BigEndian::read_f64(&b) } } impl_decode!(F64beDecoder, f64); /// Decoder which decodes `f64` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::Decode; /// use bytecodec::fixnum::F64leDecoder; /// use bytecodec::io::IoDecodeExt; /// /// let mut decoder = F64leDecoder::new(); /// let item = decoder.decode_exact([119, 190, 159, 26, 47, 221, 94, 64].as_ref()).unwrap(); /// assert_eq!(item, 123.456); /// ``` #[derive(Debug, Default)] pub struct F64leDecoder(CopyableBytesDecoder<[u8; 8]>); impl F64leDecoder { /// Makes a new `F64leDecoder` instance. pub fn new() -> Self { Self::default() } fn decode_item(b: [u8; 8]) -> f64 { LittleEndian::read_f64(&b) } } impl_decode!(F64leDecoder, f64); /// Encoder which encodes `f64` values by big-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::F64beEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = F64beEncoder::with_item(123.456).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [64, 94, 221, 47, 26, 159, 190, 119]); /// ``` #[derive(Debug, Default)] pub struct F64beEncoder(BytesEncoder<[u8; 8]>); impl F64beEncoder { /// Makes a new `F64beEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: f64, b: &mut [u8; 8]) -> Result<()> { BigEndian::write_f64(b, n); Ok(()) } } impl_encode!(F64beEncoder, f64); /// Encoder which encodes `f64` values by little-endian byte order. /// /// # Examples /// /// ``` /// use bytecodec::EncodeExt; /// use bytecodec::fixnum::F64leEncoder; /// use bytecodec::io::IoEncodeExt; /// /// let mut output = Vec::new(); /// let mut encoder = F64leEncoder::with_item(123.456).unwrap(); /// encoder.encode_all(&mut output).unwrap(); /// assert_eq!(output, [119, 190, 159, 26, 47, 221, 94, 64]); /// ``` #[derive(Debug, Default)] pub struct F64leEncoder(BytesEncoder<[u8; 8]>); impl F64leEncoder { /// Makes a new `F64leEncoder` instance. pub fn new() -> Self { Self::default() } #[allow(clippy::unnecessary_wraps)] fn encode_item(n: f64, b: &mut [u8; 8]) -> Result<()> { LittleEndian::write_f64(b, n); Ok(()) } } impl_encode!(F64leEncoder, f64); #[cfg(test)] mod test { use super::*; use crate::io::{IoDecodeExt, IoEncodeExt}; use crate::Encode; macro_rules! assert_encode_decode { ($encoder:ident, $decoder:ident, $item:expr, $bytes:expr) => { let mut output = Vec::new(); let mut encoder = $encoder::new(); track_try_unwrap!(encoder.start_encoding($item)); track_try_unwrap!(encoder.encode_all(&mut output)); assert_eq!(output, $bytes); let mut decoder = $decoder::new(); let item = track_try_unwrap!(decoder.decode_exact(&$bytes[..])); assert_eq!(item, $item); }; } #[test] fn fixnum_works() { assert_encode_decode!(U8Encoder, U8Decoder, 7, [7]); assert_encode_decode!(I8Encoder, I8Decoder, -1, [255]); assert_encode_decode!(U16beEncoder, U16beDecoder, 0x0102, [0x01, 0x02]); assert_encode_decode!(U16leEncoder, U16leDecoder, 0x0102, [0x02, 0x01]); assert_encode_decode!(I16beEncoder, I16beDecoder, -2, [0xFF, 0xFE]); assert_encode_decode!(I16leEncoder, I16leDecoder, -2, [0xFE, 0xFF]); assert_encode_decode!(U24beEncoder, U24beDecoder, 0x01_0203, [0x01, 0x02, 0x03]); assert_encode_decode!(U24leEncoder, U24leDecoder, 0x01_0203, [0x03, 0x02, 0x01]); assert_encode_decode!( U32beEncoder, U32beDecoder, 0x0102_0304, [0x01, 0x02, 0x03, 0x04] ); assert_encode_decode!( U32leEncoder, U32leDecoder, 0x0102_0304, [0x04, 0x03, 0x02, 0x01] ); assert_encode_decode!(I32beEncoder, I32beDecoder, -2, [0xFF, 0xFF, 0xFF, 0xFE]); assert_encode_decode!(I32leEncoder, I32leDecoder, -2, [0xFE, 0xFF, 0xFF, 0xFF]); assert_encode_decode!( U40beEncoder, U40beDecoder, 0x01_0203_0405, [0x01, 0x02, 0x03, 0x04, 0x05] ); assert_encode_decode!( U40leEncoder, U40leDecoder, 0x01_0203_0405, [0x05, 0x04, 0x03, 0x02, 0x01] ); assert_encode_decode!( U48beEncoder, U48beDecoder, 0x0102_0304_0506, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06] ); assert_encode_decode!( U48leEncoder, U48leDecoder, 0x0102_0304_0506, [0x06, 0x05, 0x04, 0x03, 0x02, 0x01] ); assert_encode_decode!( U56beEncoder, U56beDecoder, 0x01_0203_0405_0607, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07] ); assert_encode_decode!( U56leEncoder, U56leDecoder, 0x01_0203_0405_0607, [0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01] ); assert_encode_decode!( U64beEncoder, U64beDecoder, 0x0102_0304_0506_0708, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] ); assert_encode_decode!( U64leEncoder, U64leDecoder, 0x0102_0304_0506_0708, [0x08, 0x7, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01] ); assert_encode_decode!( I64beEncoder, I64beDecoder, -2, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE] ); assert_encode_decode!( I64leEncoder, I64leDecoder, -2, [0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] ); assert_encode_decode!(F32beEncoder, F32beDecoder, -123.4, [194, 246, 204, 205]); assert_encode_decode!(F32leEncoder, F32leDecoder, -123.4, [205, 204, 246, 194]); assert_encode_decode!( F64beEncoder, F64beDecoder, -123.456, [192, 94, 221, 47, 26, 159, 190, 119] ); assert_encode_decode!( F64leEncoder, F64leDecoder, -123.456, [119, 190, 159, 26, 47, 221, 94, 192] ); } } bytecodec-0.4.15/src/io.rs000064400000000000000000000403650000000000000134050ustar 00000000000000//! I/O (i.e., `Read` and `Write` traits) related module. use crate::{ByteCount, Decode, Encode, Eos, Error, ErrorKind, Result}; #[cfg(feature = "tokio-async")] use pin_project::pin_project; use std::cmp; use std::io::{self, Read, Write}; /// An extension of `Decode` trait to aid decodings involving I/O. pub trait IoDecodeExt: Decode { /// Consumes bytes from the given read buffer and proceeds the decoding process. fn decode_from_read_buf(&mut self, buf: &mut ReadBuf) -> Result<()> where B: AsRef<[u8]>, { let eos = Eos::new(buf.stream_state.is_eos()); let size = track!(self.decode(&buf.inner.as_ref()[buf.head..buf.tail], eos))?; buf.head += size; if buf.head == buf.tail { buf.head = 0; buf.tail = 0; } Ok(()) } /// Decodes an item from the given reader. /// /// This method reads only minimal bytes required to decode an item. /// /// Note that this is a blocking method. fn decode_exact(&mut self, mut reader: R) -> Result { let mut buf = [0; 1024]; loop { let mut size = match self.requiring_bytes() { ByteCount::Finite(n) => cmp::min(n, buf.len() as u64) as usize, ByteCount::Infinite => buf.len(), ByteCount::Unknown => 1, }; let eos = if size != 0 { size = track!(reader.read(&mut buf[..size]).map_err(Error::from))?; Eos::new(size == 0) } else { Eos::new(false) }; let consumed = track!(self.decode(&buf[..size], eos))?; track_assert_eq!(consumed, size, ErrorKind::InconsistentState; self.is_idle(), eos); if self.is_idle() { let item = track!(self.finish_decoding())?; return Ok(item); } } } } impl IoDecodeExt for T {} /// An extension of `Encode` trait to aid encodings involving I/O. pub trait IoEncodeExt: Encode { /// Encodes the items remaining in the encoder and /// writes the encoded bytes to the given write buffer. fn encode_to_write_buf(&mut self, buf: &mut WriteBuf) -> Result<()> where B: AsMut<[u8]>, { let eos = Eos::new(buf.stream_state.is_eos()); let size = track!(self.encode(&mut buf.inner.as_mut()[buf.tail..], eos))?; buf.tail += size; Ok(()) } /// Encodes the items remaining in the encoder and /// writes the encoded bytes to the given write buffer. /// If the write buffer is full and the writing cannot be performed, /// the given WriteBuf will memorize cx's `Waker`. /// This `Waker`'s `wake` will later be called when the `WriteBuf` regains its free space. #[cfg(feature = "tokio-async")] fn encode_to_write_buf_async( &mut self, buf: &mut WriteBuf, cx: &mut std::task::Context, ) -> Result<()> where B: AsMut<[u8]>, { let eos = Eos::new(buf.stream_state.is_eos()); let size = track!(self.encode(&mut buf.inner.as_mut()[buf.tail..], eos))?; buf.tail += size; buf.waker = Some(cx.waker().clone()); Ok(()) } /// Encodes all of the items remaining in the encoder and /// writes the encoded bytes to the given writer. /// /// Note that this is a blocking method. fn encode_all(&mut self, mut writer: W) -> Result<()> { let mut buf = [0; 1024]; while !self.is_idle() { let size = track!(self.encode(&mut buf[..], Eos::new(false)))?; track!(writer.write_all(&buf[..size]).map_err(Error::from))?; if !self.is_idle() { track_assert_ne!(size, 0, ErrorKind::Other); } } Ok(()) } } impl IoEncodeExt for T {} /// State of I/O streams. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum StreamState { Normal, Eos, WouldBlock, Error, } impl StreamState { /// Returns `true` if the state is `Normal`, otherwise `false`. pub fn is_normal(self) -> bool { self == StreamState::Normal } /// Returns `true` if the state is `Error`, otherwise `false`. pub fn is_error(self) -> bool { self == StreamState::Error } /// Returns `true` if the state is `Eos`, otherwise `false`. pub fn is_eos(self) -> bool { self == StreamState::Eos } /// Returns `true` if the state is `WouldBlock`, otherwise `false`. pub fn would_block(self) -> bool { self == StreamState::WouldBlock } } /// Read buffer. #[derive(Debug)] pub struct ReadBuf { pub(crate) inner: B, pub(crate) head: usize, pub(crate) tail: usize, pub(crate) stream_state: StreamState, } impl + AsMut<[u8]>> ReadBuf { /// Makes a new `ReadBuf` instance. pub fn new(inner: B) -> Self { ReadBuf { inner, head: 0, tail: 0, stream_state: StreamState::Normal, } } /// Returns the number of filled bytes in the buffer. pub fn len(&self) -> usize { self.tail - self.head } /// Returns the free space of the buffer. /// /// Invariant: `self.len() + self.room() <= self.capacity()` pub fn room(&self) -> usize { self.inner.as_ref().len() - self.tail } /// Returns the capacity of the buffer. pub fn capacity(&self) -> usize { self.inner.as_ref().len() } /// Returns `true` if the buffer is empty, otherwise `false`. pub fn is_empty(&self) -> bool { self.tail == 0 } /// Returns `true` if the buffer is full, otherwise `false`. pub fn is_full(&self) -> bool { self.tail == self.inner.as_ref().len() } /// Returns the state of the stream that operated in the last `fill()` call. pub fn stream_state(&self) -> StreamState { self.stream_state } /// Returns a mutable reference to the `StreamState` instance. pub fn stream_state_mut(&mut self) -> &mut StreamState { &mut self.stream_state } /// Fills the read buffer by reading bytes from the given reader. /// /// The fill process continues until one of the following condition is satisfied: /// - The read buffer became full /// - A read operation returned a `WouldBlock` error /// - The input stream has reached EOS pub fn fill(&mut self, mut reader: R) -> Result<()> { while !self.is_full() { match reader.read(&mut self.inner.as_mut()[self.tail..]) { Err(e) => { if e.kind() == io::ErrorKind::WouldBlock { self.stream_state = StreamState::WouldBlock; break; } else { self.stream_state = StreamState::Error; return Err(track!(Error::from(e))); } } Ok(0) => { self.stream_state = StreamState::Eos; break; } Ok(size) => { self.stream_state = StreamState::Normal; self.tail += size; } } } Ok(()) } /// Returns a reference to the inner bytes of the buffer. pub fn inner_ref(&self) -> &B { &self.inner } /// Returns a mutable reference to the inner bytes of the buffer. pub fn inner_mut(&mut self) -> &mut B { &mut self.inner } /// Takes ownership of `ReadBuf` and returns the inner bytes of the buffer. pub fn into_inner(self) -> B { self.inner } } impl + AsMut<[u8]>> Read for ReadBuf { fn read(&mut self, buf: &mut [u8]) -> io::Result { let size = cmp::min(buf.len(), self.len()); (&mut buf[..size]).copy_from_slice(&self.inner.as_ref()[self.head..][..size]); self.head += size; if self.head == self.tail { self.head = 0; self.tail = 0; } Ok(size) } } /// Write buffer. #[derive(Debug)] pub struct WriteBuf { pub(crate) inner: B, pub(crate) head: usize, pub(crate) tail: usize, pub(crate) stream_state: StreamState, #[cfg(feature = "tokio-async")] pub(crate) waker: Option, } impl + AsMut<[u8]>> WriteBuf { /// Makes a new `WriteBuf` instance. pub fn new(inner: B) -> Self { WriteBuf { inner, head: 0, tail: 0, stream_state: StreamState::Normal, #[cfg(feature = "tokio-async")] waker: None, } } /// Returns the number of encoded bytes in the buffer. pub fn len(&self) -> usize { self.tail - self.head } /// Returns the free space of the buffer. /// /// Invariant: `self.len() + self.room() <= self.capacity()` pub fn room(&self) -> usize { self.inner.as_ref().len() - self.tail } /// Returns the capacity of the buffer. pub fn capacity(&self) -> usize { self.inner.as_ref().len() } /// Returns `true` if the buffer is empty, otherwise `false`. pub fn is_empty(&self) -> bool { self.tail == 0 } /// Returns `true` if the buffer is full, otherwise `false`. pub fn is_full(&self) -> bool { self.tail == self.inner.as_ref().len() } /// Returns the state of the stream that operated in the last `flush()` call. pub fn stream_state(&self) -> StreamState { self.stream_state } /// Returns a mutable reference to the `StreamState` instance. pub fn stream_state_mut(&mut self) -> &mut StreamState { &mut self.stream_state } /// Writes the encoded bytes contained in this buffer to the given writer. /// /// The written bytes will be removed from the buffer. /// /// The flush process continues until one of the following condition is satisfied: /// - The write buffer became empty /// - A write operation returned a `WouldBlock` error /// - The output stream has reached EOS pub fn flush(&mut self, mut writer: W) -> Result<()> { while !self.is_empty() { match writer.write(&self.inner.as_ref()[self.head..self.tail]) { Err(e) => { if e.kind() == io::ErrorKind::WouldBlock { self.stream_state = StreamState::WouldBlock; break; } else { self.stream_state = StreamState::Error; return Err(track!(Error::from(e))); } } Ok(0) => { self.stream_state = StreamState::Eos; break; } Ok(size) => { self.stream_state = StreamState::Normal; self.head += size; if self.head == self.tail { self.head = 0; self.tail = 0; } } } } #[cfg(feature = "tokio-async")] if !self.is_full() { if let Some(ref waker) = self.waker { waker.wake_by_ref(); } } Ok(()) } /// Returns a reference to the inner bytes of the buffer. pub fn inner_ref(&self) -> &B { &self.inner } /// Returns a mutable reference to the inner bytes of the buffer. pub fn inner_mut(&mut self) -> &mut B { &mut self.inner } /// Takes ownership of `ReadBuf` and returns the inner bytes of the buffer. pub fn into_inner(self) -> B { self.inner } } impl + AsMut<[u8]>> Write for WriteBuf { fn write(&mut self, buf: &[u8]) -> io::Result { let size = cmp::min(buf.len(), self.room()); (&mut self.inner.as_mut()[self.tail..][..size]).copy_from_slice(&buf[..size]); self.tail += size; Ok(size) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } /// Buffered I/O stream. #[cfg_attr(feature = "tokio-async", pin_project)] #[derive(Debug)] pub struct BufferedIo { #[cfg_attr(feature = "tokio-async", pin)] pub(crate) stream: T, pub(crate) rbuf: ReadBuf>, pub(crate) wbuf: WriteBuf>, } impl BufferedIo { /// Executes an I/O operation on the inner stream. /// /// "I/O operation" means "filling the read buffer" and "flushing the write buffer". pub fn execute_io(&mut self) -> Result<()> { track!(self.rbuf.fill(&mut self.stream))?; track!(self.wbuf.flush(&mut self.stream))?; Ok(()) } } impl BufferedIo { /// Makes a new `BufferedIo` instance. pub fn new(stream: T, read_buf_size: usize, write_buf_size: usize) -> Self { BufferedIo { stream, rbuf: ReadBuf::new(vec![0; read_buf_size]), wbuf: WriteBuf::new(vec![0; write_buf_size]), } } /// Returns `true` if the inner stream reaches EOS, otherwise `false`. pub fn is_eos(&self) -> bool { self.rbuf.stream_state().is_eos() || self.wbuf.stream_state().is_eos() } /// Returns `true` if the previous I/O operation on the inner stream would block, otherwise `false`. pub fn would_block(&self) -> bool { self.rbuf.stream_state().would_block() && (self.wbuf.is_empty() || self.wbuf.stream_state().would_block()) } /// Returns a reference to the read buffer of the instance. pub fn read_buf_ref(&self) -> &ReadBuf> { &self.rbuf } /// Returns a mutable reference to the read buffer of the instance. pub fn read_buf_mut(&mut self) -> &mut ReadBuf> { &mut self.rbuf } /// Returns a reference to the write buffer of the instance. pub fn write_buf_ref(&self) -> &WriteBuf> { &self.wbuf } /// Returns a mutable reference to the write buffer of the instance. pub fn write_buf_mut(&mut self) -> &mut WriteBuf> { &mut self.wbuf } /// Returns a reference to the inner stream of the instance. pub fn stream_ref(&self) -> &T { &self.stream } /// Returns a mutable reference to the inner stream of the instance. pub fn stream_mut(&mut self) -> &mut T { &mut self.stream } /// Takes ownership of the instance, and returns the inner stream. pub fn into_stream(self) -> T { self.stream } } #[cfg(test)] mod test { use super::*; use crate::bytes::{Utf8Decoder, Utf8Encoder}; use crate::EncodeExt; use std::io::{Read, Write}; #[test] fn decode_from_read_buf_works() { let mut buf = ReadBuf::new(vec![0; 1024]); track_try_unwrap!(buf.fill(b"foo".as_ref())); assert_eq!(buf.len(), 3); assert_eq!(buf.stream_state(), StreamState::Eos); let mut decoder = Utf8Decoder::new(); track_try_unwrap!(decoder.decode_from_read_buf(&mut buf)); assert_eq!(track_try_unwrap!(decoder.finish_decoding()), "foo"); } #[test] fn read_from_read_buf_works() { let mut rbuf = ReadBuf::new(vec![0; 1024]); track_try_unwrap!(rbuf.fill(b"foo".as_ref())); assert_eq!(rbuf.len(), 3); assert_eq!(rbuf.stream_state(), StreamState::Eos); let mut buf = Vec::new(); rbuf.read_to_end(&mut buf).unwrap(); assert_eq!(buf, b"foo"); assert_eq!(rbuf.len(), 0); } #[test] fn encode_to_write_buf_works() { let mut encoder = track_try_unwrap!(Utf8Encoder::with_item("foo")); let mut buf = WriteBuf::new(vec![0; 1024]); track_try_unwrap!(encoder.encode_to_write_buf(&mut buf)); assert_eq!(buf.len(), 3); let mut v = Vec::new(); track_try_unwrap!(buf.flush(&mut v)); assert_eq!(buf.len(), 0); assert_eq!(buf.stream_state(), StreamState::Normal); assert_eq!(v, b"foo"); } #[test] fn write_to_write_buf_works() { let mut buf = WriteBuf::new(vec![0; 1024]); buf.write_all(b"foo").unwrap(); assert_eq!(buf.len(), 3); let mut v = Vec::new(); track_try_unwrap!(buf.flush(&mut v)); assert_eq!(buf.len(), 0); assert_eq!(buf.stream_state(), StreamState::Normal); assert_eq!(v, b"foo"); } } bytecodec-0.4.15/src/io_async.rs000064400000000000000000000113320000000000000145720ustar 00000000000000//! I/O (i.e., `Read` and `Write` traits) related module. use crate::io::{BufferedIo, ReadBuf, StreamState, WriteBuf}; use crate::{Error, Result}; use core::pin::Pin; use core::task::{Context, Poll}; use tokio::io::{AsyncRead, AsyncWrite}; impl + AsMut<[u8]>> ReadBuf { /// Fills the read buffer by reading bytes from the given reader. /// /// The fill process continues until one of the following condition is satisfied: /// - The read buffer became full /// - A read operation returned a `WouldBlock` error /// - The input stream has reached EOS pub fn poll_fill( &mut self, mut reader: Pin<&mut R>, cx: &mut Context<'_>, ) -> Poll> { while !self.is_full() { let mut buffer = tokio::io::ReadBuf::new(&mut self.inner.as_mut()[self.tail..]); match reader.as_mut().poll_read(cx, &mut buffer) { Poll::Pending => { self.stream_state = StreamState::WouldBlock; return Poll::Pending; } Poll::Ready(Ok(())) => { let size = buffer.filled().len(); if size == 0 { self.stream_state = StreamState::Eos; return Poll::Ready(Ok(())); } self.stream_state = StreamState::Normal; self.tail += size; } Poll::Ready(Err(e)) => { self.stream_state = StreamState::Error; return Poll::Ready(Err(track!(Error::from(e)))); } } } Poll::Ready(Ok(())) } } impl + AsMut<[u8]>> WriteBuf { /// Writes the encoded bytes contained in this buffer to the given writer. /// /// The written bytes will be removed from the buffer. /// /// The flush process continues until one of the following condition is satisfied: /// - The write buffer became empty /// - A write operation returned a `WouldBlock` error /// - The output stream has reached EOS pub fn poll_flush( &mut self, mut writer: Pin<&mut W>, cx: &mut Context<'_>, ) -> Poll> { while !self.is_empty() { match writer .as_mut() .poll_write(cx, &self.inner.as_ref()[self.head..self.tail]) { Poll::Ready(Err(e)) => { self.stream_state = StreamState::Error; return Poll::Ready(Err(track!(Error::from(e)))); } Poll::Ready(Ok(0)) => { self.stream_state = StreamState::Eos; // stream is closed. No need to wake up this future :) return Poll::Ready(Ok(())); } Poll::Ready(Ok(size)) => { self.stream_state = StreamState::Normal; self.head += size; if self.head == self.tail { self.head = 0; self.tail = 0; } } Poll::Pending => { self.stream_state = StreamState::WouldBlock; return Poll::Pending; } } } // Now the buffer is empty. Because the returned value is not Poll::Pending, // it is *the caller*'s responsibility to ensure this future is woken up. Poll::Ready(Ok(())) } } impl BufferedIo { /// Executes an I/O operation on the inner stream. /// /// "I/O operation" means "filling the read buffer" and "flushing the write buffer". /// This function returns Poll::Pending when both rbuf and wbuf are not ready for I/O operations. pub fn execute_io_poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut this = self.project(); let rresult = this.rbuf.poll_fill(this.stream.as_mut(), cx); let wresult = this.wbuf.poll_flush(this.stream.as_mut(), cx); if let (&Poll::Pending, &Poll::Pending) = (&rresult, &wresult) { // This future will be polled again when either rbuf or wbuf is ready. return Poll::Pending; } if let Poll::Ready(rresult) = rresult { track!(rresult)?; } if let Poll::Ready(wresult) = wresult { track!(wresult)?; } // If at least one of rbuf or wbuf returns Poll::Ready, // there's no guarantee that the waker is signaled at some point. // Poll::Ready here means it's the caller's responsibility to ensure the waker is signaled later. Poll::Ready(Ok(())) } } bytecodec-0.4.15/src/json_codec.rs000064400000000000000000000132210000000000000150730ustar 00000000000000//! `#[cfg(feature = "json_codec")]` JSON encoder and decoder that use [serde_json] internally. //! //! [serde_json]: https://crates.io/crates/serde_json use crate::monolithic::{MonolithicDecode, MonolithicDecoder, MonolithicEncode, MonolithicEncoder}; use crate::{ByteCount, Decode, Encode, Eos, ErrorKind, Result}; use serde::{Deserialize, Serialize}; use std::io::{Read, Write}; use std::marker::PhantomData; use trackable::error::ErrorKindExt; /// JSON decoder. /// /// Note that this decodes items monolithically /// so very large items may impair real-time property of the system. /// /// # Examples /// /// ``` /// use bytecodec::{Decode, Eos}; /// use bytecodec::json_codec::JsonDecoder; /// use serde_json::Value; /// /// let mut decoder = JsonDecoder::::new(); /// /// decoder.decode(b"[1, 2", Eos::new(false)).unwrap(); /// decoder.decode(b", 3]", Eos::new(true)).unwrap(); /// let json = decoder.finish_decoding().unwrap(); /// /// assert_eq!(json.to_string(), "[1,2,3]"); /// ``` #[derive(Debug)] pub struct JsonDecoder(MonolithicDecoder>) where T: for<'de> Deserialize<'de>; impl JsonDecoder where T: for<'de> Deserialize<'de>, { /// Makes a new `JsonDecoder` instance. pub fn new() -> Self { JsonDecoder(MonolithicDecoder::new(MonolithicJsonDecoder::new())) } } impl Decode for JsonDecoder where T: for<'de> Deserialize<'de>, { type Item = T; fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { track!(self.0.decode(buf, eos)) } fn finish_decoding(&mut self) -> Result { track!(self.0.finish_decoding()) } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } fn is_idle(&self) -> bool { self.0.is_idle() } } impl Default for JsonDecoder where T: for<'de> Deserialize<'de>, { fn default() -> Self { Self::new() } } #[derive(Debug)] struct MonolithicJsonDecoder(PhantomData); impl MonolithicJsonDecoder { fn new() -> Self { MonolithicJsonDecoder(PhantomData) } } impl MonolithicDecode for MonolithicJsonDecoder where T: for<'de> Deserialize<'de>, { type Item = T; fn monolithic_decode(&self, reader: R) -> Result { track!(serde_json::from_reader(reader).map_err(|e| ErrorKind::InvalidInput.cause(e).into())) } } /// JSON encoder. /// /// Note that this encodes items monolithically /// so very large items may impair real-time property of the system. #[derive(Debug)] pub struct JsonEncoder(MonolithicEncoder>); impl JsonEncoder where T: Serialize, { /// Makes a new `JsonEncoder` instance. pub fn new() -> Self { JsonEncoder(MonolithicEncoder::new(MonolithicJsonEncoder::new())) } } impl Encode for JsonEncoder where T: Serialize, { type Item = T; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { track!(self.0.encode(buf, eos)) } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track!(self.0.start_encoding(item)) } fn is_idle(&self) -> bool { self.0.is_idle() } fn requiring_bytes(&self) -> ByteCount { self.0.requiring_bytes() } } impl Default for JsonEncoder where T: Serialize, { fn default() -> Self { Self::new() } } #[derive(Debug)] struct MonolithicJsonEncoder(PhantomData); impl MonolithicJsonEncoder { fn new() -> Self { MonolithicJsonEncoder(PhantomData) } } impl MonolithicEncode for MonolithicJsonEncoder where T: Serialize, { type Item = T; fn monolithic_encode(&self, item: &Self::Item, writer: W) -> Result<()> { track!(serde_json::to_writer(writer, item) .map_err(|e| ErrorKind::InvalidInput.cause(e).into())) } } #[cfg(test)] mod test { use super::*; use crate::json_codec::JsonDecoder; use crate::{Decode, Encode, EncodeExt, Eos}; use serde::ser::{Serialize, SerializeStruct, Serializer}; use serde_json::Value; #[test] fn json_decoder_works() { let mut decoder = JsonDecoder::::new(); track_try_unwrap!(decoder.decode(b"[1, 2", Eos::new(false))); track_try_unwrap!(decoder.decode(b", 3]", Eos::new(true))); let json = track_try_unwrap!(decoder.finish_decoding()); assert_eq!(json.to_string(), "[1,2,3]"); } #[test] fn json_encoder_works() { let item = (1, 2, 3); let mut buf = [0; 7]; let mut encoder = JsonEncoder::with_item(item).unwrap(); assert_eq!(encoder.encode(&mut buf[..2], Eos::new(false)).unwrap(), 2); assert_eq!(encoder.encode(&mut buf[2..], Eos::new(true)).unwrap(), 5); assert_eq!(&buf, b"[1,2,3]"); } #[test] fn encode_to_json_string_using_serde_works() { #[derive(Debug)] struct Item { id: u64, name: String, } impl Serialize for Item { fn serialize(&self, serializer: S) -> std::result::Result where S: Serializer, { let mut state = serializer.serialize_struct("Item", 2)?; state.serialize_field("id", &self.id)?; state.serialize_field("name", &self.name)?; state.end() } } let item = Item { id: 4, name: "item4".to_owned(), }; let bytes = JsonEncoder::new().encode_into_bytes(item).unwrap(); assert_eq!( String::from_utf8(bytes).unwrap(), r#"{"id":4,"name":"item4"}"# ); } } bytecodec-0.4.15/src/lib.rs000064400000000000000000000050770000000000000135450ustar 00000000000000//! A tiny framework for implementing encoders/decoders of byte-oriented protocols. //! //! # Features //! //! - Suited for byte-oriented protocols //! - Incremental encoding/decoding: //! - `Encode` and `Decode` traits support incremental encoding and decoding //! - The number of bytes consumed in an execution of `encode/decode` methods //! can be completely controlled by the caller //! - This property makes it easy to implement, //! for example, multi-stream multiplexing, transmittin rate control and asynchronous I/O //! - Composable: //! - By combining multiple encoders (or decoders), //! it is easy to build a more complex encoder (or decoder) //! - See the examples of `EncodeExt` and `DecodeExt` traits //! - Reduced number of memory copies: //! - In design, only two memory copies are required //! - Considering in the decode process, //! one is the copy from the actual stream (e.g., TCP socket) to the decoding buffer, //! the other one is the copy to construct the item from the buffer. //! - Supports some [serde] implemention crates: //! - Currently [serde_json] and [bincode] are supported (as optional featuers) //! - See `json_codec` and `bincode_codec` modules //! - Easily adapt to synchronous I/O, asynchronous I/O, UDP, etc //! - Trackable errors: //! - By using [trackable] crate, the location where an error occurred can be easily specified //! - See `EncodeExt::map_err` and `DecodeExt::map_err` methods //! //! [bincode]: https://crates.io/crates/bincode //! [serde]: https://crates.io/crates/serde //! [serde_json]: https://crates.io/crates/serde_json //! [trackable]: https://crates.io/crates/trackable #![warn(missing_docs)] #[cfg(feature = "bincode_codec")] extern crate bincode; extern crate byteorder; #[cfg(feature = "serde")] extern crate serde; #[cfg(feature = "json_codec")] extern crate serde_json; #[macro_use] extern crate trackable; pub use byte_count::ByteCount; pub use decode::{Decode, DecodeExt, TaggedDecode, TryTaggedDecode}; pub use encode::{Encode, EncodeExt, SizedEncode}; pub use eos::Eos; pub use error::{Error, ErrorKind}; #[macro_use] mod macros; #[cfg(feature = "bincode_codec")] pub mod bincode_codec; pub mod bytes; pub mod combinator; pub mod fixnum; pub mod io; #[cfg(feature = "tokio-async")] pub mod io_async; #[cfg(feature = "json_codec")] pub mod json_codec; pub mod marker; pub mod monolithic; pub mod null; pub mod padding; pub mod slice; pub mod tuple; mod byte_count; mod decode; mod encode; mod eos; mod error; /// This crate specific `Result` type. pub type Result = std::result::Result; bytecodec-0.4.15/src/macros.rs000064400000000000000000000047630000000000000142640ustar 00000000000000/// Tries to encode items to the given buffer. /// /// Conceptually, this macro is expanded to the following expression. /// /// ```ignore /// if !$encoder.is_idle() { /// $offset += track!($encoder.encode(&mut $buf[$offset..], $eos))?; /// if !$encoder.is_idle() { /// return Ok($offset); /// } /// } /// ``` #[macro_export] macro_rules! bytecodec_try_encode { ($encoder:expr, $offset:expr, $buf:expr, $eos:expr) => { if !$encoder.is_idle() { $offset += track!($encoder.encode(&mut $buf[$offset..], $eos))?; if !$encoder.is_idle() { return Ok($offset); } } }; ($encoder:expr, $offset:expr, $buf:expr, $eos:expr, $($track_arg:tt)*) => { if !$encoder.is_idle() { $offset += track!($encoder.encode(&mut $buf[$offset..], $eos), $($track_arg)*)?; if !$encoder.is_idle() { return Ok($offset); } } }; ($encoder:expr, $offset:expr, $buf:expr, $eos:expr; $($track_arg:tt)*) => { if !$encoder.is_idle() { $offset += track!($encoder.encode(&mut $buf[$offset..], $eos); $($track_arg)*)?; if !$encoder.is_idle() { return Ok($offset); } } }; } /// Tries to decode an item from the given buffer. /// /// Conceptually, this macro is expanded to the following expression. /// /// ```ignore /// if !$decoder.is_idle() { /// $offset += track!($decoder.decode(&$buf[$offset..], $eos))?; /// if !$decoder.is_idle() { /// return Ok($offset); /// } /// } /// ``` #[macro_export] macro_rules! bytecodec_try_decode { ($decoder:expr, $offset:expr, $buf:expr, $eos:expr) => { if !$decoder.is_idle() { $offset += track!($decoder.decode(&$buf[$offset..], $eos))?; if !$decoder.is_idle() { return Ok($offset); } } }; ($decoder:expr, $offset:expr, $buf:expr, $eos:expr, $($track_arg:tt)*) => { if !$decoder.is_idle() { $offset += track!($decoder.decode(&$buf[$offset..], $eos), $($track_arg)*)?; if !$decoder.is_idle() { return Ok($offset); } } }; ($decoder:expr, $offset:expr, $buf:expr, $eos:expr; $($track_arg:tt)*) => { if !$decoder.is_idle() { $offset += track!($decoder.decode(&$buf[$offset..], $eos); $($track_arg)*)?; if !$decoder.is_idle() { return Ok($offset); } } }; } bytecodec-0.4.15/src/marker.rs000064400000000000000000000001270000000000000142470ustar 00000000000000//! Marker types. /// Never instantiated type. #[derive(Debug)] pub struct Never(()); bytecodec-0.4.15/src/monolithic.rs000064400000000000000000000126020000000000000151340ustar 00000000000000//! Monolithic encoder and decoder. use crate::bytes::BytesEncoder; use crate::{ByteCount, Decode, Encode, Eos, ErrorKind, Result}; use std::io::{self, Read, Write}; /// This trait allows for decoding items monolithically from a source byte stream. /// /// Although this has less flexibility than `Decode` trait, it has the merit of being easy to implement. pub trait MonolithicDecode { /// The type of items to be monolithically decoded. type Item; /// Decodes an item from the given reader. fn monolithic_decode(&self, reader: R) -> Result; } /// Monolithic decoder that implements `Decode` trait. #[derive(Debug, Default)] pub struct MonolithicDecoder { inner: D, item: Option, buf: Vec, } impl MonolithicDecoder { /// Makes a new `MonolithicDecoder` instance. pub fn new(inner: D) -> Self { MonolithicDecoder { inner, item: None, buf: Vec::new(), } } /// Returns a reference to the inner decoder. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoder. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of `MonolithicDecoder` and returns the inner decoder. pub fn into_inner(self) -> D { self.inner } } impl Decode for MonolithicDecoder { type Item = D::Item; fn decode(&mut self, mut buf: &[u8], eos: Eos) -> Result { if eos.is_reached() { let original_len = buf.len(); let item = track!( self.inner.monolithic_decode(self.buf.as_slice().chain(buf.by_ref())); original_len, self.buf.len(), buf.len(), eos )?; self.buf.clear(); self.item = Some(item); Ok(original_len - buf.len()) } else { self.buf.extend_from_slice(buf); Ok(buf.len()) } } fn finish_decoding(&mut self) -> Result { let item = track_assert_some!(self.item.take(), ErrorKind::IncompleteDecoding); Ok(item) } fn requiring_bytes(&self) -> ByteCount { if self.item.is_some() { ByteCount::Finite(0) } else { ByteCount::Unknown } } fn is_idle(&self) -> bool { self.item.is_some() } } /// This trait allows for encoding items monolithically to a destination byte stream. /// /// Although this has less flexibility than `Encode` trait, it has the merit of being easy to implement. pub trait MonolithicEncode { /// The type of items to be monolithically encoded. type Item; /// Encodes the item and writes the encoded bytes to the given writer. fn monolithic_encode(&self, item: &Self::Item, writer: W) -> Result<()>; } /// Monolithic encoder that implements `Encode` trait. #[derive(Debug, Default)] pub struct MonolithicEncoder { inner: E, item: Option, buf: BytesEncoder>, } impl MonolithicEncoder { /// Makes a new `MonolithicEncoder` instance. pub fn new(inner: E) -> Self { MonolithicEncoder { inner, item: None, buf: BytesEncoder::new(), } } /// Returns a reference to the inner encoder. pub fn inner_ref(&self) -> &E { &self.inner } /// Returns a mutable reference to the inner encoder. pub fn inner_mut(&mut self) -> &mut E { &mut self.inner } /// Takes ownership of `MonolithicEncoder` and returns the inner encoder. pub fn into_inner(self) -> E { self.inner } } impl Encode for MonolithicEncoder { type Item = E::Item; fn encode(&mut self, mut buf: &mut [u8], eos: Eos) -> Result { if let Some(item) = self.item.take() { let mut extra = Vec::new(); let original_len = buf.len(); { let writer = WriterChain::new(&mut buf, &mut extra); track!(self.inner.monolithic_encode(&item, writer))?; } if extra.is_empty() { Ok(original_len - buf.len()) } else { track!(self.buf.start_encoding(extra))?; Ok(original_len) } } else { track!(self.buf.encode(buf, eos)) } } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track_assert!(self.is_idle(), ErrorKind::EncoderFull); self.item = Some(item); Ok(()) } fn is_idle(&self) -> bool { self.item.is_none() && self.buf.is_idle() } fn requiring_bytes(&self) -> ByteCount { if self.is_idle() { ByteCount::Finite(0) } else if self.item.is_some() { ByteCount::Unknown } else { self.buf.requiring_bytes() } } } #[derive(Debug)] struct WriterChain { a: A, b: B, } impl WriterChain { fn new(a: A, b: B) -> Self { WriterChain { a, b } } } impl Write for WriterChain { fn write(&mut self, buf: &[u8]) -> io::Result { match self.a.write(buf)? { 0 => self.b.write(buf), n => Ok(n), } } fn flush(&mut self) -> io::Result<()> { Ok(()) } } bytecodec-0.4.15/src/null.rs000064400000000000000000000035110000000000000137400ustar 00000000000000//! Null decoder and encoder. use crate::{ByteCount, Decode, Encode, Eos, Result, SizedEncode}; /// Null decoder. /// /// `NullDecoder` consumes no bytes and returns `Ok(())` when `finish_decoding` method is called. #[derive(Debug, Default)] pub struct NullDecoder; impl Decode for NullDecoder { type Item = (); fn decode(&mut self, _buf: &[u8], _eos: Eos) -> Result { Ok(0) } fn finish_decoding(&mut self) -> Result { Ok(()) } fn is_idle(&self) -> bool { true } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(0) } } /// Null encoder. /// /// `NullEncoder` produces no bytes. #[derive(Debug, Default)] pub struct NullEncoder; impl Encode for NullEncoder { type Item = (); fn encode(&mut self, _buf: &mut [u8], _eos: Eos) -> Result { Ok(0) } fn start_encoding(&mut self, _item: Self::Item) -> Result<()> { Ok(()) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(0) } fn is_idle(&self) -> bool { true } } impl SizedEncode for NullEncoder { fn exact_requiring_bytes(&self) -> u64 { 0 } } #[cfg(test)] mod test { use super::*; #[test] fn null_decoder_works() { let mut decoder = NullDecoder; assert_eq!(decoder.decode(&[1][..], Eos::new(true)).ok(), Some(0)); assert_eq!(decoder.finish_decoding().ok(), Some(())); assert_eq!(decoder.finish_decoding().ok(), Some(())); } #[test] fn null_encoder_works() { let mut encoder = NullEncoder; encoder.start_encoding(()).unwrap(); assert_eq!(encoder.is_idle(), true); let mut buf = [0; 10]; assert_eq!(encoder.encode(&mut buf[..], Eos::new(true)).ok(), Some(0)); assert_eq!(encoder.is_idle(), true); } } bytecodec-0.4.15/src/padding.rs000064400000000000000000000074470000000000000144100ustar 00000000000000//! Encoder and decoder for padding bytes. use crate::{ByteCount, Decode, Encode, Eos, ErrorKind, Result}; /// Decoder for reading padding bytes from input streams. /// /// `PaddingDecoder` discards any bytes in a stream until it reaches EOS. #[derive(Debug, Default)] pub struct PaddingDecoder { expected_byte: Option, eos: bool, } impl PaddingDecoder { /// Makes a new `PaddingDecoder` instance. pub fn new(expected_byte: Option) -> Self { PaddingDecoder { expected_byte, eos: false, } } /// Returns the expected byte used for padding. /// /// `None` means that this decoder accepts any bytes. pub fn expected_byte(&self) -> Option { self.expected_byte } /// Sets the expected byte used for padding. pub fn set_expected_byte(&mut self, b: Option) { self.expected_byte = b; } } impl Decode for PaddingDecoder { type Item = (); fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { if self.eos { Ok(0) } else if let Some(expected) = self.expected_byte { for &padding_byte in buf { track_assert_eq!(padding_byte, expected, ErrorKind::InvalidInput); } self.eos = eos.is_reached(); Ok(buf.len()) } else { self.eos = eos.is_reached(); Ok(buf.len()) } } fn finish_decoding(&mut self) -> Result { track_assert!(self.eos, ErrorKind::IncompleteDecoding); self.eos = false; Ok(()) } fn is_idle(&self) -> bool { self.eos } fn requiring_bytes(&self) -> ByteCount { if self.eos { ByteCount::Finite(0) } else { ByteCount::Infinite } } } /// Encoder for writing padding bytes to output streams. /// /// After `start_encoding` is called, it will write the specified padding byte repeatedly /// until it the output stream reaches EOS. #[derive(Debug, Default)] pub struct PaddingEncoder { padding_byte: Option, } impl PaddingEncoder { /// Makes a new `PaddingEncoder` instance. pub fn new() -> Self { Self::default() } } impl Encode for PaddingEncoder { type Item = u8; fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { if let Some(padding_byte) = self.padding_byte { let n = buf.len(); for b in buf { *b = padding_byte } if eos.is_reached() { self.padding_byte = None; } Ok(n) } else { Ok(0) } } fn start_encoding(&mut self, item: Self::Item) -> Result<()> { track_assert!(self.is_idle(), ErrorKind::EncoderFull); self.padding_byte = Some(item); Ok(()) } fn requiring_bytes(&self) -> ByteCount { if self.is_idle() { ByteCount::Finite(0) } else { ByteCount::Infinite } } fn is_idle(&self) -> bool { self.padding_byte.is_none() } } #[cfg(test)] mod test { use super::*; use crate::io::IoDecodeExt; use crate::{Encode, EncodeExt, Eos}; #[test] fn padding_encoder_works() { let mut encoder = track_try_unwrap!(PaddingEncoder::with_item(3)); let mut buf = [0; 8]; track_try_unwrap!(encoder.encode(&mut buf[..], Eos::new(true))); assert_eq!(buf, [3; 8]); assert!(encoder.is_idle()); } #[test] fn padding_decoder_works() { let mut decoder = PaddingDecoder::new(None); assert!(decoder.decode_exact(&[0; 8][..]).is_ok()); let mut decoder = PaddingDecoder::new(Some(1)); assert!(decoder.decode_exact(&[1; 8][..]).is_ok()); assert!(decoder.decode_exact(&[0; 8][..]).is_err()); } } bytecodec-0.4.15/src/slice.rs000064400000000000000000000033360000000000000140720ustar 00000000000000//! Slice like types. /// Slice for owned types. /// /// # Examples /// /// ``` /// use bytecodec::slice::OwnedSlice; /// /// let slice = OwnedSlice::new([1, 2, 3, 4], 1, 3); /// assert_eq!(slice.as_ref(), [2, 3]); /// ``` #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct OwnedSlice { inner: T, start: usize, end: usize, } impl OwnedSlice { /// Makes a new `OwnedSlice` instance with the given range. pub fn new(inner: T, start: usize, end: usize) -> Self { OwnedSlice { inner, start, end } } /// Returns the start position of the slice. pub fn start(&self) -> usize { self.start } /// Returns the end position of the slice. pub fn end(&self) -> usize { self.end } /// Returns a reference to the inner value. pub fn inner_ref(&self) -> &T { &self.inner } /// Returns a mutable reference to the inner value. pub fn inner_mut(&mut self) -> &mut T { &mut self.inner } /// Takes ownership of the instance and returns the inner value. pub fn into_inner(self) -> T { self.inner } } impl AsRef<[U]> for OwnedSlice where T: AsRef<[U]>, { fn as_ref(&self) -> &[U] { &self.inner.as_ref()[self.start..self.end] } } impl AsMut<[U]> for OwnedSlice where T: AsMut<[U]>, { fn as_mut(&mut self) -> &mut [U] { &mut self.inner.as_mut()[self.start..self.end] } } #[cfg(test)] mod tests { use super::*; #[test] fn owned_slice_works() { let mut slice = OwnedSlice::new([1, 2, 3, 4], 1, 3); assert_eq!(slice.as_ref(), [2, 3]); slice.as_mut()[0] = 9; assert_eq!(slice.into_inner(), [1, 9, 3, 4]); } } bytecodec-0.4.15/src/tuple.rs000064400000000000000000000114230000000000000141200ustar 00000000000000//! Encoders and decoders for tuples. use crate::{ByteCount, Decode, Encode, Eos, Result, SizedEncode}; /// Decoder for tuples. #[derive(Debug, Default)] pub struct TupleDecoder { inner: D, } impl TupleDecoder { /// Makes a new `TupleDecoder`. pub fn new(inner: D) -> Self { TupleDecoder { inner } } /// Returns a reference to the inner decoders. pub fn inner_ref(&self) -> &D { &self.inner } /// Returns a mutable reference to the inner decoders. pub fn inner_mut(&mut self) -> &mut D { &mut self.inner } /// Takes ownership of this instance and returns the inner decoders. pub fn into_inner(self) -> D { self.inner } } macro_rules! impl_decode { ([$($t:ident),*],[$($i:tt),*]) => { impl<$($t),*> Decode for TupleDecoder<($($t),*,)> where $($t: Decode),* { type Item = ($($t::Item),*,); fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { let mut offset = 0; $(bytecodec_try_decode!(self.inner.$i, offset, buf, eos, "i={}", $i);)* Ok(offset) } fn finish_decoding(&mut self) -> Result { Ok(( $(track!(self.inner.$i.finish_decoding(), "i={}", $i)?),*, )) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(0)$(.add_for_decoding(self.inner.$i.requiring_bytes()))* } fn is_idle(&self) -> bool { $(self.inner.$i.is_idle())&&* } } } } impl_decode!([D0, D1], [0, 1]); impl_decode!([D0, D1, D2], [0, 1, 2]); impl_decode!([D0, D1, D2, D3], [0, 1, 2, 3]); impl_decode!([D0, D1, D2, D3, D4], [0, 1, 2, 3, 4]); impl_decode!([D0, D1, D2, D3, D4, D5], [0, 1, 2, 3, 4, 5]); impl_decode!([D0, D1, D2, D3, D4, D5, D6], [0, 1, 2, 3, 4, 5, 6]); impl_decode!([D0, D1, D2, D3, D4, D5, D6, D7], [0, 1, 2, 3, 4, 5, 6, 7]); /// Encoder for tuples. #[derive(Debug, Default)] pub struct TupleEncoder { inner: E, } impl TupleEncoder { /// Makes a new `TupleEncoder`. pub fn new(inner: E) -> Self { TupleEncoder { inner } } /// Returns a reference to the inner encoders. pub fn inner_ref(&self) -> &E { &self.inner } /// Returns a mutable reference to the inner encoders. pub fn inner_mut(&mut self) -> &mut E { &mut self.inner } /// Takes ownership of this instance and returns the inner encoders. pub fn into_inner(self) -> E { self.inner } } macro_rules! impl_encode { ([$($t:ident),*],[$($i:tt),*]) => { impl<$($t),*> Encode for TupleEncoder<($($t),*,)> where $($t: Encode),* { type Item = ($($t::Item),*,); fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { let mut offset = 0; $(bytecodec_try_encode!(self.inner.$i, offset, buf, eos, "i={}", $i);)* Ok(offset) } fn start_encoding(&mut self, t: Self::Item) -> Result<()> { $(track!(self.inner.$i.start_encoding(t.$i), "i={}", $i)?;)* Ok(()) } fn requiring_bytes(&self) -> ByteCount { ByteCount::Finite(0)$(.add_for_encoding(self.inner.$i.requiring_bytes()))* } fn is_idle(&self) -> bool { $(self.inner.$i.is_idle())&&* } } impl<$($t),*> SizedEncode for TupleEncoder<($($t),*,)> where $($t: SizedEncode),* { fn exact_requiring_bytes(&self) -> u64 { 0 $(+ self.inner.$i.exact_requiring_bytes())* } } }; } impl_encode!([E0, E1], [0, 1]); impl_encode!([E0, E1, E2], [0, 1, 2]); impl_encode!([E0, E1, E2, E3], [0, 1, 2, 3]); impl_encode!([E0, E1, E2, E3, E4], [0, 1, 2, 3, 4]); impl_encode!([E0, E1, E2, E3, E4, E5], [0, 1, 2, 3, 4, 5]); impl_encode!([E0, E1, E2, E3, E4, E5, E6], [0, 1, 2, 3, 4, 5, 6]); impl_encode!([E0, E1, E2, E3, E4, E5, E6, E7], [0, 1, 2, 3, 4, 5, 6, 7]); #[cfg(test)] mod test { use super::*; use crate::fixnum::{U8Decoder, U8Encoder}; use crate::io::{IoDecodeExt, IoEncodeExt}; use crate::EncodeExt; #[test] fn tuple_decoder_works() { let mut decoder = TupleDecoder::new((U8Decoder::new(), U8Decoder::new())); assert_eq!( track_try_unwrap!(decoder.decode_exact(b"foo".as_ref())), (b'f', b'o') ); } #[test] fn tuple_encoder_works() { let mut encoder = TupleEncoder::<(U8Encoder, U8Encoder)>::with_item((0, 1)).unwrap(); let mut buf = Vec::new(); encoder.encode_all(&mut buf).unwrap(); assert_eq!(buf, [0, 1]); } }