bitstream-io-2.5.0/.cargo_vcs_info.json0000644000000001360000000000100134370ustar { "git": { "sha1": "403adb1852da06fa5ab22e148f47e5d1d583ccbf" }, "path_in_vcs": "" }bitstream-io-2.5.0/.gitignore000064400000000000000000000000221046102023000142110ustar 00000000000000target Cargo.lock bitstream-io-2.5.0/Cargo.toml0000644000000022320000000000100114340ustar # 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 are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.79" name = "bitstream-io" version = "2.5.0" authors = ["Brian Langenberger "] description = "Library for reading/writing un-aligned values from/to streams in big-endian and little-endian formats." homepage = "https://github.com/tuffy/bitstream-io" documentation = "https://docs.rs/bitstream-io/" readme = "README.md" keywords = [ "bitstream", "endian", "big-endian", "little-endian", "binary", ] license = "MIT/Apache-2.0" repository = "https://github.com/tuffy/bitstream-io" [dependencies.core2] version = "0.4" features = ["alloc"] optional = true default-features = false [features] alloc = ["core2"] default = ["std"] std = [] bitstream-io-2.5.0/Cargo.toml.orig000064400000000000000000000012421046102023000151150ustar 00000000000000[package] name = "bitstream-io" description = "Library for reading/writing un-aligned values from/to streams in big-endian and little-endian formats." keywords = ["bitstream", "endian", "big-endian", "little-endian", "binary"] version = "2.5.0" authors = ["Brian Langenberger "] license = "MIT/Apache-2.0" documentation = "https://docs.rs/bitstream-io/" homepage = "https://github.com/tuffy/bitstream-io" repository = "https://github.com/tuffy/bitstream-io" edition = "2018" rust-version = "1.79" [dependencies] core2 = {version = "0.4", optional = true, default-features = false, features = ["alloc"]} [features] std = [] default = ["std"] alloc = ["core2"] bitstream-io-2.5.0/LICENSE-APACHE000064400000000000000000000251371046102023000141630ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. bitstream-io-2.5.0/LICENSE-MIT000064400000000000000000000020461046102023000136650ustar 00000000000000Copyright (c) 2017 Brian Langenberger 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. bitstream-io-2.5.0/README.md000064400000000000000000000011511046102023000135040ustar 00000000000000bitstream-io ============ A Rust library for reading or writing binary values to or from streams which may not be aligned at a whole byte. This library is intended to be flexible enough to wrap around any stream which implements the `Read` or `Write` traits. It also supports a wide array of integer data types as containers for those binary values. ## Minimum Compiler Version Beginning with version 2.4, the minimum compiler version has been updated to Rust 1.79 in order to support compile-time assertion in `const` blocks, which can be used to check for a class of errors at compile-time rather than runtime. bitstream-io-2.5.0/src/huffman.rs000064400000000000000000000261371046102023000150210ustar 00000000000000// Copyright 2017 Brian Langenberger // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Traits and implementations for reading or writing Huffman codes //! from or to a stream. #![warn(missing_docs)] use super::BitQueue; use super::Endianness; #[cfg(feature = "alloc")] use alloc::boxed::Box; #[cfg(feature = "alloc")] use alloc::collections::BTreeMap; #[cfg(feature = "alloc")] use alloc::vec::Vec; #[cfg(feature = "alloc")] use core::fmt; #[cfg(feature = "alloc")] use core::marker::PhantomData; #[cfg(feature = "alloc")] use core2::error::Error; #[cfg(not(feature = "alloc"))] use std::collections::BTreeMap; #[cfg(not(feature = "alloc"))] use std::error::Error; #[cfg(not(feature = "alloc"))] use std::fmt; #[cfg(not(feature = "alloc"))] use std::marker::PhantomData; /// A compiled Huffman tree element for use with the `read_huffman` method. /// Returned by `compile_read_tree`. /// /// Compiled read trees are optimized for faster lookup /// and are therefore endian-specific. /// /// In addition, each symbol in the source tree may occur many times /// in the compiled tree. If symbols require a nontrivial amount of space, /// consider using reference counting so that they may be cloned /// more efficiently. pub enum ReadHuffmanTree { /// The final value and new reader state Done(T, u8, u32, PhantomData), /// Another byte is necessary to determine final value Continue(Box<[ReadHuffmanTree]>), /// An invalid reader state has been used InvalidState, } /// Given a vector of symbol/code pairs, compiles a Huffman tree /// for reading. /// /// Code must be 0 or 1 bits and are always read from the stream /// from least-significant in the list to most signficant /// (which makes them easier to read for humans). /// /// All possible codes must be assigned some symbol, /// and it is acceptable for the same symbol to occur multiple times. /// /// ## Examples /// ``` /// use bitstream_io::huffman::compile_read_tree; /// use bitstream_io::BigEndian; /// assert!(compile_read_tree::( /// vec![(1, vec![0]), /// (2, vec![1, 0]), /// (3, vec![1, 1])]).is_ok()); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, HuffmanRead}; /// use bitstream_io::huffman::compile_read_tree; /// let tree = compile_read_tree( /// vec![('a', vec![0]), /// ('b', vec![1, 0]), /// ('c', vec![1, 1, 0]), /// ('d', vec![1, 1, 1])]).unwrap(); /// let data = [0b10110111]; /// let mut cursor = Cursor::new(&data); /// let mut reader = BitReader::endian(&mut cursor, BigEndian); /// assert_eq!(reader.read_huffman(&tree).unwrap(), 'b'); /// assert_eq!(reader.read_huffman(&tree).unwrap(), 'c'); /// assert_eq!(reader.read_huffman(&tree).unwrap(), 'd'); /// ``` pub fn compile_read_tree( values: Vec<(T, Vec)>, ) -> Result]>, HuffmanTreeError> where E: Endianness, T: Clone, { let tree = FinalHuffmanTree::new(values)?; let mut result = Vec::with_capacity(256); result.extend((0..256).map(|_| ReadHuffmanTree::InvalidState)); let queue = BitQueue::from_value(0, 0); let i = queue.to_state(); result[i] = compile_queue(queue, &tree); for bits in 1..8 { for value in 0..(1 << bits) { let queue = BitQueue::from_value(value, bits); let i = queue.to_state(); result[i] = compile_queue(queue, &tree); } } assert_eq!(result.len(), 256); Ok(result.into_boxed_slice()) } fn compile_queue( mut queue: BitQueue, tree: &FinalHuffmanTree, ) -> ReadHuffmanTree where E: Endianness, T: Clone, { match tree { FinalHuffmanTree::Leaf(ref value) => { let len = queue.len(); ReadHuffmanTree::Done(value.clone(), queue.value(), len, PhantomData) } FinalHuffmanTree::Tree(ref bit0, ref bit1) => { if queue.is_empty() { ReadHuffmanTree::Continue( (0..256) .map(|byte| compile_queue(BitQueue::from_value(byte as u8, 8), tree)) .collect::>>() .into_boxed_slice(), ) } else if queue.pop(1) == 0 { compile_queue(queue, bit0) } else { compile_queue(queue, bit1) } } } } // A complete Huffman tree with no empty nodes enum FinalHuffmanTree { Leaf(T), Tree(Box>, Box>), } impl FinalHuffmanTree { fn new(values: Vec<(T, Vec)>) -> Result, HuffmanTreeError> { let mut tree = WipHuffmanTree::new_empty(); for (symbol, code) in values { tree.add(code.as_slice(), symbol)?; } tree.into_read_tree() } } // Work-in-progress trees may have empty nodes during construction // but those are not allowed in a finalized tree. // If the user wants some codes to be None or an error symbol of some sort, // those will need to be specified explicitly. enum WipHuffmanTree { Empty, Leaf(T), Tree(Box>, Box>), } impl WipHuffmanTree { fn new_empty() -> WipHuffmanTree { WipHuffmanTree::Empty } fn new_leaf(value: T) -> WipHuffmanTree { WipHuffmanTree::Leaf(value) } fn new_tree() -> WipHuffmanTree { WipHuffmanTree::Tree(Box::new(Self::new_empty()), Box::new(Self::new_empty())) } fn into_read_tree(self) -> Result, HuffmanTreeError> { match self { WipHuffmanTree::Empty => Err(HuffmanTreeError::MissingLeaf), WipHuffmanTree::Leaf(v) => Ok(FinalHuffmanTree::Leaf(v)), WipHuffmanTree::Tree(zero, one) => { let zero = zero.into_read_tree()?; let one = one.into_read_tree()?; Ok(FinalHuffmanTree::Tree(Box::new(zero), Box::new(one))) } } } fn add(&mut self, code: &[u8], symbol: T) -> Result<(), HuffmanTreeError> { match self { WipHuffmanTree::Empty => { if code.is_empty() { *self = WipHuffmanTree::new_leaf(symbol); Ok(()) } else { *self = WipHuffmanTree::new_tree(); self.add(code, symbol) } } WipHuffmanTree::Leaf(_) => Err(if code.is_empty() { HuffmanTreeError::DuplicateLeaf } else { HuffmanTreeError::OrphanedLeaf }), WipHuffmanTree::Tree(ref mut zero, ref mut one) => { if code.is_empty() { Err(HuffmanTreeError::DuplicateLeaf) } else { match code[0] { 0 => zero.add(&code[1..], symbol), 1 => one.add(&code[1..], symbol), _ => Err(HuffmanTreeError::InvalidBit), } } } } } } /// An error type during Huffman tree compilation. #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum HuffmanTreeError { /// One of the bits in a Huffman code is not 0 or 1 InvalidBit, /// A Huffman code in the specification has no defined symbol MissingLeaf, /// The same Huffman code specifies multiple symbols DuplicateLeaf, /// A Huffman code is the prefix of some longer code OrphanedLeaf, } impl fmt::Display for HuffmanTreeError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { HuffmanTreeError::InvalidBit => write!(f, "invalid bit in code"), HuffmanTreeError::MissingLeaf => write!(f, "missing leaf node in specification"), HuffmanTreeError::DuplicateLeaf => write!(f, "duplicate leaf node in specification"), HuffmanTreeError::OrphanedLeaf => write!(f, "orphaned leaf node in specification"), } } } impl Error for HuffmanTreeError {} /// Given a vector of symbol/code pairs, compiles a Huffman tree /// for writing. /// /// Code must be 0 or 1 bits and are always written to the stream /// from least-significant in the list to most signficant /// (which makes them easier to read for humans). /// /// If the same symbol occurs multiple times, the first code is used. /// Unlike in read trees, not all possible codes need to be /// assigned a symbol. /// /// ## Examples /// ``` /// use bitstream_io::huffman::compile_write_tree; /// use bitstream_io::BigEndian; /// assert!(compile_write_tree::( /// vec![(1, vec![0]), /// (2, vec![1, 0]), /// (3, vec![1, 1])]).is_ok()); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, HuffmanWrite}; /// use bitstream_io::huffman::compile_write_tree; /// let tree = compile_write_tree( /// vec![('a', vec![0]), /// ('b', vec![1, 0]), /// ('c', vec![1, 1, 0]), /// ('d', vec![1, 1, 1])]).unwrap(); /// let mut data = Vec::new(); /// { /// let mut writer = BitWriter::endian(&mut data, BigEndian); /// writer.write_huffman(&tree, 'b').unwrap(); /// writer.write_huffman(&tree, 'c').unwrap(); /// writer.write_huffman(&tree, 'd').unwrap(); /// } /// assert_eq!(data, [0b10110111]); /// ``` pub fn compile_write_tree( values: Vec<(T, Vec)>, ) -> Result, HuffmanTreeError> where E: Endianness, T: Ord + Clone, { let mut map = BTreeMap::new(); for (symbol, code) in values { let mut encoded = Vec::new(); for bits in code.chunks(32) { let mut acc = BitQueue::::new(); for bit in bits { match *bit { 0 => acc.push(1, 0), 1 => acc.push(1, 1), _ => return Err(HuffmanTreeError::InvalidBit), } } let len = acc.len(); encoded.push((len, acc.value())) } map.entry(symbol) .or_insert_with(|| encoded.into_boxed_slice()); } Ok(WriteHuffmanTree { map, phantom: PhantomData, }) } /// A compiled Huffman tree for use with the `write_huffman` method. /// Returned by `compiled_write_tree`. pub struct WriteHuffmanTree { map: BTreeMap>, phantom: PhantomData, } impl WriteHuffmanTree { /// Returns true if symbol is in tree. #[inline] pub fn has_symbol(&self, symbol: &T) -> bool { self.map.contains_key(symbol) } /// Given symbol, returns iterator of /// (bits, value) pairs for writing code. /// Panics if symbol is not found. #[inline] pub fn get(&self, symbol: &T) -> impl Iterator { self.map[symbol].iter() } } bitstream-io-2.5.0/src/lib.rs000064400000000000000000000711741046102023000141440ustar 00000000000000// Copyright 2017 Brian Langenberger // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Traits and helpers for bitstream handling functionality //! //! Bitstream readers are for reading signed and unsigned integer //! values from a stream whose sizes may not be whole bytes. //! Bitstream writers are for writing signed and unsigned integer //! values to a stream, also potentially un-aligned at a whole byte. //! //! Both big-endian and little-endian streams are supported. //! //! The only requirement for wrapped reader streams is that they must //! implement the `Read` trait, and the only requirement //! for writer streams is that they must implement the `Write` trait. //! //! In addition, reader streams do not consume any more bytes //! from the underlying reader than necessary, buffering only a //! single partial byte as needed. //! Writer streams also write out all whole bytes as they are accumulated. //! //! Readers and writers are also designed to work with integer //! types of any possible size. //! Many of Rust's built-in integer types are supported by default. //! # Minimum Compiler Version //! //! Beginning with version 2.4, the minimum compiler version has been //! updated to Rust 1.79. //! //! The issue is that reading an excessive number of //! bits to a type which is too small to hold them, //! or writing an excessive number of bits from too small of a type, //! are always errors: //! ``` //! use std::io::{Read, Cursor}; //! use bitstream_io::{BigEndian, BitReader, BitRead}; //! let data = [0; 10]; //! let mut r = BitReader::endian(Cursor::new(&data), BigEndian); //! let x: Result = r.read(64); // reading 64 bits to u32 always fails at runtime //! assert!(x.is_err()); //! ``` //! but those errors will not be caught until the program runs, //! which is less than ideal for the common case in which //! the number of bits is already known at compile-time. //! //! But starting with Rust 1.79, we can now have read and write methods //! which take a constant number of bits and can validate the number of bits //! are small enough for the type being read/written at compile-time: //! ```rust,ignore //! use std::io::{Read, Cursor}; //! use bitstream_io::{BigEndian, BitReader, BitRead}; //! let data = [0; 10]; //! let mut r = BitReader::endian(Cursor::new(&data), BigEndian); //! let x: Result = r.read_in::<64, _>(); // doesn't compile at all //! ``` //! Since catching potential bugs at compile-time is preferable //! to encountering errors at runtime, this will hopefully be //! an improvement in the long run. //! # Migrating From Pre 1.0.0 //! //! There are now `BitRead` and `BitWrite` traits for bitstream //! reading and writing (analogous to the standard library's //! `Read` and `Write` traits) which you will also need to import. //! The upside to this approach is that library consumers //! can now make functions and methods generic over any sort //! of bit reader or bit writer, regardless of the underlying //! stream byte source or endianness. #![warn(missing_docs)] #![forbid(unsafe_code)] #![cfg_attr(feature = "alloc", no_std)] #[cfg(feature = "alloc")] extern crate alloc; use core::fmt::Debug; use core::marker::PhantomData; use core::mem; use core::ops::{BitOrAssign, BitXor, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub}; #[cfg(feature = "alloc")] use core2::io; #[cfg(not(feature = "alloc"))] use std::io; pub mod huffman; pub mod read; pub mod write; pub use read::{ BitRead, BitReader, ByteRead, ByteReader, FromBitStream, FromBitStreamWith, FromByteStream, FromByteStreamWith, HuffmanRead, }; pub use write::{ BitCounter, BitRecorder, BitWrite, BitWriter, ByteWrite, ByteWriter, HuffmanWrite, ToBitStream, ToBitStreamWith, ToByteStream, ToByteStreamWith, }; /// A trait intended for simple fixed-length primitives (such as ints and floats) /// which allows them to be read and written to streams of /// different endiannesses verbatim. pub trait Primitive { /// The raw byte representation of this numeric type type Bytes: AsRef<[u8]> + AsMut<[u8]>; /// An empty buffer of this type's size fn buffer() -> Self::Bytes; /// Our value in big-endian bytes fn to_be_bytes(self) -> Self::Bytes; /// Our value in little-endian bytes fn to_le_bytes(self) -> Self::Bytes; /// Convert big-endian bytes to our value fn from_be_bytes(bytes: Self::Bytes) -> Self; /// Convert little-endian bytes to our value fn from_le_bytes(bytes: Self::Bytes) -> Self; } macro_rules! define_primitive_numeric { ($t:ty) => { impl Primitive for $t { type Bytes = [u8; mem::size_of::<$t>()]; #[inline(always)] fn buffer() -> Self::Bytes { [0; mem::size_of::<$t>()] } #[inline(always)] fn to_be_bytes(self) -> Self::Bytes { self.to_be_bytes() } #[inline(always)] fn to_le_bytes(self) -> Self::Bytes { self.to_le_bytes() } #[inline(always)] fn from_be_bytes(bytes: Self::Bytes) -> Self { <$t>::from_be_bytes(bytes) } #[inline(always)] fn from_le_bytes(bytes: Self::Bytes) -> Self { <$t>::from_le_bytes(bytes) } } }; } impl Primitive for [u8; N] { type Bytes = [u8; N]; #[inline(always)] fn buffer() -> Self::Bytes { [0; N] } #[inline(always)] fn to_be_bytes(self) -> Self::Bytes { self } #[inline(always)] fn to_le_bytes(self) -> Self::Bytes { self } #[inline(always)] fn from_be_bytes(bytes: Self::Bytes) -> Self { bytes } #[inline(always)] fn from_le_bytes(bytes: Self::Bytes) -> Self { bytes } } /// This trait extends many common integer types (both unsigned and signed) /// with a few trivial methods so that they can be used /// with the bitstream handling traits. pub trait Numeric: Primitive + Sized + Copy + Default + Debug + PartialOrd + Shl + ShlAssign + Shr + ShrAssign + Rem + RemAssign + BitOrAssign + BitXor + Not + Sub { /// Size of type in bits const BITS_SIZE: u32; /// The value of 1 in this type const ONE: Self; /// Returns true if this value is 0, in its type fn is_zero(self) -> bool; /// Returns a `u8` value in this type fn from_u8(u: u8) -> Self; /// Assuming 0 <= value < 256, returns this value as a `u8` type fn to_u8(self) -> u8; /// Counts the number of 1 bits fn count_ones(self) -> u32; /// Counts the number of leading zeros fn leading_zeros(self) -> u32; /// Counts the number of trailing zeros fn trailing_zeros(self) -> u32; /// Convert to a generic unsigned write value for stream recording purposes fn unsigned_value(self) -> write::UnsignedValue; } macro_rules! define_numeric { ($t:ty) => { define_primitive_numeric!($t); impl Numeric for $t { const BITS_SIZE: u32 = mem::size_of::<$t>() as u32 * 8; const ONE: Self = 1; #[inline(always)] fn is_zero(self) -> bool { self == 0 } #[inline(always)] fn from_u8(u: u8) -> Self { u as $t } #[inline(always)] fn to_u8(self) -> u8 { self as u8 } #[inline(always)] fn count_ones(self) -> u32 { self.count_ones() } #[inline(always)] fn leading_zeros(self) -> u32 { self.leading_zeros() } #[inline(always)] fn trailing_zeros(self) -> u32 { self.trailing_zeros() } #[inline(always)] fn unsigned_value(self) -> write::UnsignedValue { self.into() } } }; } /// This trait extends many common signed integer types /// so that they can be used with the bitstream handling traits. pub trait SignedNumeric: Numeric { /// Returns true if this value is negative fn is_negative(self) -> bool; /// Given a two-complement positive value and certain number of bits, /// returns this value as a negative number. fn as_negative(self, bits: u32) -> Self; /// Given a two-complement positive value and certain number of bits, /// returns this value as a negative number. fn as_negative_fixed(self) -> Self; /// Given a negative value and a certain number of bits, /// returns this value as a twos-complement positive number. fn as_unsigned(self, bits: u32) -> Self; /// Given a negative value and a certain number of bits, /// returns this value as a twos-complement positive number. fn as_unsigned_fixed(self) -> Self; /// Converts to a generic signed value for stream recording purposes. fn signed_value(self) -> write::SignedValue; } macro_rules! define_signed_numeric { ($t:ty) => { impl SignedNumeric for $t { #[inline(always)] fn is_negative(self) -> bool { self < 0 } #[inline(always)] fn as_negative(self, bits: u32) -> Self { self + (-1 << (bits - 1)) } #[inline(always)] fn as_negative_fixed(self) -> Self { self + (-1 << (BITS - 1)) } #[inline(always)] fn as_unsigned(self, bits: u32) -> Self { self - (-1 << (bits - 1)) } #[inline(always)] fn as_unsigned_fixed(self) -> Self { self - (-1 << (BITS - 1)) } #[inline(always)] fn signed_value(self) -> write::SignedValue { self.into() } } }; } define_numeric!(u8); define_numeric!(i8); define_numeric!(u16); define_numeric!(i16); define_numeric!(u32); define_numeric!(i32); define_numeric!(u64); define_numeric!(i64); define_numeric!(u128); define_numeric!(i128); define_signed_numeric!(i8); define_signed_numeric!(i16); define_signed_numeric!(i32); define_signed_numeric!(i64); define_signed_numeric!(i128); define_primitive_numeric!(f32); define_primitive_numeric!(f64); /// A stream's endianness, or byte order, for determining /// how bits should be read. /// /// It comes in `BigEndian` and `LittleEndian` varieties /// (which may be shortened to `BE` and `LE`) /// and is not something programmers should have to implement /// in most cases. pub trait Endianness: Sized { /// Pushes the given bits and value onto an accumulator /// with the given bits and value. fn push(queue: &mut BitQueue, bits: u32, value: N) where N: Numeric; /// Pushes the given constant number of bits and value onto an accumulator /// with the given bits and value. fn push_fixed(queue: &mut BitQueue, value: N) where N: Numeric; /// Pops a value with the given number of bits from an accumulator /// with the given bits and value. fn pop(queue: &mut BitQueue, bits: u32) -> N where N: Numeric; /// Pops a value with the given number of constant bits /// from an accumulator with the given bits and value. fn pop_fixed(queue: &mut BitQueue) -> N where N: Numeric; /// Drops the given number of bits from an accumulator /// with the given bits and value. fn drop(queue: &mut BitQueue, bits: u32) where N: Numeric; /// Returns the next number of 0 bits from an accumulator /// with the given bits and value. fn next_zeros(queue: &BitQueue) -> u32 where N: Numeric; /// Returns the next number of 1 bits from an accumulator /// with the given bits and value. fn next_ones(queue: &BitQueue) -> u32 where N: Numeric; /// Reads signed value from reader in this endianness fn read_signed(r: &mut R, bits: u32) -> io::Result where R: BitRead, S: SignedNumeric; /// Reads signed value from reader in this endianness fn read_signed_fixed(r: &mut R) -> io::Result where R: BitRead, S: SignedNumeric; /// Writes signed value to writer in this endianness fn write_signed(w: &mut W, bits: u32, value: S) -> io::Result<()> where W: BitWrite, S: SignedNumeric; /// Writes signed value to writer in this endianness fn write_signed_fixed(w: &mut W, value: S) -> io::Result<()> where W: BitWrite, S: SignedNumeric; /// Reads convertable numeric value from reader in this endianness fn read_primitive(r: &mut R) -> io::Result where R: BitRead, V: Primitive; /// Writes convertable numeric value to writer in this endianness fn write_primitive(w: &mut W, value: V) -> io::Result<()> where W: BitWrite, V: Primitive; /// Reads entire numeric value from reader in this endianness fn read_numeric(r: R) -> io::Result where R: io::Read, V: Primitive; /// Writes entire numeric value to writer in this endianness fn write_numeric(w: W, value: V) -> io::Result<()> where W: io::Write, V: Primitive; } /// Big-endian, or most significant bits first #[derive(Copy, Clone, Debug)] pub struct BigEndian; /// Big-endian, or most significant bits first pub type BE = BigEndian; impl Endianness for BigEndian { #[inline] fn push(queue: &mut BitQueue, bits: u32, value: N) where N: Numeric, { if !queue.value.is_zero() { queue.value <<= bits; } queue.value |= value; queue.bits += bits; } #[inline] fn push_fixed(queue: &mut BitQueue, value: N) where N: Numeric, { if !queue.value.is_zero() { queue.value <<= B; } queue.value |= value; queue.bits += B; } #[inline] fn pop(queue: &mut BitQueue, bits: u32) -> N where N: Numeric, { if bits < queue.bits { let offset = queue.bits - bits; let to_return = queue.value >> offset; queue.value %= N::ONE << offset; queue.bits -= bits; to_return } else { let to_return = queue.value; queue.value = N::default(); queue.bits = 0; to_return } } #[inline] fn pop_fixed(queue: &mut BitQueue) -> N where N: Numeric, { if B < queue.bits { let offset = queue.bits - B; let to_return = queue.value >> offset; queue.value %= N::ONE << offset; queue.bits -= B; to_return } else { let to_return = queue.value; queue.value = N::default(); queue.bits = 0; to_return } } #[inline] fn drop(queue: &mut BitQueue, bits: u32) where N: Numeric, { if bits < queue.bits { queue.value %= N::ONE << (queue.bits - bits); queue.bits -= bits; } else { queue.value = N::default(); queue.bits = 0; } } #[inline] fn next_zeros(queue: &BitQueue) -> u32 where N: Numeric, { queue.value.leading_zeros() - (N::BITS_SIZE - queue.bits) } #[inline] fn next_ones(queue: &BitQueue) -> u32 where N: Numeric, { if queue.bits < N::BITS_SIZE { (queue.value ^ ((N::ONE << queue.bits) - N::ONE)).leading_zeros() - (N::BITS_SIZE - queue.bits) } else { (!queue.value).leading_zeros() } } fn read_signed(r: &mut R, bits: u32) -> io::Result where R: BitRead, S: SignedNumeric, { let is_negative = r.read_bit()?; let unsigned = r.read::(bits - 1)?; Ok(if is_negative { unsigned.as_negative(bits) } else { unsigned }) } fn read_signed_fixed(r: &mut R) -> io::Result where R: BitRead, S: SignedNumeric, { let is_negative = r.read_bit()?; let unsigned = r.read::(B - 1)?; Ok(if is_negative { unsigned.as_negative_fixed::() } else { unsigned }) } fn write_signed(w: &mut W, bits: u32, value: S) -> io::Result<()> where W: BitWrite, S: SignedNumeric, { if bits == S::BITS_SIZE { w.write_bytes(value.to_be_bytes().as_ref()) } else if value.is_negative() { w.write_bit(true) .and_then(|()| w.write(bits - 1, value.as_unsigned(bits))) } else { w.write_bit(false).and_then(|()| w.write(bits - 1, value)) } } fn write_signed_fixed(w: &mut W, value: S) -> io::Result<()> where W: BitWrite, S: SignedNumeric, { if B == S::BITS_SIZE { w.write_bytes(value.to_be_bytes().as_ref()) } else if value.is_negative() { w.write_bit(true) .and_then(|()| w.write(B - 1, value.as_unsigned(B))) } else { w.write_bit(false).and_then(|()| w.write(B - 1, value)) } } #[inline] fn read_primitive(r: &mut R) -> io::Result where R: BitRead, V: Primitive, { let mut buffer = V::buffer(); r.read_bytes(buffer.as_mut())?; Ok(V::from_be_bytes(buffer)) } #[inline] fn write_primitive(w: &mut W, value: V) -> io::Result<()> where W: BitWrite, V: Primitive, { w.write_bytes(value.to_be_bytes().as_ref()) } #[inline] fn read_numeric(mut r: R) -> io::Result where R: io::Read, V: Primitive, { let mut buffer = V::buffer(); r.read_exact(buffer.as_mut())?; Ok(V::from_be_bytes(buffer)) } #[inline] fn write_numeric(mut w: W, value: V) -> io::Result<()> where W: io::Write, V: Primitive, { w.write_all(value.to_be_bytes().as_ref()) } } /// Little-endian, or least significant bits first #[derive(Copy, Clone, Debug)] pub struct LittleEndian; /// Little-endian, or least significant bits first pub type LE = LittleEndian; impl Endianness for LittleEndian { #[inline] fn push(queue: &mut BitQueue, bits: u32, mut value: N) where N: Numeric, { if !value.is_zero() { value <<= queue.bits; queue.value |= value; } queue.bits += bits; } #[inline] fn push_fixed(queue: &mut BitQueue, mut value: N) where N: Numeric, { if !value.is_zero() { value <<= queue.bits; queue.value |= value; } queue.bits += B; } #[inline] fn pop(queue: &mut BitQueue, bits: u32) -> N where N: Numeric, { if bits < queue.bits { let to_return = queue.value % (N::ONE << bits); queue.value >>= bits; queue.bits -= bits; to_return } else { let to_return = queue.value; queue.value = N::default(); queue.bits = 0; to_return } } fn pop_fixed(queue: &mut BitQueue) -> N where N: Numeric, { if B < queue.bits { let to_return = queue.value % (N::ONE << B); queue.value >>= B; queue.bits -= B; to_return } else { let to_return = queue.value; queue.value = N::default(); queue.bits = 0; to_return } } #[inline] fn drop(queue: &mut BitQueue, bits: u32) where N: Numeric, { if bits < queue.bits { queue.value >>= bits; queue.bits -= bits; } else { queue.value = N::default(); queue.bits = 0; } } #[inline(always)] fn next_zeros(queue: &BitQueue) -> u32 where N: Numeric, { queue.value.trailing_zeros() } #[inline] fn next_ones(queue: &BitQueue) -> u32 where N: Numeric, { (queue.value ^ !N::default()).trailing_zeros() } fn read_signed(r: &mut R, bits: u32) -> io::Result where R: BitRead, S: SignedNumeric, { let unsigned = r.read::(bits - 1)?; let is_negative = r.read_bit()?; Ok(if is_negative { unsigned.as_negative(bits) } else { unsigned }) } fn read_signed_fixed(r: &mut R) -> io::Result where R: BitRead, S: SignedNumeric, { let unsigned = r.read::(B - 1)?; let is_negative = r.read_bit()?; Ok(if is_negative { unsigned.as_negative_fixed::() } else { unsigned }) } fn write_signed(w: &mut W, bits: u32, value: S) -> io::Result<()> where W: BitWrite, S: SignedNumeric, { if bits == S::BITS_SIZE { w.write_bytes(value.to_le_bytes().as_ref()) } else if value.is_negative() { w.write(bits - 1, value.as_unsigned(bits)) .and_then(|()| w.write_bit(true)) } else { w.write(bits - 1, value).and_then(|()| w.write_bit(false)) } } fn write_signed_fixed(w: &mut W, value: S) -> io::Result<()> where W: BitWrite, S: SignedNumeric, { if B == S::BITS_SIZE { w.write_bytes(value.to_le_bytes().as_ref()) } else if value.is_negative() { w.write(B - 1, value.as_unsigned_fixed::()) .and_then(|()| w.write_bit(true)) } else { w.write(B - 1, value).and_then(|()| w.write_bit(false)) } } #[inline] fn read_primitive(r: &mut R) -> io::Result where R: BitRead, V: Primitive, { let mut buffer = V::buffer(); r.read_bytes(buffer.as_mut())?; Ok(V::from_le_bytes(buffer)) } #[inline] fn write_primitive(w: &mut W, value: V) -> io::Result<()> where W: BitWrite, V: Primitive, { w.write_bytes(value.to_le_bytes().as_ref()) } fn read_numeric(mut r: R) -> io::Result where R: io::Read, V: Primitive, { let mut buffer = V::buffer(); r.read_exact(buffer.as_mut())?; Ok(V::from_le_bytes(buffer)) } #[inline] fn write_numeric(mut w: W, value: V) -> io::Result<()> where W: io::Write, V: Primitive, { w.write_all(value.to_le_bytes().as_ref()) } } /// A queue for efficiently pushing bits onto a value /// and popping them off a value. #[derive(Clone, Debug, Default)] pub struct BitQueue { phantom: PhantomData, value: N, bits: u32, } impl BitQueue { /// Returns a new empty queue #[inline] pub fn new() -> BitQueue { BitQueue { phantom: PhantomData, value: N::default(), bits: 0, } } /// Creates a new queue from the given value with the given size /// Panics if the value is larger than the given number of bits. #[inline] pub fn from_value(value: N, bits: u32) -> BitQueue { assert!(if bits < N::BITS_SIZE { value < (N::ONE << bits) } else { bits <= N::BITS_SIZE }); BitQueue { phantom: PhantomData, value, bits, } } /// Sets the queue to a given value with the given number of bits /// Panics if the value is larger than the given number of bits #[inline] pub fn set(&mut self, value: N, bits: u32) { assert!(if bits < N::BITS_SIZE { value < (N::ONE << bits) } else { bits <= N::BITS_SIZE }); self.value = value; self.bits = bits; } /// Consumes the queue and returns its current value #[inline(always)] pub fn value(self) -> N { self.value } /// Returns the total bits in the queue #[inline(always)] pub fn len(&self) -> u32 { self.bits } /// Returns the maximum bits the queue can hold #[inline(always)] pub fn max_len(&self) -> u32 { N::BITS_SIZE } /// Returns the remaining bits the queue can hold #[inline(always)] pub fn remaining_len(&self) -> u32 { self.max_len() - self.len() } /// Returns true if the queue is empty #[inline(always)] pub fn is_empty(&self) -> bool { self.bits == 0 } /// Returns true if the queue is full #[inline(always)] pub fn is_full(&self) -> bool { self.bits == N::BITS_SIZE } /// Drops all values in the queue #[inline(always)] pub fn clear(&mut self) { self.set(N::default(), 0) } /// Returns true if all bits remaining in the queue are 0 #[inline(always)] pub fn all_0(&self) -> bool { self.value.count_ones() == 0 } /// Returns true if all bits remaining in the queue are 1 #[inline(always)] pub fn all_1(&self) -> bool { self.value.count_ones() == self.bits } /// Pushes a value with the given number of bits onto the tail of the queue /// Panics if the number of bits pushed is larger than the queue can hold. #[inline(always)] pub fn push(&mut self, bits: u32, value: N) { assert!(bits <= self.remaining_len()); // check for overflow E::push(self, bits, value) } /// Pushes a value with the given number of bits onto the tail of the queue /// Panics if the number of bits pushed is larger than the queue can hold. #[inline(always)] pub fn push_fixed(&mut self, value: N) { assert!(B <= self.remaining_len()); // check for overflow E::push_fixed::(self, value) } /// Pops a value with the given number of bits from the head of the queue /// Panics if the number of bits popped is larger than the number /// of bits in the queue. #[inline(always)] pub fn pop(&mut self, bits: u32) -> N { assert!(bits <= self.len()); // check for underflow E::pop(self, bits) } /// Pops a value with the given number of bits from the head of the queue pub fn pop_fixed(&mut self) -> N { assert!(B <= self.len()); // check for underflow E::pop_fixed::(self) } /// Pops all the current bits from the queue /// and resets it to an empty state. #[inline] pub fn pop_all(&mut self) -> N { let to_return = self.value; self.value = N::default(); self.bits = 0; to_return } /// Drops the given number of bits from the head of the queue /// without returning them. /// Panics if the number of bits dropped is larger than the /// number of bits in the queue. #[inline(always)] pub fn drop(&mut self, bits: u32) { assert!(bits <= self.len()); // check for underflow E::drop(self, bits) } /// Pops all 0 bits up to and including the next 1 bit /// and returns the amount of 0 bits popped #[inline] pub fn pop_0(&mut self) -> u32 { let zeros = E::next_zeros(self); self.drop(zeros + 1); zeros } /// Pops all 1 bits up to and including the next 0 bit /// and returns the amount of 1 bits popped #[inline] pub fn pop_1(&mut self) -> u32 { let ones = E::next_ones(self); self.drop(ones + 1); ones } } impl BitQueue { /// Returns the state of the queue as a single value /// which can be used to perform lookups. #[inline(always)] pub fn to_state(&self) -> usize { (1 << self.bits) | (self.value as usize) } } bitstream-io-2.5.0/src/read.rs000064400000000000000000001472101046102023000143040ustar 00000000000000// Copyright 2017 Brian Langenberger // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Traits and implementations for reading bits from a stream. //! //! ## Example //! //! Reading the initial STREAMINFO block from a FLAC file, //! as documented in its //! [specification](https://xiph.org/flac/format.html#stream). //! //! ``` //! use std::io::{Cursor, Read}; //! use bitstream_io::*; //! //! #[derive(Debug, PartialEq, Eq)] //! struct BlockHeader { //! last_block: bool, // 1 bit //! block_type: u8, // 7 bits //! block_size: u32, // 24 bits //! } //! //! impl FromBitStream for BlockHeader { //! type Error = std::io::Error; //! //! fn from_reader(r: &mut R) -> std::io::Result { //! Ok(Self { //! last_block: r.read_bit()?, //! block_type: r.read_in::<7, _>()?, //! block_size: r.read_in::<24, _>()?, //! }) //! } //! } //! //! #[derive(Debug, PartialEq, Eq)] //! struct Streaminfo { //! minimum_block_size: u16, // 16 bits //! maximum_block_size: u16, // 16 bits //! minimum_frame_size: u32, // 24 bits //! maximum_frame_size: u32, // 24 bits //! sample_rate: u32, // 20 bits //! channels: u8, // 3 bits //! bits_per_sample: u8, // 5 bits //! total_samples: u64, // 36 bits //! md5: [u8; 16], // 16 bytes //! } //! //! impl FromBitStream for Streaminfo { //! type Error = std::io::Error; //! //! fn from_reader(r: &mut R) -> std::io::Result { //! Ok(Self { //! minimum_block_size: r.read_to()?, //! maximum_block_size: r.read_to()?, //! minimum_frame_size: r.read_in::<24, _>()?, //! maximum_frame_size: r.read_in::<24, _>()?, //! sample_rate: r.read_in::<20, _>()?, //! channels: r.read_in::<3, u8>()? + 1, //! bits_per_sample: r.read_in::<5, u8>()? + 1, //! total_samples: r.read_in::<36, _>()?, //! md5: r.read_to()?, //! }) //! } //! } //! //! #[derive(Debug, PartialEq, Eq)] //! struct VorbisComment { //! vendor: String, //! comment: Vec, //! } //! //! impl FromBitStream for VorbisComment { //! type Error = Box; //! //! fn from_reader(r: &mut R) -> Result { //! use bitstream_io::LE; //! //! fn read_entry( //! r: &mut R, //! ) -> Result> { //! use std::convert::TryInto; //! let size = r.read_as_to::()?.try_into()?; //! Ok(String::from_utf8(r.read_to_vec(size)?)?) //! } //! //! Ok(Self { //! vendor: read_entry(r)?, //! comment: (0..r.read_as_to::()?) //! .map(|_| read_entry(r)) //! .collect::, _>>()?, //! }) //! } //! } //! //! // test FLAC file data //! let flac: Vec = vec![0x66,0x4c,0x61,0x43,0x00,0x00,0x00,0x22, //! 0x10,0x00,0x10,0x00,0x00,0x06,0x06,0x00, //! 0x21,0x62,0x0a,0xc4,0x42,0xf0,0x00,0x04, //! 0xa6,0xcc,0xfa,0xf2,0x69,0x2f,0xfd,0xec, //! 0x2d,0x5b,0x30,0x01,0x76,0xb4,0x62,0x88, //! 0x7d,0x92,0x04,0x00,0x00,0x7a,0x20,0x00, //! 0x00,0x00,0x72,0x65,0x66,0x65,0x72,0x65, //! 0x6e,0x63,0x65,0x20,0x6c,0x69,0x62,0x46, //! 0x4c,0x41,0x43,0x20,0x31,0x2e,0x31,0x2e, //! 0x34,0x20,0x32,0x30,0x30,0x37,0x30,0x32, //! 0x31,0x33,0x04,0x00,0x00,0x00,0x16,0x00, //! 0x00,0x00,0x74,0x69,0x74,0x6c,0x65,0x3d, //! 0x32,0x63,0x68,0x20,0x34,0x34,0x31,0x30, //! 0x30,0x20,0x20,0x31,0x36,0x62,0x69,0x74, //! 0x10,0x00,0x00,0x00,0x61,0x6c,0x62,0x75, //! 0x6d,0x3d,0x54,0x65,0x73,0x74,0x20,0x41, //! 0x6c,0x62,0x75,0x6d,0x0f,0x00,0x00,0x00, //! 0x61,0x72,0x74,0x69,0x73,0x74,0x3d,0x41, //! 0x73,0x73,0x6f,0x72,0x74,0x65,0x64,0x0d, //! 0x00,0x00,0x00,0x74,0x72,0x61,0x63,0x6b, //! 0x6e,0x75,0x6d,0x62,0x65,0x72,0x3d,0x31]; //! //! let mut cursor = Cursor::new(&flac); //! //! let mut reader = BitReader::endian(&mut cursor, BigEndian); //! //! // stream marker //! assert_eq!(&reader.read_to::<[u8; 4]>().unwrap(), b"fLaC"); //! //! // metadata block header //! assert_eq!( //! reader.parse::().unwrap(), //! BlockHeader { last_block: false, block_type: 0, block_size: 34 } //! ); //! //! // STREAMINFO block //! assert_eq!( //! reader.parse::().unwrap(), //! Streaminfo { //! minimum_block_size: 4096, //! maximum_block_size: 4096, //! minimum_frame_size: 1542, //! maximum_frame_size: 8546, //! sample_rate: 44100, //! channels: 2, //! bits_per_sample: 16, //! total_samples: 304844, //! md5: *b"\xFA\xF2\x69\x2F\xFD\xEC\x2D\x5B\x30\x01\x76\xB4\x62\x88\x7D\x92", //! } //! ); //! //! // metadata block header //! assert_eq!( //! reader.parse::().unwrap(), //! BlockHeader { last_block: false, block_type: 4, block_size: 122 } //! ); //! //! // VORBIS_COMMENT block //! assert_eq!( //! reader.parse::().unwrap(), //! VorbisComment { //! vendor: "reference libFLAC 1.1.4 20070213".to_string(), //! comment: vec![ //! "title=2ch 44100 16bit".to_string(), //! "album=Test Album".to_string(), //! "artist=Assorted".to_string(), //! "tracknumber=1".to_string(), //! ], //! } //! ); #![warn(missing_docs)] #[cfg(feature = "alloc")] use alloc::vec; #[cfg(feature = "alloc")] use alloc::vec::Vec; #[cfg(feature = "alloc")] use core2::io::{self, SeekFrom}; #[cfg(not(feature = "alloc"))] use std::io::{self, SeekFrom}; use super::{ huffman::ReadHuffmanTree, BitQueue, Endianness, Numeric, PhantomData, Primitive, SignedNumeric, }; /// A trait for anything that can read a variable number of /// potentially un-aligned values from an input stream pub trait BitRead { /// Reads a single bit from the stream. /// `true` indicates 1, `false` indicates 0 /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_bit(&mut self) -> io::Result; /// Reads an unsigned value from the stream with /// the given number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Also returns an error if the output type is too small /// to hold the requested number of bits. fn read(&mut self, bits: u32) -> io::Result where U: Numeric; /// Reads an unsigned value from the stream with /// the given constant number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// A compile-time error occurs if the given number of bits /// is larger than the output type. fn read_in(&mut self) -> io::Result where U: Numeric, { self.read(BITS) } /// Reads a twos-complement signed value from the stream with /// the given number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if the number of bits is 0, /// since one bit is always needed for the sign. /// Also returns an error if the output type is too small /// to hold the requested number of bits. fn read_signed(&mut self, bits: u32) -> io::Result where S: SignedNumeric; /// Reads a twos-complement signed value from the stream with /// the given constant number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// A compile-time error occurs if the number of bits is 0, /// since one bit is always needed for the sign. /// A compile-time error occurs if the given number of bits /// is larger than the output type. fn read_signed_in(&mut self) -> io::Result where S: SignedNumeric; /// Reads whole value from the stream whose size in bits is equal /// to its type's size. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_to(&mut self) -> io::Result where V: Primitive; /// Reads whole value from the stream whose size in bits is equal /// to its type's size in an endianness that may be different /// from the stream's endianness. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_as_to(&mut self) -> io::Result where F: Endianness, V: Primitive; /// Skips the given number of bits in the stream. /// Since this method does not need an accumulator, /// it may be slightly faster than reading to an empty variable. /// In addition, since there is no accumulator, /// there is no upper limit on the number of bits /// which may be skipped. /// These bits are still read from the stream, however, /// and are never skipped via a `seek` method. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn skip(&mut self, bits: u32) -> io::Result<()>; /// Completely fills the given buffer with whole bytes. /// If the stream is already byte-aligned, it will map /// to a faster `read_exact` call. Otherwise it will read /// bytes individually in 8-bit increments. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { for b in buf.iter_mut() { *b = self.read_in::<8, _>()?; } Ok(()) } /// Completely fills a whole buffer with bytes and returns it. /// If the stream is already byte-aligned, it will map /// to a faster `read_exact` call. Otherwise it will read /// bytes individually in 8-bit increments. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. #[inline(always)] #[deprecated(since = "1.8.0", note = "use read_to() method instead")] fn read_to_bytes(&mut self) -> io::Result<[u8; SIZE]> { self.read_to() } /// Completely fills a vector of bytes and returns it. /// If the stream is already byte-aligned, it will map /// to a faster `read_exact` call. Otherwise it will read /// bytes individually in 8-bit increments. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_to_vec(&mut self, bytes: usize) -> io::Result> { let mut buf = vec![0; bytes]; self.read_bytes(&mut buf)?; Ok(buf) } /// Counts the number of 1 bits in the stream until the next /// 0 bit and returns the amount read. /// Because this field is variably-sized and may be large, /// its output is always a `u32` type. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_unary0(&mut self) -> io::Result { let mut unary = 0; while self.read_bit()? { unary += 1; } Ok(unary) } /// Counts the number of 0 bits in the stream until the next /// 1 bit and returns the amount read. /// Because this field is variably-sized and may be large, /// its output is always a `u32` type. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_unary1(&mut self) -> io::Result { let mut unary = 0; while !(self.read_bit()?) { unary += 1; } Ok(unary) } /// Parses and returns complex type fn parse(&mut self) -> Result { F::from_reader(self) } /// Parses and returns complex type with context fn parse_with<'a, F: FromBitStreamWith<'a>>( &mut self, context: &F::Context, ) -> Result { F::from_reader(self, context) } /// Returns true if the stream is aligned at a whole byte. fn byte_aligned(&self) -> bool; /// Throws away all unread bit values until the next whole byte. /// Does nothing if the stream is already aligned. fn byte_align(&mut self); } /// A trait for anything that can read Huffman codes /// of a given endianness from an input stream pub trait HuffmanRead { /// Given a compiled Huffman tree, reads bits from the stream /// until the next symbol is encountered. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_huffman(&mut self, tree: &[ReadHuffmanTree]) -> io::Result where T: Clone; } /// For reading non-aligned bits from a stream of bytes in a given endianness. /// /// This will read exactly as many whole bytes needed to return /// the requested number of bits. It may cache up to a single partial byte /// but no more. #[derive(Clone, Debug)] pub struct BitReader { reader: R, bitqueue: BitQueue, } impl BitReader { /// Wraps a BitReader around something that implements `Read` pub fn new(reader: R) -> BitReader { BitReader { reader, bitqueue: BitQueue::new(), } } /// Wraps a BitReader around something that implements `Read` /// with the given endianness. pub fn endian(reader: R, _endian: E) -> BitReader { BitReader { reader, bitqueue: BitQueue::new(), } } /// Unwraps internal reader and disposes of BitReader. /// /// # Warning /// /// Any unread partial bits are discarded. #[inline] pub fn into_reader(self) -> R { self.reader } /// If stream is byte-aligned, provides mutable reference /// to internal reader. Otherwise returns `None` #[inline] pub fn reader(&mut self) -> Option<&mut R> { if self.byte_aligned() { Some(&mut self.reader) } else { None } } /// Converts `BitReader` to `ByteReader` in the same endianness. /// /// # Warning /// /// Any unread partial bits are discarded. #[inline] pub fn into_bytereader(self) -> ByteReader { ByteReader::new(self.into_reader()) } /// If stream is byte-aligned, provides temporary `ByteReader` /// in the same endianness. Otherwise returns `None` /// /// # Warning /// /// Any reader bits left over when `ByteReader` is dropped are lost. #[inline] pub fn bytereader(&mut self) -> Option> { self.reader().map(ByteReader::new) } /// Consumes reader and returns any un-read partial byte /// as a `(bits, value)` tuple. /// /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b1010_0101, 0b0101_1010]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read::(9).unwrap(), 0b1010_0101_0); /// let (bits, value) = reader.into_unread(); /// assert_eq!(bits, 7); /// assert_eq!(value, 0b101_1010); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b1010_0101, 0b0101_1010]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read::(8).unwrap(), 0b1010_0101); /// let (bits, value) = reader.into_unread(); /// assert_eq!(bits, 0); /// assert_eq!(value, 0); /// ``` #[inline] pub fn into_unread(self) -> (u32, u8) { (self.bitqueue.len(), self.bitqueue.value()) } } impl BitRead for BitReader { /// # Examples /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), false); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), false); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), true); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), false); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), true); /// assert_eq!(reader.read_bit().unwrap(), false); /// assert_eq!(reader.read_bit().unwrap(), true); /// ``` #[inline(always)] fn read_bit(&mut self) -> io::Result { if self.bitqueue.is_empty() { self.bitqueue.set(read_byte(&mut self.reader)?, 8); } Ok(self.bitqueue.pop(1) == 1) } /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read::(1).unwrap(), 0b1); /// assert_eq!(reader.read::(2).unwrap(), 0b01); /// assert_eq!(reader.read::(5).unwrap(), 0b10111); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read::(1).unwrap(), 0b1); /// assert_eq!(reader.read::(2).unwrap(), 0b11); /// assert_eq!(reader.read::(5).unwrap(), 0b10110); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0;10]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert!(reader.read::(9).is_err()); // can't read 9 bits to u8 /// assert!(reader.read::(17).is_err()); // can't read 17 bits to u16 /// assert!(reader.read::(33).is_err()); // can't read 33 bits to u32 /// assert!(reader.read::(65).is_err()); // can't read 65 bits to u64 /// ``` fn read(&mut self, mut bits: u32) -> io::Result where U: Numeric, { if bits <= U::BITS_SIZE { let bitqueue_len = self.bitqueue.len(); if bits <= bitqueue_len { Ok(U::from_u8(self.bitqueue.pop(bits))) } else { let mut acc = BitQueue::from_value(U::from_u8(self.bitqueue.pop_all()), bitqueue_len); bits -= bitqueue_len; read_aligned(&mut self.reader, bits / 8, &mut acc)?; read_unaligned(&mut self.reader, bits % 8, &mut acc, &mut self.bitqueue)?; Ok(acc.value()) } } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type read", )) } } /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read_in::<1, u8>().unwrap(), 0b1); /// assert_eq!(reader.read_in::<2, u8>().unwrap(), 0b01); /// assert_eq!(reader.read_in::<5, u8>().unwrap(), 0b10111); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read_in::<1, u8>().unwrap(), 0b1); /// assert_eq!(reader.read_in::<2, u8>().unwrap(), 0b11); /// assert_eq!(reader.read_in::<5, u8>().unwrap(), 0b10110); /// ``` #[inline] fn read_in(&mut self) -> io::Result where U: Numeric, { const { assert!(BITS <= U::BITS_SIZE, "excessive bits for type read"); } let bitqueue_len = self.bitqueue.len(); if BITS <= bitqueue_len { Ok(U::from_u8(self.bitqueue.pop_fixed::())) } else { let mut bits = BITS; let mut acc = BitQueue::from_value(U::from_u8(self.bitqueue.pop_all()), bitqueue_len); bits -= bitqueue_len; read_aligned(&mut self.reader, bits / 8, &mut acc)?; read_unaligned(&mut self.reader, bits % 8, &mut acc, &mut self.bitqueue)?; Ok(acc.value()) } } /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read_signed::(4).unwrap(), -5); /// assert_eq!(reader.read_signed::(4).unwrap(), 7); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read_signed::(4).unwrap(), 7); /// assert_eq!(reader.read_signed::(4).unwrap(), -5); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0;10]; /// let mut r = BitReader::endian(Cursor::new(&data), BigEndian); /// assert!(r.read_signed::(9).is_err()); // can't read 9 bits to i8 /// assert!(r.read_signed::(17).is_err()); // can't read 17 bits to i16 /// assert!(r.read_signed::(33).is_err()); // can't read 33 bits to i32 /// assert!(r.read_signed::(65).is_err()); // can't read 65 bits to i64 /// ``` #[inline] fn read_signed(&mut self, bits: u32) -> io::Result where S: SignedNumeric, { match bits { 0 => Err(io::Error::new( io::ErrorKind::InvalidInput, "signed reads need at least 1 bit for sign", )), bits if bits <= S::BITS_SIZE => E::read_signed(self, bits), _ => Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type read", )), } } /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read_signed_in::<4, i8>().unwrap(), -5); /// assert_eq!(reader.read_signed_in::<4, i8>().unwrap(), 7); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read_signed_in::<4, i8>().unwrap(), 7); /// assert_eq!(reader.read_signed_in::<4, i8>().unwrap(), -5); /// ``` #[inline] fn read_signed_in(&mut self) -> io::Result where S: SignedNumeric, { const { assert!(BITS > 0, "signed reads need at least 1 bit for sign"); assert!(BITS <= S::BITS_SIZE, "excessive bits for type read"); } E::read_signed_fixed::<_, BITS, S>(self) } #[inline] fn read_to(&mut self) -> io::Result where V: Primitive, { E::read_primitive(self) } #[inline] fn read_as_to(&mut self) -> io::Result where F: Endianness, V: Primitive, { F::read_primitive(self) } /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert!(reader.skip(3).is_ok()); /// assert_eq!(reader.read::(5).unwrap(), 0b10111); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), LittleEndian); /// assert!(reader.skip(3).is_ok()); /// assert_eq!(reader.read::(5).unwrap(), 0b10110); /// ``` fn skip(&mut self, mut bits: u32) -> io::Result<()> { use core::cmp::min; let to_drop = min(self.bitqueue.len(), bits); if to_drop != 0 { self.bitqueue.drop(to_drop); bits -= to_drop; } skip_aligned(&mut self.reader, bits / 8)?; skip_unaligned(&mut self.reader, bits % 8, &mut self.bitqueue) } /// # Example /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = b"foobar"; /// let mut reader = BitReader::endian(Cursor::new(data), BigEndian); /// assert!(reader.skip(24).is_ok()); /// let mut buf = [0;3]; /// assert!(reader.read_bytes(&mut buf).is_ok()); /// assert_eq!(&buf, b"bar"); /// ``` fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { if self.byte_aligned() { self.reader.read_exact(buf) } else { for b in buf.iter_mut() { *b = self.read_in::<8, _>()?; } Ok(()) } } /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b01110111, 0b11111110]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read_unary0().unwrap(), 0); /// assert_eq!(reader.read_unary0().unwrap(), 3); /// assert_eq!(reader.read_unary0().unwrap(), 10); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b11101110, 0b01111111]; /// let mut reader = BitReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read_unary0().unwrap(), 0); /// assert_eq!(reader.read_unary0().unwrap(), 3); /// assert_eq!(reader.read_unary0().unwrap(), 10); /// ``` fn read_unary0(&mut self) -> io::Result { if self.bitqueue.is_empty() { read_aligned_unary(&mut self.reader, 0b1111_1111, &mut self.bitqueue) .map(|u| u + self.bitqueue.pop_1()) } else if self.bitqueue.all_1() { let base = self.bitqueue.len(); self.bitqueue.clear(); read_aligned_unary(&mut self.reader, 0b1111_1111, &mut self.bitqueue) .map(|u| base + u + self.bitqueue.pop_1()) } else { Ok(self.bitqueue.pop_1()) } } /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b10001000, 0b00000001]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read_unary1().unwrap(), 0); /// assert_eq!(reader.read_unary1().unwrap(), 3); /// assert_eq!(reader.read_unary1().unwrap(), 10); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b00010001, 0b10000000]; /// let mut reader = BitReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read_unary1().unwrap(), 0); /// assert_eq!(reader.read_unary1().unwrap(), 3); /// assert_eq!(reader.read_unary1().unwrap(), 10); /// ``` fn read_unary1(&mut self) -> io::Result { if self.bitqueue.is_empty() { read_aligned_unary(&mut self.reader, 0b0000_0000, &mut self.bitqueue) .map(|u| u + self.bitqueue.pop_0()) } else if self.bitqueue.all_0() { let base = self.bitqueue.len(); self.bitqueue.clear(); read_aligned_unary(&mut self.reader, 0b0000_0000, &mut self.bitqueue) .map(|u| base + u + self.bitqueue.pop_0()) } else { Ok(self.bitqueue.pop_0()) } } /// # Example /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.byte_aligned(), true); /// assert!(reader.skip(1).is_ok()); /// assert_eq!(reader.byte_aligned(), false); /// assert!(reader.skip(7).is_ok()); /// assert_eq!(reader.byte_aligned(), true); /// ``` #[inline] fn byte_aligned(&self) -> bool { self.bitqueue.is_empty() } /// # Example /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0x00, 0xFF]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read::(4).unwrap(), 0); /// reader.byte_align(); /// assert_eq!(reader.read::(8).unwrap(), 0xFF); /// ``` #[inline] fn byte_align(&mut self) { self.bitqueue.clear() } } impl BitReader where E: Endianness, R: io::Read + io::Seek, { /// # Example /// ``` /// use std::io::{Read, Cursor, SeekFrom}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0x00, 0xFF]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.position_in_bits().unwrap(), 0); /// /// let pos = reader.seek_bits(SeekFrom::Start(5)).unwrap(); /// assert!(pos == 5 && 5 == reader.position_in_bits().unwrap()); /// /// let pos = reader.seek_bits(SeekFrom::Current(-2)).unwrap(); /// assert!(pos == 3 && 3 == reader.position_in_bits().unwrap()); /// /// /// let pos = reader.seek_bits(SeekFrom::End(5)).unwrap(); /// assert!(pos == 11 && 11 == reader.position_in_bits().unwrap()); /// ``` pub fn seek_bits(&mut self, from: io::SeekFrom) -> io::Result { match from { io::SeekFrom::Start(from_start_pos) => { let (bytes, bits) = (from_start_pos / 8, (from_start_pos % 8) as u32); self.byte_align(); self.reader.seek(io::SeekFrom::Start(bytes))?; self.skip(bits)?; Ok(from_start_pos) } io::SeekFrom::End(from_end_pos) => { let reader_end = self.reader.seek(io::SeekFrom::End(0))?; let new_pos = (reader_end * 8) as i64 - from_end_pos; assert!(new_pos >= 0, "The final position should be greater than 0"); self.seek_bits(io::SeekFrom::Start(new_pos as u64)) } io::SeekFrom::Current(offset) => { let new_pos = self.position_in_bits()? as i64 + offset; assert!(new_pos >= 0, "The final position should be greater than 0"); self.seek_bits(io::SeekFrom::Start(new_pos as u64)) } } } /// # Example /// ``` /// use std::fs::read; /// use std::io::{Read, Cursor, SeekFrom}; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0x00, 0xFF]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.position_in_bits().unwrap(), 0); /// /// let _: i32 = reader.read_signed(5).unwrap(); /// assert_eq!(reader.position_in_bits().unwrap(), 5); /// /// reader.read_bit().unwrap(); /// assert_eq!(reader.position_in_bits().unwrap(), 6); /// ``` #[inline] pub fn position_in_bits(&mut self) -> io::Result { let bytes = self.reader.seek(SeekFrom::Current(0))?; Ok(bytes * 8 - (self.bitqueue.len() as u64)) } } impl HuffmanRead for BitReader { /// # Example /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, BitReader, HuffmanRead}; /// use bitstream_io::huffman::compile_read_tree; /// let tree = compile_read_tree( /// vec![('a', vec![0]), /// ('b', vec![1, 0]), /// ('c', vec![1, 1, 0]), /// ('d', vec![1, 1, 1])]).unwrap(); /// let data = [0b10110111]; /// let mut reader = BitReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read_huffman(&tree).unwrap(), 'b'); /// assert_eq!(reader.read_huffman(&tree).unwrap(), 'c'); /// assert_eq!(reader.read_huffman(&tree).unwrap(), 'd'); /// ``` fn read_huffman(&mut self, tree: &[ReadHuffmanTree]) -> io::Result where T: Clone, { let mut result: &ReadHuffmanTree = &tree[self.bitqueue.to_state()]; loop { match result { ReadHuffmanTree::Done(ref value, ref queue_val, ref queue_bits, _) => { self.bitqueue.set(*queue_val, *queue_bits); return Ok(value.clone()); } ReadHuffmanTree::Continue(ref tree) => { result = &tree[read_byte(&mut self.reader)? as usize]; } ReadHuffmanTree::InvalidState => { panic!("invalid state"); } } } } } #[inline] fn read_byte(mut reader: R) -> io::Result where R: io::Read, { let mut byte = 0; reader .read_exact(core::slice::from_mut(&mut byte)) .map(|()| byte) } fn read_aligned(mut reader: R, bytes: u32, acc: &mut BitQueue) -> io::Result<()> where R: io::Read, E: Endianness, N: Numeric, { if bytes > 0 { let mut buf = N::buffer(); reader.read_exact(&mut buf.as_mut()[0..bytes as usize])?; for b in &buf.as_ref()[0..bytes as usize] { acc.push_fixed::<8>(N::from_u8(*b)); } } Ok(()) } fn skip_aligned(mut reader: R, mut bytes: u32) -> io::Result<()> where R: io::Read, { use core::cmp::min; /*skip up to 8 bytes at a time (unlike with read_aligned, "bytes" may be larger than any native type)*/ let mut buf = [0; 8]; while bytes > 0 { let to_read = min(8, bytes); reader.read_exact(&mut buf[0..to_read as usize])?; bytes -= to_read; } Ok(()) } #[inline] fn read_unaligned( reader: R, bits: u32, acc: &mut BitQueue, rem: &mut BitQueue, ) -> io::Result<()> where R: io::Read, E: Endianness, N: Numeric, { debug_assert!(bits <= 8); if bits > 0 { rem.set(read_byte(reader)?, 8); acc.push(bits, N::from_u8(rem.pop(bits))); } Ok(()) } #[inline] fn skip_unaligned(reader: R, bits: u32, rem: &mut BitQueue) -> io::Result<()> where R: io::Read, E: Endianness, { debug_assert!(bits <= 8); if bits > 0 { rem.set(read_byte(reader)?, 8); rem.pop(bits); } Ok(()) } #[inline] fn read_aligned_unary( mut reader: R, continue_val: u8, rem: &mut BitQueue, ) -> io::Result where R: io::Read, E: Endianness, { let mut acc = 0; let mut byte = read_byte(reader.by_ref())?; while byte == continue_val { acc += 8; byte = read_byte(reader.by_ref())?; } rem.set(byte, 8); Ok(acc) } /// A trait for anything that can read aligned values from an input stream pub trait ByteRead { /// Reads whole numeric value from stream /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, ByteReader, ByteRead}; /// let data = [0b00000000, 0b11111111]; /// let mut reader = ByteReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read::().unwrap(), 0b0000000011111111); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{LittleEndian, ByteReader, ByteRead}; /// let data = [0b00000000, 0b11111111]; /// let mut reader = ByteReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read::().unwrap(), 0b1111111100000000); /// ``` fn read(&mut self) -> Result where V: Primitive; /// Reads whole numeric value from stream in a potentially different endianness /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// /// # Examples /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, ByteReader, ByteRead, LittleEndian}; /// let data = [0b00000000, 0b11111111]; /// let mut reader = ByteReader::endian(Cursor::new(&data), BigEndian); /// assert_eq!(reader.read_as::().unwrap(), 0b1111111100000000); /// ``` /// /// ``` /// use std::io::{Read, Cursor}; /// use bitstream_io::{BigEndian, ByteReader, ByteRead, LittleEndian}; /// let data = [0b00000000, 0b11111111]; /// let mut reader = ByteReader::endian(Cursor::new(&data), LittleEndian); /// assert_eq!(reader.read_as::().unwrap(), 0b0000000011111111); /// ``` fn read_as(&mut self) -> Result where F: Endianness, V: Primitive; /// Completely fills the given buffer with whole bytes. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { for b in buf.iter_mut() { *b = self.read()?; } Ok(()) } /// Completely fills a whole buffer with bytes and returns it. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. #[inline(always)] #[deprecated(since = "1.8.0", note = "use read() method instead")] fn read_to_bytes(&mut self) -> io::Result<[u8; SIZE]> { self.read() } /// Completely fills a vector of bytes and returns it. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_to_vec(&mut self, bytes: usize) -> io::Result> { let mut buf = vec![0; bytes]; self.read_bytes(&mut buf)?; Ok(buf) } /// Skips the given number of bytes in the stream. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn skip(&mut self, bytes: u32) -> io::Result<()>; /// Parses and returns complex type fn parse(&mut self) -> Result { F::from_reader(self) } /// Parses and returns complex type with context fn parse_with<'a, F: FromByteStreamWith<'a>>( &mut self, context: &F::Context, ) -> Result { F::from_reader(self, context) } /// Returns mutable reference to underlying reader fn reader_ref(&mut self) -> &mut dyn io::Read; } /// For reading aligned bytes from a stream of bytes in a given endianness. /// /// This only reads aligned values and maintains no internal state. #[derive(Debug)] pub struct ByteReader { phantom: PhantomData, reader: R, } impl ByteReader { /// Wraps a ByteReader around something that implements `Read` pub fn new(reader: R) -> ByteReader { ByteReader { phantom: PhantomData, reader, } } /// Wraps a ByteReader around something that implements `Read` /// with the given endianness. pub fn endian(reader: R, _endian: E) -> ByteReader { ByteReader { phantom: PhantomData, reader, } } /// Unwraps internal reader and disposes of `ByteReader`. #[inline] pub fn into_reader(self) -> R { self.reader } /// Provides mutable reference to internal reader #[inline] pub fn reader(&mut self) -> &mut R { &mut self.reader } /// Converts `ByteReader` to `BitReader` in the same endianness. #[inline] pub fn into_bitreader(self) -> BitReader { BitReader::new(self.into_reader()) } /// Provides temporary `BitReader` in the same endianness. /// /// # Warning /// /// Any unread bits left over when `BitReader` is dropped are lost. #[inline] pub fn bitreader(&mut self) -> BitReader<&mut R, E> { BitReader::new(self.reader()) } } impl ByteRead for ByteReader { #[inline] fn read(&mut self) -> Result where V: Primitive, { E::read_numeric(&mut self.reader) } #[inline] fn read_as(&mut self) -> Result where F: Endianness, V: Primitive, { F::read_numeric(&mut self.reader) } #[inline] fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { self.reader.read_exact(buf) } #[inline] fn skip(&mut self, bytes: u32) -> io::Result<()> { skip_aligned(&mut self.reader, bytes) } #[inline] fn reader_ref(&mut self) -> &mut dyn io::Read { &mut self.reader } } /// Implemented by complex types that don't require any additional context /// to parse themselves from a reader. Analagous to `FromStr`. /// /// # Example /// ``` /// use std::io::{Cursor, Read}; /// use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStream}; /// /// #[derive(Debug, PartialEq, Eq)] /// struct BlockHeader { /// last_block: bool, /// block_type: u8, /// block_size: u32, /// } /// /// impl FromBitStream for BlockHeader { /// type Error = std::io::Error; /// /// fn from_reader(r: &mut R) -> std::io::Result { /// Ok(Self { /// last_block: r.read_bit()?, /// block_type: r.read(7)?, /// block_size: r.read(24)?, /// }) /// } /// } /// /// let mut reader = BitReader::endian(Cursor::new(b"\x04\x00\x00\x7A"), BigEndian); /// assert_eq!( /// reader.parse::().unwrap(), /// BlockHeader { last_block: false, block_type: 4, block_size: 122 } /// ); /// ``` pub trait FromBitStream { /// Error generated during parsing, such as `io::Error` type Error; /// Parse Self from reader fn from_reader(r: &mut R) -> Result where Self: Sized; } /// Implemented by complex types that require some immutable context /// to parse themselves from a reader. /// /// # Example /// ``` /// use std::io::{Cursor, Read}; /// use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStreamWith}; /// /// #[derive(Default)] /// struct Streaminfo { /// minimum_block_size: u16, /// maximum_block_size: u16, /// minimum_frame_size: u32, /// maximum_frame_size: u32, /// sample_rate: u32, /// channels: u8, /// bits_per_sample: u8, /// total_samples: u64, /// md5: [u8; 16], /// } /// /// #[derive(Debug, PartialEq, Eq)] /// struct FrameHeader { /// variable_block_size: bool, /// block_size: u32, /// sample_rate: u32, /// channel_assignment: u8, /// sample_size: u8, /// frame_number: u64, /// crc8: u8, /// } /// /// impl FromBitStreamWith<'_> for FrameHeader { /// type Context = Streaminfo; /// /// type Error = FrameHeaderError; /// /// fn from_reader( /// r: &mut R, /// streaminfo: &Streaminfo, /// ) -> Result { /// if r.read::(14)? != 0b11111111111110 { /// return Err(FrameHeaderError::InvalidSync); /// } /// /// if r.read_bit()? != false { /// return Err(FrameHeaderError::InvalidReservedBit); /// } /// /// let variable_block_size = r.read_bit()?; /// /// let block_size_bits = r.read::(4)?; /// /// let sample_rate_bits = r.read::(4)?; /// /// let channel_assignment = r.read::(4)?; /// /// let sample_size = match r.read::(3)? { /// 0b000 => streaminfo.bits_per_sample, /// 0b001 => 8, /// 0b010 => 12, /// 0b011 => return Err(FrameHeaderError::InvalidSampleSize), /// 0b100 => 16, /// 0b101 => 20, /// 0b110 => 24, /// 0b111 => 32, /// _ => unreachable!(), /// }; /// /// if r.read_bit()? != false { /// return Err(FrameHeaderError::InvalidReservedBit); /// } /// /// let frame_number = read_utf8(r)?; /// /// Ok(FrameHeader { /// variable_block_size, /// block_size: match block_size_bits { /// 0b0000 => return Err(FrameHeaderError::InvalidBlockSize), /// 0b0001 => 192, /// n @ 0b010..=0b0101 => 576 * (1 << (n - 2)), /// 0b0110 => r.read::(8)? + 1, /// 0b0111 => r.read::(16)? + 1, /// n @ 0b1000..=0b1111 => 256 * (1 << (n - 8)), /// _ => unreachable!(), /// }, /// sample_rate: match sample_rate_bits { /// 0b0000 => streaminfo.sample_rate, /// 0b0001 => 88200, /// 0b0010 => 176400, /// 0b0011 => 192000, /// 0b0100 => 8000, /// 0b0101 => 16000, /// 0b0110 => 22050, /// 0b0111 => 24000, /// 0b1000 => 32000, /// 0b1001 => 44100, /// 0b1010 => 48000, /// 0b1011 => 96000, /// 0b1100 => r.read::(8)? * 1000, /// 0b1101 => r.read::(16)?, /// 0b1110 => r.read::(16)? * 10, /// 0b1111 => return Err(FrameHeaderError::InvalidSampleRate), /// _ => unreachable!(), /// }, /// channel_assignment, /// sample_size, /// frame_number, /// crc8: r.read(8)? /// }) /// } /// } /// /// #[derive(Debug)] /// enum FrameHeaderError { /// Io(std::io::Error), /// InvalidSync, /// InvalidReservedBit, /// InvalidSampleSize, /// InvalidBlockSize, /// InvalidSampleRate, /// } /// /// impl From for FrameHeaderError { /// fn from(err: std::io::Error) -> Self { /// Self::Io(err) /// } /// } /// /// fn read_utf8(r: &mut R) -> Result { /// r.read(8) // left unimplimented in this example /// } /// /// let mut reader = BitReader::endian(Cursor::new(b"\xFF\xF8\xC9\x18\x00\xC2"), BigEndian); /// assert_eq!( /// reader.parse_with::(&Streaminfo::default()).unwrap(), /// FrameHeader { /// variable_block_size: false, /// block_size: 4096, /// sample_rate: 44100, /// channel_assignment: 1, /// sample_size: 16, /// frame_number: 0, /// crc8: 0xC2, /// } /// ); /// ``` /// /// # Example with lifetime-contrained `Context` /// /// In some cases, the `Context` can depend on a reference to another `struct`. /// /// ``` /// use std::io::{Cursor, Read}; /// use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStreamWith}; /// /// #[derive(Default)] /// struct ModeParameters { /// size_len: u8, /// index_len: u8, /// index_delta_len: u8, /// // ... /// } /// /// struct AuHeaderParseContext<'a> { /// params: &'a ModeParameters, /// base_index: Option, /// } /// /// #[derive(Debug, PartialEq, Eq)] /// struct AuHeader { /// size: u32, /// index: u32, /// // ... /// } /// /// impl<'a> FromBitStreamWith<'a> for AuHeader { /// type Context = AuHeaderParseContext<'a>; /// /// type Error = AuHeaderError; /// /// fn from_reader( /// r: &mut R, /// ctx: &AuHeaderParseContext<'a>, /// ) -> Result { /// let size = r.read::(ctx.params.size_len as u32)?; /// let index = match ctx.base_index { /// None => r.read::(ctx.params.index_len as u32)?, /// Some(base_index) => { /// base_index /// + 1 /// + r.read::(ctx.params.index_delta_len as u32)? /// } /// }; /// /// Ok(AuHeader { /// size, /// index, /// // ... /// }) /// } /// } /// /// #[derive(Debug)] /// enum AuHeaderError { /// Io(std::io::Error), /// } /// /// impl From for AuHeaderError { /// fn from(err: std::io::Error) -> Self { /// Self::Io(err) /// } /// } /// /// let mut reader = BitReader::endian(Cursor::new(b"\xFF\xEA\xFF\x10"), BigEndian); /// /// let mode_params = ModeParameters { /// size_len: 10, /// index_len: 6, /// index_delta_len: 2, /// // ... /// }; /// /// let mut ctx = AuHeaderParseContext { /// params: &mode_params, /// base_index: None, /// }; /// /// let header1 = reader.parse_with::(&ctx).unwrap(); /// assert_eq!( /// header1, /// AuHeader { /// size: 1023, /// index: 42, /// } /// ); /// /// ctx.base_index = Some(header1.index); /// /// assert_eq!( /// reader.parse_with::(&ctx).unwrap(), /// AuHeader { /// size: 1020, /// index: 44, /// } /// ); /// ``` pub trait FromBitStreamWith<'a> { /// Some context to use when parsing type Context: 'a; /// Error generated during parsing, such as `io::Error` type Error; /// Parse Self from reader with the given context fn from_reader( r: &mut R, context: &Self::Context, ) -> Result where Self: Sized; } /// Implemented by complex types that don't require any additional context /// to parse themselves from a reader. Analagous to `FromStr`. pub trait FromByteStream { /// Error generated during parsing, such as `io::Error` type Error; /// Parse Self from reader fn from_reader(r: &mut R) -> Result where Self: Sized; } /// Implemented by complex types that require some additional context /// to parse themselves from a reader. Analagous to `FromStr`. pub trait FromByteStreamWith<'a> { /// Some context to use when parsing type Context: 'a; /// Error generated during parsing, such as `io::Error` type Error; /// Parse Self from reader fn from_reader( r: &mut R, context: &Self::Context, ) -> Result where Self: Sized; } bitstream-io-2.5.0/src/write.rs000064400000000000000000001435171046102023000145310ustar 00000000000000// Copyright 2017 Brian Langenberger // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Traits and implementations for writing bits to a stream. //! //! ## Example //! //! Writing the initial STREAMINFO block to a FLAC file, //! as documented in its //! [specification](https://xiph.org/flac/format.html#stream). //! //! ``` //! use std::convert::TryInto; //! use std::io::Write; //! use bitstream_io::{BigEndian, BitWriter, BitWrite, ByteWriter, ByteWrite, LittleEndian, ToBitStream}; //! //! #[derive(Debug, PartialEq, Eq)] //! struct BlockHeader { //! last_block: bool, // 1 bit //! block_type: u8, // 7 bits //! block_size: u32, // 24 bits //! } //! //! impl ToBitStream for BlockHeader { //! type Error = std::io::Error; //! //! fn to_writer(&self, w: &mut W) -> std::io::Result<()> { //! w.write_bit(self.last_block)?; //! w.write_out::<7, _>(self.block_type)?; //! w.write_out::<24, _>(self.block_size) //! } //! } //! //! #[derive(Debug, PartialEq, Eq)] //! struct Streaminfo { //! minimum_block_size: u16, // 16 bits //! maximum_block_size: u16, // 16 bits //! minimum_frame_size: u32, // 24 bits //! maximum_frame_size: u32, // 24 bits //! sample_rate: u32, // 20 bits //! channels: u8, // 3 bits //! bits_per_sample: u8, // 5 bits //! total_samples: u64, // 36 bits //! md5: [u8; 16], // 16 bytes //! } //! //! impl ToBitStream for Streaminfo { //! type Error = std::io::Error; //! //! fn to_writer(&self, w: &mut W) -> std::io::Result<()> { //! w.write_from(self.minimum_block_size)?; //! w.write_from(self.maximum_block_size)?; //! w.write_out::<24, _>(self.minimum_frame_size)?; //! w.write_out::<24, _>(self.maximum_frame_size)?; //! w.write_out::<20, _>(self.sample_rate)?; //! w.write_out::<3, _>(self.channels - 1)?; //! w.write_out::<5, _>(self.bits_per_sample - 1)?; //! w.write_out::<36, _>(self.total_samples)?; //! w.write_bytes(&self.md5) //! } //! } //! //! #[derive(Debug, PartialEq, Eq)] //! struct VorbisComment { //! vendor: String, //! comment: Vec, //! } //! //! impl VorbisComment { //! fn len(&self) -> usize { //! 4 + self.vendor.len() + 4 + self.comment.iter().map(|c| 4 + c.len()).sum::() //! } //! //! fn write(&self, w: &mut ByteWriter) -> std::io::Result<()> { //! use std::convert::TryInto; //! //! fn write_entry( //! w: &mut ByteWriter, //! s: &str, //! ) -> std::io::Result<()> { //! w.write::(s.len().try_into().unwrap())?; //! w.write_bytes(s.as_bytes()) //! } //! //! write_entry(w, &self.vendor)?; //! w.write::(self.comment.len().try_into().unwrap())?; //! self.comment.iter().try_for_each(|s| write_entry(w, s)) //! } //! } //! //! let mut flac: Vec = Vec::new(); //! //! let mut writer = BitWriter::endian(&mut flac, BigEndian); //! //! // stream marker //! writer.write_bytes(b"fLaC").unwrap(); //! //! // metadata block header //! writer.build(&BlockHeader { last_block: false, block_type: 0, block_size: 34 }).unwrap(); //! //! // STREAMINFO block //! writer.build(&Streaminfo { //! minimum_block_size: 4096, //! maximum_block_size: 4096, //! minimum_frame_size: 1542, //! maximum_frame_size: 8546, //! sample_rate: 44100, //! channels: 2, //! bits_per_sample: 16, //! total_samples: 304844, //! md5: *b"\xFA\xF2\x69\x2F\xFD\xEC\x2D\x5B\x30\x01\x76\xB4\x62\x88\x7D\x92", //! }).unwrap(); //! //! let comment = VorbisComment { //! vendor: "reference libFLAC 1.1.4 20070213".to_string(), //! comment: vec![ //! "title=2ch 44100 16bit".to_string(), //! "album=Test Album".to_string(), //! "artist=Assorted".to_string(), //! "tracknumber=1".to_string(), //! ], //! }; //! //! // metadata block header //! writer.build( //! &BlockHeader { //! last_block: false, //! block_type: 4, //! block_size: comment.len().try_into().unwrap(), //! } //! ).unwrap(); //! //! // VORBIS_COMMENT block (little endian) //! comment.write(&mut ByteWriter::new(writer.writer().unwrap())).unwrap(); //! //! assert_eq!(flac, vec![0x66,0x4c,0x61,0x43,0x00,0x00,0x00,0x22, //! 0x10,0x00,0x10,0x00,0x00,0x06,0x06,0x00, //! 0x21,0x62,0x0a,0xc4,0x42,0xf0,0x00,0x04, //! 0xa6,0xcc,0xfa,0xf2,0x69,0x2f,0xfd,0xec, //! 0x2d,0x5b,0x30,0x01,0x76,0xb4,0x62,0x88, //! 0x7d,0x92,0x04,0x00,0x00,0x7a,0x20,0x00, //! 0x00,0x00,0x72,0x65,0x66,0x65,0x72,0x65, //! 0x6e,0x63,0x65,0x20,0x6c,0x69,0x62,0x46, //! 0x4c,0x41,0x43,0x20,0x31,0x2e,0x31,0x2e, //! 0x34,0x20,0x32,0x30,0x30,0x37,0x30,0x32, //! 0x31,0x33,0x04,0x00,0x00,0x00,0x16,0x00, //! 0x00,0x00,0x74,0x69,0x74,0x6c,0x65,0x3d, //! 0x32,0x63,0x68,0x20,0x34,0x34,0x31,0x30, //! 0x30,0x20,0x20,0x31,0x36,0x62,0x69,0x74, //! 0x10,0x00,0x00,0x00,0x61,0x6c,0x62,0x75, //! 0x6d,0x3d,0x54,0x65,0x73,0x74,0x20,0x41, //! 0x6c,0x62,0x75,0x6d,0x0f,0x00,0x00,0x00, //! 0x61,0x72,0x74,0x69,0x73,0x74,0x3d,0x41, //! 0x73,0x73,0x6f,0x72,0x74,0x65,0x64,0x0d, //! 0x00,0x00,0x00,0x74,0x72,0x61,0x63,0x6b, //! 0x6e,0x75,0x6d,0x62,0x65,0x72,0x3d,0x31]); //! ``` #![warn(missing_docs)] #[cfg(feature = "alloc")] use alloc::boxed::Box; #[cfg(feature = "alloc")] use alloc::vec::Vec; #[cfg(feature = "alloc")] use core2::io; #[cfg(not(feature = "alloc"))] use std::io; use core::convert::From; use core::ops::{AddAssign, Rem}; use super::{ huffman::WriteHuffmanTree, BitQueue, Endianness, Numeric, PhantomData, Primitive, SignedNumeric, }; /// For writing bit values to an underlying stream in a given endianness. /// /// Because this only writes whole bytes to the underlying stream, /// it is important that output is byte-aligned before the bitstream /// writer's lifetime ends. /// **Partial bytes will be lost** if the writer is disposed of /// before they can be written. pub struct BitWriter { writer: W, bitqueue: BitQueue, } impl BitWriter { /// Wraps a BitWriter around something that implements `Write` pub fn new(writer: W) -> BitWriter { BitWriter { writer, bitqueue: BitQueue::new(), } } /// Wraps a BitWriter around something that implements `Write` /// with the given endianness. pub fn endian(writer: W, _endian: E) -> BitWriter { BitWriter { writer, bitqueue: BitQueue::new(), } } /// Unwraps internal writer and disposes of BitWriter. /// /// # Warning /// /// Any unwritten partial bits are discarded. #[inline] pub fn into_writer(self) -> W { self.writer } /// If stream is byte-aligned, provides mutable reference /// to internal writer. Otherwise returns `None` #[inline] pub fn writer(&mut self) -> Option<&mut W> { if self.byte_aligned() { Some(&mut self.writer) } else { None } } /// Converts `BitWriter` to `ByteWriter` in the same endianness. /// /// # Warning /// /// Any written partial bits are discarded. #[inline] pub fn into_bytewriter(self) -> ByteWriter { ByteWriter::new(self.into_writer()) } /// If stream is byte-aligned, provides temporary `ByteWriter` /// in the same endianness. Otherwise returns `None` /// /// # Warning /// /// Any unwritten bits left over when `ByteWriter` is dropped are lost. #[inline] pub fn bytewriter(&mut self) -> Option> { self.writer().map(ByteWriter::new) } /// Consumes writer and returns any un-written partial byte /// as a `(bits, value)` tuple. /// /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut data = Vec::new(); /// let (bits, value) = { /// let mut writer = BitWriter::endian(&mut data, BigEndian); /// writer.write(15, 0b1010_0101_0101_101).unwrap(); /// writer.into_unwritten() /// }; /// assert_eq!(data, [0b1010_0101]); /// assert_eq!(bits, 7); /// assert_eq!(value, 0b0101_101); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut data = Vec::new(); /// let (bits, value) = { /// let mut writer = BitWriter::endian(&mut data, BigEndian); /// writer.write(8, 0b1010_0101).unwrap(); /// writer.into_unwritten() /// }; /// assert_eq!(data, [0b1010_0101]); /// assert_eq!(bits, 0); /// assert_eq!(value, 0); /// ``` #[inline(always)] pub fn into_unwritten(self) -> (u32, u8) { (self.bitqueue.len(), self.bitqueue.value()) } /// Flushes output stream to disk, if necessary. /// Any partial bytes are not flushed. /// /// # Errors /// /// Passes along any errors from the underlying stream. #[inline(always)] pub fn flush(&mut self) -> io::Result<()> { self.writer.flush() } } /// A trait for anything that can write a variable number of /// potentially un-aligned values to an output stream pub trait BitWrite { /// Writes a single bit to the stream. /// `true` indicates 1, `false` indicates 0 /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn write_bit(&mut self, bit: bool) -> io::Result<()>; /// Writes an unsigned value to the stream using the given /// number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if the input type is too small /// to hold the given number of bits. /// Returns an error if the value is too large /// to fit the given number of bits. fn write(&mut self, bits: u32, value: U) -> io::Result<()> where U: Numeric; /// Writes an unsigned value to the stream using the given /// const number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if the value is too large /// to fit the given number of bits. /// A compile-time error occurs if the given number of bits /// is larger than the output type. fn write_out(&mut self, value: U) -> io::Result<()> where U: Numeric, { self.write(BITS, value) } /// Writes a twos-complement signed value to the stream /// with the given number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if the input type is too small /// to hold the given number of bits. /// Returns an error if the number of bits is 0, /// since one bit is always needed for the sign. /// Returns an error if the value is too large /// to fit the given number of bits. fn write_signed(&mut self, bits: u32, value: S) -> io::Result<()> where S: SignedNumeric; /// Writes a twos-complement signed value to the stream /// with the given const number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if the value is too large /// to fit the given number of bits. /// A compile-time error occurs if the number of bits is 0, /// since one bit is always needed for the sign. /// A compile-time error occurs if the given number of bits /// is larger than the output type. fn write_signed_out(&mut self, value: S) -> io::Result<()> where S: SignedNumeric; /// Writes whole value to the stream whose size in bits /// is equal to its type's size. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive; /// Writes whole value to the stream whose size in bits /// is equal to its type's size in an endianness that may /// be different from the stream's endianness. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive; /// Writes the entirety of a byte buffer to the stream. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// /// # Example /// /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write(8, 0x66).unwrap(); /// writer.write(8, 0x6F).unwrap(); /// writer.write(8, 0x6F).unwrap(); /// writer.write_bytes(b"bar").unwrap(); /// assert_eq!(writer.into_writer(), b"foobar"); /// ``` #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { buf.iter().try_for_each(|b| self.write_out::<8, _>(*b)) } /// Writes `value` number of 1 bits to the stream /// and then writes a 0 bit. This field is variably-sized. /// /// # Errors /// /// Passes along any I/O error from the underyling stream. /// /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_unary0(0).unwrap(); /// writer.write_unary0(3).unwrap(); /// writer.write_unary0(10).unwrap(); /// assert_eq!(writer.into_writer(), [0b01110111, 0b11111110]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); /// writer.write_unary0(0).unwrap(); /// writer.write_unary0(3).unwrap(); /// writer.write_unary0(10).unwrap(); /// assert_eq!(writer.into_writer(), [0b11101110, 0b01111111]); /// ``` fn write_unary0(&mut self, value: u32) -> io::Result<()> { match value { 0 => self.write_bit(false), bits @ 1..=31 => self .write(value, (1u32 << bits) - 1) .and_then(|()| self.write_bit(false)), 32 => self .write(value, 0xFFFF_FFFFu32) .and_then(|()| self.write_bit(false)), bits @ 33..=63 => self .write(value, (1u64 << bits) - 1) .and_then(|()| self.write_bit(false)), 64 => self .write(value, 0xFFFF_FFFF_FFFF_FFFFu64) .and_then(|()| self.write_bit(false)), mut bits => { while bits > 64 { self.write(64, 0xFFFF_FFFF_FFFF_FFFFu64)?; bits -= 64; } self.write_unary0(bits) } } } /// Writes `value` number of 0 bits to the stream /// and then writes a 1 bit. This field is variably-sized. /// /// # Errors /// /// Passes along any I/O error from the underyling stream. /// /// # Example /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_unary1(0).unwrap(); /// writer.write_unary1(3).unwrap(); /// writer.write_unary1(10).unwrap(); /// assert_eq!(writer.into_writer(), [0b10001000, 0b00000001]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); /// writer.write_unary1(0).unwrap(); /// writer.write_unary1(3).unwrap(); /// writer.write_unary1(10).unwrap(); /// assert_eq!(writer.into_writer(), [0b00010001, 0b10000000]); /// ``` fn write_unary1(&mut self, value: u32) -> io::Result<()> { match value { 0 => self.write_bit(true), 1..=32 => self.write(value, 0u32).and_then(|()| self.write_bit(true)), 33..=64 => self.write(value, 0u64).and_then(|()| self.write_bit(true)), mut bits => { while bits > 64 { self.write(64, 0u64)?; bits -= 64; } self.write_unary1(bits) } } } /// Builds and writes complex type fn build(&mut self, build: &T) -> Result<(), T::Error> { build.to_writer(self) } /// Builds and writes complex type with context fn build_with<'a, T: ToBitStreamWith<'a>>( &mut self, build: &T, context: &T::Context, ) -> Result<(), T::Error> { build.to_writer(self, context) } /// Returns true if the stream is aligned at a whole byte. fn byte_aligned(&self) -> bool; /// Pads the stream with 0 bits until it is aligned at a whole byte. /// Does nothing if the stream is already aligned. /// /// # Errors /// /// Passes along any I/O error from the underyling stream. /// /// # Example /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write(1, 0).unwrap(); /// writer.byte_align().unwrap(); /// writer.write(8, 0xFF).unwrap(); /// assert_eq!(writer.into_writer(), [0x00, 0xFF]); /// ``` fn byte_align(&mut self) -> io::Result<()> { while !self.byte_aligned() { self.write_bit(false)?; } Ok(()) } } /// A trait for anything that can write Huffman codes /// of a given endianness to an output stream pub trait HuffmanWrite { /// Writes Huffman code for the given symbol to the stream. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn write_huffman(&mut self, tree: &WriteHuffmanTree, symbol: T) -> io::Result<()> where T: Ord + Copy; } impl BitWrite for BitWriter { /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_bit(true).unwrap(); /// writer.write_bit(false).unwrap(); /// writer.write_bit(true).unwrap(); /// writer.write_bit(true).unwrap(); /// writer.write_bit(false).unwrap(); /// writer.write_bit(true).unwrap(); /// writer.write_bit(true).unwrap(); /// writer.write_bit(true).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); /// writer.write_bit(true).unwrap(); /// writer.write_bit(true).unwrap(); /// writer.write_bit(true).unwrap(); /// writer.write_bit(false).unwrap(); /// writer.write_bit(true).unwrap(); /// writer.write_bit(true).unwrap(); /// writer.write_bit(false).unwrap(); /// writer.write_bit(true).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` fn write_bit(&mut self, bit: bool) -> io::Result<()> { self.bitqueue.push(1, u8::from(bit)); if self.bitqueue.is_full() { write_byte(&mut self.writer, self.bitqueue.pop(8)) } else { Ok(()) } } /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write(1, 0b1).unwrap(); /// writer.write(2, 0b01).unwrap(); /// writer.write(5, 0b10111).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); /// writer.write(1, 0b1).unwrap(); /// writer.write(2, 0b11).unwrap(); /// writer.write(5, 0b10110).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use std::io::{Write, sink}; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut w = BitWriter::endian(sink(), BigEndian); /// assert!(w.write(9, 0u8).is_err()); // can't write u8 in 9 bits /// assert!(w.write(17, 0u16).is_err()); // can't write u16 in 17 bits /// assert!(w.write(33, 0u32).is_err()); // can't write u32 in 33 bits /// assert!(w.write(65, 0u64).is_err()); // can't write u64 in 65 bits /// assert!(w.write(1, 2).is_err()); // can't write 2 in 1 bit /// assert!(w.write(2, 4).is_err()); // can't write 4 in 2 bits /// assert!(w.write(3, 8).is_err()); // can't write 8 in 3 bits /// assert!(w.write(4, 16).is_err()); // can't write 16 in 4 bits /// ``` fn write(&mut self, bits: u32, value: U) -> io::Result<()> where U: Numeric, { if bits > U::BITS_SIZE { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type written", )) } else if (bits < U::BITS_SIZE) && (value >= (U::ONE << bits)) { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive value for bits written", )) } else if bits < self.bitqueue.remaining_len() { self.bitqueue.push(bits, value.to_u8()); Ok(()) } else { let mut acc = BitQueue::from_value(value, bits); write_unaligned(&mut self.writer, &mut acc, &mut self.bitqueue)?; write_aligned(&mut self.writer, &mut acc)?; self.bitqueue.push(acc.len(), acc.value().to_u8()); Ok(()) } } /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_out::<1, _>(0b1).unwrap(); /// writer.write_out::<2, _>(0b01).unwrap(); /// writer.write_out::<5, _>(0b10111).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); /// writer.write_out::<1, _>(0b1).unwrap(); /// writer.write_out::<2, _>(0b11).unwrap(); /// writer.write_out::<5, _>(0b10110).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use std::io::{Write, sink}; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut w = BitWriter::endian(sink(), BigEndian); /// assert!(w.write_out::<1, _>(2).is_err()); // can't write 2 in 1 bit /// assert!(w.write_out::<2, _>(4).is_err()); // can't write 4 in 2 bits /// assert!(w.write_out::<3, _>(8).is_err()); // can't write 8 in 3 bits /// assert!(w.write_out::<4, _>(16).is_err()); // can't write 16 in 4 bits /// ``` fn write_out(&mut self, value: U) -> io::Result<()> where U: Numeric, { const { assert!(BITS <= U::BITS_SIZE, "excessive bits for type written"); } if (BITS < U::BITS_SIZE) && (value >= (U::ONE << BITS)) { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive value for bits written", )) } else if BITS < self.bitqueue.remaining_len() { self.bitqueue.push_fixed::(value.to_u8()); Ok(()) } else { let mut acc = BitQueue::from_value(value, BITS); write_unaligned(&mut self.writer, &mut acc, &mut self.bitqueue)?; write_aligned(&mut self.writer, &mut acc)?; self.bitqueue.push(acc.len(), acc.value().to_u8()); Ok(()) } } /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_signed(4, -5).unwrap(); /// writer.write_signed(4, 7).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); /// writer.write_signed(4, 7).unwrap(); /// writer.write_signed(4, -5).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` #[inline] fn write_signed(&mut self, bits: u32, value: S) -> io::Result<()> where S: SignedNumeric, { match bits { 0 => Err(io::Error::new( io::ErrorKind::InvalidInput, "signed writes need at least 1 bit for sign", )), bits if bits <= S::BITS_SIZE => E::write_signed(self, bits, value), _ => Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type written", )), } } /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_signed_out::<4, _>(-5).unwrap(); /// writer.write_signed_out::<4, _>(7).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), LittleEndian); /// writer.write_signed_out::<4, _>(7).unwrap(); /// writer.write_signed_out::<4, _>(-5).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` #[inline] fn write_signed_out(&mut self, value: S) -> io::Result<()> where S: SignedNumeric, { const { assert!(BITS > 0, "signed writes need at least 1 bit for sign"); assert!(BITS <= S::BITS_SIZE, "excessive bits for type written"); } E::write_signed_fixed::<_, BITS, S>(self, value) } #[inline] fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive, { E::write_primitive(self, value) } #[inline] fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { F::write_primitive(self, value) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { if self.byte_aligned() { self.writer.write_all(buf) } else { buf.iter().try_for_each(|b| self.write_out::<8, _>(*b)) } } /// # Example /// ``` /// use std::io::{Write, sink}; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(sink(), BigEndian); /// assert_eq!(writer.byte_aligned(), true); /// writer.write(1, 0).unwrap(); /// assert_eq!(writer.byte_aligned(), false); /// writer.write(7, 0).unwrap(); /// assert_eq!(writer.byte_aligned(), true); /// ``` #[inline(always)] fn byte_aligned(&self) -> bool { self.bitqueue.is_empty() } } impl HuffmanWrite for BitWriter { /// # Example /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, HuffmanWrite}; /// use bitstream_io::huffman::compile_write_tree; /// let tree = compile_write_tree( /// vec![('a', vec![0]), /// ('b', vec![1, 0]), /// ('c', vec![1, 1, 0]), /// ('d', vec![1, 1, 1])]).unwrap(); /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_huffman(&tree, 'b').unwrap(); /// writer.write_huffman(&tree, 'c').unwrap(); /// writer.write_huffman(&tree, 'd').unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` #[inline] fn write_huffman(&mut self, tree: &WriteHuffmanTree, symbol: T) -> io::Result<()> where T: Ord + Copy, { tree.get(&symbol) .try_for_each(|(bits, value)| self.write(*bits, *value)) } } /// For counting the number of bits written but generating no output. /// /// # Example /// ``` /// use bitstream_io::{BigEndian, BitWrite, BitCounter}; /// let mut writer: BitCounter = BitCounter::new(); /// writer.write(1, 0b1).unwrap(); /// writer.write(2, 0b01).unwrap(); /// writer.write(5, 0b10111).unwrap(); /// assert_eq!(writer.written(), 8); /// ``` #[derive(Default)] pub struct BitCounter { bits: N, phantom: PhantomData, } impl BitCounter { /// Creates new counter #[inline] pub fn new() -> Self { BitCounter { bits: N::default(), phantom: PhantomData, } } /// Returns number of bits written #[inline] pub fn written(&self) -> N { self.bits } } impl BitWrite for BitCounter where E: Endianness, N: Copy + AddAssign + From + Rem + PartialEq, { #[inline] fn write_bit(&mut self, _bit: bool) -> io::Result<()> { self.bits += 1.into(); Ok(()) } #[inline] fn write(&mut self, bits: u32, value: U) -> io::Result<()> where U: Numeric, { if bits > U::BITS_SIZE { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type written", )) } else if (bits < U::BITS_SIZE) && (value >= (U::ONE << bits)) { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive value for bits written", )) } else { self.bits += bits.into(); Ok(()) } } fn write_out(&mut self, value: U) -> io::Result<()> where U: Numeric, { const { assert!(BITS <= U::BITS_SIZE, "excessive bits for type written"); } if (BITS < U::BITS_SIZE) && (value >= (U::ONE << BITS)) { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive value for bits written", )) } else { self.bits += BITS.into(); Ok(()) } } #[inline] fn write_signed(&mut self, bits: u32, value: S) -> io::Result<()> where S: SignedNumeric, { match bits { 0 => Err(io::Error::new( io::ErrorKind::InvalidInput, "signed writes need at least 1 bit for sign", )), bits if bits <= S::BITS_SIZE => E::write_signed(self, bits, value), _ => Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type written", )), } } #[inline] fn write_signed_out(&mut self, value: S) -> io::Result<()> where S: SignedNumeric, { const { assert!(BITS > 0, "signed writes need at least 1 bit for sign"); assert!(BITS <= S::BITS_SIZE, "excessive bits for type written"); } E::write_signed_fixed::<_, BITS, S>(self, value) } #[inline] fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive, { E::write_primitive(self, value) } #[inline] fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { F::write_primitive(self, value) } #[inline] fn write_unary1(&mut self, value: u32) -> io::Result<()> { self.bits += (value + 1).into(); Ok(()) } #[inline] fn write_unary0(&mut self, value: u32) -> io::Result<()> { self.bits += (value + 1).into(); Ok(()) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { self.bits += (buf.len() as u32 * 8).into(); Ok(()) } #[inline] fn byte_aligned(&self) -> bool { self.bits % 8.into() == 0.into() } } impl HuffmanWrite for BitCounter where E: Endianness, N: AddAssign + From, { fn write_huffman(&mut self, tree: &WriteHuffmanTree, symbol: T) -> io::Result<()> where T: Ord + Copy, { for &(bits, _) in tree.get(&symbol) { let bits: N = bits.into(); self.bits += bits; } Ok(()) } } /// A generic unsigned value for stream recording purposes pub struct UnsignedValue(InnerUnsignedValue); enum InnerUnsignedValue { U8(u8), U16(u16), U32(u32), U64(u64), U128(u128), I8(i8), I16(i16), I32(i32), I64(i64), I128(i128), } macro_rules! define_unsigned_value { ($t:ty, $n:ident) => { impl From<$t> for UnsignedValue { #[inline] fn from(v: $t) -> Self { UnsignedValue(InnerUnsignedValue::$n(v)) } } }; } define_unsigned_value!(u8, U8); define_unsigned_value!(u16, U16); define_unsigned_value!(u32, U32); define_unsigned_value!(u64, U64); define_unsigned_value!(u128, U128); define_unsigned_value!(i8, I8); define_unsigned_value!(i16, I16); define_unsigned_value!(i32, I32); define_unsigned_value!(i64, I64); define_unsigned_value!(i128, I128); /// A generic signed value for stream recording purposes pub struct SignedValue(InnerSignedValue); enum InnerSignedValue { I8(i8), I16(i16), I32(i32), I64(i64), I128(i128), } macro_rules! define_signed_value { ($t:ty, $n:ident) => { impl From<$t> for SignedValue { #[inline] fn from(v: $t) -> Self { SignedValue(InnerSignedValue::$n(v)) } } }; } define_signed_value!(i8, I8); define_signed_value!(i16, I16); define_signed_value!(i32, I32); define_signed_value!(i64, I64); define_signed_value!(i128, I128); enum WriteRecord { Bit(bool), Unsigned { bits: u32, value: UnsignedValue }, Signed { bits: u32, value: SignedValue }, Unary0(u32), Unary1(u32), Bytes(Box<[u8]>), } impl WriteRecord { fn playback(&self, writer: &mut W) -> io::Result<()> { match self { WriteRecord::Bit(v) => writer.write_bit(*v), WriteRecord::Unsigned { bits, value: UnsignedValue(value), } => match value { InnerUnsignedValue::U8(v) => writer.write(*bits, *v), InnerUnsignedValue::U16(v) => writer.write(*bits, *v), InnerUnsignedValue::U32(v) => writer.write(*bits, *v), InnerUnsignedValue::U64(v) => writer.write(*bits, *v), InnerUnsignedValue::U128(v) => writer.write(*bits, *v), InnerUnsignedValue::I8(v) => writer.write(*bits, *v), InnerUnsignedValue::I16(v) => writer.write(*bits, *v), InnerUnsignedValue::I32(v) => writer.write(*bits, *v), InnerUnsignedValue::I64(v) => writer.write(*bits, *v), InnerUnsignedValue::I128(v) => writer.write(*bits, *v), }, WriteRecord::Signed { bits, value: SignedValue(value), } => match value { InnerSignedValue::I8(v) => writer.write_signed(*bits, *v), InnerSignedValue::I16(v) => writer.write_signed(*bits, *v), InnerSignedValue::I32(v) => writer.write_signed(*bits, *v), InnerSignedValue::I64(v) => writer.write_signed(*bits, *v), InnerSignedValue::I128(v) => writer.write_signed(*bits, *v), }, WriteRecord::Unary0(v) => writer.write_unary0(*v), WriteRecord::Unary1(v) => writer.write_unary1(*v), WriteRecord::Bytes(bytes) => writer.write_bytes(bytes), } } } /// For recording writes in order to play them back on another writer /// # Example /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite, BitRecorder}; /// let mut recorder: BitRecorder = BitRecorder::new(); /// recorder.write(1, 0b1).unwrap(); /// recorder.write(2, 0b01).unwrap(); /// recorder.write(5, 0b10111).unwrap(); /// assert_eq!(recorder.written(), 8); /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// recorder.playback(&mut writer); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` #[derive(Default)] pub struct BitRecorder { counter: BitCounter, records: Vec, } impl BitRecorder { /// Creates new recorder #[inline] pub fn new() -> Self { BitRecorder { counter: BitCounter::new(), records: Vec::new(), } } /// Creates new recorder sized for the given number of writes #[inline] pub fn with_capacity(writes: usize) -> Self { BitRecorder { counter: BitCounter::new(), records: Vec::with_capacity(writes), } } /// Creates new recorder with the given endianness #[inline] pub fn endian(_endian: E) -> Self { BitRecorder { counter: BitCounter::new(), records: Vec::new(), } } /// Returns number of bits written #[inline] pub fn written(&self) -> N { self.counter.written() } /// Plays recorded writes to the given writer #[inline] pub fn playback(&self, writer: &mut W) -> io::Result<()> { self.records .iter() .try_for_each(|record| record.playback(writer)) } } impl BitWrite for BitRecorder where E: Endianness, N: Copy + From + AddAssign + Rem + Eq, { #[inline] fn write_bit(&mut self, bit: bool) -> io::Result<()> { self.records.push(WriteRecord::Bit(bit)); self.counter.write_bit(bit) } #[inline] fn write(&mut self, bits: u32, value: U) -> io::Result<()> where U: Numeric, { self.counter.write(bits, value)?; self.records.push(WriteRecord::Unsigned { bits, value: value.unsigned_value(), }); Ok(()) } #[inline] fn write_out(&mut self, value: U) -> io::Result<()> where U: Numeric, { self.counter.write_out::(value)?; self.records.push(WriteRecord::Unsigned { bits: BITS, value: value.unsigned_value(), }); Ok(()) } #[inline] fn write_signed(&mut self, bits: u32, value: S) -> io::Result<()> where S: SignedNumeric, { self.counter.write_signed(bits, value)?; self.records.push(WriteRecord::Signed { bits, value: value.signed_value(), }); Ok(()) } #[inline] fn write_signed_out(&mut self, value: S) -> io::Result<()> where S: SignedNumeric, { self.counter.write_signed_out::(value)?; self.records.push(WriteRecord::Signed { bits: BITS, value: value.signed_value(), }); Ok(()) } #[inline] fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive, { E::write_primitive(self, value) } #[inline] fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { F::write_primitive(self, value) } #[inline] fn write_unary0(&mut self, value: u32) -> io::Result<()> { self.records.push(WriteRecord::Unary0(value)); self.counter.write_unary0(value) } #[inline] fn write_unary1(&mut self, value: u32) -> io::Result<()> { self.records.push(WriteRecord::Unary1(value)); self.counter.write_unary1(value) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { self.records.push(WriteRecord::Bytes(buf.into())); self.counter.write_bytes(buf) } #[inline] fn byte_aligned(&self) -> bool { self.counter.byte_aligned() } } impl HuffmanWrite for BitRecorder where E: Endianness, N: Copy + From + AddAssign + Rem + Eq, { #[inline] fn write_huffman(&mut self, tree: &WriteHuffmanTree, symbol: T) -> io::Result<()> where T: Ord + Copy, { tree.get(&symbol) .try_for_each(|(bits, value)| self.write(*bits, *value)) } } #[inline] fn write_byte(mut writer: W, byte: u8) -> io::Result<()> where W: io::Write, { writer.write_all(core::slice::from_ref(&byte)) } fn write_unaligned( writer: W, acc: &mut BitQueue, rem: &mut BitQueue, ) -> io::Result<()> where W: io::Write, E: Endianness, N: Numeric, { if rem.is_empty() { Ok(()) } else { use core::cmp::min; let bits_to_transfer = min(8 - rem.len(), acc.len()); rem.push(bits_to_transfer, acc.pop(bits_to_transfer).to_u8()); if rem.len() == 8 { write_byte(writer, rem.pop(8)) } else { Ok(()) } } } fn write_aligned(mut writer: W, acc: &mut BitQueue) -> io::Result<()> where W: io::Write, E: Endianness, N: Numeric, { let to_write = (acc.len() / 8) as usize; if to_write > 0 { let mut buf = N::buffer(); let buf_ref: &mut [u8] = buf.as_mut(); for b in buf_ref[0..to_write].iter_mut() { *b = acc.pop_fixed::<8>().to_u8(); } writer.write_all(&buf_ref[0..to_write]) } else { Ok(()) } } /// For writing aligned bytes to a stream of bytes in a given endianness. /// /// This only writes aligned values and maintains no internal state. pub struct ByteWriter { phantom: PhantomData, writer: W, } impl ByteWriter { /// Wraps a ByteWriter around something that implements `Write` pub fn new(writer: W) -> ByteWriter { ByteWriter { phantom: PhantomData, writer, } } /// Wraps a BitWriter around something that implements `Write` /// with the given endianness. pub fn endian(writer: W, _endian: E) -> ByteWriter { ByteWriter { phantom: PhantomData, writer, } } /// Unwraps internal writer and disposes of `ByteWriter`. /// Any unwritten partial bits are discarded. #[inline] pub fn into_writer(self) -> W { self.writer } /// Provides mutable reference to internal writer. #[inline] pub fn writer(&mut self) -> &mut W { &mut self.writer } /// Converts `ByteWriter` to `BitWriter` in the same endianness. #[inline] pub fn into_bitwriter(self) -> BitWriter { BitWriter::new(self.into_writer()) } /// Provides temporary `BitWriter` in the same endianness. /// /// # Warning /// /// Any unwritten bits left over when `BitWriter` is dropped are lost. #[inline] pub fn bitwriter(&mut self) -> BitWriter<&mut W, E> { BitWriter::new(self.writer()) } } /// A trait for anything that can write aligned values to an output stream pub trait ByteWrite { /// Writes whole numeric value to stream /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, ByteWriter, ByteWrite}; /// let mut writer = ByteWriter::endian(Vec::new(), BigEndian); /// writer.write(0b0000000011111111u16).unwrap(); /// assert_eq!(writer.into_writer(), [0b00000000, 0b11111111]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, ByteWriter, ByteWrite}; /// let mut writer = ByteWriter::endian(Vec::new(), LittleEndian); /// writer.write(0b0000000011111111u16).unwrap(); /// assert_eq!(writer.into_writer(), [0b11111111, 0b00000000]); /// ``` fn write(&mut self, value: V) -> io::Result<()> where V: Primitive; /// Writes whole numeric value to stream in a potentially different endianness /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// /// # Examples /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, ByteWriter, ByteWrite, LittleEndian}; /// let mut writer = ByteWriter::endian(Vec::new(), BigEndian); /// writer.write_as::(0b0000000011111111).unwrap(); /// assert_eq!(writer.into_writer(), [0b11111111, 0b00000000]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, ByteWriter, ByteWrite, LittleEndian}; /// let mut writer = ByteWriter::endian(Vec::new(), LittleEndian); /// writer.write_as::(0b0000000011111111).unwrap(); /// assert_eq!(writer.into_writer(), [0b00000000, 0b11111111]); /// ``` fn write_as(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive; /// Writes the entirety of a byte buffer to the stream. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()>; /// Builds and writes complex type fn build(&mut self, build: &T) -> Result<(), T::Error> { build.to_writer(self) } /// Builds and writes complex type with context fn build_with<'a, T: ToByteStreamWith<'a>>( &mut self, build: &T, context: &T::Context, ) -> Result<(), T::Error> { build.to_writer(self, context) } /// Returns mutable reference to underlying writer fn writer_ref(&mut self) -> &mut dyn io::Write; } impl ByteWrite for ByteWriter { #[inline] fn write(&mut self, value: V) -> io::Result<()> where V: Primitive, { E::write_numeric(&mut self.writer, value) } #[inline] fn write_as(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { F::write_numeric(&mut self.writer, value) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { self.writer.write_all(buf) } #[inline] fn writer_ref(&mut self) -> &mut dyn io::Write { &mut self.writer } } /// Implemented by complex types that don't require any additional context /// to build themselves to a writer /// /// # Example /// ``` /// use std::io::{Cursor, Read}; /// use bitstream_io::{BigEndian, BitWrite, BitWriter, ToBitStream}; /// /// #[derive(Debug, PartialEq, Eq)] /// struct BlockHeader { /// last_block: bool, /// block_type: u8, /// block_size: u32, /// } /// /// impl ToBitStream for BlockHeader { /// type Error = std::io::Error; /// /// fn to_writer(&self, w: &mut W) -> std::io::Result<()> { /// w.write_bit(self.last_block)?; /// w.write(7, self.block_type)?; /// w.write(24, self.block_size) /// } /// } /// /// let mut data = Vec::new(); /// let mut writer = BitWriter::endian(&mut data, BigEndian); /// writer.build(&BlockHeader { last_block: false, block_type: 4, block_size: 122 }).unwrap(); /// assert_eq!(data, b"\x04\x00\x00\x7A"); /// ``` pub trait ToBitStream { /// Error generated during building, such as `io::Error` type Error; /// Generate self to writer fn to_writer(&self, w: &mut W) -> Result<(), Self::Error> where Self: Sized; } /// Implemented by complex types that require additional context /// to build themselves to a writer pub trait ToBitStreamWith<'a> { /// Some context to use when writing type Context: 'a; /// Error generated during building, such as `io::Error` type Error; /// Generate self to writer fn to_writer( &self, w: &mut W, context: &Self::Context, ) -> Result<(), Self::Error> where Self: Sized; } /// Implemented by complex types that don't require any additional context /// to build themselves to a writer pub trait ToByteStream { /// Error generated during building, such as `io::Error` type Error; /// Generate self to writer fn to_writer(&self, w: &mut W) -> Result<(), Self::Error> where Self: Sized; } /// Implemented by complex types that require additional context /// to build themselves to a writer pub trait ToByteStreamWith<'a> { /// Some context to use when writing type Context: 'a; /// Error generated during building, such as `io::Error` type Error; /// Generate self to writer fn to_writer( &self, w: &mut W, context: &Self::Context, ) -> Result<(), Self::Error> where Self: Sized; } bitstream-io-2.5.0/tests/huffman.rs000064400000000000000000000116771046102023000153770ustar 00000000000000extern crate bitstream_io; use bitstream_io::huffman::{compile_read_tree, compile_write_tree, HuffmanTreeError}; #[test] fn test_huffman_errors() { use bitstream_io::BE; let empty: Vec<(i32, Vec)> = Vec::new(); assert!(if let Err(err) = compile_read_tree::(empty) { err == HuffmanTreeError::MissingLeaf } else { false }); assert!( if let Err(err) = compile_read_tree::(vec![(0u32, vec![0, 1, 2])]) { err == HuffmanTreeError::InvalidBit } else { false } ); assert!(if let Err(err) = compile_read_tree::(vec![(0u32, vec![1]), (1u32, vec![0, 1])]) { err == HuffmanTreeError::MissingLeaf } else { false }); assert!(if let Err(err) = compile_read_tree::(vec![ (0u32, vec![1]), (1u32, vec![0, 1]), (2u32, vec![0, 0]), (3u32, vec![0, 0]), ]) { err == HuffmanTreeError::DuplicateLeaf } else { false }); assert!(if let Err(err) = compile_read_tree::(vec![ (0u32, vec![1]), (1u32, vec![0]), (2u32, vec![0, 0]), (3u32, vec![0, 1]), ]) { err == HuffmanTreeError::OrphanedLeaf } else { false }); assert!( if let Err(err) = compile_write_tree::(vec![(0, vec![1, 1, 2])]) { err == HuffmanTreeError::InvalidBit } else { false } ); } #[test] fn test_huffman_values() { use bitstream_io::huffman::compile_read_tree; use bitstream_io::{BigEndian, BitReader, HuffmanRead}; use std::io::Cursor; use std::ops::Deref; use std::rc::Rc; let data = [0xB1, 0xED]; // we can lookup values that aren't just integers also let tree = compile_read_tree(vec![ (Some(0), vec![0]), (Some(1), vec![1, 0]), (Some(2), vec![1, 1, 0]), (None, vec![1, 1, 1]), ]) .unwrap(); let mut r = BitReader::endian(Cursor::new(&data), BigEndian); assert_eq!(r.read_huffman(&tree).unwrap(), Some(1)); assert_eq!(r.read_huffman(&tree).unwrap(), Some(2)); assert_eq!(r.read_huffman(&tree).unwrap(), Some(0)); assert_eq!(r.read_huffman(&tree).unwrap(), Some(0)); assert_eq!(r.read_huffman(&tree).unwrap(), None); // we can even lookup potentially large values, // preferably using Rc to avoid making copies of each one let tree = compile_read_tree(vec![ (Rc::new("foo".to_owned()), vec![0]), (Rc::new("bar".to_owned()), vec![1, 0]), (Rc::new("baz".to_owned()), vec![1, 1, 0]), (Rc::new("kelp".to_owned()), vec![1, 1, 1]), ]) .unwrap(); let mut r = BitReader::endian(Cursor::new(&data), BigEndian); assert_eq!(r.read_huffman(&tree).unwrap().deref(), "bar"); assert_eq!(r.read_huffman(&tree).unwrap().deref(), "baz"); assert_eq!(r.read_huffman(&tree).unwrap().deref(), "foo"); assert_eq!(r.read_huffman(&tree).unwrap().deref(), "foo"); assert_eq!(r.read_huffman(&tree).unwrap().deref(), "kelp"); } #[test] fn test_lengthy_huffman_values() { use bitstream_io::huffman::{compile_read_tree, compile_write_tree}; use bitstream_io::{BitReader, BitWrite, BitWriter, HuffmanRead, HuffmanWrite, BE, LE}; use std::io::Cursor; let max_bits = 70; let mut spec = Vec::new(); for bits in 0..max_bits { let mut entry = Vec::new(); for _ in 0..bits { entry.push(0); } entry.push(1); spec.push((Some(bits), entry)); } let mut entry = Vec::new(); for _ in 0..max_bits { entry.push(0); } spec.push((None, entry)); let read_tree_be = compile_read_tree::>(spec.clone()).unwrap(); let write_tree_be = compile_write_tree::>(spec.clone()).unwrap(); let read_tree_le = compile_read_tree::>(spec.clone()).unwrap(); let write_tree_le = compile_write_tree::>(spec).unwrap(); let mut data_be = Vec::new(); let mut data_le = Vec::new(); { let mut writer_be = BitWriter::new(&mut data_be); let mut writer_le = BitWriter::new(&mut data_le); for _ in 0..20 { for bits in 0..max_bits { writer_be.write_huffman(&write_tree_be, Some(bits)).unwrap(); writer_le.write_huffman(&write_tree_le, Some(bits)).unwrap(); } } writer_be.byte_align().unwrap(); writer_le.byte_align().unwrap(); } { let mut cursor_be = Cursor::new(&data_be); let mut cursor_le = Cursor::new(&data_le); let mut reader_be = BitReader::new(&mut cursor_be); let mut reader_le = BitReader::new(&mut cursor_le); for _ in 0..20 { for bits in 0..max_bits { assert_eq!(reader_be.read_huffman(&read_tree_be).unwrap(), Some(bits)); assert_eq!(reader_le.read_huffman(&read_tree_le).unwrap(), Some(bits)); } } } } bitstream-io-2.5.0/tests/read.rs000064400000000000000000000717201046102023000146610ustar 00000000000000// Copyright 2017 Brian Langenberger // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. extern crate bitstream_io; use std::io::Cursor; #[test] fn test_read_queue_be() { use bitstream_io::{BitQueue, BE}; let mut q: BitQueue = BitQueue::new(); assert!(q.is_empty()); assert_eq!(q.len(), 0); q.push(8, 0b10_110_001); assert_eq!(q.len(), 8); assert_eq!(q.pop(2), 0b10); assert_eq!(q.len(), 6); assert_eq!(q.pop(3), 0b110); assert_eq!(q.len(), 3); q.push(8, 0b11_101_101); assert_eq!(q.len(), 11); assert_eq!(q.pop(5), 0b001_11); assert_eq!(q.len(), 6); assert_eq!(q.pop(3), 0b101); q.push(8, 0b00111011); q.push(8, 0b11000001); assert_eq!(q.pop(19), 0b101_00111011_11000001); assert!(q.is_empty()); assert_eq!(q.value(), 0); } #[test] fn test_read_queue_le() { use bitstream_io::{BitQueue, LE}; let mut q: BitQueue = BitQueue::new(); assert!(q.is_empty()); assert_eq!(q.len(), 0); q.push(8, 0b101_100_01); assert_eq!(q.len(), 8); assert_eq!(q.pop(2), 0b01); assert_eq!(q.len(), 6); assert_eq!(q.pop(3), 0b100); assert_eq!(q.len(), 3); q.push(8, 0b111_011_01); assert_eq!(q.len(), 11); assert_eq!(q.pop(5), 0b01_101); assert_eq!(q.len(), 6); assert_eq!(q.pop(3), 0b011); q.push(8, 0b00111011); q.push(8, 0b11000001); assert_eq!(q.pop(19), 0b11000001_00111011_111); assert!(q.is_empty()); assert_eq!(q.value(), 0); } #[test] fn test_reader_be() { use bitstream_io::{BigEndian, BitRead, BitReader}; let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; /*reading individual bits*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), true); /*reading unsigned values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.byte_aligned()); assert_eq!(r.read::(2).unwrap(), 2); assert!(!r.byte_aligned()); assert_eq!(r.read::(3).unwrap(), 6); assert!(!r.byte_aligned()); assert_eq!(r.read::(5).unwrap(), 7); assert!(!r.byte_aligned()); assert_eq!(r.read::(3).unwrap(), 5); assert!(!r.byte_aligned()); assert_eq!(r.read::(19).unwrap(), 0x53BC1); assert!(r.byte_aligned()); assert!(r.read::(1).is_err()); /*reading const unsigned values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.byte_aligned()); assert_eq!(r.read_in::<2, u32>().unwrap(), 2); assert!(!r.byte_aligned()); assert_eq!(r.read_in::<3, u32>().unwrap(), 6); assert!(!r.byte_aligned()); assert_eq!(r.read_in::<5, u32>().unwrap(), 7); assert!(!r.byte_aligned()); assert_eq!(r.read_in::<3, u32>().unwrap(), 5); assert!(!r.byte_aligned()); assert_eq!(r.read_in::<19, u32>().unwrap(), 0x53BC1); assert!(r.byte_aligned()); assert!(r.read_in::<1, u32>().is_err()); /*skipping bits*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read::(2).unwrap(), 2); assert!(r.skip(3).is_ok()); assert_eq!(r.read::(5).unwrap(), 7); assert!(r.skip(3).is_ok()); assert_eq!(r.read::(19).unwrap(), 0x53BC1); /*reading signed values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read_signed::(2).unwrap(), -2); assert_eq!(r.read_signed::(3).unwrap(), -2); assert_eq!(r.read_signed::(5).unwrap(), 7); assert_eq!(r.read_signed::(3).unwrap(), -3); assert_eq!(r.read_signed::(19).unwrap(), -181311); /*reading const signed values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read_signed_in::<2, i32>().unwrap(), -2); assert_eq!(r.read_signed_in::<3, i32>().unwrap(), -2); assert_eq!(r.read_signed_in::<5, i32>().unwrap(), 7); assert_eq!(r.read_signed_in::<3, i32>().unwrap(), -3); assert_eq!(r.read_signed_in::<19, i32>().unwrap(), -181311); /*reading unary 0 values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read_unary0().unwrap(), 1); assert_eq!(r.read_unary0().unwrap(), 2); assert_eq!(r.read_unary0().unwrap(), 0); assert_eq!(r.read_unary0().unwrap(), 0); assert_eq!(r.read_unary0().unwrap(), 4); /*reading unary 1 values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read_unary1().unwrap(), 0); assert_eq!(r.read_unary1().unwrap(), 1); assert_eq!(r.read_unary1().unwrap(), 0); assert_eq!(r.read_unary1().unwrap(), 3); assert_eq!(r.read_unary1().unwrap(), 0); /*byte aligning*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read::(3).unwrap(), 5); r.byte_align(); assert_eq!(r.read::(3).unwrap(), 7); r.byte_align(); r.byte_align(); assert_eq!(r.read::(8).unwrap(), 59); r.byte_align(); assert_eq!(r.read::(4).unwrap(), 12); /*reading bytes, aligned*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); let mut sub_data = [0; 2]; assert!(r.read_bytes(&mut sub_data).is_ok()); assert_eq!(&sub_data, b"\xB1\xED"); /*reading bytes, un-aligned*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); let mut sub_data = [0; 2]; assert_eq!(r.read::(4).unwrap(), 11); assert!(r.read_bytes(&mut sub_data).is_ok()); assert_eq!(&sub_data, b"\x1E\xD3"); } #[test] fn test_edge_cases_be() { use bitstream_io::{BigEndian, BitRead, BitReader}; let data: Vec = vec![ 0, 0, 0, 0, 255, 255, 255, 255, 128, 0, 0, 0, 127, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 255, 255, 255, 255, 255, ]; /*0 bit reads*/ let mut r = BitReader::endian(Cursor::new(vec![255]), BigEndian); assert_eq!(r.read::(0).unwrap(), 0); assert_eq!(r.read::(0).unwrap(), 0); assert_eq!(r.read::(0).unwrap(), 0); assert_eq!(r.read::(0).unwrap(), 0); assert_eq!(r.read::(8).unwrap(), 255); let mut r = BitReader::endian(Cursor::new(vec![255]), BigEndian); assert_eq!(r.read_in::<0, u8>().unwrap(), 0); assert_eq!(r.read_in::<0, u16>().unwrap(), 0); assert_eq!(r.read_in::<0, u32>().unwrap(), 0); assert_eq!(r.read_in::<0, u64>().unwrap(), 0); assert_eq!(r.read_in::<8, u8>().unwrap(), 255); let mut r = BitReader::endian(Cursor::new(vec![255]), BigEndian); assert!(r.read_signed::(0).is_err()); assert!(r.read_signed::(0).is_err()); assert!(r.read_signed::(0).is_err()); assert!(r.read_signed::(0).is_err()); /*unsigned 32 and 64-bit values*/ let mut r = BitReader::endian(Cursor::new(&data), BigEndian); assert_eq!(r.read::(32).unwrap(), 0); assert_eq!(r.read::(32).unwrap(), 4294967295); assert_eq!(r.read::(32).unwrap(), 2147483648); assert_eq!(r.read::(32).unwrap(), 2147483647); assert_eq!(r.read::(64).unwrap(), 0); assert_eq!(r.read::(64).unwrap(), 0xFFFFFFFFFFFFFFFF); assert_eq!(r.read::(64).unwrap(), 9223372036854775808); assert_eq!(r.read::(64).unwrap(), 9223372036854775807); let mut r = BitReader::endian(Cursor::new(&data), BigEndian); assert_eq!(r.read_in::<32, u32>().unwrap(), 0); assert_eq!(r.read_in::<32, u32>().unwrap(), 4294967295); assert_eq!(r.read_in::<32, u32>().unwrap(), 2147483648); assert_eq!(r.read_in::<32, u32>().unwrap(), 2147483647); assert_eq!(r.read_in::<64, u64>().unwrap(), 0); assert_eq!(r.read_in::<64, u64>().unwrap(), 0xFFFFFFFFFFFFFFFF); assert_eq!(r.read_in::<64, u64>().unwrap(), 9223372036854775808); assert_eq!(r.read_in::<64, u64>().unwrap(), 9223372036854775807); /*signed 32 and 64-bit values*/ let mut r = BitReader::endian(Cursor::new(&data), BigEndian); assert_eq!(r.read::(32).unwrap(), 0); assert_eq!(r.read::(32).unwrap(), -1); assert_eq!(r.read::(32).unwrap(), -2147483648); assert_eq!(r.read::(32).unwrap(), 2147483647); assert_eq!(r.read::(64).unwrap(), 0); assert_eq!(r.read::(64).unwrap(), -1); assert_eq!(r.read::(64).unwrap(), -9223372036854775808); assert_eq!(r.read::(64).unwrap(), 9223372036854775807); let mut r = BitReader::endian(Cursor::new(&data), BigEndian); assert_eq!(r.read_in::<32, i32>().unwrap(), 0); assert_eq!(r.read_in::<32, i32>().unwrap(), -1); assert_eq!(r.read_in::<32, i32>().unwrap(), -2147483648); assert_eq!(r.read_in::<32, i32>().unwrap(), 2147483647); assert_eq!(r.read_in::<64, i64>().unwrap(), 0); assert_eq!(r.read_in::<64, i64>().unwrap(), -1); assert_eq!(r.read_in::<64, i64>().unwrap(), -9223372036854775808); assert_eq!(r.read_in::<64, i64>().unwrap(), 9223372036854775807); } #[test] fn test_reader_huffman_be() { use bitstream_io::huffman::compile_read_tree; use bitstream_io::{BigEndian, BitReader, HuffmanRead}; let tree = compile_read_tree(vec![ (0, vec![1, 1]), (1, vec![1, 0]), (2, vec![0, 1]), (3, vec![0, 0, 1]), (4, vec![0, 0, 0]), ]) .unwrap(); let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 4); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 2); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 2); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 2); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 4); assert_eq!(r.read_huffman(&tree).unwrap(), 2); } #[test] fn test_reader_le() { use bitstream_io::{BitRead, BitReader, LittleEndian}; let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; /*reading individual bits*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), false); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_bit().unwrap(), true); /*reading unsigned values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert!(r.byte_aligned()); assert_eq!(r.read::(2).unwrap(), 1); assert!(!r.byte_aligned()); assert_eq!(r.read::(3).unwrap(), 4); assert!(!r.byte_aligned()); assert_eq!(r.read::(5).unwrap(), 13); assert!(!r.byte_aligned()); assert_eq!(r.read::(3).unwrap(), 3); assert!(!r.byte_aligned()); assert_eq!(r.read::(19).unwrap(), 0x609DF); assert!(r.byte_aligned()); assert!(r.read::(1).is_err()); /*reading const unsigned values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert!(r.byte_aligned()); assert_eq!(r.read_in::<2, u32>().unwrap(), 1); assert!(!r.byte_aligned()); assert_eq!(r.read_in::<3, u32>().unwrap(), 4); assert!(!r.byte_aligned()); assert_eq!(r.read_in::<5, u32>().unwrap(), 13); assert!(!r.byte_aligned()); assert_eq!(r.read_in::<3, u32>().unwrap(), 3); assert!(!r.byte_aligned()); assert_eq!(r.read_in::<19, u32>().unwrap(), 0x609DF); assert!(r.byte_aligned()); assert!(r.read_in::<1, u32>().is_err()); /*skipping bits*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read::(2).unwrap(), 1); assert!(r.skip(3).is_ok()); assert_eq!(r.read::(5).unwrap(), 13); assert!(r.skip(3).is_ok()); assert_eq!(r.read::(19).unwrap(), 0x609DF); /*reading signed values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read_signed::(2).unwrap(), 1); assert_eq!(r.read_signed::(3).unwrap(), -4); assert_eq!(r.read_signed::(5).unwrap(), 13); assert_eq!(r.read_signed::(3).unwrap(), 3); assert_eq!(r.read_signed::(19).unwrap(), -128545); /*reading const signed values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read_signed_in::<2, i32>().unwrap(), 1); assert_eq!(r.read_signed_in::<3, i32>().unwrap(), -4); assert_eq!(r.read_signed_in::<5, i32>().unwrap(), 13); assert_eq!(r.read_signed_in::<3, i32>().unwrap(), 3); assert_eq!(r.read_signed_in::<19, i32>().unwrap(), -128545); /*reading unary 0 values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read_unary0().unwrap(), 1); assert_eq!(r.read_unary0().unwrap(), 0); assert_eq!(r.read_unary0().unwrap(), 0); assert_eq!(r.read_unary0().unwrap(), 2); assert_eq!(r.read_unary0().unwrap(), 2); /*reading unary 1 values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read_unary1().unwrap(), 0); assert_eq!(r.read_unary1().unwrap(), 3); assert_eq!(r.read_unary1().unwrap(), 0); assert_eq!(r.read_unary1().unwrap(), 1); assert_eq!(r.read_unary1().unwrap(), 0); /*byte aligning*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read::(3).unwrap(), 1); r.byte_align(); assert_eq!(r.read::(3).unwrap(), 5); r.byte_align(); r.byte_align(); assert_eq!(r.read::(8).unwrap(), 59); r.byte_align(); assert_eq!(r.read::(4).unwrap(), 1); /*reading bytes, aligned*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); let mut sub_data = [0; 2]; assert!(r.read_bytes(&mut sub_data).is_ok()); assert_eq!(&sub_data, b"\xB1\xED"); /*reading bytes, un-aligned*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); let mut sub_data = [0; 2]; assert_eq!(r.read::(4).unwrap(), 1); assert!(r.read_bytes(&mut sub_data).is_ok()); assert_eq!(&sub_data, b"\xDB\xBE"); } #[test] fn test_edge_cases_le() { use bitstream_io::{BitRead, BitReader, LittleEndian}; let data: Vec = vec![ 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 128, 255, 255, 255, 127, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 128, 255, 255, 255, 255, 255, 255, 255, 127, ]; /*0 bit reads*/ let mut r = BitReader::endian(Cursor::new(vec![255]), LittleEndian); assert_eq!(r.read::(0).unwrap(), 0); assert_eq!(r.read::(0).unwrap(), 0); assert_eq!(r.read::(0).unwrap(), 0); assert_eq!(r.read::(0).unwrap(), 0); assert_eq!(r.read::(8).unwrap(), 255); let mut r = BitReader::endian(Cursor::new(vec![255]), LittleEndian); assert_eq!(r.read_in::<0, u8>().unwrap(), 0); assert_eq!(r.read_in::<0, u16>().unwrap(), 0); assert_eq!(r.read_in::<0, u32>().unwrap(), 0); assert_eq!(r.read_in::<0, u64>().unwrap(), 0); assert_eq!(r.read_in::<8, u8>().unwrap(), 255); let mut r = BitReader::endian(Cursor::new(vec![255]), LittleEndian); assert!(r.read_signed::(0).is_err()); assert!(r.read_signed::(0).is_err()); assert!(r.read_signed::(0).is_err()); assert!(r.read_signed::(0).is_err()); /*unsigned 32 and 64-bit values*/ let mut r = BitReader::endian(Cursor::new(&data), LittleEndian); assert_eq!(r.read::(32).unwrap(), 0); assert_eq!(r.read::(32).unwrap(), 4294967295); assert_eq!(r.read::(32).unwrap(), 2147483648); assert_eq!(r.read::(32).unwrap(), 2147483647); assert_eq!(r.read::(64).unwrap(), 0); assert_eq!(r.read::(64).unwrap(), 0xFFFFFFFFFFFFFFFF); assert_eq!(r.read::(64).unwrap(), 9223372036854775808); assert_eq!(r.read::(64).unwrap(), 9223372036854775807); let mut r = BitReader::endian(Cursor::new(&data), LittleEndian); assert_eq!(r.read_in::<32, u32>().unwrap(), 0); assert_eq!(r.read_in::<32, u32>().unwrap(), 4294967295); assert_eq!(r.read_in::<32, u32>().unwrap(), 2147483648); assert_eq!(r.read_in::<32, u32>().unwrap(), 2147483647); assert_eq!(r.read_in::<64, u64>().unwrap(), 0); assert_eq!(r.read_in::<64, u64>().unwrap(), 0xFFFFFFFFFFFFFFFF); assert_eq!(r.read_in::<64, u64>().unwrap(), 9223372036854775808); assert_eq!(r.read_in::<64, u64>().unwrap(), 9223372036854775807); let mut r = BitReader::endian(Cursor::new(&data), LittleEndian); assert_eq!(r.read_signed::(32).unwrap(), 0); assert_eq!(r.read_signed::(32).unwrap(), -1); assert_eq!(r.read_signed::(32).unwrap(), -2147483648); assert_eq!(r.read_signed::(32).unwrap(), 2147483647); assert_eq!(r.read_signed::(64).unwrap(), 0); assert_eq!(r.read_signed::(64).unwrap(), -1); assert_eq!(r.read_signed::(64).unwrap(), -9223372036854775808); assert_eq!(r.read_signed::(64).unwrap(), 9223372036854775807); let mut r = BitReader::endian(Cursor::new(&data), LittleEndian); assert_eq!(r.read_signed_in::<32, i32>().unwrap(), 0); assert_eq!(r.read_signed_in::<32, i32>().unwrap(), -1); assert_eq!(r.read_signed_in::<32, i32>().unwrap(), -2147483648); assert_eq!(r.read_signed_in::<32, i32>().unwrap(), 2147483647); assert_eq!(r.read_signed_in::<64, i64>().unwrap(), 0); assert_eq!(r.read_signed_in::<64, i64>().unwrap(), -1); assert_eq!(r.read_signed_in::<64, i64>().unwrap(), -9223372036854775808); assert_eq!(r.read_signed_in::<64, i64>().unwrap(), 9223372036854775807); } #[test] fn test_reader_huffman_le() { use bitstream_io::huffman::compile_read_tree; use bitstream_io::{BitReader, HuffmanRead, LittleEndian}; let tree = compile_read_tree(vec![ (0, vec![1, 1]), (1, vec![1, 0]), (2, vec![0, 1]), (3, vec![0, 0, 1]), (4, vec![0, 0, 0]), ]) .unwrap(); let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 3); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 2); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 0); assert_eq!(r.read_huffman(&tree).unwrap(), 1); assert_eq!(r.read_huffman(&tree).unwrap(), 2); assert_eq!(r.read_huffman(&tree).unwrap(), 4); assert_eq!(r.read_huffman(&tree).unwrap(), 3); } #[test] fn test_reader_io_errors_be() { use bitstream_io::{BigEndian, BitRead, BitReader}; use std::io::ErrorKind; let actual_data: [u8; 1] = [0xB1]; /*individual bits*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert_eq!(r.read_bit().unwrap_err().kind(), ErrorKind::UnexpectedEof); /*skipping bits*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.read::(7).is_ok()); assert_eq!(r.skip(5).unwrap_err().kind(), ErrorKind::UnexpectedEof); /*signed values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.read_signed::(2).is_ok()); assert!(r.read_signed::(3).is_ok()); assert_eq!( r.read_signed::(5).unwrap_err().kind(), ErrorKind::UnexpectedEof ); let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.read_signed_in::<2, i32>().is_ok()); assert!(r.read_signed_in::<3, i32>().is_ok()); assert_eq!( r.read_signed_in::<5, i32>().unwrap_err().kind(), ErrorKind::UnexpectedEof ); /*unary 0 values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.read_unary0().is_ok()); assert!(r.read_unary0().is_ok()); assert!(r.read_unary0().is_ok()); assert!(r.read_unary0().is_ok()); assert_eq!( r.read_unary0().unwrap_err().kind(), ErrorKind::UnexpectedEof ); /*unary 1 values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.read_unary1().is_ok()); assert!(r.read_unary1().is_ok()); assert!(r.read_unary1().is_ok()); assert!(r.read_unary1().is_ok()); assert_eq!( r.read_unary1().unwrap_err().kind(), ErrorKind::UnexpectedEof ); /*reading bytes, aligned*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); let mut sub_data = [0; 2]; assert_eq!( r.read_bytes(&mut sub_data).unwrap_err().kind(), ErrorKind::UnexpectedEof ); /*reading bytes, un-aligned*/ let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); let mut sub_data = [0; 2]; assert!(r.read::(4).is_ok()); assert_eq!( r.read_bytes(&mut sub_data).unwrap_err().kind(), ErrorKind::UnexpectedEof ); } #[test] fn test_reader_io_errors_le() { use bitstream_io::{BitRead, BitReader, LittleEndian}; use std::io::ErrorKind; let actual_data: [u8; 1] = [0xB1]; /*individual bits*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert!(r.read_bit().is_ok()); assert_eq!(r.read_bit().unwrap_err().kind(), ErrorKind::UnexpectedEof); /*skipping bits*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert!(r.read::(7).is_ok()); assert_eq!(r.skip(5).unwrap_err().kind(), ErrorKind::UnexpectedEof); /*signed values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert!(r.read_signed::(2).is_ok()); assert!(r.read_signed::(3).is_ok()); assert_eq!( r.read_signed::(5).unwrap_err().kind(), ErrorKind::UnexpectedEof ); let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert!(r.read_signed_in::<2, i32>().is_ok()); assert!(r.read_signed_in::<3, i32>().is_ok()); assert_eq!( r.read_signed_in::<5, i32>().unwrap_err().kind(), ErrorKind::UnexpectedEof ); /*unary 0 values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert!(r.read_unary0().is_ok()); assert!(r.read_unary0().is_ok()); assert!(r.read_unary0().is_ok()); assert!(r.read_unary0().is_ok()); assert_eq!( r.read_unary0().unwrap_err().kind(), ErrorKind::UnexpectedEof ); /*unary 1 values*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert!(r.read_unary1().is_ok()); assert!(r.read_unary1().is_ok()); assert!(r.read_unary1().is_ok()); assert!(r.read_unary1().is_ok()); assert_eq!( r.read_unary1().unwrap_err().kind(), ErrorKind::UnexpectedEof ); /*reading bytes, aligned*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); let mut sub_data = [0; 2]; assert_eq!( r.read_bytes(&mut sub_data).unwrap_err().kind(), ErrorKind::UnexpectedEof ); /*reading bytes, un-aligned*/ let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); let mut sub_data = [0; 2]; assert!(r.read::(4).is_ok()); assert_eq!( r.read_bytes(&mut sub_data).unwrap_err().kind(), ErrorKind::UnexpectedEof ); } #[test] fn test_reader_bits_errors() { use bitstream_io::{BigEndian, BitRead, BitReader, LittleEndian}; use std::io::ErrorKind; let actual_data = [0u8; 10]; let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert_eq!(r.read::(9).unwrap_err().kind(), ErrorKind::InvalidInput); assert_eq!( r.read::(17).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read::(33).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read::(65).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed::(9).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed::(17).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed::(33).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed::(65).unwrap_err().kind(), ErrorKind::InvalidInput ); let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); assert_eq!(r.read::(9).unwrap_err().kind(), ErrorKind::InvalidInput); assert_eq!( r.read::(17).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read::(33).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read::(65).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed::(9).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed::(17).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed::(33).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed::(65).unwrap_err().kind(), ErrorKind::InvalidInput ); } #[test] fn test_clone() { use bitstream_io::{BigEndian, BitRead, BitReader}; // Reading unsigned examples, cloning while unaligned. let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); assert!(r.byte_aligned()); assert_eq!(r.read::(4).unwrap(), 0xB); let mut r2 = r.clone(); assert!(!r.byte_aligned()); assert_eq!(r.read::(4).unwrap(), 0x1); assert_eq!(r.read::(8).unwrap(), 0xED); assert!(!r2.byte_aligned()); assert_eq!(r2.read::(4).unwrap(), 0x1); assert_eq!(r2.read::(8).unwrap(), 0xED); // Can still instantiate a BitReader when the backing std::io::Read is // !Clone. struct NotCloneRead<'a>(&'a [u8]); impl<'a> std::io::Read for NotCloneRead<'a> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { self.0.read(buf) } } let _r = BitReader::endian(NotCloneRead(&actual_data[..]), BigEndian); } #[test] fn test_read_bytes() { use bitstream_io::{BigEndian, BitRead, BitReader, LittleEndian}; let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); let read_data: [u8; 4] = r.read_to().unwrap(); assert_eq!(actual_data, read_data); let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(Cursor::new(&actual_data), LittleEndian); let read_data: [u8; 4] = r.read_to().unwrap(); assert_eq!(actual_data, read_data); } bitstream-io-2.5.0/tests/read_seek.rs000064400000000000000000000075721046102023000156740ustar 00000000000000use std::io; use std::io::{Cursor, SeekFrom}; use bitstream_io::{BigEndian, BitRead, BitReader, Endianness, LittleEndian}; #[test] fn test_reader_pos_be() -> io::Result<()> { test_reader_pos::() } #[test] fn test_reader_pos_le() -> io::Result<()> { test_reader_pos::() } fn test_reader_pos() -> io::Result<()> { let actual_data: [u8; 7] = [ 0b1000_1110, 0b1000_1110, 0b1000_1110, 0b1000_1110, 0b1000_1110, 0b1000_1110, 0b1000_1110, ]; let mut r: BitReader<_, E> = BitReader::new(Cursor::new(&actual_data)); assert_eq!(r.position_in_bits()?, 0); r.read_bit()?; r.read_bit()?; assert_eq!(r.position_in_bits()?, 2); let _: u32 = r.read(5)?; assert_eq!(r.position_in_bits()?, 7); let _: u32 = r.read(4)?; assert_eq!(r.position_in_bits()?, 11); let mut buf = [0u8; 2]; r.read_bytes(&mut buf)?; assert_eq!(r.position_in_bits()?, 27); r.read_bit()?; r.read_bit()?; r.read_bit()?; r.read_bit()?; r.read_bit()?; r.read_bit()?; r.read_bit()?; let _: i32 = r.read_signed(9)?; assert_eq!(r.position_in_bits()?, 43); let _: i32 = r.read_signed(5)?; assert_eq!(r.position_in_bits()?, 48); Ok(()) } #[test] pub fn test_reader_seek_start() -> io::Result<()> { let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); r.seek_bits(SeekFrom::Start(0))?; assert_eq!(r.position_in_bits()?, 0); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, true); assert_eq!(r.position_in_bits()?, 8); r.seek_bits(SeekFrom::Start(2))?; assert_eq!(r.position_in_bits()?, 2); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, true); assert_eq!(r.position_in_bits()?, 8); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, true); assert_eq!(r.position_in_bits()?, 10); r.seek_bits(SeekFrom::Start(7))?; assert_eq!(r.position_in_bits()?, 7); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, false); Ok(()) } #[test] pub fn test_reader_seek_current() -> io::Result<()> { let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); r.seek_bits(SeekFrom::Current(2))?; assert_eq!(r.position_in_bits()?, 2); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, false); let _: i32 = r.read_signed(11)?; assert_eq!(r.position_in_bits()?, 17); r.seek_bits(SeekFrom::Current(-3))?; assert_eq!(r.position_in_bits()?, 14); r.skip(10)?; assert_eq!(r.position_in_bits()?, 24); r.seek_bits(SeekFrom::Current(0))?; assert_eq!(r.position_in_bits()?, 24); Ok(()) } #[test] pub fn test_reader_seek_end() -> io::Result<()> { let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(Cursor::new(&actual_data), BigEndian); r.seek_bits(SeekFrom::End(7))?; assert_eq!(r.position_in_bits()?, 25); assert_eq!(r.read_bit()?, true); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, false); assert_eq!(r.read_bit()?, false); assert_eq!(r.position_in_bits()?, 29); r.seek_bits(SeekFrom::End(0))?; assert_eq!(r.position_in_bits()?, 32); Ok(()) } bitstream-io-2.5.0/tests/roundtrip.rs000064400000000000000000000115251046102023000157710ustar 00000000000000// Copyright 2017 Brian Langenberger // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. extern crate bitstream_io; use bitstream_io::{BigEndian, BitRead, BitReader, BitWrite, BitWriter, LittleEndian}; use std::io::Cursor; macro_rules! define_roundtrip { ($func_name:ident, $endianness:ident) => { #[test] fn $func_name() { /*unsigned values*/ for bits in 1..17 { let max = 1 << bits; let mut output: Vec = Vec::with_capacity(max); { let mut writer = BitWriter::endian(&mut output, $endianness); for value in 0..max { writer.write(bits, value as u32).unwrap(); } writer.byte_align().unwrap(); } { let mut c = Cursor::new(&output); let mut reader = BitReader::endian(&mut c, $endianness); for value in 0..max { assert_eq!(reader.read::(bits).unwrap(), value as u32); } } } /*signed values*/ for bits in 2..17 { let min = -1i32 << (bits - 1); let max = 1i32 << (bits - 1); let mut output: Vec = Vec::with_capacity(max as usize); { let mut writer = BitWriter::endian(&mut output, $endianness); for value in min..max { writer.write_signed(bits, value as i32).unwrap(); } writer.byte_align().unwrap(); } { let mut c = Cursor::new(&output); let mut reader = BitReader::endian(&mut c, $endianness); for value in min..max { assert_eq!(reader.read_signed::(bits).unwrap(), value as i32); } } } } }; } define_roundtrip!(test_roundtrip_be, BigEndian); define_roundtrip!(test_roundtrip_le, LittleEndian); macro_rules! define_unary_roundtrip { ($func_name:ident, $endianness:ident) => { #[test] fn $func_name() { let mut output: Vec = Vec::new(); { let mut writer = BitWriter::endian(&mut output, $endianness); for value in 0..1024 { writer.write_unary0(value).unwrap(); } writer.byte_align().unwrap(); } { let mut c = Cursor::new(&output); let mut reader = BitReader::endian(&mut c, $endianness); for value in 0..1024 { assert_eq!(reader.read_unary0().unwrap(), value); } } let mut output: Vec = Vec::new(); { let mut writer = BitWriter::endian(&mut output, $endianness); for value in 0..1024 { writer.write_unary1(value).unwrap(); } writer.byte_align().unwrap(); } { let mut c = Cursor::new(&output); let mut reader = BitReader::endian(&mut c, $endianness); for value in 0..1024 { assert_eq!(reader.read_unary1().unwrap(), value); } } } }; } define_unary_roundtrip!(test_unary_roundtrip_be, BigEndian); define_unary_roundtrip!(test_unary_roundtrip_le, LittleEndian); macro_rules! define_float_roundtrip { ($func_name:ident, $endianness:ident, $t:ty) => { #[test] fn $func_name() { let mut output: Vec = Vec::new(); { let mut writer = BitWriter::endian(&mut output, $endianness); // these values should all be exact in floating-point for value in 0..1024 { writer.write_from(value as $t).unwrap(); } writer.byte_align().unwrap(); } { let mut c = Cursor::new(&output); let mut reader = BitReader::endian(&mut c, $endianness); for value in 0..1024 { assert_eq!(reader.read_to::<$t>().unwrap(), value as $t); } } } }; } define_float_roundtrip!(test_f32_roundtrip_be, BigEndian, f32); define_float_roundtrip!(test_f64_roundtrip_be, BigEndian, f64); define_float_roundtrip!(test_f32_roundtrip_le, LittleEndian, f32); define_float_roundtrip!(test_f64_roundtrip_le, LittleEndian, f64); bitstream-io-2.5.0/tests/write.rs000064400000000000000000001660751046102023000151100ustar 00000000000000// Copyright 2017 Brian Langenberger // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. extern crate bitstream_io; #[test] fn test_write_queue_be() { use bitstream_io::{BitQueue, Numeric, BE}; let mut q: BitQueue = BitQueue::new(); let mut v = BitQueue::::from_value(0b10u8, 2); q.push(2, v.pop(2).to_u8()); let mut v = BitQueue::::from_value(0b110u8, 3); q.push(3, v.pop(3).to_u8()); let mut v = BitQueue::::from_value(0b001_11u8, 5); q.push(3, v.pop(3).to_u8()); assert_eq!(q.len(), 8); assert_eq!(q.pop(8), 0b10_110_001); q.push(2, v.pop(2).to_u8()); let mut v = BitQueue::::from_value(0b101u8, 3); q.push(3, v.pop(3).to_u8()); let mut v = BitQueue::::from_value(0b101_00111011_11000001, 19); q.push(3, v.pop(3).to_u8()); assert_eq!(q.len(), 8); assert_eq!(q.pop(8), 0b11_101_101); q.push(8, v.pop(8).to_u8()); assert_eq!(q.len(), 8); assert_eq!(q.pop(8), 0b00111011); q.push(8, v.pop(8).to_u8()); assert_eq!(q.len(), 8); assert_eq!(q.pop(8), 0b11000001); assert!(v.is_empty()); assert!(q.is_empty()); } #[test] fn test_write_queue_edge_be() { use bitstream_io::{BitQueue, BE}; let mut q: BitQueue = BitQueue::from_value(0, 0); q.push(8, 0b11111111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b1, 1); q.push(7, 0b1111111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b11, 2); q.push(6, 0b111111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b111, 3); q.push(5, 0b11111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b1111, 4); q.push(4, 0b1111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b11111, 5); q.push(3, 0b111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b111111, 6); q.push(2, 0b11); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b1111111, 7); q.push(1, 0b1); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b11111111, 8); q.push(0, 0); assert_eq!(q.pop(8), 0b11111111); } #[test] fn test_write_queue_le() { use bitstream_io::{BitQueue, Numeric, LE}; let mut q: BitQueue = BitQueue::new(); let mut v = BitQueue::::from_value(0b01u8, 2); q.push(2, v.pop(2).to_u8()); let mut v = BitQueue::::from_value(0b100u8, 3); q.push(3, v.pop(3).to_u8()); let mut v = BitQueue::::from_value(0b01_101u8, 5); q.push(3, v.pop(3).to_u8()); assert_eq!(q.len(), 8); assert_eq!(q.pop(8), 0b101_100_01); q.push(2, v.pop(2).to_u8()); let mut v = BitQueue::::from_value(0b011u8, 3); q.push(3, v.pop(3).to_u8()); let mut v = BitQueue::::from_value(0b11000001_00111011_111, 19); q.push(3, v.pop(3).to_u8()); assert_eq!(q.len(), 8); assert_eq!(q.pop(8), 0b111_011_01); q.push(8, v.pop(8).to_u8()); assert_eq!(q.len(), 8); assert_eq!(q.pop(8), 0b00111011); q.push(8, v.pop(8).to_u8()); assert_eq!(q.len(), 8); assert_eq!(q.pop(8), 0b11000001); assert!(v.is_empty()); assert!(q.is_empty()); } #[test] fn test_write_queue_edge_le() { use bitstream_io::{BitQueue, LE}; let mut q: BitQueue = BitQueue::from_value(0, 0); q.push(8, 0b11111111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b1, 1); q.push(7, 0b1111111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b11, 2); q.push(6, 0b111111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b111, 3); q.push(5, 0b11111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b1111, 4); q.push(4, 0b1111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b11111, 5); q.push(3, 0b111); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b111111, 6); q.push(2, 0b11); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b1111111, 7); q.push(1, 0b1); assert_eq!(q.pop(8), 0b11111111); let mut q: BitQueue = BitQueue::from_value(0b11111111, 8); q.push(0, 0); assert_eq!(q.pop(8), 0b11111111); } #[test] fn test_writer_be() { use bitstream_io::{BigEndian, BitWrite, BitWriter}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; /*writing individual bits*/ let mut w = BitWriter::endian(Vec::with_capacity(2), BigEndian); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data[0..2]); /*writing unsigned values*/ let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); assert!(w.byte_aligned()); w.write(2, 2u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 6u32).unwrap(); assert!(!w.byte_aligned()); w.write(5, 7u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 5u32).unwrap(); assert!(!w.byte_aligned()); w.write(19, 0x53BC1u32).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.into_writer().as_slice(), &final_data); let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); assert!(w.byte_aligned()); w.write_out::<2, u32>(2).unwrap(); assert!(!w.byte_aligned()); w.write_out::<3, u32>(6).unwrap(); assert!(!w.byte_aligned()); w.write_out::<5, u32>(7).unwrap(); assert!(!w.byte_aligned()); w.write_out::<3, u32>(5).unwrap(); assert!(!w.byte_aligned()); w.write_out::<19, u32>(0x53BC1).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.into_writer().as_slice(), &final_data); /*writing signed values*/ let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write_signed(2, -2).unwrap(); w.write_signed(3, -2).unwrap(); w.write_signed(5, 7).unwrap(); w.write_signed(3, -3).unwrap(); w.write_signed(19, -181311).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write_signed_out::<2, i32>(-2).unwrap(); w.write_signed_out::<3, i32>(-2).unwrap(); w.write_signed_out::<5, i32>(7).unwrap(); w.write_signed_out::<3, i32>(-3).unwrap(); w.write_signed_out::<19, i32>(-181311).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); /*writing unary 0 values*/ let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write_unary0(1).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(4).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(3).unwrap(); w.write_unary0(4).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write(1, 1u32).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); /*writing unary 1 values*/ let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(3).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(2).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(5).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); /*byte aligning*/ let aligned_data = [0xA0, 0xE0, 0x3B, 0xC0]; let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write(4, 12u32).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer().as_slice(), &aligned_data); /*writing bytes, aligned*/ let final_data = [0xB1, 0xED]; let mut w = BitWriter::endian(Vec::with_capacity(2), BigEndian); w.write_bytes(b"\xB1\xED").unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); /*writing bytes, un-aligned*/ let final_data = [0xBB, 0x1E, 0xD0]; let mut w = BitWriter::endian(Vec::with_capacity(3), BigEndian); w.write(4, 11u32).unwrap(); w.write_bytes(b"\xB1\xED").unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); } #[test] fn test_writer_edge_cases_be() { use bitstream_io::{BigEndian, BitWrite, BitWriter}; // 0 bit writes let mut w = BitWriter::endian(Vec::new(), BigEndian); w.write(0, 0u8).unwrap(); w.write(0, 0u16).unwrap(); w.write(0, 0u32).unwrap(); w.write(0, 0u64).unwrap(); assert!(w.into_writer().is_empty()); let mut w = BitWriter::endian(Vec::new(), BigEndian); assert!(w.write_signed(0, 0i8).is_err()); assert!(w.write_signed(0, 0i16).is_err()); assert!(w.write_signed(0, 0i32).is_err()); assert!(w.write_signed(0, 0i64).is_err()); assert!(w.into_writer().is_empty()); let final_data: Vec = vec![ 0, 0, 0, 0, 255, 255, 255, 255, 128, 0, 0, 0, 127, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 128, 0, 0, 0, 0, 0, 0, 0, 127, 255, 255, 255, 255, 255, 255, 255, ]; /*unsigned 32 and 64-bit values*/ let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); w.write(32, 0u32).unwrap(); w.write(32, 4294967295u32).unwrap(); w.write(32, 2147483648u32).unwrap(); w.write(32, 2147483647u32).unwrap(); w.write(64, 0u64).unwrap(); w.write(64, 0xFFFFFFFFFFFFFFFFu64).unwrap(); w.write(64, 9223372036854775808u64).unwrap(); w.write(64, 9223372036854775807u64).unwrap(); assert_eq!(w.into_writer(), final_data); let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); w.write_out::<32, u32>(0).unwrap(); w.write_out::<32, u32>(4294967295).unwrap(); w.write_out::<32, u32>(2147483648).unwrap(); w.write_out::<32, u32>(2147483647).unwrap(); w.write_out::<64, u64>(0).unwrap(); w.write_out::<64, u64>(0xFFFFFFFFFFFFFFFF).unwrap(); w.write_out::<64, u64>(9223372036854775808).unwrap(); w.write_out::<64, u64>(9223372036854775807).unwrap(); assert_eq!(w.into_writer(), final_data); /*signed 32 and 64-bit values*/ let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); w.write(32, 0i32).unwrap(); w.write(32, -1i32).unwrap(); w.write(32, -2147483648i32).unwrap(); w.write(32, 2147483647i32).unwrap(); w.write(64, 0i64).unwrap(); w.write(64, -1i64).unwrap(); w.write(64, -9223372036854775808i64).unwrap(); w.write(64, 9223372036854775807i64).unwrap(); assert_eq!(w.into_writer(), final_data); let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); w.write_out::<32, i32>(0).unwrap(); w.write_out::<32, i32>(-1).unwrap(); w.write_out::<32, i32>(-2147483648).unwrap(); w.write_out::<32, i32>(2147483647).unwrap(); w.write_out::<64, i64>(0).unwrap(); w.write_out::<64, i64>(-1).unwrap(); w.write_out::<64, i64>(-9223372036854775808).unwrap(); w.write_out::<64, i64>(9223372036854775807).unwrap(); assert_eq!(w.into_writer(), final_data); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(8, std::i8::MAX) .unwrap(); } assert_eq!(bytes, std::i8::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(8, std::i8::MIN) .unwrap(); } assert_eq!(bytes, std::i8::MIN.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(16, std::i16::MAX) .unwrap(); } assert_eq!(bytes, std::i16::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(16, std::i16::MIN) .unwrap(); } assert_eq!(bytes, std::i16::MIN.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(32, std::i32::MAX) .unwrap(); } assert_eq!(bytes, std::i32::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(32, std::i32::MIN) .unwrap(); } assert_eq!(bytes, std::i32::MIN.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(64, std::i64::MAX) .unwrap(); } assert_eq!(bytes, std::i64::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(64, std::i64::MIN) .unwrap(); } assert_eq!(bytes, std::i64::MIN.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(128, std::i128::MAX) .unwrap(); } assert_eq!(bytes, std::i128::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed(128, std::i128::MIN) .unwrap(); } assert_eq!(bytes, std::i128::MIN.to_be_bytes()); } #[test] fn test_writer_huffman_be() { use bitstream_io::huffman::compile_write_tree; use bitstream_io::{BigEndian, BitWrite, BitWriter, HuffmanWrite}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let tree = compile_write_tree(vec![ (0, vec![1, 1]), (1, vec![1, 0]), (2, vec![0, 1]), (3, vec![0, 0, 1]), (4, vec![0, 0, 0]), ]) .unwrap(); let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); } #[test] fn test_writer_le() { use bitstream_io::{BitWrite, BitWriter, LittleEndian}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; /*writing individual bits*/ let mut w = BitWriter::endian(Vec::with_capacity(2), LittleEndian); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data[0..2]); /*writing unsigned values*/ let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); assert!(w.byte_aligned()); w.write(2, 1u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 4u32).unwrap(); assert!(!w.byte_aligned()); w.write(5, 13u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 3u32).unwrap(); assert!(!w.byte_aligned()); w.write(19, 0x609DFu32).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.into_writer().as_slice(), &final_data); let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); assert!(w.byte_aligned()); w.write_out::<2, u32>(1).unwrap(); assert!(!w.byte_aligned()); w.write_out::<3, u32>(4).unwrap(); assert!(!w.byte_aligned()); w.write_out::<5, u32>(13).unwrap(); assert!(!w.byte_aligned()); w.write_out::<3, u32>(3).unwrap(); assert!(!w.byte_aligned()); w.write_out::<19, u32>(0x609DF).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.into_writer().as_slice(), &final_data); /*writing signed values*/ let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.write_signed(2, 1).unwrap(); w.write_signed(3, -4).unwrap(); w.write_signed(5, 13).unwrap(); w.write_signed(3, 3).unwrap(); w.write_signed(19, -128545).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.write_signed_out::<2, i32>(1).unwrap(); w.write_signed_out::<3, i32>(-4).unwrap(); w.write_signed_out::<5, i32>(13).unwrap(); w.write_signed_out::<3, i32>(3).unwrap(); w.write_signed_out::<19, i32>(-128545).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); /*writing unary 0 values*/ let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(5).unwrap(); w.write_unary0(3).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write(2, 3u32).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); /*writing unary 1 values*/ let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.write_unary1(0).unwrap(); w.write_unary1(3).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(2).unwrap(); w.write_unary1(5).unwrap(); w.write_unary1(0).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); /*byte aligning*/ let aligned_data = [0x05, 0x07, 0x3B, 0x0C]; let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.write(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write(4, 12u32).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer().as_slice(), &aligned_data); /*writing bytes, aligned*/ let final_data = [0xB1, 0xED]; let mut w = BitWriter::endian(Vec::with_capacity(2), LittleEndian); w.write_bytes(b"\xB1\xED").unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); /*writing bytes, un-aligned*/ let final_data = [0x1B, 0xDB, 0x0E]; let mut w = BitWriter::endian(Vec::with_capacity(3), LittleEndian); w.write(4, 11u32).unwrap(); w.write_bytes(b"\xB1\xED").unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); } #[test] fn test_writer_edge_cases_le() { use bitstream_io::{BitWrite, BitWriter, LittleEndian}; // 0 bit writes let mut w = BitWriter::endian(Vec::new(), LittleEndian); w.write(0, 0u8).unwrap(); w.write(0, 0u16).unwrap(); w.write(0, 0u32).unwrap(); w.write(0, 0u64).unwrap(); assert!(w.into_writer().is_empty()); let mut w = BitWriter::endian(Vec::new(), LittleEndian); assert!(w.write_signed(0, 0i8).is_err()); assert!(w.write_signed(0, 0i16).is_err()); assert!(w.write_signed(0, 0i32).is_err()); assert!(w.write_signed(0, 0i64).is_err()); assert!(w.into_writer().is_empty()); let final_data: Vec = vec![ 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 128, 255, 255, 255, 127, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 128, 255, 255, 255, 255, 255, 255, 255, 127, ]; /*unsigned 32 and 64-bit values*/ let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); w.write(32, 0u32).unwrap(); w.write(32, 4294967295u32).unwrap(); w.write(32, 2147483648u32).unwrap(); w.write(32, 2147483647u32).unwrap(); w.write(64, 0u64).unwrap(); w.write(64, 0xFFFFFFFFFFFFFFFFu64).unwrap(); w.write(64, 9223372036854775808u64).unwrap(); w.write(64, 9223372036854775807u64).unwrap(); assert_eq!(w.into_writer(), final_data); let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); w.write_out::<32, u32>(0).unwrap(); w.write_out::<32, u32>(4294967295).unwrap(); w.write_out::<32, u32>(2147483648).unwrap(); w.write_out::<32, u32>(2147483647).unwrap(); w.write_out::<64, u64>(0).unwrap(); w.write_out::<64, u64>(0xFFFFFFFFFFFFFFFF).unwrap(); w.write_out::<64, u64>(9223372036854775808).unwrap(); w.write_out::<64, u64>(9223372036854775807).unwrap(); assert_eq!(w.into_writer(), final_data); /*signed 32 and 64-bit values*/ let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); w.write(32, 0i32).unwrap(); w.write(32, -1i32).unwrap(); w.write(32, -2147483648i32).unwrap(); w.write(32, 2147483647i32).unwrap(); w.write(64, 0i64).unwrap(); w.write(64, -1i64).unwrap(); w.write(64, -9223372036854775808i64).unwrap(); w.write(64, 9223372036854775807i64).unwrap(); assert_eq!(w.into_writer(), final_data); let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); w.write_out::<32, i32>(0).unwrap(); w.write_out::<32, i32>(-1).unwrap(); w.write_out::<32, i32>(-2147483648).unwrap(); w.write_out::<32, i32>(2147483647).unwrap(); w.write_out::<64, i64>(0).unwrap(); w.write_out::<64, i64>(-1).unwrap(); w.write_out::<64, i64>(-9223372036854775808).unwrap(); w.write_out::<64, i64>(9223372036854775807).unwrap(); assert_eq!(w.into_writer(), final_data); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(8, std::i8::MAX) .unwrap(); } assert_eq!(bytes, std::i8::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(8, std::i8::MIN) .unwrap(); } assert_eq!(bytes, std::i8::MIN.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(16, std::i16::MAX) .unwrap(); } assert_eq!(bytes, std::i16::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(16, std::i16::MIN) .unwrap(); } assert_eq!(bytes, std::i16::MIN.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(32, std::i32::MAX) .unwrap(); } assert_eq!(bytes, std::i32::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(32, std::i32::MIN) .unwrap(); } assert_eq!(bytes, std::i32::MIN.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(64, std::i64::MAX) .unwrap(); } assert_eq!(bytes, std::i64::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(64, std::i64::MIN) .unwrap(); } assert_eq!(bytes, std::i64::MIN.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(128, std::i128::MAX) .unwrap(); } assert_eq!(bytes, std::i128::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed(128, std::i128::MIN) .unwrap(); } assert_eq!(bytes, std::i128::MIN.to_le_bytes()); } #[test] fn test_writer_huffman_le() { use bitstream_io::huffman::compile_write_tree; use bitstream_io::{BitWrite, BitWriter, HuffmanWrite, LittleEndian}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let tree = compile_write_tree(vec![ (0, vec![1, 1]), (1, vec![1, 0]), (2, vec![0, 1]), (3, vec![0, 0, 1]), (4, vec![0, 0, 0]), ]) .unwrap(); let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 3).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 3).unwrap(); w.write(1, 1).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); } struct LimitedWriter { can_write: usize, } impl LimitedWriter { fn new(max_bytes: usize) -> LimitedWriter { LimitedWriter { can_write: max_bytes, } } } impl std::io::Write for LimitedWriter { fn write(&mut self, buf: &[u8]) -> Result { use std::cmp::min; let to_write = min(buf.len(), self.can_write); self.can_write -= to_write; Ok(to_write) } fn flush(&mut self) -> Result<(), std::io::Error> { Ok(()) } } #[test] fn test_writer_io_errors_be() { use bitstream_io::{BigEndian, BitWrite, BitWriter}; use std::io::ErrorKind; /*individual bits*/ let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(false).is_ok()); assert_eq!(w.write_bit(true).unwrap_err().kind(), ErrorKind::WriteZero); /*unsigned values*/ let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write(2, 2u32).is_ok()); assert!(w.write(3, 6u32).is_ok()); assert!(w.write(5, 7u32).is_ok()); assert!(w.write(3, 5u32).is_ok()); assert_eq!( w.write(19, 0x53BC1u32).unwrap_err().kind(), ErrorKind::WriteZero ); /*signed values*/ let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write_signed(2, -2).is_ok()); assert!(w.write_signed(3, -2).is_ok()); assert!(w.write_signed(5, 7).is_ok()); assert!(w.write_signed(3, -3).is_ok()); assert_eq!( w.write_signed(19, -181311).unwrap_err().kind(), ErrorKind::WriteZero ); /*unary 0 values*/ let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write_unary0(1).is_ok()); assert!(w.write_unary0(2).is_ok()); assert!(w.write_unary0(0).is_ok()); assert!(w.write_unary0(0).is_ok()); assert!(w.write_unary0(4).is_ok()); assert!(w.write_unary0(2).is_ok()); assert_eq!(w.write_unary0(1).unwrap_err().kind(), ErrorKind::WriteZero); /*unary 1 values*/ let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(1).is_ok()); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(3).is_ok()); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(1).is_ok()); assert!(w.write_unary1(0).is_ok()); assert_eq!(w.write_unary1(1).unwrap_err().kind(), ErrorKind::WriteZero); /*byte aligning*/ let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write::(9, 0b111111111).is_ok()); assert_eq!(w.byte_align().unwrap_err().kind(), ErrorKind::WriteZero); /*aligned bytes*/ let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert_eq!( w.write_bytes(b"\xB1\xED").unwrap_err().kind(), ErrorKind::WriteZero ); /*un-aligned bytes*/ let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write(4, 11).is_ok()); assert_eq!( w.write_bytes(b"\xB1\xED").unwrap_err().kind(), ErrorKind::WriteZero ); } #[test] fn test_writer_io_errors_le() { use bitstream_io::{BitWrite, BitWriter, LittleEndian}; use std::io::ErrorKind; /*individual bits*/ let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(false).is_ok()); assert!(w.write_bit(true).is_ok()); assert!(w.write_bit(true).is_ok()); assert_eq!(w.write_bit(true).unwrap_err().kind(), ErrorKind::WriteZero); /*unsigned values*/ let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write(2, 1u32).is_ok()); assert!(w.write(3, 4u32).is_ok()); assert!(w.write(5, 13u32).is_ok()); assert!(w.write(3, 3u32).is_ok()); assert_eq!( w.write(19, 0x609DFu32).unwrap_err().kind(), ErrorKind::WriteZero ); /*signed values*/ let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write_signed(2, 1).is_ok()); assert!(w.write_signed(3, -4).is_ok()); assert!(w.write_signed(5, 13).is_ok()); assert!(w.write_signed(3, 3).is_ok()); assert_eq!( w.write_signed(19, -128545).unwrap_err().kind(), ErrorKind::WriteZero ); /*unary 0 values*/ let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write_unary0(1).is_ok()); assert!(w.write_unary0(0).is_ok()); assert!(w.write_unary0(0).is_ok()); assert!(w.write_unary0(2).is_ok()); assert!(w.write_unary0(2).is_ok()); assert!(w.write_unary0(2).is_ok()); assert_eq!(w.write_unary0(5).unwrap_err().kind(), ErrorKind::WriteZero); /*unary 1 values*/ let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(3).is_ok()); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(1).is_ok()); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(1).is_ok()); assert!(w.write_unary1(0).is_ok()); assert!(w.write_unary1(1).is_ok()); assert!(w.write_unary1(0).is_ok()); assert_eq!(w.write_unary1(1).unwrap_err().kind(), ErrorKind::WriteZero); /*byte aligning*/ let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write::(9, 0b111111111).is_ok()); assert_eq!(w.byte_align().unwrap_err().kind(), ErrorKind::WriteZero); /*aligned bytes*/ let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert_eq!( w.write_bytes(b"\xB1\xED").unwrap_err().kind(), ErrorKind::WriteZero ); /*un-aligned bytes*/ let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write(4, 11).is_ok()); assert_eq!( w.write_bytes(b"\xB1\xED").unwrap_err().kind(), ErrorKind::WriteZero ); } #[test] fn test_writer_bits_errors() { use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian}; use std::io::{sink, ErrorKind}; let mut w = BitWriter::endian(sink(), BigEndian); assert_eq!(w.write(9, 0u8).unwrap_err().kind(), ErrorKind::InvalidInput); assert_eq!( w.write(17, 0u16).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(33, 0u32).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(65, 0u64).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(1, 0b10).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(2, 0b100).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(3, 0b1000).unwrap_err().kind(), ErrorKind::InvalidInput ); for bits in 1..8 { let val = 1u8 << bits; assert_eq!( w.write(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 8..16 { let val = 1u16 << bits; assert_eq!( w.write(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 16..32 { let val = 1u32 << bits; assert_eq!( w.write(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 32..64 { let val = 1u64 << bits; assert_eq!( w.write(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } assert_eq!( w.write_signed(9, 0i8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed(17, 0i16).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed(33, 0i32).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed(65, 0i64).unwrap_err().kind(), ErrorKind::InvalidInput ); let mut w = BitWriter::endian(sink(), LittleEndian); assert_eq!(w.write(9, 0u8).unwrap_err().kind(), ErrorKind::InvalidInput); assert_eq!( w.write(17, 0u16).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(33, 0u32).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(65, 0u64).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(1, 0b10).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(2, 0b100).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write(3, 0b1000).unwrap_err().kind(), ErrorKind::InvalidInput ); for bits in 1..8 { let val = 1u8 << bits; assert_eq!( w.write(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 8..16 { let val = 1u16 << bits; assert_eq!( w.write(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 16..32 { let val = 1u32 << bits; assert_eq!( w.write(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 32..64 { let val = 1u64 << bits; assert_eq!( w.write(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } assert_eq!( w.write_signed(9, 0i8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed(17, 0i16).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed(33, 0i32).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed(65, 0i64).unwrap_err().kind(), ErrorKind::InvalidInput ); } #[test] fn test_counter_be() { use bitstream_io::{BigEndian, BitCounter, BitWrite}; /*writing individual bits*/ let mut w: BitCounter = BitCounter::new(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); assert_eq!(w.written(), 16); /*writing unsigned values*/ let mut w: BitCounter = BitCounter::new(); assert!(w.byte_aligned()); w.write(2, 2u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 6u32).unwrap(); assert!(!w.byte_aligned()); w.write(5, 7u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 5u32).unwrap(); assert!(!w.byte_aligned()); w.write(19, 0x53BC1u32).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.written(), 32); /*writing signed values*/ let mut w: BitCounter = BitCounter::new(); w.write_signed(2, -2).unwrap(); w.write_signed(3, -2).unwrap(); w.write_signed(5, 7).unwrap(); w.write_signed(3, -3).unwrap(); w.write_signed(19, -181311).unwrap(); assert_eq!(w.written(), 32); /*writing unary 0 values*/ let mut w: BitCounter = BitCounter::new(); w.write_unary0(1).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(4).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(3).unwrap(); w.write_unary0(4).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write(1, 1u32).unwrap(); assert_eq!(w.written(), 32); /*writing unary 1 values*/ let mut w: BitCounter = BitCounter::new(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(3).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(2).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(5).unwrap(); assert_eq!(w.written(), 32); /*byte aligning*/ let mut w: BitCounter = BitCounter::new(); w.write(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write(4, 12u32).unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 32); /*writing bytes, aligned*/ let mut w: BitCounter = BitCounter::new(); w.write_bytes(b"\xB1\xED").unwrap(); assert_eq!(w.written(), 16); /*writing bytes, un-aligned*/ let mut w: BitCounter = BitCounter::new(); w.write(4, 11u32).unwrap(); w.write_bytes(b"\xB1\xED").unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 24); } #[test] fn test_counter_huffman_be() { use bitstream_io::huffman::compile_write_tree; use bitstream_io::{BigEndian, BitCounter, BitWrite, HuffmanWrite}; let tree = compile_write_tree(vec![ (0, vec![1, 1]), (1, vec![1, 0]), (2, vec![0, 1]), (3, vec![0, 0, 1]), (4, vec![0, 0, 0]), ]) .unwrap(); let mut w: BitCounter = BitCounter::new(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 32); } #[test] fn test_counter_le() { use bitstream_io::{BitCounter, BitWrite, LittleEndian}; /*writing individual bits*/ let mut w: BitCounter = BitCounter::new(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); assert_eq!(w.written(), 16); /*writing unsigned values*/ let mut w: BitCounter = BitCounter::new(); assert!(w.byte_aligned()); w.write(2, 1u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 4u32).unwrap(); assert!(!w.byte_aligned()); w.write(5, 13u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 3u32).unwrap(); assert!(!w.byte_aligned()); w.write(19, 0x609DFu32).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.written(), 32); /*writing signed values*/ let mut w: BitCounter = BitCounter::new(); w.write_signed(2, 1).unwrap(); w.write_signed(3, -4).unwrap(); w.write_signed(5, 13).unwrap(); w.write_signed(3, 3).unwrap(); w.write_signed(19, -128545).unwrap(); assert_eq!(w.written(), 32); /*writing unary 0 values*/ let mut w: BitCounter = BitCounter::new(); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(5).unwrap(); w.write_unary0(3).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write(2, 3u32).unwrap(); assert_eq!(w.written(), 32); /*writing unary 1 values*/ let mut w: BitCounter = BitCounter::new(); w.write_unary1(0).unwrap(); w.write_unary1(3).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(2).unwrap(); w.write_unary1(5).unwrap(); w.write_unary1(0).unwrap(); assert_eq!(w.written(), 32); /*byte aligning*/ let mut w: BitCounter = BitCounter::new(); w.write(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write(4, 12u32).unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 32); /*writing bytes, aligned*/ let mut w: BitCounter = BitCounter::new(); w.write_bytes(b"\xB1\xED").unwrap(); assert_eq!(w.written(), 16); /*writing bytes, un-aligned*/ let mut w: BitCounter = BitCounter::new(); w.write(4, 11u32).unwrap(); w.write_bytes(b"\xB1\xED").unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 24); } #[test] fn test_counter_huffman_le() { use bitstream_io::huffman::compile_write_tree; use bitstream_io::{BitCounter, BitWrite, HuffmanWrite, LittleEndian}; let tree = compile_write_tree(vec![ (0, vec![1, 1]), (1, vec![1, 0]), (2, vec![0, 1]), (3, vec![0, 0, 1]), (4, vec![0, 0, 0]), ]) .unwrap(); let mut w: BitCounter = BitCounter::new(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 3).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 3).unwrap(); w.write(1, 1).unwrap(); assert_eq!(w.written(), 32); } #[test] fn test_recorder_be() { use bitstream_io::{BigEndian, BitRecorder, BitWrite, BitWriter}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; /*writing individual bits*/ let mut w: BitRecorder = BitRecorder::new(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); assert_eq!(w.written(), 16); let mut w2 = BitWriter::endian(Vec::with_capacity(2), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data[0..2]); /*writing unsigned values*/ let mut w: BitRecorder = BitRecorder::new(); assert!(w.byte_aligned()); w.write(2, 2u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 6u32).unwrap(); assert!(!w.byte_aligned()); w.write(5, 7u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 5u32).unwrap(); assert!(!w.byte_aligned()); w.write(19, 0x53BC1u32).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*writing signed values*/ let mut w: BitRecorder = BitRecorder::new(); w.write_signed(2, -2).unwrap(); w.write_signed(3, -2).unwrap(); w.write_signed(5, 7).unwrap(); w.write_signed(3, -3).unwrap(); w.write_signed(19, -181311).unwrap(); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*writing unary 0 values*/ let mut w: BitRecorder = BitRecorder::new(); w.write_unary0(1).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(4).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(3).unwrap(); w.write_unary0(4).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write(1, 1u32).unwrap(); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*writing unary 1 values*/ let mut w: BitRecorder = BitRecorder::new(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(3).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(2).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(5).unwrap(); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*byte aligning*/ let aligned_data = [0xA0, 0xE0, 0x3B, 0xC0]; let mut w: BitRecorder = BitRecorder::new(); w.write(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write(4, 12u32).unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &aligned_data); /*writing bytes, aligned*/ let final_data = [0xB1, 0xED]; let mut w: BitRecorder = BitRecorder::new(); w.write_bytes(b"\xB1\xED").unwrap(); assert_eq!(w.written(), 16); let mut w2 = BitWriter::endian(Vec::with_capacity(2), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*writing bytes, un-aligned*/ let mut w: BitRecorder = BitRecorder::new(); let final_data = [0xBB, 0x1E, 0xD0]; w.write(4, 11u32).unwrap(); w.write_bytes(b"\xB1\xED").unwrap(); w.byte_align().unwrap(); let mut w2 = BitWriter::endian(Vec::with_capacity(3), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); } #[test] fn test_recorder_huffman_be() { use bitstream_io::huffman::compile_write_tree; use bitstream_io::{BigEndian, BitRecorder, BitWrite, BitWriter, HuffmanWrite}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let tree = compile_write_tree(vec![ (0, vec![1, 1]), (1, vec![1, 0]), (2, vec![0, 1]), (3, vec![0, 0, 1]), (4, vec![0, 0, 0]), ]) .unwrap(); let mut w: BitRecorder = BitRecorder::new(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.byte_align().unwrap(); let mut w2 = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); } #[test] fn test_recorder_le() { use bitstream_io::{BitRecorder, BitWrite, BitWriter, LittleEndian}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; /*writing individual bits*/ let mut w: BitRecorder = BitRecorder::new(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(false).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); w.write_bit(true).unwrap(); assert_eq!(w.written(), 16); let mut w2 = BitWriter::endian(Vec::with_capacity(2), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data[0..2]); /*writing unsigned values*/ let mut w: BitRecorder = BitRecorder::new(); assert!(w.byte_aligned()); w.write(2, 1u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 4u32).unwrap(); assert!(!w.byte_aligned()); w.write(5, 13u32).unwrap(); assert!(!w.byte_aligned()); w.write(3, 3u32).unwrap(); assert!(!w.byte_aligned()); w.write(19, 0x609DFu32).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*writing signed values*/ let mut w: BitRecorder = BitRecorder::new(); w.write_signed(2, 1).unwrap(); w.write_signed(3, -4).unwrap(); w.write_signed(5, 13).unwrap(); w.write_signed(3, 3).unwrap(); w.write_signed(19, -128545).unwrap(); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*writing unary 0 values*/ let mut w: BitRecorder = BitRecorder::new(); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(2).unwrap(); w.write_unary0(5).unwrap(); w.write_unary0(3).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(1).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write_unary0(0).unwrap(); w.write(2, 3u32).unwrap(); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*writing unary 1 values*/ let mut w: BitRecorder = BitRecorder::new(); w.write_unary1(0).unwrap(); w.write_unary1(3).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(1).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(0).unwrap(); w.write_unary1(2).unwrap(); w.write_unary1(5).unwrap(); w.write_unary1(0).unwrap(); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*byte aligning*/ let aligned_data = [0x05, 0x07, 0x3B, 0x0C]; let mut w: BitRecorder = BitRecorder::new(); w.write(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write(4, 12u32).unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 32); let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &aligned_data); /*writing bytes, aligned*/ let final_data = [0xB1, 0xED]; let mut w: BitRecorder = BitRecorder::new(); w.write_bytes(b"\xB1\xED").unwrap(); assert_eq!(w.written(), 16); let mut w2 = BitWriter::endian(Vec::with_capacity(2), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); /*writing bytes, un-aligned*/ let final_data = [0x1B, 0xDB, 0x0E]; let mut w: BitRecorder = BitRecorder::new(); w.write(4, 11u32).unwrap(); w.write_bytes(b"\xB1\xED").unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 24); let mut w2 = BitWriter::endian(Vec::with_capacity(3), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); } #[test] fn test_recorder_huffman_le() { use bitstream_io::huffman::compile_write_tree; use bitstream_io::{BitRecorder, BitWrite, BitWriter, HuffmanWrite, LittleEndian}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let tree = compile_write_tree(vec![ (0, vec![1, 1]), (1, vec![1, 0]), (2, vec![0, 1]), (3, vec![0, 0, 1]), (4, vec![0, 0, 0]), ]) .unwrap(); let mut w: BitRecorder = BitRecorder::new(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 3).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 0).unwrap(); w.write_huffman(&tree, 1).unwrap(); w.write_huffman(&tree, 2).unwrap(); w.write_huffman(&tree, 4).unwrap(); w.write_huffman(&tree, 3).unwrap(); w.write(1, 1).unwrap(); let mut w2 = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.playback(&mut w2).unwrap(); assert_eq!(w2.into_writer().as_slice(), &final_data); }