bitstream-io-4.9.0/.cargo_vcs_info.json0000644000000001360000000000100134450ustar { "git": { "sha1": "63e05b218f27217b0d83384efa6d4e12e419c953" }, "path_in_vcs": "" }bitstream-io-4.9.0/.github/workflows/ci.yml000064400000000000000000000014501046102023000167500ustar 00000000000000name: Rust CI on: push: pull_request: jobs: build: name: Build & Lint runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Rust uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal components: clippy - name: Install cargo-binstall uses: cargo-bins/cargo-binstall@main - name: Run tests run: cargo test - name: Check (no_std) run: cargo check --no-default-features - name: Check (no_std, alloc) run: cargo check --no-default-features --features alloc - name: Run clippy run: cargo clippy - name: Install cargo-msrv run: cargo binstall --no-confirm cargo-msrv - name: Verify MSRV run: cargo msrv verify bitstream-io-4.9.0/.gitignore000064400000000000000000000000221046102023000142170ustar 00000000000000target Cargo.lock bitstream-io-4.9.0/CHANGES.md000064400000000000000000000030501046102023000136250ustar 00000000000000# 4.9.0 - Further extend VBR integer support # 4.8.0 - Add io::Seek support to ByteReader # 4.7.0 - Add support for LLVM-style variable bit rate integers # 4.6.0 - Add no alloc support # 4.5.0 - Implement new `CheckedSignedFixed` type alias - Implement `FixedSignedBitCount` for use by `CheckedSignedFixed` # 4.4.0 - Implement new `CheckedUnsignedFixed` type alias - Implement `FixedBitCount` for use by `CheckedUnsignedFixed` # 4.3.0 - Add `bytes` method to ToByteStream traits with default implementations # 4.2.0 - Add `Checked` API for avoiding redundant validation during writes - Add `BitCount`-related helper methods to optimize unary writes # 4.1.0 - Implement `FromBitStreamUsing` convenience trait - Implement `FromByteStreamUsing` convenience trait - Implement `ToBitStreamUsing` convenience trait - Implement `ToByteStreamUsing` convenience trait # 4.0.0 - Implement `SignedBitCount` for signed integer types. - Remove endianness requirement for `BitCounter` - Optimize `BitRecorder` implementation to be much faster - Optimize read/write_bytes to be much faster for un-aligned bytes - Seal `Endianness` traits from further downstream implementation # 3.2.0 - Implement `Integer` for `bool` and arrays of `Integer` types. - Add a `read_const` method to `BitRead` for consisency with `BitWrite::write_const`. - Widen unknown `BitCount` values to handle more edge cases. # 3.1.0 - Implement `Integer` for the unsigned `NonZero` types. - Add byte alignment convenience methods. - Fix `BitCount.checked_sub` for consistency with `checked_add`. bitstream-io-4.9.0/Cargo.lock0000644000000011220000000000100114140ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "bitstream-io" version = "4.9.0" dependencies = [ "core2", ] [[package]] name = "core2" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ "memchr", ] [[package]] name = "memchr" version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" bitstream-io-4.9.0/Cargo.toml0000644000000034760000000000100114550ustar # 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.83" name = "bitstream-io" version = "4.9.0" authors = ["Brian Langenberger "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false 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" [package.metadata.docs.rs] all-features = true rustdoc-args = [ "--cfg", "docsrs", ] [features] alloc = ["core2/alloc"] default = ["std"] std = [ "core2/std", "alloc", ] [lib] name = "bitstream_io" path = "src/lib.rs" [[example]] name = "flac-metadata-read" path = "examples/flac-metadata-read.rs" [[example]] name = "flac-metadata-write" path = "examples/flac-metadata-write.rs" [[test]] name = "huffman" path = "tests/huffman.rs" [[test]] name = "read" path = "tests/read.rs" [[test]] name = "read_seek" path = "tests/read_seek.rs" [[test]] name = "roundtrip" path = "tests/roundtrip.rs" [[test]] name = "write" path = "tests/write.rs" [dependencies.core2] version = "0.4" default-features = false bitstream-io-4.9.0/Cargo.toml.orig000064400000000000000000000013521046102023000151250ustar 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 = "4.9.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.83" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] core2 = { version = "0.4", default-features = false } [features] std = ["core2/std", "alloc"] alloc = ["core2/alloc"] default = ["std"] bitstream-io-4.9.0/LICENSE-APACHE000064400000000000000000000251371046102023000141710ustar 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-4.9.0/LICENSE-MIT000064400000000000000000000020461046102023000136730ustar 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-4.9.0/README.md000064400000000000000000000011511046102023000135120ustar 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-4.9.0/examples/data/metadata-only.flac000064400000000000000000000002501046102023000203470ustar 00000000000000fLaC"!b ÄBð¦Ìúòi/ýì-[0v´bˆ}’z reference libFLAC 1.1.4 20070213title=2ch 44100 16bitalbum=Test Albumartist=Assorted tracknumber=1bitstream-io-4.9.0/examples/flac-metadata-read.rs000064400000000000000000000102771046102023000200240ustar 00000000000000//! Reading the initial STREAMINFO block from a FLAC file, //! as documented in its //! [specification](https://xiph.org/flac/format.html#stream). //! extern crate bitstream_io; use bitstream_io::{BigEndian, BitRead, BitReader, FromBitStream}; use std::num::NonZero; #[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::<7, _>()?, block_size: r.read::<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: NonZero, // 3 bits bits_per_sample: NonZero, // 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::<24, _>()?, maximum_frame_size: r.read::<24, _>()?, sample_rate: r.read::<20, _>()?, channels: r.read::<3, _>()?, bits_per_sample: r.read::<5, _>()?, total_samples: r.read::<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::, _>>()?, }) } } fn main() { // test FLAC file data let flac = include_bytes!("data/metadata-only.flac"); let mut reader = BitReader::endian(flac.as_slice(), 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!( dbg!(reader.parse::().unwrap()), Streaminfo { minimum_block_size: 4096, maximum_block_size: 4096, minimum_frame_size: 1542, maximum_frame_size: 8546, sample_rate: 44100, channels: NonZero::new(2).unwrap(), bits_per_sample: NonZero::new(16).unwrap(), 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!( dbg!(reader.parse::().unwrap()), BlockHeader { last_block: false, block_type: 4, block_size: 122 } ); // VORBIS_COMMENT block assert_eq!( dbg!(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(), ], } ); } bitstream-io-4.9.0/examples/flac-metadata-write.rs000064400000000000000000000102151046102023000202330ustar 00000000000000extern crate bitstream_io; // Writing the initial STREAMINFO block to a FLAC file, // as documented in its // [specification](https://xiph.org/flac/format.html#stream). use bitstream_io::{ BigEndian, BitWrite, BitWriter, ByteWrite, ByteWriter, LittleEndian, ToBitStream, }; use std::convert::TryInto; use std::num::NonZero; #[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::<7, _>(self.block_type)?; w.write::<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: NonZero, // 3 bits bits_per_sample: NonZero, // 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::<24, _>(self.minimum_frame_size)?; w.write::<24, _>(self.maximum_frame_size)?; w.write::<20, _>(self.sample_rate)?; w.write::<3, _>(self.channels)?; w.write::<5, _>(self.bits_per_sample)?; w.write::<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)) } } fn main() { 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: NonZero::new(2).unwrap(), bits_per_sample: NonZero::new(16).unwrap(), 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, include_bytes!("data/metadata-only.flac")); } bitstream-io-4.9.0/src/byte_io.rs000064400000000000000000000022051046102023000150230ustar 00000000000000pub trait ByteSource: Sized { type Error: Sized; #[inline(always)] fn read_byte(&mut self) -> Result { let mut byte = 0; self.read_bytes(core::slice::from_mut(&mut byte)) .map(|()| byte) } fn read_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error>; fn skip_bytes(&mut self, bytes: u32) -> Result<(), Self::Error> { fn skip_chunks( reader: &mut R, mut bytes: usize, ) -> Result<(), R::Error> where R: ByteSource, { let mut buf = [0; SIZE]; while bytes > 0 { let to_read = bytes.min(SIZE); reader.read_bytes(&mut buf[0..to_read])?; bytes -= to_read; } Ok(()) } match bytes { 0..256 => skip_chunks::<8, Self>(self, bytes as usize), 256..1024 => skip_chunks::<256, Self>(self, bytes as usize), 1024..4096 => skip_chunks::<1024, Self>(self, bytes as usize), _ => skip_chunks::<4096, Self>(self, bytes as usize), } } } bitstream-io-4.9.0/src/huffman.rs000064400000000000000000000205751046102023000150270ustar 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)] /// A trait for building a final value from individual bits /// /// Though similar to the [`crate::read::FromBitStream`] trait, /// this is intended to parse short symbols from a stream of bits /// while `FromBitStream` is meant for parsing larger structs from /// a whole reader. /// For example, one might have several [`FromBits`] implementations /// in a single program that all generate `i32` symbols from bits, /// but implementing `FromBitStream` multiple times for `i32` /// isn't possible (or practical). pub trait FromBits { /// Our returned symbol type type Symbol; /// Given a fallable bit generator, return our output type /// /// # Errors /// /// Passes along any error from the bit generator fn from_bits(next: F) -> Result where F: FnMut() -> Result; } /// For building individual bits from a final value /// /// Though similar to the [`crate::write::ToBitStream`] trait, /// this is intended to generate a stream of bits from short symbols /// while `ToBitStream` is meant for writing larger structs to /// a whole writer. /// For example, one might have several [`ToBits`] implementations /// in a single program that all write `i32` symbols to bits, /// but implementing `ToBitStream` multiple times for `i32` /// isn't possible (or practical). pub trait ToBits { /// The type we accept to output type Symbol; /// Given a value to generate, write out bits as needed. /// /// Outputs nothing if the symbol isn't defined. /// /// # Errors /// /// Passes along any error from the bit generator fn to_bits(value: Self::Symbol, write: F) -> Result<(), E> where F: FnMut(bool) -> Result<(), E>; } /// Defines a new Huffman tree for reading and writing /// /// Its syntax is: `define_huffman_tree!(name : type = nodes)` /// where `name` is some identifier to identify the tree in the /// macro's current scope, `type` is the tree's output /// type (which should implement `Copy` and `Eq`), and `nodes` is either a /// final leaf value or a `[bit_0, bit_1]` pair where `bit_0` is /// the tree visited on a `0` bit, and `bit_1` is the tree visited /// on a `1` bit. /// /// # Example /// /// ``` /// use bitstream_io::{define_huffman_tree, huffman::FromBits}; /// define_huffman_tree!(TreeName : &'static str = ["bit 0", ["bit 1->0", "bit 1->1"]]); /// let mut bits = [true, false].iter().copied(); /// assert_eq!(TreeName::from_bits(|| bits.next().ok_or(())).unwrap(), "bit 1->0"); /// ``` #[macro_export] macro_rules! define_huffman_tree { ($name:ident : $type:ty = $nodes:tt) => { #[derive(Copy, Clone, Debug)] struct $name; impl $crate::huffman::FromBits for $name { type Symbol = $type; fn from_bits(mut next: F) -> Result where F: FnMut() -> Result, { $crate::compile_read_tree_nodes!(next, $nodes) } } impl $crate::huffman::ToBits for $name { type Symbol = $type; fn to_bits(value: Self::Symbol, mut write: F) -> Result<(), E> where F: FnMut(bool) -> Result<(), E> { $crate::compile_write_tree_nodes!(value ; write ; $nodes ; ); Ok(()) } } }; } /// A helper macro for compiling individual Huffman tree nodes #[macro_export] macro_rules! compile_read_tree_nodes { ($next:ident , [$bit_0:tt, $bit_1:tt]) => { if $next()? { $crate::compile_read_tree_nodes!($next, $bit_1) } else { $crate::compile_read_tree_nodes!($next, $bit_0) } }; ($next:ident , $final:tt) => { Ok($final) }; } /// A helper macro for compiling individual Huffman tree nodes #[macro_export] macro_rules! compile_write_tree_nodes { ($value:ident ; $write:ident ; [$bit_0:tt, $bit_1:tt] ; ) => { $crate::compile_write_tree_nodes!($value ; $write ; $bit_0 ; false); $crate::compile_write_tree_nodes!($value ; $write ; $bit_1 ; true); }; ($value:ident ; $write:ident ; [$bit_0:tt, $bit_1:tt] ; $($bits:tt),*) => { $crate::compile_write_tree_nodes!($value ; $write ; $bit_0 ; $($bits),* , false); $crate::compile_write_tree_nodes!($value ; $write ; $bit_1 ; $($bits),* , true); }; ($value:ident ; $write:ident ; $final:tt ; $( $bits:tt),* ) => { if $value == $final { $( $write($bits)?; )* return Ok(()); } }; } /// A limited unary reader which stops at the given maximum. /// /// Counts non-`STOP_BIT` values (which must be 0 or 1) /// until `STOP_BIT`, or until `MAXIMUM` is reached. /// Returns the number of non-`STOP_BIT` bits, or `None` if /// maximum is reached beforehand. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian, huffman::LimitedUnary}; /// /// let data: &[u8] = &[0b001_00000, 0b1111_1111]; /// let mut r = BitReader::endian(data, BigEndian); /// // get 2 bits until the next 1 bit /// assert_eq!(r.read_huffman::>().unwrap(), Some(2)); /// // but 5 bits in a row is our maximum /// assert_eq!(r.read_huffman::>().unwrap(), None); /// // the remaining 8 bits are ok to be read /// assert_eq!(r.read::<8, u8>().unwrap(), 0b1111_1111); /// ``` /// /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian, huffman::LimitedUnary}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writes 2 as a regular unary value which stops at the 1 bit /// w.write_huffman::>(Some(2)).unwrap(); /// // writing values beyond the maximum does nothing /// w.write_huffman::>(Some(10)).unwrap(); /// // writes 5, 0 bits (which is our maximum) /// w.write_huffman::>(None).unwrap(); /// // write some 1 bits to pad out the stream /// w.write::<8, u8>(0b1111_1111); /// /// assert_eq!(w.into_writer(), &[0b001_00000, 0b1111_1111]); /// ``` #[derive(Copy, Clone, Debug)] pub struct LimitedUnary; impl FromBits for LimitedUnary { type Symbol = Option; fn from_bits(mut next: F) -> Result where F: FnMut() -> Result, { const { assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); } let mut bits = 0; while bits < MAXIMUM { if next()? != match STOP_BIT { 0 => false, 1 => true, _ => unreachable!(), } { bits += 1; } else { return Ok(Some(bits)); } } Ok(None) } } impl ToBits for LimitedUnary { type Symbol = Option; fn to_bits(value: Option, mut write: F) -> Result<(), E> where F: FnMut(bool) -> Result<(), E>, { const { assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); } match value { Some(bits) if bits < MAXIMUM => { (0..bits).try_for_each(|_| { write(match STOP_BIT { 0 => true, 1 => false, _ => unreachable!(), }) })?; write(match STOP_BIT { 0 => false, 1 => true, _ => unreachable!(), }) } Some(_) => { /*more bits than MAXIMUM, so output nothing*/ Ok(()) } None => (0..MAXIMUM).try_for_each(|_| { write(match STOP_BIT { 0 => true, 1 => false, _ => unreachable!(), }) }), } } } bitstream-io-4.9.0/src/lib.rs000064400000000000000000003611141046102023000141460ustar 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 [`io::Read`] trait, and the only requirement //! for writer streams is that they must implement the [`io::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_var(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,compile_fail //! 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, _>(); // 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. //! # Changes From 3.X.X //! //! Version 4.0.0 features significant optimizations to the [`BitRecorder`] //! and deprecates the [`BitCounter`] in favor of [`BitsWritten`], //! which no longer requires specifying an endianness. //! //! In addition, the [`BitRead::read_bytes`] and [`BitWrite::write_bytes`] //! methods are significantly optimized in the case of non-aligned //! reads and writes. //! //! Finally, the [`Endianness`] traits have been sealed so as not //! to be implemented by other packages. Given that other endianness //! types are extremely rare in file formats and end users should not //! have to implement this trait themselves, this should not be a //! concern. //! //! # Changes From 2.X.X //! //! Version 3.0.0 has made many breaking changes to the [`BitRead`] and //! [`BitWrite`] traits. //! //! The [`BitRead::read`] method takes a constant number of bits, //! and the [`BitRead::read_var`] method takes a variable number of bits //! (reversing the older [`BitRead2::read_in`] and [`BitRead2::read`] //! calling methods to emphasize using the constant-based one, //! which can do more validation at compile-time). //! A new [`BitRead2`] trait uses the older calling convention //! for compatibility with existing code and is available //! for anything implementing [`BitRead`]. //! //! In addition, the main reading methods return primitive types which //! implement a new [`Integer`] trait, //! which delegates to [`BitRead::read_unsigned`] //! or [`BitRead::read_signed`] depending on whether the output //! is an unsigned or signed type. //! //! [`BitWrite::write`] and [`BitWrite::write_var`] work //! similarly to the reader's `read` methods, taking anything //! that implements [`Integer`] and writing an unsigned or //! signed value to [`BitWrite::write_unsigned`] or //! [`BitWrite::write_signed`] as appropriate. //! //! And as with reading, a [`BitWrite2`] trait is offered //! for compatibility. //! //! In addition, the Huffman code handling has been rewritten //! to use a small amount of macro magic to write //! code to read and write symbols at compile-time. //! This is significantly faster than the older version //! and can no longer fail to compile at runtime. //! //! Lastly, there's a new [`BitCount`] struct which wraps a humble //! `u32` but encodes the maximum possible number of bits //! at the type level. //! This is intended for file formats which encode the number //! of bits to be read in the format itself. //! For example, FLAC's predictor coefficient precision //! is a 4 bit value which indicates how large each predictor //! coefficient is in bits //! (each coefficient might be an `i32` type). //! By keeping track of the maximum value at compile time //! (4 bits' worth, in this case), we can eliminate //! any need to check that coefficients aren't too large //! for an `i32` at runtime. //! This is accomplished by using [`BitRead::read_count`] to //! read a [`BitCount`] and then reading final values with //! that number of bits using [`BitRead::read_counted`]. //! # 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. #![cfg_attr(docsrs, feature(doc_cfg))] #![warn(missing_docs)] #![forbid(unsafe_code)] #![no_std] #[cfg(feature = "alloc")] extern crate alloc; #[cfg(feature = "std")] extern crate std; #[cfg(not(feature = "std"))] use core2::io; use core::convert::TryInto; use core::num::NonZero; use core::ops::{ BitAnd, BitOr, BitOrAssign, BitXor, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, }; use core::{fmt::Debug, marker::PhantomData, mem}; #[cfg(feature = "std")] use std::io; pub mod huffman; pub mod read; pub mod write; pub use read::{ BitRead, BitRead2, BitReader, ByteRead, ByteReader, FromBitStream, FromBitStreamUsing, FromBitStreamWith, FromByteStream, FromByteStreamUsing, FromByteStreamWith, }; #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] #[cfg(feature = "alloc")] pub use write::BitRecorder; pub use write::{ BitWrite, BitWrite2, BitWriter, BitsWritten, ByteWrite, ByteWriter, ToBitStream, ToBitStreamUsing, ToBitStreamWith, ToByteStream, ToByteStreamUsing, ToByteStreamWith, }; #[allow(deprecated)] pub use write::BitCounter; /// 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 is for integer types which can be read or written /// to a bit stream as a partial amount of bits. /// /// It unifies signed and unsigned integer types by delegating /// reads and writes to the signed and unsigned reading /// and writing methods as appropriate. pub trait Integer { /// Reads a value of ourself from the stream /// with the given 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 our type. fn read(reader: &mut R) -> io::Result where Self: Sized; /// Reads a value of ourself 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 our type is too small /// to hold the requested number of bits. fn read_var(reader: &mut R, bits: BitCount) -> io::Result where R: BitRead + ?Sized, Self: Sized; /// Writes ourself 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 our 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 our type. fn write(self, writer: &mut W) -> io::Result<()>; /// Writes ourself to the stream using the given number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if our value is too small /// to hold the given number of bits. /// Returns an error if our value is too large /// to fit the given number of bits. fn write_var( self, writer: &mut W, bits: BitCount, ) -> io::Result<()>; } /// This trait is for integer types which can be read or written /// to a bit stream as variable-width integers. /// /// It unifies signed and unsigned integer types by delegating /// reads and write to the signed and unsigned vbr reading and /// writing methods as appropriate. pub trait VBRInteger: Integer { /// Reads a value of ourself from the stream using a variable width integer. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn read_vbr(reader: &mut R) -> io::Result where R: BitRead + ?Sized, Self: Sized; /// Writes ourself to the stream using a variable width integer. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn write_vbr( self, writer: &mut W, ) -> io::Result<()>; } /// Reading and writing booleans as `Integer` requires the number of bits to be 1. /// /// This is more useful when combined with the fixed array target /// for reading blocks of bit flags. /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// #[derive(Debug, PartialEq, Eq)] /// struct Flags { /// a: bool, /// b: bool, /// c: bool, /// d: bool, /// } /// /// let data: &[u8] = &[0b1011_0000]; /// let mut r = BitReader::endian(data, BigEndian); /// // note the number of bits must be 1 per read /// // while the quantity of flags is indicated by the array length /// let flags = r.read::<1, [bool; 4]>().map(|[a, b, c, d]| Flags { a, b, c, d }).unwrap(); /// assert_eq!(flags, Flags { a: true, b: false, c: true, d: true }); /// ``` impl Integer for bool { #[inline(always)] fn read(reader: &mut R) -> io::Result where Self: Sized, { const { assert!(BITS == 1, "booleans require exactly 1 bit"); } reader.read_bit() } fn read_var( reader: &mut R, BitCount { bits }: BitCount, ) -> io::Result where R: BitRead + ?Sized, Self: Sized, { if bits == 1 { reader.read_bit() } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "booleans require exactly 1 bit", )) } } #[inline(always)] fn write(self, writer: &mut W) -> io::Result<()> { const { assert!(BITS == 1, "booleans require exactly 1 bit"); } writer.write_bit(self) } fn write_var( self, writer: &mut W, BitCount { bits }: BitCount, ) -> io::Result<()> { if bits == 1 { writer.write_bit(self) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "booleans require exactly 1 bit", )) } } } impl Integer for [I; SIZE] { #[inline] fn read(reader: &mut R) -> io::Result where Self: Sized, { let mut a = [I::default(); SIZE]; a.iter_mut().try_for_each(|v| { *v = reader.read::()?; Ok::<(), io::Error>(()) })?; Ok(a) } #[inline] fn read_var(reader: &mut R, count: BitCount) -> io::Result where R: BitRead + ?Sized, Self: Sized, { let mut a = [I::default(); SIZE]; a.iter_mut().try_for_each(|v| { *v = reader.read_counted(count)?; Ok::<(), io::Error>(()) })?; Ok(a) } #[inline] fn write(self, writer: &mut W) -> io::Result<()> { IntoIterator::into_iter(self).try_for_each(|v| writer.write::(v)) } #[inline] fn write_var( self, writer: &mut W, count: BitCount, ) -> io::Result<()> { IntoIterator::into_iter(self).try_for_each(|v| writer.write_counted(count, v)) } } impl VBRInteger for [I; SIZE] { fn read_vbr(reader: &mut R) -> io::Result where R: BitRead + ?Sized, Self: Sized, { let mut a = [I::default(); SIZE]; a.iter_mut().try_for_each(|v| { I::read_vbr::(reader).map(|item| { *v = item; }) })?; Ok(a) } fn write_vbr( self, writer: &mut W, ) -> io::Result<()> { IntoIterator::into_iter(self).try_for_each(|v| I::write_vbr::(v, writer)) } } /// 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 + BitAnd + BitOr + BitOrAssign + BitXor + Not + Sub { /// Size of type in bits const BITS_SIZE: u32; /// The value of 0 in this type const ZERO: Self; /// The value of 1 in this type const ONE: Self; /// 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; } 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 ZERO: Self = 0; const ONE: Self = 1; #[inline(always)] fn from_u8(u: u8) -> Self { u as $t } #[inline(always)] fn to_u8(self) -> u8 { self as u8 } } }; } /// This trait extends many common unsigned integer types /// so that they can be used with the bitstream handling traits. pub trait UnsignedInteger: Numeric { /// This type's most-significant bit const MSB_BIT: Self; /// This type's least significant bit const LSB_BIT: Self; /// This type with all bits set const ALL: Self; /// The signed variant of ourself type Signed: SignedInteger; /// Given a twos-complement value, /// return this value is a non-negative signed number. /// The location of the sign bit depends on the stream's endianness /// and is not stored in the result. /// /// # Example /// ``` /// use bitstream_io::UnsignedInteger; /// assert_eq!(0b00000001u8.as_non_negative(), 1i8); /// ``` fn as_non_negative(self) -> Self::Signed; /// Given a two-complement positive value and certain number of bits, /// returns this value as a negative signed number. /// The location of the sign bit depends on the stream's endianness /// and is not stored in the result. /// /// # Example /// ``` /// use bitstream_io::UnsignedInteger; /// assert_eq!(0b01111111u8.as_negative(8), -1i8); /// ``` fn as_negative(self, bits: u32) -> Self::Signed; /// Given a two-complement positive value and certain number of bits, /// returns this value as a negative number. /// /// # Example /// ``` /// use bitstream_io::UnsignedInteger; /// assert_eq!(0b01111111u8.as_negative_fixed::<8>(), -1i8); /// ``` fn as_negative_fixed(self) -> Self::Signed; /// Checked shift left fn checked_shl(self, rhs: u32) -> Option; /// Checked shift right fn checked_shr(self, rhs: u32) -> Option; /// Shift left up to our length in bits /// /// If rhs equals our length in bits, returns default fn shl_default(self, rhs: u32) -> Self { self.checked_shl(rhs).unwrap_or(Self::ZERO) } /// Shift left up to our length in bits /// /// If rhs equals our length in bits, returns zero fn shr_default(self, rhs: u32) -> Self { self.checked_shr(rhs).unwrap_or(Self::ZERO) } } macro_rules! define_unsigned_integer { ($t:ty, $s:ty) => { define_numeric!($t); impl UnsignedInteger for $t { type Signed = $s; const MSB_BIT: Self = 1 << (Self::BITS_SIZE - 1); const LSB_BIT: Self = 1; const ALL: Self = <$t>::MAX; #[inline(always)] fn as_non_negative(self) -> Self::Signed { self as $s } #[inline(always)] fn as_negative(self, bits: u32) -> Self::Signed { (self as $s) + (-1 << (bits - 1)) } #[inline(always)] fn as_negative_fixed(self) -> Self::Signed { (self as $s) + (-1 << (BITS - 1)) } #[inline(always)] fn checked_shl(self, rhs: u32) -> Option { self.checked_shl(rhs) } #[inline(always)] fn checked_shr(self, rhs: u32) -> Option { self.checked_shr(rhs) } // TODO - enable these in the future // #[inline(always)] // fn shl_default(self, rhs: u32) -> Self { // self.unbounded_shl(rhs) // } // #[inline(always)] // fn shr_default(self, rhs: u32) -> Self { // self.unbounded_shr(rhs) // } } impl Integer for $t { #[inline(always)] fn read(reader: &mut R) -> io::Result where Self: Sized, { reader.read_unsigned::() } #[inline(always)] fn read_var(reader: &mut R, bits: BitCount) -> io::Result where R: BitRead + ?Sized, Self: Sized, { reader.read_unsigned_counted::(bits) } #[inline(always)] fn write( self, writer: &mut W, ) -> io::Result<()> { writer.write_unsigned::(self) } #[inline(always)] fn write_var( self, writer: &mut W, bits: BitCount, ) -> io::Result<()> { writer.write_unsigned_counted(bits, self) } } impl VBRInteger for $t { #[inline(always)] fn read_vbr(reader: &mut R) -> io::Result where R: BitRead + ?Sized, Self: Sized, { reader.read_unsigned_vbr::() } #[inline(always)] fn write_vbr( self, writer: &mut W, ) -> io::Result<()> { writer.write_unsigned_vbr::(self) } } /// Unsigned NonZero types increment their value by 1 /// when being read and decrement it by 1 /// when being written. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// use core::num::NonZero; /// /// let data: &[u8] = &[0b001_00000]; /// // reading a regular u8 in 3 bits yields 1 /// assert_eq!(BitReader::endian(data, BigEndian).read::<3, u8>().unwrap(), 1); /// // reading a NonZero in 3 bits of the same data yields 2 /// assert_eq!(BitReader::endian(data, BigEndian).read::<3, NonZero>().unwrap().get(), 2); /// ``` /// /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// use core::num::NonZero; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writing 1 as a regular u8 in 3 bits /// w.write::<3, u8>(1).unwrap(); /// w.byte_align(); /// assert_eq!(w.into_writer(), &[0b001_00000]); /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writing 1 as a NonZero in 3 bits /// w.write::<3, NonZero>(NonZero::new(1).unwrap()).unwrap(); /// w.byte_align(); /// assert_eq!(w.into_writer(), &[0b000_00000]); /// ``` impl Integer for NonZero<$t> { #[inline] fn read(reader: &mut R) -> io::Result where Self: Sized, { const { assert!( BITS < <$t>::BITS_SIZE, "BITS must be less than the type's size in bits" ); } <$t as Integer>::read::(reader).map(|u| NonZero::new(u + 1).unwrap()) } #[inline] fn read_var( reader: &mut R, count @ BitCount { bits }: BitCount, ) -> io::Result where R: BitRead + ?Sized, Self: Sized, { if MAX < <$t>::BITS_SIZE || bits < <$t>::BITS_SIZE { <$t as Integer>::read_var::(reader, count) .map(|u| NonZero::new(u + 1).unwrap()) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "bit count must be less than the type's size in bits", )) } } #[inline] fn write( self, writer: &mut W, ) -> io::Result<()> { const { assert!( BITS < <$t>::BITS_SIZE, "BITS must be less than the type's size in bits" ); } <$t as Integer>::write::(self.get() - 1, writer) } #[inline] fn write_var( self, writer: &mut W, count @ BitCount { bits }: BitCount, ) -> io::Result<()> { if MAX < <$t>::BITS_SIZE || bits < <$t>::BITS_SIZE { <$t as Integer>::write_var::(self.get() - 1, writer, count) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "bit count must be less than the type's size in bits", )) } } } impl VBRInteger for NonZero<$t> { #[inline] fn read_vbr(reader: &mut R) -> io::Result where R: BitRead + ?Sized, Self: Sized, { <$t as VBRInteger>::read_vbr::(reader) .map(|u| NonZero::new(u + 1).unwrap()) } #[inline] fn write_vbr( self, writer: &mut W, ) -> io::Result<()> { <$t as VBRInteger>::write_vbr::(self.get() - 1, writer) } } impl Integer for Option> { #[inline] fn read(reader: &mut R) -> io::Result where Self: Sized, { <$t as Integer>::read::(reader).map(NonZero::new) } #[inline] fn read_var(reader: &mut R, count: BitCount) -> io::Result where R: BitRead + ?Sized, Self: Sized, { <$t as Integer>::read_var::(reader, count).map(NonZero::new) } #[inline] fn write( self, writer: &mut W, ) -> io::Result<()> { <$t as Integer>::write::(self.map(|n| n.get()).unwrap_or(0), writer) } #[inline] fn write_var( self, writer: &mut W, count: BitCount, ) -> io::Result<()> { <$t as Integer>::write_var::( self.map(|n| n.get()).unwrap_or(0), writer, count, ) } } impl VBRInteger for Option> { #[inline(always)] fn read_vbr(reader: &mut R) -> io::Result where R: BitRead + ?Sized, Self: Sized, { <$t as VBRInteger>::read_vbr::(reader).map(NonZero::new) } #[inline] fn write_vbr( self, writer: &mut W, ) -> io::Result<()> { <$t as VBRInteger>::write_vbr::( self.map(|n| n.get()).unwrap_or(0), writer, ) } } }; } /// This trait extends many common signed integer types /// so that they can be used with the bitstream handling traits. /// /// This trait was formerly named `SignedNumeric` in 2.X.X code. /// If backwards-compatibility is needed one can /// import `SignedInteger` as `SignedNumeric`. pub trait SignedInteger: Numeric { /// The unsigned variant of ourself type Unsigned: UnsignedInteger; /// Returns true if this value is negative /// /// # Example /// ``` /// use bitstream_io::SignedInteger; /// assert!(!1i8.is_negative()); /// assert!((-1i8).is_negative()); /// ``` fn is_negative(self) -> bool; /// Returns ourself as a non-negative value. /// The location of the sign bit depends on the stream's endianness /// and is not stored in the result. /// /// # Example /// ``` /// use bitstream_io::SignedInteger; /// assert_eq!(1i8.as_non_negative(), 0b00000001u8); /// ``` fn as_non_negative(self) -> Self::Unsigned; /// Given a negative value and a certain number of bits, /// returns this value as a twos-complement positive number. /// The location of the sign bit depends on the stream's endianness /// and is not stored in the result. /// /// # Example /// ``` /// use bitstream_io::SignedInteger; /// assert_eq!((-1i8).as_negative(8), 0b01111111u8); /// ``` fn as_negative(self, bits: u32) -> Self::Unsigned; /// Given a negative value and a certain number of bits, /// returns this value as a twos-complement positive number. /// /// # Example /// ``` /// use bitstream_io::SignedInteger; /// assert_eq!((-1i8).as_negative_fixed::<8>(), 0b01111111u8); /// ``` fn as_negative_fixed(self) -> Self::Unsigned; } macro_rules! define_signed_integer { ($t:ty, $u:ty) => { define_numeric!($t); impl SignedInteger for $t { type Unsigned = $u; #[inline(always)] fn is_negative(self) -> bool { self.is_negative() } fn as_non_negative(self) -> Self::Unsigned { self as $u } fn as_negative(self, bits: u32) -> Self::Unsigned { (self - (-1 << (bits - 1))) as $u } fn as_negative_fixed(self) -> Self::Unsigned { (self - (-1 << (BITS - 1))) as $u } } impl Integer for $t { #[inline(always)] fn read(reader: &mut R) -> io::Result where Self: Sized, { reader.read_signed::() } #[inline(always)] fn read_var(reader: &mut R, bits: BitCount) -> io::Result where R: BitRead + ?Sized, Self: Sized, { reader.read_signed_counted::(bits) } #[inline(always)] fn write( self, writer: &mut W, ) -> io::Result<()> { writer.write_signed::(self) } #[inline(always)] fn write_var( self, writer: &mut W, bits: BitCount, ) -> io::Result<()> { writer.write_signed_counted::(bits, self) } } impl VBRInteger for $t { #[inline(always)] fn read_vbr(reader: &mut R) -> io::Result where R: BitRead + ?Sized, Self: Sized, { reader.read_signed_vbr::() } #[inline(always)] fn write_vbr( self, writer: &mut W, ) -> io::Result<()> { writer.write_signed_vbr::(self) } } }; } define_unsigned_integer!(u8, i8); define_unsigned_integer!(u16, i16); define_unsigned_integer!(u32, i32); define_unsigned_integer!(u64, i64); define_unsigned_integer!(u128, i128); define_signed_integer!(i8, u8); define_signed_integer!(i16, u16); define_signed_integer!(i32, u32); define_signed_integer!(i64, u64); define_signed_integer!(i128, u128); define_primitive_numeric!(f32); define_primitive_numeric!(f64); mod private { use crate::{ io, BitCount, BitRead, BitWrite, CheckedSigned, CheckedUnsigned, Primitive, SignedBitCount, SignedInteger, UnsignedInteger, }; #[test] fn test_checked_signed() { assert!(CheckedSigned::new(SignedBitCount::<8>::new::<8>(), -128i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<8>(), 127i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<7>(), -64i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<7>(), 63i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<6>(), -32i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<6>(), 31i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<5>(), -16i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<5>(), 15i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<4>(), -8i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<4>(), 7i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<3>(), -4i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<3>(), 3i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<2>(), -2i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<2>(), 1i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<1>(), -1i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<1>(), 0i8).is_ok()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<7>(), -65i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<7>(), 64i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<6>(), -33i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<6>(), 32i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<5>(), -17i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<5>(), 16i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<4>(), -9i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<4>(), 8i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<3>(), -5i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<3>(), 4i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<2>(), -3i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<2>(), 2i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<1>(), -2i8).is_err()); assert!(CheckedSigned::new(SignedBitCount::<8>::new::<1>(), 1i8).is_err()); } pub trait Endianness: Sized { /// Pops the next bit from the queue, /// repleneshing it from the given reader if necessary fn pop_bit_refill( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read; /// Pops the next unary value from the source until /// `STOP_BIT` is encountered, replenishing it from the given /// closure if necessary. /// /// `STOP_BIT` must be 0 or 1. fn pop_unary( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read; /// Pushes the next bit into the queue, /// and returns `Some` value if the queue is full. fn push_bit_flush(queue_value: &mut u8, queue_bits: &mut u32, bit: bool) -> Option; /// For performing bulk reads from a bit source to an output type. fn read_bits( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, count: BitCount, ) -> io::Result where R: io::Read, U: UnsignedInteger; /// For performing bulk reads from a bit source to an output type. fn read_bits_fixed( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read, U: UnsignedInteger; /// For performing a checked write to a bit sink fn write_bits_checked( writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, value: CheckedUnsigned, ) -> io::Result<()> where W: io::Write, U: UnsignedInteger; /// For performing a checked signed write to a bit sink fn write_signed_bits_checked( writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, value: CheckedSigned, ) -> io::Result<()> where W: io::Write, S: SignedInteger; /// Reads signed value from reader in this endianness fn read_signed_counted( r: &mut R, bits: SignedBitCount, ) -> io::Result where R: BitRead, S: SignedInteger; /// Reads whole set of bytes to output buffer fn read_bytes( reader: &mut R, queue_value: &mut u8, queue_bits: u32, buf: &mut [u8], ) -> io::Result<()> where R: io::Read; /// Writes whole set of bytes to output buffer fn write_bytes( writer: &mut W, queue_value: &mut u8, queue_bits: u32, buf: &[u8], ) -> io::Result<()> where W: io::Write; /// Converts a primitive's byte buffer to a primitive fn bytes_to_primitive(buf: P::Bytes) -> P; /// Converts a primitive to a primitive's byte buffer fn primitive_to_bytes(p: P) -> P::Bytes; /// Reads convertable numeric value from reader in this endianness #[deprecated(since = "4.0.0")] fn read_primitive(r: &mut R) -> io::Result where R: BitRead, V: Primitive; /// Writes convertable numeric value to writer in this endianness #[deprecated(since = "4.0.0")] fn write_primitive(w: &mut W, value: V) -> io::Result<()> where W: BitWrite, V: Primitive; } pub trait Checkable { fn write_endian( self, writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result<()> where E: Endianness, W: io::Write; } } /// 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 implement directly. pub trait Endianness: private::Endianness {} #[inline(always)] 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) } #[inline(always)] fn write_byte(mut writer: W, byte: u8) -> io::Result<()> where W: io::Write, { writer.write_all(core::slice::from_ref(&byte)) } /// A number of bits to be consumed or written, with a known maximum /// /// Although [`BitRead::read`] and [`BitWrite::write`] should be /// preferred when the number of bits is fixed and known at compile-time - /// because they can validate the bit count is less than or equal /// to the type's size in bits at compile-time - /// there are many instances where bit count is dynamic and /// determined by the file format itself. /// But when using [`BitRead::read_var`] or [`BitWrite::write_var`] /// we must pessimistically assume any number of bits as an argument /// and validate that the number of bits is not larger than the /// type being read or written on every call. /// /// ``` /// use bitstream_io::{BitRead, BitReader, BigEndian}; /// /// let data: &[u8] = &[0b100_0001_1, 0b111_0110_0]; /// let mut r = BitReader::endian(data, BigEndian); /// // our bit count is a 3 bit value /// let count = r.read::<3, u32>().unwrap(); /// // that count indicates we need to read 4 bits (0b100) /// assert_eq!(count, 4); /// // read the first 4-bit value /// assert_eq!(r.read_var::(count).unwrap(), 0b0001); /// // read the second 4-bit value /// assert_eq!(r.read_var::(count).unwrap(), 0b1111); /// // read the third 4-bit value /// assert_eq!(r.read_var::(count).unwrap(), 0b0110); /// ``` /// /// In the preceding example, even though we know `count` is a /// 3 bit value whose maximum value will never be greater than 7, /// the subsequent `read_var` calls have no way to know that. /// They must assume `count` could be 9, or `u32::MAX` or any other `u32` value /// and validate the count is not larger than the `u8` types we're reading. /// /// But we can convert our example to use the `BitCount` type: /// /// ``` /// use bitstream_io::{BitRead, BitReader, BigEndian, BitCount}; /// /// let data: &[u8] = &[0b100_0001_1, 0b111_0110_0]; /// let mut r = BitReader::endian(data, BigEndian); /// // our bit count is a 3 bit value with a maximum value of 7 /// let count = r.read_count::<0b111>().unwrap(); /// // that count indicates we need to read 4 bits (0b100) /// assert_eq!(count, BitCount::<7>::new::<4>()); /// // read the first 4-bit value /// assert_eq!(r.read_counted::<7, u8>(count).unwrap(), 0b0001); /// // read the second 4-bit value /// assert_eq!(r.read_counted::<7, u8>(count).unwrap(), 0b1111); /// // read the third 4-bit value /// assert_eq!(r.read_counted::<7, u8>(count).unwrap(), 0b0110); /// ``` /// /// Because the [`BitRead::read_counted`] methods know at compile-time /// that the bit count will be larger than 7, that check can be eliminated /// simply by taking advantage of information we already know. /// /// Leveraging the `BitCount` type also allows us to reason about /// bit counts in a more formal way, and use checked permutation methods /// to modify them while ensuring they remain constrained by /// the file format's requirements. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub struct BitCount { // The amount of bits may be less than or equal to the maximum, // but never more. bits: u32, } impl BitCount { /// Builds a bit count from a constant number /// of bits, which must not be greater than `MAX`. /// /// Intended to be used for defining constants. /// /// Use `TryFrom` to conditionally build /// counts from values at runtime. /// /// # Examples /// /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian, BitCount}; /// let data: &[u8] = &[0b111_00000]; /// let mut r = BitReader::endian(data, BigEndian); /// // reading 3 bits from a stream out of a maximum of 8 /// // doesn't require checking that the bit count is larger /// // than a u8 at runtime because specifying the maximum of 8 /// // guarantees our bit count will not be larger than 8 /// assert_eq!(r.read_counted::<8, u8>(BitCount::new::<3>()).unwrap(), 0b111); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::BitCount; /// // trying to build a count of 10 with a maximum of 8 /// // fails to compile at all /// let count = BitCount::<8>::new::<10>(); /// ``` pub const fn new() -> Self { const { assert!(BITS <= MAX, "BITS must be <= MAX"); } Self { bits: BITS } } /// Add a number of bits to our count, /// returning a new count with a new maximum. /// /// Returns `None` if the new count goes above our new maximum. /// /// # Examples /// /// ``` /// use bitstream_io::BitCount; /// /// let count = BitCount::<2>::new::<1>(); /// // adding 2 to 1 and increasing the max to 3 yields a new count of 3 /// assert_eq!(count.checked_add::<3>(2), Some(BitCount::<3>::new::<3>())); /// // adding 2 to 1 without increasing the max yields None /// assert_eq!(count.checked_add::<2>(2), None); /// ``` #[inline] pub const fn checked_add(self, bits: u32) -> Option> { match self.bits.checked_add(bits) { Some(bits) if bits <= NEW_MAX => Some(BitCount { bits }), _ => None, } } /// Subtracts a number of bits from our count, /// returning a new count with a new maximum. /// /// Returns `None` if the new count goes below 0 /// or below our new maximum. /// /// # Example /// ``` /// use bitstream_io::BitCount; /// let count = BitCount::<5>::new::<5>(); /// // subtracting 1 from 5 yields a new count of 4 /// assert_eq!(count.checked_sub::<5>(1), Some(BitCount::<5>::new::<4>())); /// // subtracting 6 from 5 yields None /// assert!(count.checked_sub::<5>(6).is_none()); /// // subtracting 1 with a new maximum of 3 also yields None /// // because 4 is larger than the maximum of 3 /// assert!(count.checked_sub::<3>(1).is_none()); /// ``` #[inline] pub const fn checked_sub(self, bits: u32) -> Option> { match self.bits.checked_sub(bits) { Some(bits) if bits <= NEW_MAX => Some(BitCount { bits }), _ => None, } } /// Attempt to convert our count to a count with a new /// bit count and new maximum. /// /// Returns `Some(count)` if the updated number of bits /// is less than or equal to the new maximum. /// Returns `None` if not. /// /// # Examples /// ``` /// use bitstream_io::BitCount; /// /// let count = BitCount::<5>::new::<5>(); /// // muliplying 5 bits by 2 with a new max of 10 is ok /// assert_eq!( /// count.try_map::<10, _>(|i| i.checked_mul(2)), /// Some(BitCount::<10>::new::<10>()), /// ); /// /// // multiplying 5 bits by 3 with a new max of 10 overflows /// assert_eq!(count.try_map::<10, _>(|i| i.checked_mul(3)), None); /// ``` #[inline] pub fn try_map(self, f: F) -> Option> where F: FnOnce(u32) -> Option, { f(self.bits) .filter(|bits| *bits <= NEW_MAX) .map(|bits| BitCount { bits }) } /// Returns our maximum bit count /// /// # Example /// ``` /// use bitstream_io::BitCount; /// /// let count = BitCount::<10>::new::<5>(); /// assert_eq!(count.max(), 10); /// ``` #[inline(always)] pub const fn max(&self) -> u32 { MAX } /// Returns signed count if our bit count is greater than 0 /// /// # Example /// /// ``` /// use bitstream_io::{BitCount, SignedBitCount}; /// /// let count = BitCount::<10>::new::<5>(); /// assert_eq!(count.signed_count(), Some(SignedBitCount::<10>::new::<5>())); /// /// let count = BitCount::<10>::new::<0>(); /// assert_eq!(count.signed_count(), None); /// ``` #[inline(always)] pub const fn signed_count(&self) -> Option> { match self.bits.checked_sub(1) { Some(bits) => Some(SignedBitCount { bits: *self, unsigned: BitCount { bits }, }), None => None, } } /// Masks off the least-significant bits for the given type /// /// Returns closure that takes a value and returns a /// pair of the most-significant and least-significant /// bits. Because the least-significant bits cannot /// be larger than this bit count, that value is /// returned as a [`Checked`] type. /// /// # Examples /// /// ``` /// use bitstream_io::BitCount; /// /// // create a bit count of 3 /// let count = BitCount::<8>::new::<3>(); /// /// // create a mask suitable for u8 types /// let mask = count.mask_lsb::(); /// /// let (msb, lsb) = mask(0b11011_110); /// assert_eq!(msb, 0b11011); // the most-significant bits /// assert_eq!(lsb.into_value(), 0b110); // the least-significant bits /// /// let (msb, lsb) = mask(0b01100_010); /// assert_eq!(msb, 0b01100); // the most-significant bits /// assert_eq!(lsb.into_value(), 0b010); // the least-significant bits /// /// let (msb, lsb) = mask(0b00000_111); /// assert_eq!(msb, 0b00000); // the most-significant bits /// assert_eq!(lsb.into_value(), 0b111); // the least-significant bits /// ``` /// /// ``` /// use bitstream_io::BitCount; /// /// // a mask with a bit count of 0 puts everything in msb /// let mask = BitCount::<8>::new::<0>().mask_lsb::(); /// /// let (msb, lsb) = mask(0b11111111); /// assert_eq!(msb, 0b11111111); /// assert_eq!(lsb.into_value(), 0); /// /// // a mask with a bit count larger than the type /// // is restricted to that type's size, if possible /// let mask = BitCount::<16>::new::<9>().mask_lsb::(); /// /// let (msb, lsb) = mask(0b11111111); /// assert_eq!(msb, 0); /// assert_eq!(lsb.into_value(), 0b11111111); /// ``` pub fn mask_lsb(self) -> impl Fn(U) -> (U, CheckedUnsigned) { use core::convert::TryFrom; let (mask, shift, count) = match U::BITS_SIZE.checked_sub(self.bits) { Some(mask_bits) => (U::ALL.shr_default(mask_bits), self.bits, self), None => ( U::ALL, U::BITS_SIZE, BitCount::try_from(U::BITS_SIZE).expect("bit count too small for type"), ), }; move |v| { ( v.shr_default(shift), Checked { value: v & mask, count, }, ) } } /// Returns this bit count's range for the given unsigned type /// /// # Example /// /// ``` /// use bitstream_io::BitCount; /// /// assert_eq!(BitCount::<9>::new::<0>().range::(), 0..=0); /// assert_eq!(BitCount::<9>::new::<1>().range::(), 0..=0b1); /// assert_eq!(BitCount::<9>::new::<2>().range::(), 0..=0b11); /// assert_eq!(BitCount::<9>::new::<3>().range::(), 0..=0b111); /// assert_eq!(BitCount::<9>::new::<4>().range::(), 0..=0b1111); /// assert_eq!(BitCount::<9>::new::<5>().range::(), 0..=0b11111); /// assert_eq!(BitCount::<9>::new::<6>().range::(), 0..=0b111111); /// assert_eq!(BitCount::<9>::new::<7>().range::(), 0..=0b1111111); /// assert_eq!(BitCount::<9>::new::<8>().range::(), 0..=0b11111111); /// // a count that exceeds the type's size is /// // naturally restricted to that type's maximum range /// assert_eq!(BitCount::<9>::new::<9>().range::(), 0..=0b11111111); /// ``` #[inline] pub fn range(&self) -> core::ops::RangeInclusive { match U::ONE.checked_shl(self.bits) { Some(top) => U::ZERO..=(top - U::ONE), None => U::ZERO..=U::ALL, } } /// Returns minimum value between ourself and bit count /// /// # Example /// /// ``` /// use bitstream_io::BitCount; /// /// let count = BitCount::<8>::new::<7>(); /// assert_eq!(count.min(6), BitCount::new::<6>()); /// assert_eq!(count.min(8), BitCount::new::<7>()); /// ``` #[inline(always)] pub fn min(self, bits: u32) -> Self { // the minimum of ourself and another bit count // can never exceed our maximum bit count Self { bits: self.bits.min(bits), } } /// Returns the minimum value of an unsigned int in this bit count /// /// # Example /// /// ``` /// use bitstream_io::BitCount; /// /// assert_eq!(BitCount::<8>::new::<0>().none::().into_value(), 0b0); /// assert_eq!(BitCount::<8>::new::<1>().none::().into_value(), 0b0); /// assert_eq!(BitCount::<8>::new::<2>().none::().into_value(), 0b00); /// assert_eq!(BitCount::<8>::new::<3>().none::().into_value(), 0b000); /// assert_eq!(BitCount::<8>::new::<4>().none::().into_value(), 0b0000); /// assert_eq!(BitCount::<8>::new::<5>().none::().into_value(), 0b00000); /// assert_eq!(BitCount::<8>::new::<6>().none::().into_value(), 0b000000); /// assert_eq!(BitCount::<8>::new::<7>().none::().into_value(), 0b0000000); /// assert_eq!(BitCount::<8>::new::<8>().none::().into_value(), 0b00000000); /// ``` #[inline(always)] pub fn none(self) -> CheckedUnsigned { CheckedUnsigned { value: U::ZERO, count: self, } } /// Returns the maximum value of an unsigned int in this bit count /// /// # Example /// /// ``` /// use bitstream_io::BitCount; /// /// assert_eq!(BitCount::<8>::new::<0>().all::().into_value(), 0b0); /// assert_eq!(BitCount::<8>::new::<1>().all::().into_value(), 0b1); /// assert_eq!(BitCount::<8>::new::<2>().all::().into_value(), 0b11); /// assert_eq!(BitCount::<8>::new::<3>().all::().into_value(), 0b111); /// assert_eq!(BitCount::<8>::new::<4>().all::().into_value(), 0b1111); /// assert_eq!(BitCount::<8>::new::<5>().all::().into_value(), 0b11111); /// assert_eq!(BitCount::<8>::new::<6>().all::().into_value(), 0b111111); /// assert_eq!(BitCount::<8>::new::<7>().all::().into_value(), 0b1111111); /// assert_eq!(BitCount::<8>::new::<8>().all::().into_value(), 0b11111111); /// ``` #[inline(always)] pub fn all(self) -> CheckedUnsigned { CheckedUnsigned { value: match U::ONE.checked_shl(self.bits) { Some(top) => top - U::ONE, None => U::ALL, }, count: self, } } } impl core::convert::TryFrom for BitCount { type Error = u32; /// Attempts to convert a `u32` bit count to a `BitCount` /// /// Attempting a bit maximum bit count larger than the /// largest supported type is a compile-time error /// /// # Examples /// ``` /// use bitstream_io::BitCount; /// use std::convert::TryInto; /// /// assert_eq!(8u32.try_into(), Ok(BitCount::<8>::new::<8>())); /// assert_eq!(9u32.try_into(), Err::, _>(9)); /// ``` fn try_from(bits: u32) -> Result { (bits <= MAX).then_some(Self { bits }).ok_or(bits) } } impl core::fmt::Display for BitCount { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { core::fmt::Display::fmt(&self.bits, f) } } impl BitCount<{ u32::MAX }> { /// Builds a bit count where the maximum bits is unknown. /// /// # Example /// ``` /// use bitstream_io::BitCount; /// assert_eq!(BitCount::unknown(5), BitCount::<{ u32::MAX }>::new::<5>()); /// ``` pub const fn unknown(bits: u32) -> Self { Self { bits } } } #[test] fn test_unknown_bitcount() { let count = BitCount::unknown(u32::MAX); assert!(u32::from(count) <= count.max()); } impl From> for u32 { #[inline(always)] fn from(BitCount { bits }: BitCount) -> u32 { bits } } /// A number of bits to be read or written for signed integers, with a known maximum /// /// This is closely related to the [`BitCount`] type, but further constrained /// to have a minimum value of 1 - because signed values require at least /// 1 bit for the sign. /// /// Let's start with a basic example: /// /// ``` /// use bitstream_io::{BitRead, BitReader, BigEndian}; /// /// let data: &[u8] = &[0b100_0001_1, 0b111_0110_0]; /// let mut r = BitReader::endian(data, BigEndian); /// // our bit count is a 3 bit value /// let count = r.read::<3, u32>().unwrap(); /// // that count indicates we need to read 4 bits (0b100) /// assert_eq!(count, 4); /// // read the first 4-bit signed value /// assert_eq!(r.read_var::(count).unwrap(), 1); /// // read the second 4-bit signed value /// assert_eq!(r.read_var::(count).unwrap(), -1); /// // read the third 4-bit signed value /// assert_eq!(r.read_var::(count).unwrap(), 6); /// ``` /// /// In the preceding example, even though we know `count` is a /// 3 bit value whose maximum value will never be greater than 7, /// the subsequent `read_var` calls have no way to know that. /// They must assume `count` could be 9, or `u32::MAX` or any other `u32` value /// and validate the count is not larger than the `i8` types we're reading /// while also greater than 0 because `i8` requires a sign bit. /// /// But we can convert our example to use the `SignedBitCount` type: /// ``` /// use bitstream_io::{BitRead, BitReader, BigEndian, SignedBitCount}; /// /// let data: &[u8] = &[0b100_0001_1, 0b111_0110_0]; /// let mut r = BitReader::endian(data, BigEndian); /// // our bit count is a 3 bit value with a maximum value of 7 /// let count = r.read_count::<0b111>().unwrap(); /// // convert that count to a signed bit count, /// // which guarantees its value is greater than 0 /// let count = count.signed_count().unwrap(); /// // that count indicates we need to read 4 bits (0b100) /// assert_eq!(count, SignedBitCount::<7>::new::<4>()); /// // read the first 4-bit value /// assert_eq!(r.read_signed_counted::<7, i8>(count).unwrap(), 1); /// // read the second 4-bit value /// assert_eq!(r.read_signed_counted::<7, i8>(count).unwrap(), -1); /// // read the third 4-bit value /// assert_eq!(r.read_signed_counted::<7, i8>(count).unwrap(), 6); /// ``` /// /// Because the [`BitRead::read_signed_counted`] methods know at compile-time /// that the bit count will be larger than 7, that check can be eliminated /// simply by taking advantage of information we already know. /// /// Leveraging the `SignedBitCount` type also allows us to reason about /// bit counts in a more formal way, and use checked permutation methods /// to modify them while ensuring they remain constrained by /// the file format's requirements. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub struct SignedBitCount { // the whole original bit count bits: BitCount, // a bit count with one bit removed for the sign unsigned: BitCount, } impl SignedBitCount { /// Builds a signed bit count from a constant number /// of bits, which must be greater than 0 and /// not be greater than `MAX`. /// /// Intended to be used for defining constants. /// /// Use `TryFrom` to conditionally build /// counts from values at runtime. /// /// # Examples /// /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian, SignedBitCount}; /// let data: &[u8] = &[0b111_00000]; /// let mut r = BitReader::endian(data, BigEndian); /// // reading 3 bits from a stream out of a maximum of 8 /// // doesn't require checking that the bit count is larger /// // than a u8 at runtime because specifying the maximum of 8 /// // guarantees our bit count will not be larger than 8 /// assert_eq!(r.read_signed_counted::<8, i8>(SignedBitCount::new::<3>()).unwrap(), -1); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::SignedBitCount; /// // trying to build a count of 10 with a maximum of 8 /// // fails to compile at all /// let count = SignedBitCount::<8>::new::<10>(); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::SignedBitCount; /// // trying to build a count of 0 also fails to compile /// let count = SignedBitCount::<8>::new::<0>(); /// ``` pub const fn new() -> Self { const { assert!(BITS > 0, "BITS must be > 0"); } Self { bits: BitCount::new::(), unsigned: BitCount { bits: BITS - 1 }, } } /// Add a number of bits to our count, /// returning a new count with a new maximum. /// /// Returns `None` if the new count goes above our new maximum. /// /// # Examples /// /// ``` /// use bitstream_io::SignedBitCount; /// /// let count = SignedBitCount::<2>::new::<1>(); /// // adding 2 to 1 and increasing the max to 3 yields a new count of 3 /// assert_eq!(count.checked_add::<3>(2), Some(SignedBitCount::<3>::new::<3>())); /// // adding 2 to 1 without increasing the max yields None /// assert_eq!(count.checked_add::<2>(2), None); /// ``` #[inline] pub const fn checked_add( self, bits: u32, ) -> Option> { match self.bits.checked_add(bits) { Some(bits_new) => match self.unsigned.checked_add(bits) { Some(unsigned) => Some(SignedBitCount { bits: bits_new, unsigned, }), None => None, }, None => None, } } /// Subtracts a number of bits from our count, /// returning a new count with a new maximum. /// /// Returns `None` if the new count goes below 1 /// or below our new maximum. /// /// # Example /// ``` /// use bitstream_io::SignedBitCount; /// let count = SignedBitCount::<5>::new::<5>(); /// // subtracting 1 from 5 yields a new count of 4 /// assert_eq!(count.checked_sub::<5>(1), Some(SignedBitCount::<5>::new::<4>())); /// // subtracting 6 from 5 yields None /// assert!(count.checked_sub::<5>(6).is_none()); /// // subtracting 1 with a new maximum of 3 also yields None /// // because 4 is larger than the maximum of 3 /// assert!(count.checked_sub::<3>(1).is_none()); /// // subtracting 5 from 5 also yields None /// // because SignedBitCount always requires 1 bit for the sign /// assert!(count.checked_sub::<5>(5).is_none()); /// ``` #[inline] pub const fn checked_sub( self, bits: u32, ) -> Option> { match self.bits.checked_sub(bits) { Some(bits_new) => match self.unsigned.checked_sub(bits) { Some(unsigned) => Some(SignedBitCount { bits: bits_new, unsigned, }), None => None, }, None => None, } } /// Attempt to convert our count to a count with a new /// bit count and new maximum. /// /// Returns `Some(count)` if the updated number of bits /// is less than or equal to the new maximum /// and greater than 0. /// Returns `None` if not. /// /// # Examples /// ``` /// use bitstream_io::SignedBitCount; /// /// let count = SignedBitCount::<5>::new::<5>(); /// // muliplying 5 bits by 2 with a new max of 10 is ok /// assert_eq!( /// count.try_map::<10, _>(|i| i.checked_mul(2)), /// Some(SignedBitCount::<10>::new::<10>()), /// ); /// /// // multiplying 5 bits by 3 with a new max of 10 overflows /// assert_eq!(count.try_map::<10, _>(|i| i.checked_mul(3)), None); /// /// // multiplying 5 bits by 0 results in 0 bits, /// // which isn't value for a SignedBitCount /// assert_eq!(count.try_map::<10, _>(|i| Some(i * 0)), None); /// ``` #[inline] pub fn try_map(self, f: F) -> Option> where F: FnOnce(u32) -> Option, { self.bits.try_map(f).and_then(|b| b.signed_count()) } /// Returns our maximum bit count /// /// # Example /// ``` /// use bitstream_io::SignedBitCount; /// /// let count = SignedBitCount::<10>::new::<5>(); /// assert_eq!(count.max(), 10); /// ``` #[inline(always)] pub const fn max(&self) -> u32 { MAX } /// Returns regular unsigned bit count /// /// # Example /// /// ``` /// use bitstream_io::{BitCount, SignedBitCount}; /// /// let signed_count = SignedBitCount::<10>::new::<5>(); /// assert_eq!(signed_count.count(), BitCount::<10>::new::<5>()); /// ``` #[inline(always)] pub const fn count(&self) -> BitCount { self.bits } /// Returns this bit count's range for the given signed type /// /// # Example /// /// ``` /// use bitstream_io::SignedBitCount; /// /// assert_eq!(SignedBitCount::<9>::new::<1>().range::(), -1..=0); /// assert_eq!(SignedBitCount::<9>::new::<2>().range::(), -2..=1); /// assert_eq!(SignedBitCount::<9>::new::<3>().range::(), -4..=3); /// assert_eq!(SignedBitCount::<9>::new::<4>().range::(), -8..=7); /// assert_eq!(SignedBitCount::<9>::new::<5>().range::(), -16..=15); /// assert_eq!(SignedBitCount::<9>::new::<6>().range::(), -32..=31); /// assert_eq!(SignedBitCount::<9>::new::<7>().range::(), -64..=63); /// assert_eq!(SignedBitCount::<9>::new::<8>().range::(), -128..=127); /// // a count that exceeds the type's size is /// // naturally restricted to that type's maximum range /// assert_eq!(SignedBitCount::<9>::new::<9>().range::(), -128..=127); /// ``` pub fn range(&self) -> core::ops::RangeInclusive { // a bit of a hack to get around the somewhat restrictive // SignedInteger trait I've created for myself if self.bits.bits < S::BITS_SIZE { (!S::ZERO << self.unsigned.bits)..=((S::ONE << self.unsigned.bits) - S::ONE) } else { S::Unsigned::ZERO.as_negative(S::BITS_SIZE)..=(S::Unsigned::ALL >> 1).as_non_negative() } } } impl core::fmt::Display for SignedBitCount { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { core::fmt::Display::fmt(&self.bits, f) } } impl core::convert::TryFrom> for SignedBitCount { type Error = (); #[inline] fn try_from(count: BitCount) -> Result { count.signed_count().ok_or(()) } } impl core::convert::TryFrom for SignedBitCount { type Error = u32; #[inline] fn try_from(count: u32) -> Result { BitCount::::try_from(count).and_then(|b| b.signed_count().ok_or(count)) } } impl From> for u32 { #[inline(always)] fn from( SignedBitCount { bits: BitCount { bits }, .. }: SignedBitCount, ) -> u32 { bits } } /// An error when converting a value to a [`Checked`] struct #[derive(Copy, Clone, Debug)] pub enum CheckedError { /// Excessive bits for type ExcessiveBits, /// Excessive value for bits ExcessiveValue, } impl core::error::Error for CheckedError {} impl core::fmt::Display for CheckedError { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match self { Self::ExcessiveBits => core::fmt::Display::fmt("excessive bits for type written", f), Self::ExcessiveValue => core::fmt::Display::fmt("excessive value for bits written", f), } } } impl From for io::Error { #[inline] fn from(error: CheckedError) -> Self { match error { CheckedError::ExcessiveBits => io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type written", ), CheckedError::ExcessiveValue => io::Error::new( io::ErrorKind::InvalidInput, "excessive value for bits written", ), } } } /// A type for eliminating redundant validation when writing /// /// Normally, when writing a value, not only must the number of bits /// must be checked against the type being written /// (e.g. writing 9 bits from a `u8` is always an error), /// but the value must also be checked against the number of bits /// (e.g. writing a value of 2 in 1 bit is always an error). /// /// But when the value's range can be checked in advance, /// the write-time check can be skipped through the use /// of the [`BitWrite::write_checked`] method. #[derive(Copy, Clone, Debug)] pub struct Checked { count: C, value: T, } impl Checked { /// Returns our bit count and value #[inline] pub fn into_count_value(self) -> (C, T) { (self.count, self.value) } /// Returns our value #[inline] pub fn into_value(self) -> T { self.value } } impl AsRef for Checked { fn as_ref(&self) -> &T { &self.value } } /// An unsigned type with a verified value pub type CheckedUnsigned = Checked, T>; impl Checkable for CheckedUnsigned { #[inline] fn write(&self, writer: &mut W) -> io::Result<()> { // a naive default implementation writer.write_unsigned_counted(self.count, self.value) } #[inline] fn written_bits(&self) -> u32 { self.count.bits } } impl CheckablePrimitive for CheckedUnsigned { type CountType = BitCount; #[inline] fn read(reader: &mut R, count: Self::CountType) -> io::Result { reader .read_unsigned_counted(count) .map(|value| Self { value, count }) } } impl private::Checkable for CheckedUnsigned { fn write_endian( self, writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result<()> where E: private::Endianness, W: io::Write, { E::write_bits_checked(writer, queue_value, queue_bits, self) } } impl CheckedUnsigned { /// Returns our value if it fits in the given number of bits /// /// # Example /// /// ``` /// use bitstream_io::{BitCount, CheckedUnsigned, CheckedError}; /// /// // a value of 7 fits into a 3 bit count /// assert!(CheckedUnsigned::<8, u8>::new(3, 0b111).is_ok()); /// /// // a value of 8 does not fit into a 3 bit count /// assert!(matches!( /// CheckedUnsigned::<8, u8>::new(3, 0b1000), /// Err(CheckedError::ExcessiveValue), /// )); /// /// // a bit count of 9 is too large for u8 /// assert!(matches!( /// CheckedUnsigned::<9, _>::new(9, 1u8), /// Err(CheckedError::ExcessiveBits), /// )); /// ``` #[inline] pub fn new(count: impl TryInto>, value: U) -> Result { let count @ BitCount { bits } = count.try_into().map_err(|_| CheckedError::ExcessiveBits)?; if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE { if bits == 0 { Ok(Self { count, value: U::ZERO, }) } else if value <= U::ALL >> (U::BITS_SIZE - bits) { Ok(Self { count, value }) } else { Err(CheckedError::ExcessiveValue) } } else { Err(CheckedError::ExcessiveBits) } } /// Returns our value if it fits in the given number of const bits /// /// # Examples /// /// ``` /// use bitstream_io::{CheckedUnsigned, CheckedError}; /// /// // a value of 7 fits into a 3 bit count /// assert!(CheckedUnsigned::<8, u8>::new_fixed::<3>(0b111).is_ok()); /// /// // a value of 8 does not fit into a 3 bit count /// assert!(matches!( /// CheckedUnsigned::<8, u8>::new_fixed::<3>(0b1000), /// Err(CheckedError::ExcessiveValue), /// )); /// ``` /// /// ```compile_fail /// use bitstream_io::{BitCount, CheckedUnsigned}; /// /// // a bit count of 9 is too large for u8 /// /// // because this is checked at compile-time, /// // it does not compile at all /// let c = CheckedUnsigned::<16, u8>::new_fixed::<9>(1); /// ``` pub fn new_fixed(value: U) -> Result { const { assert!(BITS <= U::BITS_SIZE, "excessive bits for type written"); } if BITS == 0 { Ok(Self { count: BitCount::new::<0>(), value: U::ZERO, }) } else if BITS == U::BITS_SIZE || value <= (U::ALL >> (U::BITS_SIZE - BITS)) { Ok(Self { // whether BITS is larger than MAX is checked here count: BitCount::new::(), value, }) } else { Err(CheckedError::ExcessiveValue) } } } /// A fixed number of bits to be consumed or written /// /// Analagous to [`BitCount`], this is a zero-sized type /// whose value is fixed at compile-time and cannot be changed. /// /// # Example /// /// ``` /// use bitstream_io::{ /// BigEndian, BitRead, BitReader, BitWrite, BitWriter, CheckedUnsignedFixed, FixedBitCount, /// }; /// /// type FourBits = CheckedUnsignedFixed<4, u8>; /// /// let input: &[u8] = &[0b0001_1111, 0b0110_1001]; /// let mut r = BitReader::endian(input, BigEndian); /// /// // read 4, 4-bit values /// let v1 = r.read_checked::(FixedBitCount).unwrap(); /// let v2 = r.read_checked::(FixedBitCount).unwrap(); /// let v3 = r.read_checked::(FixedBitCount).unwrap(); /// let v4 = r.read_checked::(FixedBitCount).unwrap(); /// /// assert_eq!(v1.into_value(), 0b0001); /// assert_eq!(v2.into_value(), 0b1111); /// assert_eq!(v3.into_value(), 0b0110); /// assert_eq!(v4.into_value(), 0b1001); /// /// // write those same values back to disk /// let mut w = BitWriter::endian(vec![], BigEndian); /// w.write_checked(v1).unwrap(); /// w.write_checked(v2).unwrap(); /// w.write_checked(v3).unwrap(); /// w.write_checked(v4).unwrap(); /// /// // ensure they're the same /// assert_eq!(w.into_writer().as_slice(), input); /// ``` #[derive(Copy, Clone, Debug)] pub struct FixedBitCount; impl From> for BitCount { fn from(_count: FixedBitCount) -> Self { BitCount::new::() } } impl core::convert::TryFrom> for FixedBitCount { type Error = BitCount; fn try_from(count: BitCount) -> Result { (count.bits == BITS).then_some(FixedBitCount).ok_or(count) } } /// An unsigned type with a verified value for a fixed number of bits pub type CheckedUnsignedFixed = Checked, T>; impl CheckedUnsignedFixed { /// Returns our checked value if it fits in the given number of const bits /// /// # Examples /// /// ``` /// use bitstream_io::{CheckedUnsignedFixed, CheckedError}; /// /// // a value of 7 fits into a maximum of 3 bits /// assert!(CheckedUnsignedFixed::<3, u8>::new_fixed(0b111).is_ok()); /// /// // a value of 8 does not fit into a maximum of 3 bits /// assert!(matches!( /// CheckedUnsignedFixed::<3, u8>::new_fixed(0b1000), /// Err(CheckedError::ExcessiveValue), /// )); /// ``` /// /// ```compile_fail /// use bitstream_io::CheckedUnsignedFixed; /// /// // a bit count of 9 is too large for u8 /// /// // because this is checked at compile-time, /// // it does not compile at all /// let c = CheckedUnsignedFixed::<9, u8>::new_fixed(1); /// ``` pub fn new_fixed(value: U) -> Result { const { assert!(BITS <= U::BITS_SIZE, "excessive bits for type written"); } if BITS == 0 { Ok(Self { count: FixedBitCount, value: U::ZERO, }) } else if BITS == U::BITS_SIZE || value <= (U::ALL >> (U::BITS_SIZE - BITS)) { Ok(Self { count: FixedBitCount, value, }) } else { Err(CheckedError::ExcessiveValue) } } } impl Checkable for CheckedUnsignedFixed { #[inline] fn write(&self, writer: &mut W) -> io::Result<()> { // a naive default implementation writer.write_unsigned::(self.value) } #[inline] fn written_bits(&self) -> u32 { BITS } } impl private::Checkable for CheckedUnsignedFixed { fn write_endian( self, writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result<()> where E: private::Endianness, W: io::Write, { E::write_bits_checked( writer, queue_value, queue_bits, Checked { value: self.value, count: self.count.into(), }, ) } } impl CheckablePrimitive for CheckedUnsignedFixed { type CountType = FixedBitCount; fn read(reader: &mut R, count: FixedBitCount) -> io::Result { Ok(Self { value: reader.read_unsigned::()?, count, }) } } /// A signed type with a verified value pub type CheckedSigned = Checked, T>; impl Checkable for CheckedSigned { #[inline] fn write(&self, writer: &mut W) -> io::Result<()> { // a naive default implementation writer.write_signed_counted(self.count, self.value) } #[inline] fn written_bits(&self) -> u32 { self.count.bits.into() } } impl CheckablePrimitive for CheckedSigned { type CountType = SignedBitCount; #[inline] fn read(reader: &mut R, count: Self::CountType) -> io::Result { reader .read_signed_counted(count) .map(|value| Self { value, count }) } } impl private::Checkable for CheckedSigned { #[inline] fn write_endian( self, writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result<()> where E: private::Endianness, W: io::Write, { E::write_signed_bits_checked(writer, queue_value, queue_bits, self) } } impl CheckedSigned { /// Returns our value if it fits in the given number of bits /// /// # Example /// /// ``` /// use bitstream_io::{SignedBitCount, CheckedSigned, CheckedError}; /// /// // a value of 3 fits into a 3 bit count /// assert!(CheckedSigned::<8, _>::new(3, 3i8).is_ok()); /// /// // a value of 4 does not fit into a 3 bit count /// assert!(matches!( /// CheckedSigned::<8, _>::new(3, 4i8), /// Err(CheckedError::ExcessiveValue), /// )); /// /// // a bit count of 9 is too large for i8 /// assert!(matches!( /// CheckedSigned::<9, _>::new(9, 1i8), /// Err(CheckedError::ExcessiveBits), /// )); /// ``` #[inline] pub fn new(count: impl TryInto>, value: S) -> Result { let count @ SignedBitCount { bits: BitCount { bits }, unsigned: BitCount { bits: unsigned_bits, }, } = count.try_into().map_err(|_| CheckedError::ExcessiveBits)?; if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE { if bits == S::BITS_SIZE || (((S::ZERO - S::ONE) << unsigned_bits) <= value && value < (S::ONE << unsigned_bits)) { Ok(Self { count, value }) } else { Err(CheckedError::ExcessiveValue) } } else { Err(CheckedError::ExcessiveBits) } } /// Returns our value if it fits in the given number of const bits /// /// # Examples /// /// ``` /// use bitstream_io::{CheckedSigned, CheckedError}; /// /// // a value of 3 fits into a 3 bit count /// assert!(CheckedSigned::<8, i8>::new_fixed::<3>(3).is_ok()); /// /// // a value of 4 does not fit into a 3 bit count /// assert!(matches!( /// CheckedSigned::<8, i8>::new_fixed::<3>(4), /// Err(CheckedError::ExcessiveValue), /// )); /// ``` /// /// ```compile_fail /// use bitstream_io::{BitCount, CheckedSigned}; /// /// // a bit count of 9 is too large for i8 /// /// // because this is checked at compile-time, /// // it does not compile at all /// let c = CheckedSigned::<16, i8>::new_fixed::<9>(1); /// ``` pub fn new_fixed(value: S) -> Result { const { assert!(BITS <= S::BITS_SIZE, "excessive bits for type written"); } if BITS == S::BITS_SIZE || (((S::ZERO - S::ONE) << (BITS - 1)) <= value && value < (S::ONE << (BITS - 1))) { Ok(Self { count: SignedBitCount::new::(), value, }) } else { Err(CheckedError::ExcessiveValue) } } } /// A fixed number of bits to be consumed or written /// /// Analagous to [`SignedBitCount`], this is a zero-sized type /// whose value is fixed at compile-time and cannot be changed. /// /// # Example /// /// ``` /// use bitstream_io::{ /// BigEndian, BitRead, BitReader, BitWrite, BitWriter, /// CheckedSignedFixed, FixedSignedBitCount, /// }; /// /// type FourBits = CheckedSignedFixed<4, i8>; /// /// let input: &[u8] = &[0b0001_1111, 0b0110_1001]; /// let mut r = BitReader::endian(input, BigEndian); /// /// // read 4, 4-bit values /// let v1 = r.read_checked::(FixedSignedBitCount).unwrap(); /// let v2 = r.read_checked::(FixedSignedBitCount).unwrap(); /// let v3 = r.read_checked::(FixedSignedBitCount).unwrap(); /// let v4 = r.read_checked::(FixedSignedBitCount).unwrap(); /// /// assert_eq!(v1.into_value(), 1); /// assert_eq!(v2.into_value(), -1); /// assert_eq!(v3.into_value(), 6); /// assert_eq!(v4.into_value(), -7); /// /// // write those same values back to disk /// let mut w = BitWriter::endian(vec![], BigEndian); /// w.write_checked(v1).unwrap(); /// w.write_checked(v2).unwrap(); /// w.write_checked(v3).unwrap(); /// w.write_checked(v4).unwrap(); /// /// // ensure they're the same /// assert_eq!(w.into_writer().as_slice(), input); /// ``` #[derive(Copy, Clone, Debug)] pub struct FixedSignedBitCount; impl From> for SignedBitCount { fn from(_count: FixedSignedBitCount) -> Self { SignedBitCount::new::() } } impl core::convert::TryFrom> for FixedSignedBitCount { type Error = SignedBitCount; fn try_from(count: SignedBitCount) -> Result { (count.bits.bits == BITS) .then_some(FixedSignedBitCount) .ok_or(count) } } /// A signed type with a verified value for a fixed number of bits pub type CheckedSignedFixed = Checked, T>; impl CheckedSignedFixed { /// Returns our checked value if it fits in the given number of const bits /// /// # Examples /// /// ``` /// use bitstream_io::{SignedBitCount, CheckedSignedFixed, CheckedError}; /// /// // a value of 3 fits into a 3 bit count /// assert!(CheckedSignedFixed::<3, _>::new_fixed(3i8).is_ok()); /// /// // a value of 4 does not fit into a 3 bit count /// assert!(matches!( /// CheckedSignedFixed::<3, _>::new_fixed(4i8), /// Err(CheckedError::ExcessiveValue), /// )); /// ``` /// /// ```compile_fail /// use bitstream_io::CheckedSignedFixed; /// /// // a bit count of 9 is too large for i8 /// /// // because this is checked at compile-time, /// // it does not compile at all /// let c = CheckedSignedFixed::<9, _>::new_fixed(1i8); /// ``` pub fn new_fixed(value: S) -> Result { const { assert!(BITS <= S::BITS_SIZE, "excessive bits for type written"); } if BITS == S::BITS_SIZE || (((S::ZERO - S::ONE) << (BITS - 1)) <= value && value < (S::ONE << (BITS - 1))) { Ok(Self { count: FixedSignedBitCount, value, }) } else { Err(CheckedError::ExcessiveValue) } } } impl Checkable for CheckedSignedFixed { #[inline] fn write(&self, writer: &mut W) -> io::Result<()> { // a naive default implementation writer.write_signed::(self.value) } #[inline] fn written_bits(&self) -> u32 { BITS } } impl private::Checkable for CheckedSignedFixed { #[inline] fn write_endian( self, writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result<()> where E: private::Endianness, W: io::Write, { E::write_signed_bits_checked( writer, queue_value, queue_bits, CheckedSigned { value: self.value, count: self.count.into(), }, ) } } impl CheckablePrimitive for CheckedSignedFixed { type CountType = FixedSignedBitCount; fn read( reader: &mut R, count: FixedSignedBitCount, ) -> io::Result { Ok(Self { value: reader.read_signed::()?, count, }) } } /// A trait for writable types whose values can be validated /// /// Ordinarily, when writing a value to a stream with a given /// number of bits, the value must be validated to ensure /// it will fit within that number of bits. /// /// # Example 1 /// /// ``` /// use bitstream_io::{BitWrite, BitWriter, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// /// // writing a value of 2 in 1 bit is always an error /// // which is checked here at write-time /// assert!(w.write::<1, u8>(2).is_err()); /// ``` /// /// But if the value can be checked beforehand, /// it doesn't need to be checked at write-time. /// /// # Example 2 /// /// ``` /// use bitstream_io::{BitWrite, BitWriter, BigEndian, CheckedUnsigned}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// /// // writing a value of 1 in 1 bit is ok /// // and we're checking that validity at this stage /// let value = CheckedUnsigned::<1, u8>::new_fixed::<1>(1).unwrap(); /// /// // because we've pre-validated the value beforehand, /// // it doesn't need to be checked again here /// // (though the write itself may still fail) /// assert!(w.write_checked(value).is_ok()); /// ``` /// pub trait Checkable: private::Checkable + Sized { /// Write our value to the given stream fn write(&self, writer: &mut W) -> io::Result<()>; /// The number of written bits fn written_bits(&self) -> u32; } /// A trait for readable types whose bit counts can be saved /// /// Because the intent of reading checkable values is /// to avoid validating their values when being written, /// implementing the [`Checkable`] trait is required. pub trait CheckablePrimitive: Checkable { /// Our bit count type for reading type CountType; /// Reads our value from the given stream fn read(reader: &mut R, count: Self::CountType) -> io::Result; } /// 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 BigEndian { // checked in the sense that we've verified // the output type is large enough to hold the // requested number of bits #[inline] fn read_bits_checked( reader: &mut R, queue: &mut u8, queue_bits: &mut u32, BitCount { bits }: BitCount, ) -> io::Result where R: io::Read, U: UnsignedInteger, { // reads a whole value with the given number of // bytes in our endianness, where the number of bytes // must be less than or equal to the type's size in bytes #[inline(always)] fn read_bytes(reader: &mut R, bytes: usize) -> io::Result where R: io::Read, U: UnsignedInteger, { let mut buf = U::buffer(); reader .read_exact(&mut buf.as_mut()[(mem::size_of::() - bytes)..]) .map(|()| U::from_be_bytes(buf)) } if bits <= *queue_bits { // all bits in queue, so no byte needed let value = queue.shr_default(u8::BITS_SIZE - bits); *queue = queue.shl_default(bits); *queue_bits -= bits; Ok(U::from_u8(value)) } else { // at least one byte needed // bits needed beyond what's in the queue let needed_bits = bits - *queue_bits; match (needed_bits / 8, needed_bits % 8) { (0, needed) => { // only one additional byte needed, // which we share between our returned value // and the bit queue let next_byte = read_byte(reader)?; Ok(U::from_u8( mem::replace(queue, next_byte.shl_default(needed)).shr_default( u8::BITS_SIZE - mem::replace(queue_bits, u8::BITS_SIZE - needed), ), ) .shl_default(needed) | U::from_u8(next_byte.shr_default(u8::BITS_SIZE - needed))) } (bytes, 0) => { // exact number of bytes needed beyond what's // available in the queue // so read a whole value from the reader // and prepend what's left of our queue onto it Ok(U::from_u8( mem::take(queue).shr_default(u8::BITS_SIZE - mem::take(queue_bits)), ) .shl_default(needed_bits) | read_bytes(reader, bytes as usize)?) } (bytes, needed) => { // read a whole value from the reader // prepend what's in the queue at the front of it // *and* append a partial byte at the end of it // while also updating the queue and its bit count let whole: U = read_bytes(reader, bytes as usize)?; let next_byte = read_byte(reader)?; Ok(U::from_u8( mem::replace(queue, next_byte.shl_default(needed)).shr_default( u8::BITS_SIZE - mem::replace(queue_bits, u8::BITS_SIZE - needed), ), ) .shl_default(needed_bits) | whole.shl_default(needed) | U::from_u8(next_byte.shr_default(u8::BITS_SIZE - needed))) } } } } } impl Endianness for BigEndian {} impl private::Endianness for BigEndian { #[inline] fn push_bit_flush(queue_value: &mut u8, queue_bits: &mut u32, bit: bool) -> Option { *queue_value = (*queue_value << 1) | u8::from(bit); *queue_bits = (*queue_bits + 1) % 8; (*queue_bits == 0).then(|| mem::take(queue_value)) } #[inline] fn read_bits( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, count @ BitCount { bits }: BitCount, ) -> io::Result where R: io::Read, U: UnsignedInteger, { if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE { Self::read_bits_checked::(reader, queue_value, queue_bits, count) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type read", )) } } #[inline] fn read_bits_fixed( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read, U: UnsignedInteger, { const { assert!(BITS <= U::BITS_SIZE, "excessive bits for type read"); } Self::read_bits_checked::( reader, queue_value, queue_bits, BitCount::new::(), ) } // checked in the sense that we've verified // the input type is large enough to hold the // requested number of bits and that the value is // not too large for those bits #[inline] fn write_bits_checked( writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, CheckedUnsigned { count: BitCount { bits }, value, }: CheckedUnsigned, ) -> io::Result<()> where W: io::Write, U: UnsignedInteger, { fn write_bytes(writer: &mut W, bytes: usize, value: U) -> io::Result<()> where W: io::Write, U: UnsignedInteger, { let buf = U::to_be_bytes(value); writer.write_all(&buf.as_ref()[(mem::size_of::() - bytes)..]) } // the amount of available bits in the queue let available_bits = u8::BITS_SIZE - *queue_bits; if bits < available_bits { // all bits fit in queue, so no write needed *queue_value = queue_value.shl_default(bits) | U::to_u8(value); *queue_bits += bits; Ok(()) } else { // at least one byte needs to be written // bits beyond what can fit in the queue let excess_bits = bits - available_bits; match (excess_bits / 8, excess_bits % 8) { (0, excess) => { // only one byte to be written, // while the excess bits are shared // between the written byte and the bit queue *queue_bits = excess; write_byte( writer, mem::replace( queue_value, U::to_u8(value & U::ALL.shr_default(U::BITS_SIZE - excess)), ) .shl_default(available_bits) | U::to_u8(value.shr_default(excess)), ) } (bytes, 0) => { // no excess bytes beyond what can fit the queue // so write a whole byte and // the remainder of the whole value *queue_bits = 0; write_byte( writer.by_ref(), mem::take(queue_value).shl_default(available_bits) | U::to_u8(value.shr_default(bytes * 8)), )?; write_bytes(writer, bytes as usize, value) } (bytes, excess) => { // write what's in the queue along // with the head of our whole value, // write the middle section of our whole value, // while also replacing the queue with // the tail of our whole value *queue_bits = excess; write_byte( writer.by_ref(), mem::replace( queue_value, U::to_u8(value & U::ALL.shr_default(U::BITS_SIZE - excess)), ) .shl_default(available_bits) | U::to_u8(value.shr_default(excess + bytes * 8)), )?; write_bytes(writer, bytes as usize, value.shr_default(excess)) } } } } fn write_signed_bits_checked( writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, value: CheckedSigned, ) -> io::Result<()> where W: io::Write, S: SignedInteger, { let ( SignedBitCount { bits: BitCount { bits }, unsigned, }, value, ) = value.into_count_value(); if let Some(b) = Self::push_bit_flush(queue_value, queue_bits, value.is_negative()) { write_byte(writer.by_ref(), b)?; } Self::write_bits_checked( writer, queue_value, queue_bits, Checked { value: if value.is_negative() { value.as_negative(bits) } else { value.as_non_negative() }, count: unsigned, }, ) } #[inline] fn pop_bit_refill( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read, { Ok(if *queue_bits == 0 { let value = read_byte(reader)?; let msb = value & u8::MSB_BIT; *queue_value = value << 1; *queue_bits = u8::BITS_SIZE - 1; msb } else { let msb = *queue_value & u8::MSB_BIT; *queue_value <<= 1; *queue_bits -= 1; msb } != 0) } #[inline] fn pop_unary( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read, { const { assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); } match STOP_BIT { 0 => find_unary( reader, queue_value, queue_bits, |v| v.leading_ones(), |q| *q, |v, b| v.checked_shl(b), ), 1 => find_unary( reader, queue_value, queue_bits, |v| v.leading_zeros(), |_| u8::BITS_SIZE, |v, b| v.checked_shl(b), ), _ => unreachable!(), } } #[inline] fn read_signed_counted( r: &mut R, SignedBitCount { bits: BitCount { bits }, unsigned, }: SignedBitCount, ) -> io::Result where R: BitRead, S: SignedInteger, { if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE { let is_negative = r.read_bit()?; let unsigned = r.read_unsigned_counted::(unsigned)?; Ok(if is_negative { unsigned.as_negative(bits) } else { unsigned.as_non_negative() }) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type read", )) } } fn read_bytes( reader: &mut R, queue_value: &mut u8, queue_bits: u32, buf: &mut [u8], ) -> io::Result<()> where R: io::Read, { if queue_bits == 0 { reader.read_exact(buf) } else { let mut input_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE]; for output_chunk in buf.chunks_mut(CHUNK_SIZE) { let input_chunk = &mut input_chunk[0..output_chunk.len()]; reader.read_exact(input_chunk)?; // shift down each byte in our input to eventually // accomodate the contents of the bit queue // and make that our output output_chunk .iter_mut() .zip(input_chunk.iter()) .for_each(|(o, i)| { *o = i >> queue_bits; }); // include leftover bits from the next byte // shifted to the top output_chunk[1..] .iter_mut() .zip(input_chunk.iter()) .for_each(|(o, i)| { *o |= *i << (u8::BITS_SIZE - queue_bits); }); // finally, prepend the queue's contents // to the first byte in the chunk // while replacing those contents // with the final byte of the input output_chunk[0] |= mem::replace( queue_value, input_chunk.last().unwrap() << (u8::BITS_SIZE - queue_bits), ); } Ok(()) } } fn write_bytes( writer: &mut W, queue_value: &mut u8, queue_bits: u32, buf: &[u8], ) -> io::Result<()> where W: io::Write, { if queue_bits == 0 { writer.write_all(buf) } else { let mut output_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE]; for input_chunk in buf.chunks(CHUNK_SIZE) { let output_chunk = &mut output_chunk[0..input_chunk.len()]; output_chunk .iter_mut() .zip(input_chunk.iter()) .for_each(|(o, i)| { *o = i >> queue_bits; }); output_chunk[1..] .iter_mut() .zip(input_chunk.iter()) .for_each(|(o, i)| { *o |= *i << (u8::BITS_SIZE - queue_bits); }); output_chunk[0] |= mem::replace( queue_value, input_chunk.last().unwrap() & (u8::ALL >> (u8::BITS_SIZE - queue_bits)), ) << (u8::BITS_SIZE - queue_bits); writer.write_all(output_chunk)?; } Ok(()) } } #[inline(always)] fn bytes_to_primitive(buf: P::Bytes) -> P { P::from_be_bytes(buf) } #[inline(always)] fn primitive_to_bytes(p: P) -> P::Bytes { p.to_be_bytes() } #[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()) } } /// 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 LittleEndian { // checked in the sense that we've verified // the output type is large enough to hold the // requested number of bits #[inline] fn read_bits_checked( reader: &mut R, queue: &mut u8, queue_bits: &mut u32, BitCount { bits }: BitCount, ) -> io::Result where R: io::Read, U: UnsignedInteger, { // reads a whole value with the given number of // bytes in our endianness, where the number of bytes // must be less than or equal to the type's size in bytes #[inline(always)] fn read_bytes(reader: &mut R, bytes: usize) -> io::Result where R: io::Read, U: UnsignedInteger, { let mut buf = U::buffer(); reader .read_exact(&mut buf.as_mut()[0..bytes]) .map(|()| U::from_le_bytes(buf)) } if bits <= *queue_bits { // all bits in queue, so no byte needed let value = *queue & u8::ALL.shr_default(u8::BITS_SIZE - bits); *queue = queue.shr_default(bits); *queue_bits -= bits; Ok(U::from_u8(value)) } else { // at least one byte needed // bits needed beyond what's in the queue let needed_bits = bits - *queue_bits; match (needed_bits / 8, needed_bits % 8) { (0, needed) => { // only one additional byte needed, // which we share between our returned value // and the bit queue let next_byte = read_byte(reader)?; Ok( U::from_u8(mem::replace(queue, next_byte.shr_default(needed))) | (U::from_u8(next_byte & (u8::ALL >> (u8::BITS_SIZE - needed))) << mem::replace(queue_bits, u8::BITS_SIZE - needed)), ) } (bytes, 0) => { // exact number of bytes needed beyond what's // available in the queue // so read a whole value from the reader // and prepend what's left of our queue onto it Ok(U::from_u8(mem::take(queue)) | (read_bytes::(reader, bytes as usize)? << mem::take(queue_bits))) } (bytes, needed) => { // read a whole value from the reader // prepend what's in the queue at the front of it // *and* append a partial byte at the end of it // while also updating the queue and its bit count let whole: U = read_bytes(reader, bytes as usize)?; let next_byte = read_byte(reader)?; Ok( U::from_u8(mem::replace(queue, next_byte.shr_default(needed))) | (whole << *queue_bits) | (U::from_u8(next_byte & (u8::ALL >> (u8::BITS_SIZE - needed))) << (mem::replace(queue_bits, u8::BITS_SIZE - needed) + bytes * 8)), ) } } } } } impl Endianness for LittleEndian {} impl private::Endianness for LittleEndian { #[inline] fn push_bit_flush(queue_value: &mut u8, queue_bits: &mut u32, bit: bool) -> Option { *queue_value |= u8::from(bit) << *queue_bits; *queue_bits = (*queue_bits + 1) % 8; (*queue_bits == 0).then(|| mem::take(queue_value)) } #[inline] fn read_bits( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, count @ BitCount { bits }: BitCount, ) -> io::Result where R: io::Read, U: UnsignedInteger, { if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE { Self::read_bits_checked::(reader, queue_value, queue_bits, count) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type read", )) } } #[inline] fn read_bits_fixed( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read, U: UnsignedInteger, { const { assert!(BITS <= U::BITS_SIZE, "excessive bits for type read"); } Self::read_bits_checked::( reader, queue_value, queue_bits, BitCount::new::(), ) } // checked in the sense that we've verified // the input type is large enough to hold the // requested number of bits and that the value is // not too large for those bits #[inline] fn write_bits_checked( writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, CheckedUnsigned { count: BitCount { bits }, value, }: CheckedUnsigned, ) -> io::Result<()> where W: io::Write, U: UnsignedInteger, { fn write_bytes(writer: &mut W, bytes: usize, value: U) -> io::Result<()> where W: io::Write, U: UnsignedInteger, { let buf = U::to_le_bytes(value); writer.write_all(&buf.as_ref()[0..bytes]) } // the amount of available bits in the queue let available_bits = u8::BITS_SIZE - *queue_bits; if bits < available_bits { // all bits fit in queue, so no write needed *queue_value |= U::to_u8(value.shl_default(*queue_bits)); *queue_bits += bits; Ok(()) } else { // at least one byte needs to be written // bits beyond what can fit in the queue let excess_bits = bits - available_bits; match (excess_bits / 8, excess_bits % 8) { (0, excess) => { // only one byte to be written, // while the excess bits are shared // between the written byte and the bit queue write_byte( writer, mem::replace(queue_value, U::to_u8(value.shr_default(available_bits))) | U::to_u8( (value << mem::replace(queue_bits, excess)) & U::from_u8(u8::ALL), ), ) } (bytes, 0) => { // no excess bytes beyond what can fit the queue // so write a whole byte and // the remainder of the whole value write_byte( writer.by_ref(), mem::take(queue_value) | U::to_u8((value << mem::take(queue_bits)) & U::from_u8(u8::ALL)), )?; write_bytes(writer, bytes as usize, value >> available_bits) } (bytes, excess) => { // write what's in the queue along // with the head of our whole value, // write the middle section of our whole value, // while also replacing the queue with // the tail of our whole value write_byte( writer.by_ref(), mem::replace( queue_value, U::to_u8(value.shr_default(available_bits + bytes * 8)), ) | U::to_u8( (value << mem::replace(queue_bits, excess)) & U::from_u8(u8::ALL), ), )?; write_bytes(writer, bytes as usize, value >> available_bits) } } } } fn write_signed_bits_checked( writer: &mut W, queue_value: &mut u8, queue_bits: &mut u32, value: CheckedSigned, ) -> io::Result<()> where W: io::Write, S: SignedInteger, { // little-endian let ( SignedBitCount { bits: BitCount { bits }, unsigned, }, value, ) = value.into_count_value(); Self::write_bits_checked( writer.by_ref(), queue_value, queue_bits, Checked { value: if value.is_negative() { value.as_negative(bits) } else { value.as_non_negative() }, count: unsigned, }, )?; match Self::push_bit_flush(queue_value, queue_bits, value.is_negative()) { Some(b) => write_byte(writer, b), None => Ok(()), } } #[inline] fn pop_bit_refill( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read, { Ok(if *queue_bits == 0 { let value = read_byte(reader)?; let lsb = value & u8::LSB_BIT; *queue_value = value >> 1; *queue_bits = u8::BITS_SIZE - 1; lsb } else { let lsb = *queue_value & u8::LSB_BIT; *queue_value >>= 1; *queue_bits -= 1; lsb } != 0) } #[inline] fn pop_unary( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, ) -> io::Result where R: io::Read, { const { assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); } match STOP_BIT { 0 => find_unary( reader, queue_value, queue_bits, |v| v.trailing_ones(), |q| *q, |v, b| v.checked_shr(b), ), 1 => find_unary( reader, queue_value, queue_bits, |v| v.trailing_zeros(), |_| u8::BITS_SIZE, |v, b| v.checked_shr(b), ), _ => unreachable!(), } } #[inline] fn read_signed_counted( r: &mut R, SignedBitCount { bits: BitCount { bits }, unsigned, }: SignedBitCount, ) -> io::Result where R: BitRead, S: SignedInteger, { if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE { let unsigned = r.read_unsigned_counted::(unsigned)?; let is_negative = r.read_bit()?; Ok(if is_negative { unsigned.as_negative(bits) } else { unsigned.as_non_negative() }) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type read", )) } } fn read_bytes( reader: &mut R, queue_value: &mut u8, queue_bits: u32, buf: &mut [u8], ) -> io::Result<()> where R: io::Read, { if queue_bits == 0 { reader.read_exact(buf) } else { let mut input_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE]; for output_chunk in buf.chunks_mut(CHUNK_SIZE) { let input_chunk = &mut input_chunk[0..output_chunk.len()]; reader.read_exact(input_chunk)?; output_chunk .iter_mut() .zip(input_chunk.iter()) .for_each(|(o, i)| { *o = i << queue_bits; }); output_chunk[1..] .iter_mut() .zip(input_chunk.iter()) .for_each(|(o, i)| { *o |= i >> (u8::BITS_SIZE - queue_bits); }); output_chunk[0] |= mem::replace( queue_value, input_chunk.last().unwrap() >> (u8::BITS_SIZE - queue_bits), ); } Ok(()) } } fn write_bytes( writer: &mut W, queue_value: &mut u8, queue_bits: u32, buf: &[u8], ) -> io::Result<()> where W: io::Write, { if queue_bits == 0 { writer.write_all(buf) } else { let mut output_chunk: [u8; CHUNK_SIZE] = [0; CHUNK_SIZE]; for input_chunk in buf.chunks(CHUNK_SIZE) { let output_chunk = &mut output_chunk[0..input_chunk.len()]; output_chunk .iter_mut() .zip(input_chunk.iter()) .for_each(|(o, i)| { *o = i << queue_bits; }); output_chunk[1..] .iter_mut() .zip(input_chunk.iter()) .for_each(|(o, i)| { *o |= i >> (u8::BITS_SIZE - queue_bits); }); output_chunk[0] |= mem::replace( queue_value, input_chunk.last().unwrap() >> (u8::BITS_SIZE - queue_bits), ); writer.write_all(output_chunk)?; } Ok(()) } } #[inline(always)] fn bytes_to_primitive(buf: P::Bytes) -> P { P::from_le_bytes(buf) } #[inline(always)] fn primitive_to_bytes(p: P) -> P::Bytes { p.to_le_bytes() } #[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()) } } #[inline] fn find_unary( reader: &mut R, queue_value: &mut u8, queue_bits: &mut u32, leading_bits: impl Fn(u8) -> u32, max_bits: impl Fn(&mut u32) -> u32, checked_shift: impl Fn(u8, u32) -> Option, ) -> io::Result where R: io::Read, { let mut acc = 0; loop { match leading_bits(*queue_value) { bits if bits == max_bits(queue_bits) => { // all bits exhausted // fetch another byte and keep going acc += *queue_bits; *queue_value = read_byte(reader.by_ref())?; *queue_bits = u8::BITS_SIZE; } bits => match checked_shift(*queue_value, bits + 1) { Some(value) => { // fetch part of source byte *queue_value = value; *queue_bits -= bits + 1; break Ok(acc + bits); } None => { // fetch all of source byte *queue_value = 0; *queue_bits = 0; break Ok(acc + bits); } }, } } } bitstream-io-4.9.0/src/read.rs000064400000000000000000002337531046102023000143220ustar 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. #![warn(missing_docs)] #[cfg(not(feature = "std"))] use core2::io; #[cfg(feature = "alloc")] use alloc::{vec, vec::Vec}; #[cfg(feature = "std")] use std::io; use super::{ BitCount, CheckablePrimitive, Endianness, Integer, PhantomData, Primitive, SignedBitCount, SignedInteger, UnsignedInteger, VBRInteger, }; use core::convert::TryInto; /// An error returned if performing VBR read overflows #[derive(Copy, Clone, Debug)] pub(crate) struct VariableWidthOverflow; impl core::fmt::Display for VariableWidthOverflow { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { "variable bit rate overflowed".fmt(f) } } impl core::error::Error for VariableWidthOverflow {} impl From for io::Error { fn from(VariableWidthOverflow: VariableWidthOverflow) -> Self { io::Error::new( #[cfg(feature = "std")] { io::ErrorKind::StorageFull }, #[cfg(not(feature = "std"))] { io::ErrorKind::Other }, "variable bit rate overflow", ) } } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b1000_1110]; /// let mut r = BitReader::endian(bytes, BigEndian); /// 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(), false); /// assert!(r.read_bit().is_err()); // no more bits to read /// ``` /// /// ``` /// use bitstream_io::{BitReader, BitRead, LittleEndian}; /// /// let bytes: &[u8] = &[0b1000_1110]; /// let mut r = BitReader::endian(bytes, LittleEndian); /// 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(), false); /// assert_eq!(r.read_bit().unwrap(), false); /// assert_eq!(r.read_bit().unwrap(), false); /// assert_eq!(r.read_bit().unwrap(), true); /// assert!(r.read_bit().is_err()); // no more bits to read /// ``` fn read_bit(&mut self) -> io::Result { self.read_unsigned::<1, u8>().map(|b| b == 1) } /// Reads a signed or 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. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b0001_1111, 0b1011_11_00]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // reading unsigned value is ok /// assert_eq!(r.read::<4, u8>().unwrap(), 1); /// // reading signed value is also ok /// assert_eq!(r.read::<4, i8>().unwrap(), -1); /// // reading an array of bits is ok too /// assert_eq!(r.read::<1, [bool; 4]>().unwrap(), [true, false, true, true]); /// // reading an array of any Integer type is ok /// assert_eq!(r.read::<2, [u8; 2]>().unwrap(), [0b11, 0b00]); /// // reading more bytes than we have is an error /// assert!(r.read::<4, u8>().is_err()); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b0001_1111, 0, 0]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // reading 9 bits to a u8 is a compile-time error /// r.read::<9, u8>(); /// ``` #[inline] fn read(&mut self) -> io::Result where I: Integer, { I::read::(self) } /// Reads a signed or unsigned value from the stream with /// the given variable 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. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// let bytes: &[u8] = &[0b0001_1111]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // reading unsigned value is ok /// assert_eq!(r.read_var::(4).unwrap(), 1); /// // reading signed value is also ok /// assert_eq!(r.read_var::(4).unwrap(), -1); /// // reading more bytes than we have is an error /// assert!(r.read_var::(4).is_err()); /// ``` /// /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// let bytes: &[u8] = &[0, 0, 0, 0, 0]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // reading 9 bits to a u8 is a runtime error /// // no matter how much data is left /// assert!(r.read_var::(9).is_err()); /// ``` #[inline] fn read_var(&mut self, bits: u32) -> io::Result where I: Integer + Sized, { I::read_var(self, BitCount::unknown(bits)) } /// Given a desired maximum value for a bit count, /// reads the necessary bits to fill up to that amount. /// /// For example, if the maximum bit count is 15 - or `0b1111` - /// reads a 4-bit unsigned value from the stream and returns a [`BitCount`] /// which can be used in subsequent reads. /// /// Note that `MAX` must be greater than 0, and `MAX + 1` must be /// an exact power of two. /// /// # Errors /// /// Passes along an I/O error from the underlying stream. /// /// # Examples /// /// ``` /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// /// let bytes: &[u8] = &[0b100_11110]; /// let mut r = BitReader::endian(bytes, BigEndian); /// let count = r.read::<3, u32>().unwrap(); /// assert_eq!(count, 4); // reads 0b100 - or 4 /// // may need to verify count is not larger than u8 at runtime /// assert_eq!(r.read_var::(count).unwrap(), 0b1111); /// ``` /// /// ``` /// use bitstream_io::{BigEndian, BitReader, BitRead, BitCount}; /// /// let bytes: &[u8] = &[0b100_11110]; /// let mut r = BitReader::endian(bytes, BigEndian); /// let count = r.read_count::<0b111>().unwrap(); /// assert_eq!(count, BitCount::new::<4>()); // reads 0b100 - or 4 /// // maximum size of bit count is known to be 7 at compile-time, /// // so no runtime check needed to know 7 bits is not larger than a u8 /// assert_eq!(r.read_counted::<0b111, u8>(count).unwrap(), 0b1111); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// /// let bytes: &[u8] = &[0b100_11110]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // maximum bit count is 6 (0b110), so we need to read 3 bits /// // but no idea what to do if a value of 7 (0b111) is read, /// // so this does not compile at all /// let count = r.read_count::<0b110>(); /// ``` fn read_count(&mut self) -> io::Result> { const { assert!(MAX > 0, "MAX value must be > 0"); assert!( MAX == u32::MAX || (MAX + 1).is_power_of_two(), "MAX should fill some whole number of bits ('0b111', '0b1111', etc.)" ) } self.read_unsigned_var(if MAX < u32::MAX { (MAX + 1).ilog2() } else { 32 }) .map(|bits| BitCount { bits }) } /// Reads a signed or 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. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian, BitCount}; /// /// let bytes: &[u8] = &[0b1111_0000]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // reading 4 bits with a maximum of 4 will fit into a u8 /// // so no runtime check needed /// assert_eq!(r.read_counted::<4, u8>(BitCount::new::<4>()).unwrap(), 0b1111); /// // reading 4 bits with a maximum of 64 might not fit into a u8 /// // so we need to verify this at runtime /// assert_eq!(r.read_counted::<64, u8>(BitCount::new::<4>()).unwrap(), 0b0000); /// ``` #[inline(always)] fn read_counted(&mut self, bits: BitCount) -> io::Result where I: Integer + Sized, { I::read_var(self, bits) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data: &[u8] = &[0b1_01_10111]; /// let mut reader = BitReader::endian(data, BigEndian); /// assert_eq!(reader.read_unsigned::<1, u8>().unwrap(), 0b1); /// assert_eq!(reader.read_unsigned::<2, u8>().unwrap(), 0b01); /// assert_eq!(reader.read_unsigned::<5, u8>().unwrap(), 0b10111); /// ``` /// /// ``` /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data: &[u8] = &[0b10110_11_1]; /// let mut reader = BitReader::endian(data, LittleEndian); /// assert_eq!(reader.read_unsigned::<1, u8>().unwrap(), 0b1); /// assert_eq!(reader.read_unsigned::<2, u8>().unwrap(), 0b11); /// assert_eq!(reader.read_unsigned::<5, u8>().unwrap(), 0b10110); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data: &[u8] = &[0, 0, 0, 0, 0]; /// let mut reader = BitReader::endian(data, BigEndian); /// // doesn't compile at all /// reader.read_unsigned::<9, u8>(); // can't read 9 bits to u8 /// ``` fn read_unsigned(&mut self) -> io::Result where U: UnsignedInteger, { self.read_unsigned_var(BITS) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data: &[u8] = &[0b1_01_10111]; /// let mut reader = BitReader::endian(data, BigEndian); /// assert_eq!(reader.read_unsigned_var::(1).unwrap(), 0b1); /// assert_eq!(reader.read_unsigned_var::(2).unwrap(), 0b01); /// assert_eq!(reader.read_unsigned_var::(5).unwrap(), 0b10111); /// ``` /// /// ``` /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data: &[u8] = &[0b10110_11_1]; /// let mut reader = BitReader::endian(data, LittleEndian); /// assert_eq!(reader.read_unsigned_var::(1).unwrap(), 0b1); /// assert_eq!(reader.read_unsigned_var::(2).unwrap(), 0b11); /// assert_eq!(reader.read_unsigned_var::(5).unwrap(), 0b10110); /// ``` /// /// ``` /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data: &[u8] = &[0, 0, 0, 0, 0]; /// let mut reader = BitReader::endian(data, BigEndian); /// assert!(reader.read_unsigned_var::(9).is_err()); // can't read 9 bits to u8 /// assert!(reader.read_unsigned_var::(17).is_err()); // can't read 17 bits to u16 /// assert!(reader.read_unsigned_var::(33).is_err()); // can't read 33 bits to u32 /// assert!(reader.read_unsigned_var::(65).is_err()); // can't read 65 bits to u64 /// ``` #[inline(always)] fn read_unsigned_var(&mut self, bits: u32) -> io::Result where U: UnsignedInteger, { self.read_unsigned_counted(BitCount::unknown(bits)) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian, BitCount}; /// /// let bytes: &[u8] = &[0b1111_0000]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // reading 4 bits with a maximum of 4 will fit into a u8 /// // so no runtime check needed /// assert_eq!(r.read_unsigned_counted::<4, u8>(BitCount::new::<4>()).unwrap(), 0b1111); /// // reading 4 bits with a maximum of 64 might not fit into a u8 /// // so we need to verify this at runtime /// assert_eq!(r.read_unsigned_counted::<64, u8>(BitCount::new::<4>()).unwrap(), 0b0000); /// ``` fn read_unsigned_counted(&mut self, bits: BitCount) -> io::Result where U: UnsignedInteger; /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// /// let data: &[u8] = &[0b1011_0111]; /// let mut reader = BitReader::endian(data, BigEndian); /// assert_eq!(reader.read_signed::<4, i8>().unwrap(), -5); /// assert_eq!(reader.read_signed::<4, i8>().unwrap(), 7); /// assert!(reader.read_signed::<4, i8>().is_err()); /// ``` /// /// ``` /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// /// let data: &[u8] = &[0b1011_0111]; /// let mut reader = BitReader::endian(data, LittleEndian); /// assert_eq!(reader.read_signed::<4, i8>().unwrap(), 7); /// assert_eq!(reader.read_signed::<4, i8>().unwrap(), -5); /// assert!(reader.read_signed::<4, i8>().is_err()); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// /// let data: &[u8] = &[0, 0, 0, 0, 0]; /// let mut reader = BitReader::endian(data, LittleEndian); /// // reading 9 bits to an i8 is a compile-time error /// reader.read_signed::<9, i8>(); /// ``` fn read_signed(&mut self) -> io::Result where S: SignedInteger, { self.read_signed_var(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. /// /// # Examples /// ``` /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data: &[u8] = &[0b1011_0111]; /// let mut reader = BitReader::endian(data, BigEndian); /// assert_eq!(reader.read_signed_var::(4).unwrap(), -5); /// assert_eq!(reader.read_signed_var::(4).unwrap(), 7); /// ``` /// /// ``` /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data: &[u8] = &[0b1011_0111]; /// let mut reader = BitReader::endian(data, LittleEndian); /// assert_eq!(reader.read_signed_var::(4).unwrap(), 7); /// assert_eq!(reader.read_signed_var::(4).unwrap(), -5); /// ``` /// /// ``` /// use std::io::Read; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; /// let mut r = BitReader::endian(data, BigEndian); /// assert!(r.read_signed_var::(9).is_err()); // can't read 9 bits to i8 /// assert!(r.read_signed_var::(17).is_err()); // can't read 17 bits to i16 /// assert!(r.read_signed_var::(33).is_err()); // can't read 33 bits to i32 /// assert!(r.read_signed_var::(65).is_err()); // can't read 65 bits to i64 /// ``` fn read_signed_var(&mut self, bits: u32) -> io::Result where S: SignedInteger, { self.read_signed_counted(BitCount::unknown(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. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian, BitCount}; /// /// let bytes: &[u8] = &[0b0001_1111]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // reading 4 bits with a maximum of 4 will fit into an i8 /// // so no runtime check needed /// assert_eq!(r.read_signed_counted::<4, i8>(BitCount::new::<4>()).unwrap(), 1); /// // reading 4 bits with a maximum of 64 might not fit into an i8 /// // so we need to verify this at runtime /// assert_eq!(r.read_signed_counted::<64, i8>(BitCount::new::<4>()).unwrap(), -1); /// ``` fn read_signed_counted( &mut self, bits: impl TryInto>, ) -> io::Result where S: SignedInteger; /// Reads the given constant value from the stream with the /// given number of bits. /// /// Due to current limitations of constant paramters, /// this is limited to `u32` values. /// /// If the constant read from the stream doesn't match the expected /// value, returns the generated error from the closure. /// /// # Errors /// /// Passes along any I/O error from the underlying stream, /// converted to the mismatch error. Returns the generated /// error if the read value doesn't match the expected constant. /// /// # Examples /// /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// enum Error { /// Mismatch, /// Io, /// } /// /// impl From for Error { /// fn from(_err: std::io::Error) -> Self { /// Self::Io /// } /// } /// /// let data: &[u8] = &[0b1000_1011, 0b0000_0001]; /// let mut r = BitReader::endian(data, BigEndian); /// assert!(r.read_const::<4, 0b1000, _>(Error::Mismatch).is_ok()); /// assert!(r.read_const::<4, 0b1011, _>(Error::Mismatch).is_ok()); /// // 0b1000 doesn't match 0b0000 /// assert!(matches!(r.read_const::<4, 0b1000, _>(Error::Mismatch), Err(Error::Mismatch))); /// // 0b1011 doesn't match 0b0001 /// assert!(matches!(r.read_const::<4, 0b1011, _>(Error::Mismatch), Err(Error::Mismatch))); /// // run out of bits to check /// assert!(matches!(r.read_const::<4, 0b0000, _>(Error::Mismatch), Err(Error::Io))); /// ``` #[inline] fn read_const(&mut self, err: E) -> Result<(), E> where E: From, { use super::Numeric; const { assert!( BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)), "excessive value for bits read" ); } (self.read::()? == VALUE) .then_some(()) .ok_or(err) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0x12, 0x34, 0x56, 0x78]; /// let mut r = BitReader::endian(bytes, BigEndian); /// assert_eq!(r.read_to::().unwrap(), 0x12_34_56_78); /// ``` /// /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0x12, 0x34, 0x56, 0x78]; /// let mut r = BitReader::endian(bytes, BigEndian); /// assert_eq!(r.read_to::<[u8; 4]>().unwrap(), [0x12, 0x34, 0x56, 0x78]); /// ``` 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. /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian, LittleEndian}; /// /// let bytes: &[u8] = &[0x12, 0x34, 0x56, 0x78]; /// let mut r = BitReader::endian(bytes, BigEndian); /// assert_eq!(r.read_as_to::().unwrap(), 0x78_56_34_12); /// ``` 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. /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b1_00000_10]; /// let mut r = BitReader::endian(bytes, BigEndian); /// assert_eq!(r.read_bit().unwrap(), true); /// assert!(r.skip(5).is_ok()); /// assert_eq!(r.read_bit().unwrap(), true); /// assert_eq!(r.read_bit().unwrap(), false); /// assert!(r.read_bit().is_err()); /// ``` fn skip(&mut self, bits: u32) -> io::Result<()> { (0..bits).try_for_each(|_| self.read_bit().map(|_| ())) } /// 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. /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03, 0x04]; /// let mut r = BitReader::endian(bytes, BigEndian); /// let mut buf = [0; 3]; /// assert_eq!(r.read::<8, u8>().unwrap(), 0x00); /// assert!(r.read_bytes(&mut buf).is_ok()); /// assert_eq!(&buf, &[0x01, 0x02, 0x03]); /// assert_eq!(r.read::<8, u8>().unwrap(), 0x04); /// ``` fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { for b in buf.iter_mut() { *b = self.read_unsigned::<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. /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0x00, 0x01, 0x02, 0x03, 0x04]; /// let mut r = BitReader::endian(bytes, BigEndian); /// let mut buf = [0; 3]; /// assert_eq!(r.read::<8, u8>().unwrap(), 0x00); /// assert_eq!(r.read_to_vec(3).unwrap().as_slice(), &[0x01, 0x02, 0x03]); /// assert_eq!(r.read::<8, u8>().unwrap(), 0x04); /// ``` #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] fn read_to_vec(&mut self, bytes: usize) -> io::Result> { read_to_vec(|buf| self.read_bytes(buf), bytes) } /// Counts the number of bits in the stream until `STOP_BIT` /// and returns the amount read. /// `STOP_BIT` must be 0 or 1. /// 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. /// May panic if the number of bits exceeds `u32`. /// /// # Examples /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b0_10_11111, 0b10_000000]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // read 1 bits until stop bit of 0, big-endian order /// assert_eq!(r.read_unary::<0>().unwrap(), 0); /// assert_eq!(r.read_unary::<0>().unwrap(), 1); /// assert_eq!(r.read_unary::<0>().unwrap(), 6); /// ``` /// /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b1_01_00000, 0b01_000000]; /// let mut r = BitReader::endian(bytes, BigEndian); /// // read 0 bits until stop bit of 1, big-endian order /// assert_eq!(r.read_unary::<1>().unwrap(), 0); /// assert_eq!(r.read_unary::<1>().unwrap(), 1); /// assert_eq!(r.read_unary::<1>().unwrap(), 6); /// ``` /// /// ``` /// use bitstream_io::{BitReader, BitRead, LittleEndian}; /// /// let bytes: &[u8] = &[0b11111_01_0, 0b000000_01]; /// let mut r = BitReader::endian(bytes, LittleEndian); /// // read 1 bits until stop bit of 0, little-endian order /// assert_eq!(r.read_unary::<0>().unwrap(), 0); /// assert_eq!(r.read_unary::<0>().unwrap(), 1); /// assert_eq!(r.read_unary::<0>().unwrap(), 6); /// ``` /// /// ``` /// use bitstream_io::{BitReader, BitRead, LittleEndian}; /// /// let bytes: &[u8] = &[0b00000_10_1, 0b111111_10]; /// let mut r = BitReader::endian(bytes, LittleEndian); /// // read 0 bits until stop bit of 1, little-endian order /// assert_eq!(r.read_unary::<1>().unwrap(), 0); /// assert_eq!(r.read_unary::<1>().unwrap(), 1); /// assert_eq!(r.read_unary::<1>().unwrap(), 6); /// ``` fn read_unary(&mut self) -> io::Result { const { assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); } // a simple implementation which works anywhere let mut unary = 0; while self.read::<1, u8>()? != STOP_BIT { unary += 1; } Ok(unary) } /// Reads to a checked value that is known to fit a given number of bits /// /// # Example /// ``` /// use bitstream_io::{ /// BitRead, BitReader, BigEndian, Checked, CheckedUnsigned, CheckedSigned, /// BitCount, SignedBitCount, BitWrite, BitWriter, /// }; /// /// let data: &[u8] = &[0b1001_1111]; /// let mut r = BitReader::endian(data, BigEndian); /// /// let bit_count = BitCount::<4>::new::<4>(); /// let checked_u8 = r.read_checked::>(bit_count).unwrap(); /// assert_eq!(checked_u8.into_value(), 0b1001); /// /// let bit_count = SignedBitCount::<4>::new::<4>(); /// let checked_i8 = r.read_checked::>(bit_count).unwrap(); /// assert_eq!(checked_i8.into_value(), -1); /// /// // note that checked values already know their bit count /// // so none is required when writing them to a stream /// let mut w = BitWriter::endian(vec![], BigEndian); /// w.write_checked(checked_u8).unwrap(); /// w.write_checked(checked_i8).unwrap(); /// assert_eq!(w.into_writer().as_slice(), data); /// ``` #[inline] fn read_checked(&mut self, count: C::CountType) -> io::Result where C: CheckablePrimitive, { C::read(self, count) } /// 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) } /// Parses and returns complex type with owned context fn parse_using(&mut self, context: F::Context) -> Result { F::from_reader(self, context) } /// Returns true if the stream is aligned at a whole byte. /// /// # Example /// ``` /// use std::io::Read; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0]; /// let mut reader = BitReader::endian(data.as_slice(), 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); /// ``` fn byte_aligned(&self) -> bool; /// Throws away all unread bit values until the next whole byte. /// Does nothing if the stream is already aligned. /// /// # Example /// ``` /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data: &[u8] = &[0x00, 0xFF]; /// let mut reader = BitReader::endian(data, BigEndian); /// assert_eq!(reader.read::<4, u8>().unwrap(), 0); /// reader.byte_align(); /// assert_eq!(reader.read::<8, u8>().unwrap(), 0xFF); /// ``` fn byte_align(&mut self); /// 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. /// /// # Example /// /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian, define_huffman_tree, huffman::FromBits}; /// /// define_huffman_tree!(TreeName : char = ['a', ['b', ['c', 'd']]]); /// // 'a' is 0 /// // 'b' is 1 -> 0 /// // 'c' is 1 -> 1 -> 0 /// // 'd' is 1 -> 1 -> 1 /// /// let data: &[u8] = &[0b0_10_110_11, 0b1_0000000]; /// let mut r = BitReader::endian(data, BigEndian); /// assert_eq!(r.read_huffman::().unwrap(), 'a'); /// assert_eq!(r.read_huffman::().unwrap(), 'b'); /// assert_eq!(r.read_huffman::().unwrap(), 'c'); /// assert_eq!(r.read_huffman::().unwrap(), 'd'); /// ``` #[inline] fn read_huffman(&mut self) -> io::Result where T: crate::huffman::FromBits, { T::from_bits(|| self.read_bit()) } /// Reads a number using a variable using a variable width integer. /// This optimises the case when the number is small. /// /// The integer is mapped to an unsigned value using zigzag encoding. /// For an integer X: /// - if X >= 0 -> 2X /// - else -> -2X + 1 /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if the data read would overflow the size of the result /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b0111_1100, 0b1100_0001]; /// let mut r = BitReader::endian(bytes, BigEndian); /// assert_eq!(r.read_unsigned_vbr::<4, u32>().unwrap(), 7); /// assert_eq!(r.read_unsigned_vbr::<4, u32>().unwrap(), 100); /// ``` /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b1111_1111, 0b0011_1000, 0b1000_0100, 0b1000_1000, 0b1000_0000]; /// let mut r = BitReader::endian(bytes, BigEndian); /// assert_eq!(r.read_unsigned_vbr::<4, u8>().unwrap(), 255); // Tries to read <011><111><111> /// assert!(r.read_unsigned_vbr::<4, u8>().is_err()); // Tries to read a value of <100><000><000> /// assert!(r.read_unsigned_vbr::<4, u8>().is_err()); // Tries to read a value of <000><000><000><000> /// ``` fn read_unsigned_vbr(&mut self) -> io::Result { const { assert!(FIELD_SIZE >= 2 && FIELD_SIZE < U::BITS_SIZE) }; let payload_bits = FIELD_SIZE - 1; let mut value = U::ZERO; let mut shift = 0u32; loop { let (data, continuation) = self.read_unsigned::().map(|item| { ( item & ((U::ONE << payload_bits) - U::ONE), (item >> payload_bits) != U::ZERO, ) })?; let shifted = data << shift; value |= shifted; if !continuation { if (data << shift) >> shift == data { break Ok(value); } else { break Err(VariableWidthOverflow {}.into()); } } shift += payload_bits; if shift >= U::BITS_SIZE { break Err(VariableWidthOverflow {}.into()); } } } /// Reads a number using a variable using a variable width integer. /// This optimises the case when the number is small. /// /// The integer is mapped to an unsigned value using zigzag encoding. /// For an integer X: /// - if X >= 0 -> 2X /// - else -> -2X + 1 /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if the data read would overflow the size of the result /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b0110_1011, 0b1100_0001]; /// let mut r = BitReader::endian(bytes, BigEndian); /// assert_eq!(r.read_signed_vbr::<4, i32>().unwrap(), 3); /// assert_eq!(r.read_signed_vbr::<4, i32>().unwrap(), -50); /// ``` fn read_signed_vbr(&mut self) -> io::Result { self.read_unsigned_vbr::() .map(|zig_zag| { let shifted = zig_zag >> 1; let complimented = zig_zag & ::ONE; let neg = I::ZERO - complimented.as_non_negative(); shifted.as_non_negative() ^ neg }) } /// Reads a signed or unsigned variable width integer from the stream. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// Returns an error if the data read would overflow the size of the result /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// let bytes: &[u8] = &[0b0110_1011, 0b1100_0001]; /// let mut r = BitReader::endian(bytes, BigEndian); /// assert_eq!(r.read_vbr::<4, u32>().unwrap(), 6); /// assert_eq!(r.read_vbr::<4, i32>().unwrap(), -50); /// ``` #[inline] fn read_vbr(&mut self) -> io::Result { I::read_vbr::(self) } /// Creates a "by reference" adaptor for this `BitRead` /// /// The returned adapter also implements `BitRead` /// and will borrow the current reader. /// /// # Example /// ``` /// use bitstream_io::{BitReader, BitRead, BigEndian}; /// /// fn parse(r: R) { /// // perform some parsing /// } /// /// let data: &[u8] = &[0]; /// let mut reader = BitReader::endian(data, BigEndian); /// // performing parsing by reference /// parse(reader.by_ref()); /// // original owned reader still available /// assert_eq!(reader.read::<8, u8>().unwrap(), 0); /// ``` #[inline] fn by_ref(&mut self) -> &mut Self { self } } impl BitRead for &mut R { #[inline] fn read_bit(&mut self) -> io::Result { (**self).read_bit() } #[inline] fn read(&mut self) -> io::Result where I: Integer, { (**self).read::() } #[inline] fn read_var(&mut self, bits: u32) -> io::Result where I: Integer + Sized, { (**self).read_var(bits) } #[inline] fn read_count(&mut self) -> io::Result> { (**self).read_count::() } #[inline] fn read_counted(&mut self, bits: BitCount) -> io::Result where I: Integer + Sized, { (**self).read_counted::(bits) } #[inline] fn read_unsigned(&mut self) -> io::Result where U: UnsignedInteger, { (**self).read_unsigned::() } #[inline] fn read_unsigned_var(&mut self, bits: u32) -> io::Result where U: UnsignedInteger, { (**self).read_unsigned_var(bits) } #[inline] fn read_unsigned_counted(&mut self, bits: BitCount) -> io::Result where U: UnsignedInteger, { (**self).read_unsigned_counted::(bits) } #[inline] fn read_signed(&mut self) -> io::Result where S: SignedInteger, { (**self).read_signed::() } #[inline] fn read_signed_var(&mut self, bits: u32) -> io::Result where S: SignedInteger, { (**self).read_signed_var(bits) } #[inline] fn read_signed_counted( &mut self, bits: impl TryInto>, ) -> io::Result where S: SignedInteger, { (**self).read_signed_counted::(bits) } #[inline] fn read_to(&mut self) -> io::Result where V: Primitive, { (**self).read_to::() } #[inline] fn read_as_to(&mut self) -> io::Result where F: Endianness, V: Primitive, { (**self).read_as_to::() } #[inline] fn skip(&mut self, bits: u32) -> io::Result<()> { (**self).skip(bits) } #[inline] fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { (**self).read_bytes(buf) } #[inline] #[cfg(feature = "alloc")] fn read_to_vec(&mut self, bytes: usize) -> io::Result> { (**self).read_to_vec(bytes) } #[inline] fn read_unary(&mut self) -> io::Result { (**self).read_unary::() } #[inline] fn parse(&mut self) -> Result { (**self).parse::() } #[inline] fn parse_with<'a, F: FromBitStreamWith<'a>>( &mut self, context: &F::Context, ) -> Result { (**self).parse_with::(context) } #[inline] fn byte_aligned(&self) -> bool { (**self).byte_aligned() } #[inline] fn byte_align(&mut self) { (**self).byte_align() } #[inline] fn read_huffman(&mut self) -> io::Result where T: crate::huffman::FromBits, { (**self).read_huffman::() } } /// A compatibility trait for older code implementing [`BitRead`] /// /// This is a trait largely compatible with older code /// from the 2.X.X version, /// which one can use with a named import as needed. /// /// New code should prefer the regular [`BitRead`] trait. /// /// # Example /// ``` /// use bitstream_io::BitRead2 as BitRead; /// use bitstream_io::{BitReader, BigEndian}; /// let byte = &[0b1111_0000]; /// let mut reader = BitReader::endian(byte.as_slice(), BigEndian); /// assert_eq!(reader.read::(4).unwrap(), 0b1111); /// assert_eq!(reader.read_in::<4, u8>().unwrap(), 0b0000); /// ``` pub trait BitRead2 { /// 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 I: Integer + Sized; /// 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 I: Integer, { 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: SignedInteger; /// 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: SignedInteger, { self.read_signed(BITS) } /// 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. #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] fn read_to_vec(&mut self, bytes: usize) -> io::Result> { read_to_vec(|buf| self.read_bytes(buf), bytes) } /// 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 where Self: BitRead, { F::from_reader(self) } /// Parses and returns complex type with context fn parse_with<'a, F: FromBitStreamWith<'a>>( &mut self, context: &F::Context, ) -> Result where Self: BitRead, { 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); /// 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. #[inline] fn read_huffman(&mut self) -> io::Result where T: crate::huffman::FromBits, { T::from_bits(|| self.read_bit()) } } impl BitRead2 for R { #[inline(always)] fn read_bit(&mut self) -> io::Result { BitRead::read_bit(self) } #[inline(always)] fn read(&mut self, bits: u32) -> io::Result where I: Integer + Sized, { self.read_var(bits) } #[inline(always)] fn read_in(&mut self) -> io::Result where I: Integer, { BitRead::read::(self) } #[inline(always)] fn read_signed(&mut self, bits: u32) -> io::Result where S: SignedInteger, { self.read_signed_var(bits) } #[inline(always)] fn read_signed_in(&mut self) -> io::Result where S: SignedInteger, { BitRead::read_signed::(self) } #[inline(always)] fn read_to(&mut self) -> io::Result where V: Primitive, { BitRead::read_to::(self) } #[inline(always)] fn read_as_to(&mut self) -> io::Result where F: Endianness, V: Primitive, { BitRead::read_as_to::(self) } #[inline(always)] fn skip(&mut self, bits: u32) -> io::Result<()> { BitRead::skip(self, bits) } #[inline(always)] fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { BitRead::read_bytes(self, buf) } #[inline(always)] fn read_unary0(&mut self) -> io::Result { self.read_unary::<0>() } #[inline(always)] fn read_unary1(&mut self) -> io::Result { self.read_unary::<1>() } #[inline(always)] fn byte_aligned(&self) -> bool { BitRead::byte_aligned(self) } #[inline(always)] fn byte_align(&mut self) { BitRead::byte_align(self) } } /// 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 { // our underlying reader reader: R, // our partial byte value: u8, // the number of bits in our partial byte bits: u32, // a container for our endiannness phantom: PhantomData, } impl BitReader { /// Wraps a BitReader around something that implements `Read` pub fn new(reader: R) -> BitReader { BitReader { reader, value: 0, bits: 0, phantom: PhantomData, } } /// Wraps a BitReader around something that implements `Read` /// with the given endianness. pub fn endian(reader: R, _endian: E) -> BitReader { BitReader { reader, value: 0, bits: 0, phantom: PhantomData, } } /// Unwraps internal reader and disposes of BitReader. /// /// # Warning /// /// Any unread partial bits are discarded. #[inline] pub fn into_reader(self) -> R { self.reader } } impl BitReader { /// If stream is byte-aligned, provides mutable reference /// to internal reader. Otherwise returns `None` #[inline] pub fn reader(&mut self) -> Option<&mut R> { if BitRead::byte_aligned(self) { Some(&mut self.reader) } else { None } } /// Returns byte-aligned mutable reference to internal reader. /// /// Bytes aligns stream if it is not already aligned. #[inline] pub fn aligned_reader(&mut self) -> &mut R { BitRead::byte_align(self); &mut self.reader } /// 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) } } impl BitRead for BitReader { #[inline(always)] fn read_bit(&mut self) -> io::Result { let Self { value, bits, reader, .. } = self; E::pop_bit_refill(reader, value, bits) } #[inline(always)] fn read_unsigned_counted(&mut self, bits: BitCount) -> io::Result where U: UnsignedInteger, { let Self { value: queue_value, bits: queue_bits, reader, .. } = self; E::read_bits(reader, queue_value, queue_bits, bits) } #[inline] fn read_unsigned(&mut self) -> io::Result where U: UnsignedInteger, { let Self { value, bits, reader, .. } = self; E::read_bits_fixed::(reader, value, bits) } #[inline(always)] fn read_signed_counted( &mut self, bits: impl TryInto>, ) -> io::Result where S: SignedInteger, { E::read_signed_counted( self, bits.try_into().map_err(|_| { io::Error::new( io::ErrorKind::InvalidInput, "signed reads need at least 1 bit for sign", ) })?, ) } #[inline] fn read_signed(&mut self) -> io::Result where S: SignedInteger, { let count = const { assert!(BITS <= S::BITS_SIZE, "excessive bits for type read"); let count = BitCount::::new::().signed_count(); assert!(count.is_some(), "signed reads need at least 1 bit for sign"); count.unwrap() }; E::read_signed_counted(self, count) } #[inline] fn read_to(&mut self) -> io::Result where V: Primitive, { let mut buffer = V::buffer(); E::read_bytes::<8, _>( &mut self.reader, &mut self.value, self.bits, buffer.as_mut(), )?; Ok(E::bytes_to_primitive(buffer)) } #[inline] fn read_as_to(&mut self) -> io::Result where F: Endianness, V: Primitive, { let mut buffer = V::buffer(); F::read_bytes::<8, _>( &mut self.reader, &mut self.value, self.bits, buffer.as_mut(), )?; Ok(F::bytes_to_primitive(buffer)) } /// # Examples /// ``` /// use std::io::Read; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(data.as_slice(), BigEndian); /// assert!(reader.skip(3).is_ok()); /// assert_eq!(reader.read::<5, u8>().unwrap(), 0b10111); /// ``` /// /// ``` /// use std::io::Read; /// use bitstream_io::{LittleEndian, BitReader, BitRead}; /// let data = [0b10110111]; /// let mut reader = BitReader::endian(data.as_slice(), LittleEndian); /// assert!(reader.skip(3).is_ok()); /// assert_eq!(reader.read::<5, u8>().unwrap(), 0b10110); /// ``` fn skip(&mut self, mut bits: u32) -> io::Result<()> { if BitRead::byte_aligned(self) && bits % 8 == 0 { skip_aligned(self.reader.by_ref(), bits / 8) } else { loop { match bits { 0 => break Ok(()), bits @ 1..64 => break self.read_var(bits).map(|_: u64| ()), _ => { let _ = BitRead::read::<64, u64>(self)?; bits -= 64; } } } } } /// # Example /// ``` /// use std::io::Read; /// use bitstream_io::{BigEndian, BitReader, BitRead}; /// let data = b"foobar"; /// let mut reader = BitReader::endian(data.as_slice(), 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"); /// ``` #[inline] fn read_bytes(&mut self, buf: &mut [u8]) -> io::Result<()> { E::read_bytes::<1024, _>(&mut self.reader, &mut self.value, self.bits, buf) } fn read_unary(&mut self) -> io::Result { let Self { value, bits, reader, .. } = self; E::pop_unary::(reader, value, bits) } #[inline] fn byte_aligned(&self) -> bool { self.bits == 0 } #[inline] fn byte_align(&mut self) { self.value = 0; self.bits = 0; } } 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); BitRead::byte_align(self); self.reader.seek(io::SeekFrom::Start(bytes))?; BitRead::skip(self, 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] #[allow(clippy::seek_from_current)] pub fn position_in_bits(&mut self) -> io::Result { // core2 doesn't have `seek_from_current` let bytes = self.reader.seek(io::SeekFrom::Current(0))?; Ok(bytes * 8 - (self.bits as u64)) } } fn skip_aligned(reader: R, bytes: u32) -> io::Result<()> where R: io::Read, { fn skip_chunks(mut reader: R, mut bytes: usize) -> io::Result<()> where R: io::Read, { let mut buf = [0; SIZE]; while bytes > 0 { let to_read = bytes.min(SIZE); reader.read_exact(&mut buf[0..to_read])?; bytes -= to_read; } Ok(()) } match bytes { 0..256 => skip_chunks::<8, R>(reader, bytes as usize), 256..1024 => skip_chunks::<256, R>(reader, bytes as usize), 1024..4096 => skip_chunks::<1024, R>(reader, bytes as usize), _ => skip_chunks::<4096, R>(reader, bytes as usize), } } /// 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; /// use bitstream_io::{BigEndian, ByteReader, ByteRead}; /// let data = [0b00000000, 0b11111111]; /// let mut reader = ByteReader::endian(data.as_slice(), BigEndian); /// assert_eq!(reader.read::().unwrap(), 0b0000000011111111); /// ``` /// /// ``` /// use std::io::Read; /// use bitstream_io::{LittleEndian, ByteReader, ByteRead}; /// let data = [0b00000000, 0b11111111]; /// let mut reader = ByteReader::endian(data.as_slice(), 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; /// use bitstream_io::{BigEndian, ByteReader, ByteRead, LittleEndian}; /// let data = [0b00000000, 0b11111111]; /// let mut reader = ByteReader::endian(data.as_slice(), BigEndian); /// assert_eq!(reader.read_as::().unwrap(), 0b1111111100000000); /// ``` /// /// ``` /// use std::io::Read; /// use bitstream_io::{BigEndian, ByteReader, ByteRead, LittleEndian}; /// let data = [0b00000000, 0b11111111]; /// let mut reader = ByteReader::endian(data.as_slice(), 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. #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] fn read_to_vec(&mut self, bytes: usize) -> io::Result> { read_to_vec(|buf| self.read_bytes(buf), bytes) } /// 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) } /// Parses and returns complex type with owned context fn parse_using(&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, { let mut buf = V::buffer(); self.read_bytes(buf.as_mut())?; Ok(E::bytes_to_primitive(buf)) } #[inline] fn read_as(&mut self) -> Result where F: Endianness, V: Primitive, { let mut buf = V::buffer(); self.read_bytes(buf.as_mut())?; Ok(F::bytes_to_primitive(buf)) } #[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 } } impl io::Seek for ByteReader { fn seek(&mut self, pos: io::SeekFrom) -> io::Result { self.reader().seek(pos) } } /// Implemented by complex types that don't require any additional context /// to parse themselves from a reader. Analogous to [`std::str::FromStr`]. /// /// # Example /// ``` /// use std::io::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(b"\x04\x00\x00\x7A".as_slice(), 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::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, u16>()? != 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, u8>()?; /// /// let sample_rate_bits = r.read::<4, u8>()?; /// /// let channel_assignment = r.read::<4, u8>()?; /// /// let sample_size = match r.read::<3, u8>()? { /// 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, u32>()? + 1, /// 0b0111 => r.read::<16, u32>()? + 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, u32>()? * 1000, /// 0b1101 => r.read::<16, u32>()?, /// 0b1110 => r.read::<16, u32>()? * 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(b"\xFF\xF8\xC9\x18\x00\xC2".as_slice(), 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::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_var::(ctx.params.size_len as u32)?; /// let index = match ctx.base_index { /// None => r.read_var::(ctx.params.index_len as u32)?, /// Some(base_index) => { /// base_index /// + 1 /// + r.read_var::(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(b"\xFF\xEA\xFF\x10".as_slice(), 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 consume some immutable context /// to parse themselves from a reader. /// /// Like [`FromBitStreamWith`], but consumes its context /// rather than taking a shared reference to it. pub trait FromBitStreamUsing { /// Some context to consume when parsing type Context; /// 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; } /// Implemented by complex types that consume some additional context /// to parse themselves from a reader. /// /// Like [`FromByteStreamWith`], but consumes the context. pub trait FromByteStreamUsing { /// Some context to use when parsing type Context; /// 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; } #[cfg(feature = "alloc")] fn read_to_vec( mut read: impl FnMut(&mut [u8]) -> io::Result<()>, bytes: usize, ) -> io::Result> { const MAX_CHUNK: usize = 4096; match bytes { 0 => Ok(Vec::new()), bytes if bytes <= MAX_CHUNK => { let mut buf = vec![0; bytes]; read(&mut buf)?; Ok(buf) } mut bytes => { let mut whole = Vec::with_capacity(MAX_CHUNK); let mut chunk: [u8; MAX_CHUNK] = [0; MAX_CHUNK]; while bytes > 0 { let chunk_size = bytes.min(MAX_CHUNK); let chunk = &mut chunk[0..chunk_size]; read(chunk)?; whole.extend_from_slice(chunk); bytes -= chunk_size; } Ok(whole) } } } bitstream-io-4.9.0/src/write.rs000064400000000000000000002642741046102023000145430ustar 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. #![warn(missing_docs)] #[cfg(not(feature = "std"))] use core2::io; #[cfg(feature = "alloc")] use alloc::vec::Vec; use core::{ convert::{From, TryFrom, TryInto}, fmt, }; #[cfg(feature = "std")] use std::io; use super::{ BitCount, Checkable, CheckedSigned, CheckedUnsigned, Endianness, Integer, Numeric, PhantomData, Primitive, SignedBitCount, SignedInteger, UnsignedInteger, VBRInteger, }; #[cfg(feature = "alloc")] pub use bit_recorder::BitRecorder; /// 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 { // our underlying writer writer: W, // our partial byte value: u8, // the number of bits in our partial byte bits: u32, // a container for our endianness phantom: PhantomData, } impl BitWriter { /// Wraps a BitWriter around something that implements `Write` pub fn new(writer: W) -> BitWriter { BitWriter { writer, value: 0, bits: 0, phantom: PhantomData, } } /// Wraps a BitWriter around something that implements `Write` /// with the given endianness. pub fn endian(writer: W, _endian: E) -> BitWriter { BitWriter { writer, value: 0, bits: 0, phantom: PhantomData, } } /// 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 BitWrite::byte_aligned(self) { Some(&mut self.writer) } else { None } } /// Returns byte-aligned mutable reference to internal writer. /// /// Bytes aligns stream if it is not already aligned. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. #[inline] pub fn aligned_writer(&mut self) -> io::Result<&mut W> { BitWrite::byte_align(self)?; Ok(&mut self.writer) } /// 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) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// 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(false).is_ok()); /// assert_eq!(w.into_writer(), &[0b1000_1110]); /// ``` /// /// ``` /// use bitstream_io::{BitWriter, BitWrite, LittleEndian}; /// /// let mut w = BitWriter::endian(vec![], LittleEndian); /// 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(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_eq!(w.into_writer(), &[0b1000_1110]); /// ``` #[inline] fn write_bit(&mut self, bit: bool) -> io::Result<()> { self.write_unsigned::<1, u8>(u8::from(bit)) } /// Writes a signed or 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. /// /// # Examples /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writing unsigned value is ok /// assert!(w.write::<4, u8>(1).is_ok()); /// // writing signed value is ok /// assert!(w.write::<4, i8>(-1).is_ok()); /// // writing an array of bits is ok too /// assert!(w.write::<1, [bool; 4]>([true, false, true, true]).is_ok()); /// // writing an array of any Integer type is ok /// assert!(w.write::<2, [u8; 2]>([0b11, 0b00]).is_ok()); /// // trying to write a value larger than 4 bits in 4 bits is an error /// assert!(w.write::<4, u8>(u8::MAX).is_err()); /// /// assert_eq!(w.into_writer(), &[0b0001_1111, 0b1011_11_00]); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // trying to write 9 bits from a u8 is a compile-time error /// w.write::<9, u8>(1); /// ``` #[inline] fn write(&mut self, value: I) -> io::Result<()> where I: Integer, { Integer::write::(value, self) } /// Writes a signed or 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. /// /// # Examples /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writing unsigned value is ok /// assert!(w.write_var::(4, 1).is_ok()); /// // writing signed value is also ok /// assert!(w.write_var::(4, -1).is_ok()); /// assert_eq!(w.into_writer(), &[0b0001_1111]); /// ``` /// /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writing a value larger than 4 bits in 4 bits is a runtime error /// assert!(w.write_var::(4, u8::MAX).is_err()); /// // writing 9 bits from a u8 is also a runtime error /// assert!(w.write_var::(9, 0).is_err()); /// ``` #[inline] fn write_var(&mut self, bits: u32, value: I) -> io::Result<()> where I: Integer, { self.write_counted(BitCount::unknown(bits), value) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], BigEndian); /// writer.write_unsigned::<1, u8>(0b1).unwrap(); /// writer.write_unsigned::<2, u8>(0b01).unwrap(); /// writer.write_unsigned::<5, u8>(0b10111).unwrap(); /// assert_eq!(writer.into_writer(), [0b1_01_10111]); /// ``` /// /// ``` /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], LittleEndian); /// writer.write_unsigned::<1, u8>(0b1).unwrap(); /// writer.write_unsigned::<2, u8>(0b11).unwrap(); /// writer.write_unsigned::<5, u8>(0b10110).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110_11_1]); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], BigEndian); /// // trying to write 9 bits from a u8 is a compile-time error /// writer.write_unsigned::<9, u8>(1); /// ``` /// /// ``` /// use std::io::{Write, sink}; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// /// let mut w = BitWriter::endian(sink(), BigEndian); /// assert!(w.write_unsigned::<1, u8>(2).is_err()); // can't write 2 in 1 bit /// assert!(w.write_unsigned::<2, u8>(4).is_err()); // can't write 4 in 2 bits /// assert!(w.write_unsigned::<3, u8>(8).is_err()); // can't write 8 in 3 bits /// assert!(w.write_unsigned::<4, u8>(16).is_err()); // can't write 16 in 4 bits /// ``` #[inline] fn write_unsigned(&mut self, value: U) -> io::Result<()> where U: UnsignedInteger, { self.write_unsigned_var(BITS, value) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], BigEndian); /// writer.write_unsigned_var::(1, 0b1).unwrap(); /// writer.write_unsigned_var::(2, 0b01).unwrap(); /// writer.write_unsigned_var::(5, 0b10111).unwrap(); /// assert_eq!(writer.into_writer(), [0b1_01_10111]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], LittleEndian); /// writer.write_unsigned_var::(1, 0b1).unwrap(); /// writer.write_unsigned_var::(2, 0b11).unwrap(); /// writer.write_unsigned_var::(5, 0b10110).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110_11_1]); /// ``` /// /// ``` /// use std::io::{Write, sink}; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// /// let mut w = BitWriter::endian(sink(), BigEndian); /// assert!(w.write_unsigned_var::(9, 0).is_err()); // can't write u8 in 9 bits /// assert!(w.write_unsigned_var::(17, 0).is_err()); // can't write u16 in 17 bits /// assert!(w.write_unsigned_var::(33, 0).is_err()); // can't write u32 in 33 bits /// assert!(w.write_unsigned_var::(65, 0).is_err()); // can't write u64 in 65 bits /// assert!(w.write_unsigned_var::(1, 2).is_err()); // can't write 2 in 1 bit /// assert!(w.write_unsigned_var::(2, 4).is_err()); // can't write 4 in 2 bits /// assert!(w.write_unsigned_var::(3, 8).is_err()); // can't write 8 in 3 bits /// assert!(w.write_unsigned_var::(4, 16).is_err()); // can't write 16 in 4 bits /// ``` fn write_unsigned_var(&mut self, bits: u32, value: U) -> io::Result<()> where U: UnsignedInteger, { self.write_unsigned_counted(BitCount::unknown(bits), value) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], BigEndian); /// writer.write_signed::<4, i8>(-5).unwrap(); /// writer.write_signed::<4, i8>(7).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], LittleEndian); /// writer.write_signed::<4, i8>(7).unwrap(); /// writer.write_signed::<4, i8>(-5).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], LittleEndian); /// // writing a value too large for 4 bits in 4 bits is a runtime error /// assert!(writer.write_signed::<4, i8>(i8::MAX).is_err()); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], LittleEndian); /// // writing 9 bits from an i8 is a compile-time error /// assert!(writer.write_signed::<9, i8>(1).is_err()); /// ``` fn write_signed(&mut self, value: S) -> io::Result<()> where S: SignedInteger, { self.write_signed_var(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. /// /// # Examples /// ``` /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], BigEndian); /// writer.write_signed_var(4, -5).unwrap(); /// writer.write_signed_var(4, 7).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` /// /// ``` /// use bitstream_io::{LittleEndian, BitWriter, BitWrite}; /// /// let mut writer = BitWriter::endian(vec![], LittleEndian); /// writer.write_signed_var(4, 7).unwrap(); /// writer.write_signed_var(4, -5).unwrap(); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` #[inline(always)] fn write_signed_var(&mut self, bits: u32, value: S) -> io::Result<()> where S: SignedInteger, { self.write_signed_counted(BitCount::unknown(bits), value) } /// Writes the given bit count to the stream /// with the necessary maximum number of bits. /// /// For example, if the maximum bit count is 15 - or `0b1111` - /// writes the bit count to the stream as a 4-bit unsigned value /// which can be used in subsequent writes. /// /// Note that `MAX` must be greater than 0. /// Unlike the bit reader, the bit count need not be an exact /// power of two when writing. Any bits higher than the /// bit count can reach are simply left 0. /// /// # Errors /// /// Passes along an I/O error from the underlying stream. /// /// ``` /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// let count = 4; /// w.write::<3, u32>(count).unwrap(); /// // may need to verify count is not larger than u8 at runtime /// w.write_var::(count, 0b1111).unwrap(); /// w.byte_align().unwrap(); /// assert_eq!(w.into_writer(), &[0b100_11110]); /// ``` /// /// ``` /// use bitstream_io::{BigEndian, BitWriter, BitWrite, BitCount}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // a bit count of 4, with a maximum of 7 (0b111) /// let count: BitCount<0b111> = BitCount::new::<4>(); /// w.write_count(count).unwrap(); /// // maximum size of count is known to be 7 bits at compile-time /// // so no need to check that 7 bits is larger than a u8 at runtime /// w.write_counted::<0b111, u8>(count, 0b1111).unwrap(); /// w.byte_align().unwrap(); /// assert_eq!(w.into_writer(), &[0b100_11110]); /// ``` /// /// ``` /// use bitstream_io::{BigEndian, BitWriter, BitWrite, BitCount}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // a bit count of 4, with a maximum of 6 (0b110) /// let count: BitCount<0b110> = BitCount::new::<4>(); /// w.write_count(count).unwrap(); /// w.write_counted::<0b110, u8>(count, 0b1111).unwrap(); /// w.byte_align().unwrap(); /// // bit count is written in 3 bits /// // while actual value is written in 4 bits /// assert_eq!(w.into_writer(), &[0b100_11110]); /// ``` fn write_count(&mut self, BitCount { bits }: BitCount) -> io::Result<()> { const { assert!(MAX > 0, "MAX value must be > 0"); } self.write_unsigned_var( if MAX == u32::MAX { 32 } else if (MAX + 1).is_power_of_two() { (MAX + 1).ilog2() } else { (MAX + 1).ilog2() + 1 }, bits, ) } /// Writes a signed or unsigned 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 value is too large /// to fit the given number of bits. /// /// # Examples /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian, BitCount}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writing 4 bits with a maximum of 8 will fit into a u8 /// // so we only need check the value fits into 4 bits /// assert!(w.write_counted::<4, u8>(BitCount::new::<4>(), 0b1111).is_ok()); /// assert!(w.write_counted::<4, u8>(BitCount::new::<4>(), 0b1111 + 1).is_err()); /// // writing 4 bits with a maximum of 64 might not fit into a u8 /// // so need to verify this at runtime /// assert!(w.write_counted::<64, u8>(BitCount::new::<4>(), 0b0000).is_ok()); /// assert_eq!(w.into_writer(), &[0b1111_0000]); /// ``` fn write_counted(&mut self, bits: BitCount, value: I) -> io::Result<()> where I: Integer + Sized, { I::write_var::(value, self, bits) } /// Writes a 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 value is too large /// to fit the given number of bits. /// /// # Examples /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian, BitCount}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writing 4 bits with a maximum of 8 will fit into a u8 /// // so we only need check the value fits into 4 bits /// assert!(w.write_unsigned_counted::<4, u8>(BitCount::new::<4>(), 0b1111).is_ok()); /// assert!(w.write_unsigned_counted::<4, u8>(BitCount::new::<4>(), 0b1111 + 1).is_err()); /// // writing 4 bits with a maximum of 64 might not fit into a u8 /// // so need to verify this at runtime /// assert!(w.write_unsigned_counted::<64, u8>(BitCount::new::<4>(), 0b0000).is_ok()); /// assert_eq!(w.into_writer(), &[0b1111_0000]); /// ``` fn write_unsigned_counted( &mut self, bits: BitCount, value: U, ) -> io::Result<()> where U: UnsignedInteger; /// Writes an unsigned 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 value is too large /// to fit the given number of bits. /// /// # Examples /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian, BitCount}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // writing 4 bits with a maximum of 8 will fit into an i8 /// // so we only need check the value fits into 4 bits /// assert!(w.write_signed_counted::<4, i8>(BitCount::new::<4>(), 0b0111).is_ok()); /// assert!(w.write_signed_counted::<4, i8>(BitCount::new::<4>(), 0b0111 + 1).is_err()); /// // writing 4 bits with a maximum of 64 might not fit into a i8 /// // so need to verify this at runtime /// assert!(w.write_signed_counted::<64, i8>(BitCount::new::<4>(), 0b0000).is_ok()); /// assert_eq!(w.into_writer(), &[0b0111_0000]); /// ``` fn write_signed_counted( &mut self, bits: impl TryInto>, value: S, ) -> io::Result<()> where S: SignedInteger; /// Writes the given constant value to the stream with /// the given number of bits. /// /// Due to current limitations of constant parameters, /// this is limited to `u32` values. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// A compile-time error occurs if the number of bits is larger /// than 32 or if the value is too large too fit the /// requested number of bits. /// /// # Examples /// /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// assert!(w.write_const::<4, 0b1000>().is_ok()); /// assert!(w.write_const::<4, 0b1011>().is_ok()); /// assert_eq!(w.into_writer(), &[0b1000_1011]); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // trying to write a 5 bit value in 4 bits is a compile-time error /// w.write_const::<4, 0b11111>(); /// ``` /// /// ```rust,compile_fail /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// // trying to write a 33 bit value is also a compile-time error /// w.write_const::<33, 1>(); /// ``` #[inline] fn write_const(&mut self) -> io::Result<()> { const { assert!( BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)), "excessive value for bits written" ); } self.write::(VALUE) } /// 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. /// /// # Examples /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// assert!(w.write_from::(0x12_34_56_78).is_ok()); /// assert_eq!(w.into_writer(), &[0x12, 0x34, 0x56, 0x78]); /// ``` /// /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// assert!(w.write_from::<[u8; 4]>([0x12, 0x34, 0x56, 0x78]).is_ok()); /// assert_eq!(w.into_writer(), &[0x12, 0x34, 0x56, 0x78]); /// ``` 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. /// /// # Examples /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian, LittleEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// assert!(w.write_as_from::(0x12_34_56_78).is_ok()); /// assert_eq!(w.into_writer(), &[0x78, 0x56, 0x34, 0x12]); /// ``` fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive; /// Pads the stream by writing 0 over the given number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// /// # Example /// /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// let mut w = BitWriter::endian(vec![], BigEndian); /// assert!(w.write_bit(true).is_ok()); /// assert!(w.pad(7).is_ok()); /// assert_eq!(w.into_writer(), &[0b1_0000000]); /// ``` fn pad(&mut self, mut bits: u32) -> io::Result<()> { loop { match bits { 0 => break Ok(()), bits @ 1..64 => break self.write_var(bits, 0u64), _ => { self.write::<64, u64>(0)?; bits -= 64; } } } } /// 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_var(8, 0x66u8).unwrap(); /// writer.write_var(8, 0x6Fu8).unwrap(); /// writer.write_var(8, 0x6Fu8).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_unsigned::<8, _>(*b)) } /// Writes `value` number of non `STOP_BIT` bits to the stream /// and then writes a `STOP_BIT`. This field is variably-sized. /// `STOP_BIT` must be 0 or 1. /// /// # 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_unary::<0>(0).unwrap(); /// writer.write_unary::<0>(3).unwrap(); /// writer.write_unary::<0>(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_unary::<0>(0).unwrap(); /// writer.write_unary::<0>(3).unwrap(); /// writer.write_unary::<0>(10).unwrap(); /// assert_eq!(writer.into_writer(), [0b11101110, 0b01111111]); /// ``` /// /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_unary::<1>(0).unwrap(); /// writer.write_unary::<1>(3).unwrap(); /// writer.write_unary::<1>(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_unary::<1>(0).unwrap(); /// writer.write_unary::<1>(3).unwrap(); /// writer.write_unary::<1>(10).unwrap(); /// assert_eq!(writer.into_writer(), [0b00010001, 0b10000000]); /// ``` fn write_unary(&mut self, mut value: u32) -> io::Result<()> { const { assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); } const MAX: BitCount<32> = BitCount::new::<32>(); match STOP_BIT { 0 => { while value > 0 { let to_write = MAX.min(value); self.write_checked(to_write.all::())?; value -= u32::from(to_write); } self.write_bit(false) } 1 => { while value > 0 { let to_write = MAX.min(value); self.write_checked(to_write.none::())?; value -= u32::from(to_write); } self.write_bit(true) } _ => unreachable!(), } } /// Writes checked value that is known to fit a given number of bits fn write_checked(&mut self, value: C) -> io::Result<()> { // a naive default implementation value.write(self) } /// 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) } /// Builds and writes complex type with owned context fn build_using( &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. /// /// # 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_var(1, 0u8).unwrap(); /// assert_eq!(writer.byte_aligned(), false); /// writer.write_var(7, 0u8).unwrap(); /// assert_eq!(writer.byte_aligned(), true); /// ``` 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_var(1, 0u8).unwrap(); /// writer.byte_align().unwrap(); /// writer.write_var(8, 0xFFu8).unwrap(); /// assert_eq!(writer.into_writer(), [0x00, 0xFF]); /// ``` fn byte_align(&mut self) -> io::Result<()> { while !BitWrite::byte_aligned(self) { self.write_bit(false)?; } Ok(()) } /// Given a symbol, writes its representation to the output stream as bits. /// Generates no output if the symbol isn't defined in the Huffman tree. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// /// # Example /// ``` /// use bitstream_io::{BigEndian, BitWriter, BitWrite}; /// use bitstream_io::define_huffman_tree; /// /// define_huffman_tree!(TreeName : char = ['a', ['b', ['c', 'd']]]); /// // 'a' is 0 /// // 'b' is 1 -> 0 /// // 'c' is 1 -> 1 -> 0 /// // 'd' is 1 -> 1 -> 1 /// /// let mut writer = BitWriter::endian(vec![], BigEndian); /// writer.write_huffman::('b').unwrap(); /// writer.write_huffman::('c').unwrap(); /// writer.write_huffman::('d').unwrap(); /// assert_eq!(writer.into_writer(), [0b10_110_111]); /// ``` fn write_huffman(&mut self, value: T::Symbol) -> io::Result<()> where T: crate::huffman::ToBits, { T::to_bits(value, |b| self.write_bit(b)) } /// Writes a number using a variable using a variable width integer. /// This optimises the case when the number is small. /// /// Given a 4-bit VBR field, any 3-bit value (0 through 7) is encoded directly, with the high bit set to zero. /// Values larger than N-1 bits emit their bits in a series of N-1 bit chunks, where all but the last set the high bit. /// /// # 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_unsigned_vbr::<4,_>(7u32); /// writer.write_unsigned_vbr::<4,_>(100u32); /// assert_eq!(writer.into_writer(), [0b0111_1100, 0b1100_0001]); /// ``` fn write_unsigned_vbr( &mut self, value: U, ) -> io::Result<()> { const { assert!(FIELD_SIZE >= 2 && FIELD_SIZE < U::BITS_SIZE) }; let payload_bits = FIELD_SIZE - 1; let continuation_bit = U::ONE.shl(payload_bits); let payload_mask = continuation_bit.sub(U::ONE); let mut value = value; loop { let payload = value & payload_mask; value >>= payload_bits; if value != U::ZERO { self.write_unsigned::(payload | continuation_bit)?; } else { self.write_unsigned::(payload)?; break; } } Ok(()) } /// Writes a number using a variable using a variable width integer. /// This optimises the case when the number is small. /// /// The integer is mapped to an unsigned value using zigzag encoding. /// For an integer X: /// - if X >= 0 -> 2X /// - else -> -2X + 1 /// /// # 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_signed_vbr::<4,_>(3); /// writer.write_signed_vbr::<4,_>(-50); /// assert_eq!(writer.into_writer(), [0b0110_1011, 0b1100_0001]); /// ``` #[inline] fn write_signed_vbr( &mut self, value: I, ) -> io::Result<()> { let zig_zag = value.shl(1).bitxor(value.shr(I::BITS_SIZE - 1)); self.write_unsigned_vbr::(zig_zag.as_non_negative()) } /// Writes a signed or unsigned variable width integer 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_vbr::<4,_>(6u32); /// writer.write_vbr::<4,_>(-50i32); /// assert_eq!(writer.into_writer(), [0b0110_1011, 0b1100_0001]); /// ``` #[inline] fn write_vbr(&mut self, value: I) -> io::Result<()> { I::write_vbr::(value, self) } /// Creates a "by reference" adaptor for this `BitWrite` /// /// The returned adapter also implements `BitWrite` /// and will borrow the current reader. /// /// # Example /// ``` /// use bitstream_io::{BitWriter, BitWrite, BigEndian}; /// /// fn build(w: W) { /// // perform some building /// } /// /// let mut writer = BitWriter::endian(vec![], BigEndian); /// // performing building by reference /// build(writer.by_ref()); /// // original owned writer still available /// writer.write::<8, u8>(0).unwrap(); /// assert_eq!(writer.into_writer(), &[0]); /// ``` #[inline] fn by_ref(&mut self) -> &mut Self { self } } impl BitWrite for &mut W { #[inline] fn write_bit(&mut self, bit: bool) -> io::Result<()> { (**self).write_bit(bit) } #[inline] fn write(&mut self, value: I) -> io::Result<()> where I: Integer, { (**self).write::(value) } #[inline] fn write_const(&mut self) -> io::Result<()> { (**self).write_const::() } #[inline] fn write_var(&mut self, bits: u32, value: I) -> io::Result<()> where I: Integer, { (**self).write_var(bits, value) } #[inline] fn write_unsigned(&mut self, value: U) -> io::Result<()> where U: UnsignedInteger, { (**self).write_unsigned::(value) } #[inline] fn write_unsigned_var(&mut self, bits: u32, value: U) -> io::Result<()> where U: UnsignedInteger, { (**self).write_unsigned_var(bits, value) } #[inline] fn write_signed(&mut self, value: S) -> io::Result<()> where S: SignedInteger, { (**self).write_signed::(value) } #[inline(always)] fn write_signed_var(&mut self, bits: u32, value: S) -> io::Result<()> where S: SignedInteger, { (**self).write_signed_var(bits, value) } #[inline] fn write_count(&mut self, count: BitCount) -> io::Result<()> { (**self).write_count::(count) } #[inline] fn write_counted(&mut self, bits: BitCount, value: I) -> io::Result<()> where I: Integer + Sized, { (**self).write_counted::(bits, value) } #[inline] fn write_unsigned_counted( &mut self, bits: BitCount, value: U, ) -> io::Result<()> where U: UnsignedInteger, { (**self).write_unsigned_counted::(bits, value) } #[inline] fn write_signed_counted( &mut self, bits: impl TryInto>, value: S, ) -> io::Result<()> where S: SignedInteger, { (**self).write_signed_counted::(bits, value) } #[inline] fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive, { (**self).write_from::(value) } #[inline] fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { (**self).write_as_from::(value) } #[inline] fn pad(&mut self, bits: u32) -> io::Result<()> { (**self).pad(bits) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { (**self).write_bytes(buf) } #[inline] fn write_unary(&mut self, value: u32) -> io::Result<()> { (**self).write_unary::(value) } #[inline] fn write_checked(&mut self, value: C) -> io::Result<()> { (**self).write_checked(value) } #[inline] fn build(&mut self, build: &T) -> Result<(), T::Error> { (**self).build(build) } #[inline] fn build_with<'a, T: ToBitStreamWith<'a>>( &mut self, build: &T, context: &T::Context, ) -> Result<(), T::Error> { (**self).build_with(build, context) } #[inline] fn byte_aligned(&self) -> bool { (**self).byte_aligned() } #[inline] fn byte_align(&mut self) -> io::Result<()> { (**self).byte_align() } #[inline] fn write_huffman(&mut self, value: T::Symbol) -> io::Result<()> where T: crate::huffman::ToBits, { (**self).write_huffman::(value) } } /// A compatibility trait for older code implementing [`BitWrite`] /// /// This is a trait largely compatible with older code /// from the 2.X.X version, /// which one can use with a named import as needed. /// /// New code should prefer the regular [`BitWrite`] trait. /// /// # Example /// ``` /// use bitstream_io::BitWrite2 as BitWrite; /// use bitstream_io::{BitWriter, BigEndian}; /// let mut byte = vec![]; /// let mut writer = BitWriter::endian(byte, BigEndian); /// writer.write::(4, 0b1111).unwrap(); /// writer.write_out::<4, u8>(0b0000).unwrap(); /// assert_eq!(writer.into_writer(), [0b1111_0000]); /// ``` pub trait BitWrite2 { /// 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<()> { self.write_unsigned_out::<1, u8>(u8::from(bit)) } /// Writes a signed or 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: I) -> io::Result<()> where I: Integer; /// Writes a signed or 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: I) -> io::Result<()> where I: Integer; /// 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_unsigned(&mut self, bits: u32, value: U) -> io::Result<()> where U: UnsignedInteger; /// 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. #[inline] fn write_unsigned_out(&mut self, value: U) -> io::Result<()> where U: UnsignedInteger, { self.write_unsigned(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: SignedInteger; /// 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: SignedInteger, { self.write_signed(BITS, value) } /// 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; /// Pads the stream by writing 0 over the given number of bits. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn pad(&mut self, mut bits: u32) -> io::Result<()> { loop { match bits { 0 => break Ok(()), bits @ 1..64 => break self.write(bits, 0u64), _ => { self.write_out::<64, u64>(0)?; bits -= 64; } } } } /// 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_var(8, 0x66u8).unwrap(); /// writer.write_var(8, 0x6Fu8).unwrap(); /// writer.write_var(8, 0x6Fu8).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_unsigned_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. fn write_unary0(&mut self, value: u32) -> io::Result<()>; /// 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. fn write_unary1(&mut self, value: u32) -> io::Result<()>; /// Builds and writes complex type fn build(&mut self, build: &T) -> Result<(), T::Error> where Self: BitWrite, { 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> where Self: BitWrite, { 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_var(1, 0u8).unwrap(); /// writer.byte_align().unwrap(); /// writer.write_var(8, 0xFFu8).unwrap(); /// assert_eq!(writer.into_writer(), [0x00, 0xFF]); /// ``` fn byte_align(&mut self) -> io::Result<()> { while !self.byte_aligned() { self.write_bit(false)?; } Ok(()) } /// Given a symbol, writes its representation to the output stream as bits. /// Generates no output if the symbol isn't defined in the Huffman tree. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. /// /// # Example /// ``` /// use std::io::Write; /// use bitstream_io::{BigEndian, BitWriter, BitWrite2}; /// use bitstream_io::define_huffman_tree; /// define_huffman_tree!(TreeName : char = ['a', ['b', ['c', 'd']]]); /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// writer.write_huffman::('b').unwrap(); /// writer.write_huffman::('c').unwrap(); /// writer.write_huffman::('d').unwrap(); /// assert_eq!(writer.into_writer(), [0b10_110_111]); /// ``` fn write_huffman(&mut self, value: T::Symbol) -> io::Result<()> where T: crate::huffman::ToBits, { T::to_bits(value, |b| self.write_bit(b)) } } impl BitWrite2 for W { #[inline] fn write_bit(&mut self, bit: bool) -> io::Result<()> { BitWrite::write_bit(self, bit) } #[inline] fn write(&mut self, bits: u32, value: I) -> io::Result<()> where I: Integer, { BitWrite::write_var(self, bits, value) } #[inline] fn write_out(&mut self, value: I) -> io::Result<()> where I: Integer, { BitWrite::write::(self, value) } #[inline] fn write_unsigned(&mut self, bits: u32, value: U) -> io::Result<()> where U: UnsignedInteger, { BitWrite::write_unsigned_var::(self, bits, value) } #[inline] fn write_unsigned_out(&mut self, value: U) -> io::Result<()> where U: UnsignedInteger, { BitWrite::write_unsigned::(self, value) } #[inline] fn write_signed(&mut self, bits: u32, value: S) -> io::Result<()> where S: SignedInteger, { BitWrite::write_signed_var::(self, bits, value) } #[inline] fn write_signed_out(&mut self, value: S) -> io::Result<()> where S: SignedInteger, { BitWrite::write_signed::(self, value) } #[inline] fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive, { BitWrite::write_from(self, value) } #[inline] fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { BitWrite::write_as_from::(self, value) } #[inline] fn pad(&mut self, bits: u32) -> io::Result<()> { BitWrite::pad(self, bits) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { BitWrite::write_bytes(self, buf) } #[inline] fn write_unary0(&mut self, value: u32) -> io::Result<()> { BitWrite::write_unary::<0>(self, value) } #[inline] fn write_unary1(&mut self, value: u32) -> io::Result<()> { BitWrite::write_unary::<1>(self, value) } #[inline] fn byte_aligned(&self) -> bool { BitWrite::byte_aligned(self) } #[inline] fn byte_align(&mut self) -> io::Result<()> { BitWrite::byte_align(self) } } impl BitWrite for BitWriter { fn write_bit(&mut self, bit: bool) -> io::Result<()> { match E::push_bit_flush(&mut self.value, &mut self.bits, bit) { None => Ok(()), Some(byte) => write_byte(&mut self.writer, byte), } } #[inline(always)] fn write_unsigned(&mut self, value: U) -> io::Result<()> where U: UnsignedInteger, { let Self { value: queue_value, bits: queue_bits, writer, .. } = self; E::write_bits_checked( writer, queue_value, queue_bits, CheckedUnsigned::::new_fixed::(value)?, ) } fn write_unsigned_counted( &mut self, count: BitCount, value: U, ) -> io::Result<()> where U: UnsignedInteger, { let Self { value: queue_value, bits: queue_bits, writer, .. } = self; E::write_bits_checked( writer, queue_value, queue_bits, CheckedUnsigned::new(count, value)?, ) } #[inline(always)] fn write_signed_counted( &mut self, bits: impl TryInto>, value: S, ) -> io::Result<()> where S: SignedInteger, { E::write_signed_bits_checked( &mut self.writer, &mut self.value, &mut self.bits, CheckedSigned::new( bits.try_into().map_err(|_| { io::Error::new( io::ErrorKind::InvalidInput, "signed writes need at least 1 bit for sign", ) })?, value, )?, ) } #[inline] fn write_signed(&mut self, value: S) -> io::Result<()> where S: SignedInteger, { E::write_signed_bits_checked( &mut self.writer, &mut self.value, &mut self.bits, CheckedSigned::::new_fixed::(value)?, ) } #[inline] fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive, { E::write_bytes::<8, _>( &mut self.writer, &mut self.value, self.bits, E::primitive_to_bytes(value).as_ref(), ) } #[inline] fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { F::write_bytes::<8, _>( &mut self.writer, &mut self.value, self.bits, F::primitive_to_bytes(value).as_ref(), ) } #[inline] fn write_checked(&mut self, value: C) -> io::Result<()> { value.write_endian::(&mut self.writer, &mut self.value, &mut self.bits) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { E::write_bytes::<1024, _>(&mut self.writer, &mut self.value, self.bits, buf) } #[inline(always)] fn byte_aligned(&self) -> bool { self.bits == 0 } } /// An error returned if performing math operations would overflow #[derive(Copy, Clone, Debug)] pub struct Overflowed; impl fmt::Display for Overflowed { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { "overflow occured in counter".fmt(f) } } impl core::error::Error for Overflowed {} impl From for io::Error { fn from(Overflowed: Overflowed) -> Self { io::Error::new( #[cfg(feature = "std")] { io::ErrorKind::StorageFull }, #[cfg(not(feature = "std"))] { io::ErrorKind::Other }, "bitstream accumulator overflow", ) } } /// A common trait for integer types for performing math operations /// which may check for overflow. pub trait Counter: Default + Sized + From + TryFrom + TryFrom { /// add rhs to self, returning `Overflowed` if the result is too large fn checked_add_assign(&mut self, rhs: Self) -> Result<(), Overflowed>; /// multiply self by rhs, returning `Overflowed` if the result is too large fn checked_mul(self, rhs: Self) -> Result; /// returns `true` if the number if bits written is divisible by 8 fn byte_aligned(&self) -> bool; } macro_rules! define_counter { ($t:ty) => { impl Counter for $t { fn checked_add_assign(&mut self, rhs: Self) -> Result<(), Overflowed> { *self = <$t>::checked_add(*self, rhs).ok_or(Overflowed)?; Ok(()) } fn checked_mul(self, rhs: Self) -> Result { <$t>::checked_mul(self, rhs).ok_or(Overflowed) } fn byte_aligned(&self) -> bool { self % 8 == 0 } } }; } define_counter!(u8); define_counter!(u16); define_counter!(u32); define_counter!(u64); define_counter!(u128); /// For counting the number of bits written but generating no output. /// /// # Example /// ``` /// use bitstream_io::{BigEndian, BitWrite, BitsWritten}; /// let mut writer: BitsWritten = BitsWritten::new(); /// writer.write_var(1, 0b1u8).unwrap(); /// writer.write_var(2, 0b01u8).unwrap(); /// writer.write_var(5, 0b10111u8).unwrap(); /// assert_eq!(writer.written(), 8); /// ``` #[derive(Default)] pub struct BitsWritten { bits: N, } impl BitsWritten { /// Creates new empty BitsWritten value #[inline] pub fn new() -> Self { Self { bits: N::default() } } } impl BitsWritten { /// Returns number of bits written #[inline] pub fn written(&self) -> N { self.bits } } impl BitsWritten { /// Returns number of bits written #[inline] pub fn into_written(self) -> N { self.bits } } impl BitWrite for BitsWritten { #[inline] fn write_bit(&mut self, _bit: bool) -> io::Result<()> { self.bits.checked_add_assign(1u8.into())?; Ok(()) } #[inline] fn write_const(&mut self) -> io::Result<()> { const { assert!( BITS == 0 || VALUE <= (u32::ALL >> (u32::BITS_SIZE - BITS)), "excessive value for bits written" ); } self.bits .checked_add_assign(BITS.try_into().map_err(|_| Overflowed)?)?; Ok(()) } #[inline] fn write_unsigned(&mut self, value: U) -> io::Result<()> where U: UnsignedInteger, { const { assert!(BITS <= U::BITS_SIZE, "excessive bits for type written"); } if BITS == 0 { Ok(()) } else if value <= (U::ALL >> (U::BITS_SIZE - BITS)) { self.bits .checked_add_assign(BITS.try_into().map_err(|_| Overflowed)?)?; Ok(()) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive value for bits written", )) } } #[inline] fn write_signed(&mut self, value: S) -> io::Result<()> where S: SignedInteger, { let SignedBitCount { bits: BitCount { bits }, unsigned, } = const { assert!(BITS <= S::BITS_SIZE, "excessive bits for type written"); let count = BitCount::::new::().signed_count(); assert!( count.is_some(), "signed writes need at least 1 bit for sign" ); count.unwrap() }; // doesn't matter which side the sign is on // so long as it's added to the bit count self.bits.checked_add_assign(1u8.into())?; self.write_unsigned_counted( unsigned, if value.is_negative() { value.as_negative(bits) } else { value.as_non_negative() }, ) } #[inline] fn write_unsigned_counted( &mut self, BitCount { bits }: BitCount, value: U, ) -> io::Result<()> where U: UnsignedInteger, { if MAX <= U::BITS_SIZE || bits <= U::BITS_SIZE { if bits == 0 { Ok(()) } else if value <= U::ALL >> (U::BITS_SIZE - bits) { self.bits .checked_add_assign(bits.try_into().map_err(|_| Overflowed)?)?; Ok(()) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive value for bits written", )) } } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type written", )) } } #[inline] fn write_signed_counted( &mut self, bits: impl TryInto>, value: S, ) -> io::Result<()> where S: SignedInteger, { let SignedBitCount { bits: BitCount { bits }, unsigned, } = bits.try_into().map_err(|_| { io::Error::new( io::ErrorKind::InvalidInput, "signed writes need at least 1 bit for sign", ) })?; if MAX <= S::BITS_SIZE || bits <= S::BITS_SIZE { // doesn't matter which side the sign is on // so long as it's added to the bit count self.bits.checked_add_assign(1u8.into())?; self.write_unsigned_counted( unsigned, if value.is_negative() { value.as_negative(bits) } else { value.as_non_negative() }, ) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "excessive bits for type written", )) } } #[inline] fn write_from(&mut self, _: V) -> io::Result<()> where V: Primitive, { self.bits.checked_add_assign( N::try_from(core::mem::size_of::()) .map_err(|_| Overflowed)? .checked_mul(8u8.into())?, )?; Ok(()) } #[inline] fn write_as_from(&mut self, _: V) -> io::Result<()> where F: Endianness, V: Primitive, { self.bits.checked_add_assign( N::try_from(core::mem::size_of::()) .map_err(|_| Overflowed)? .checked_mul(8u8.into())?, )?; Ok(()) } #[inline] fn pad(&mut self, bits: u32) -> io::Result<()> { self.bits .checked_add_assign(bits.try_into().map_err(|_| Overflowed)?)?; Ok(()) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { self.bits.checked_add_assign( N::try_from(buf.len()) .map_err(|_| Overflowed)? .checked_mul(8u8.into())?, )?; Ok(()) } fn write_unary(&mut self, value: u32) -> io::Result<()> { const { assert!(matches!(STOP_BIT, 0 | 1), "stop bit must be 0 or 1"); } self.bits .checked_add_assign(value.try_into().map_err(|_| Overflowed)?)?; self.bits.checked_add_assign(1u8.into())?; Ok(()) } fn write_checked(&mut self, value: C) -> io::Result<()> { Ok(self .bits .checked_add_assign(value.written_bits().try_into().map_err(|_| Overflowed)?)?) } #[inline] fn byte_aligned(&self) -> bool { self.bits.byte_aligned() } } /// 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_var(1, 0b1u8).unwrap(); /// writer.write_var(2, 0b01u8).unwrap(); /// writer.write_var(5, 0b10111u8).unwrap(); /// assert_eq!(writer.written(), 8); /// ``` #[derive(Default)] #[deprecated(since = "4.0.0", note = "use of BitsWritten is preferred")] pub struct BitCounter { bits: BitsWritten, phantom: PhantomData, } #[allow(deprecated)] impl BitCounter { /// Creates new counter #[inline] pub fn new() -> Self { BitCounter { bits: BitsWritten::new(), phantom: PhantomData, } } } #[allow(deprecated)] impl BitCounter { /// Returns number of bits written #[inline] pub fn written(&self) -> N { self.bits.written() } } #[allow(deprecated)] impl BitCounter { /// Returns number of bits written #[inline] pub fn into_written(self) -> N { self.bits.into_written() } } #[allow(deprecated)] impl BitWrite for BitCounter where E: Endianness, N: Counter, { #[inline] fn write_bit(&mut self, bit: bool) -> io::Result<()> { BitWrite::write_bit(&mut self.bits, bit) } #[inline] fn write_const(&mut self) -> io::Result<()> { BitWrite::write_const::(&mut self.bits) } #[inline] fn write_unsigned(&mut self, value: U) -> io::Result<()> where U: UnsignedInteger, { BitWrite::write_unsigned::(&mut self.bits, value) } #[inline] fn write_signed(&mut self, value: S) -> io::Result<()> where S: SignedInteger, { BitWrite::write_signed::(&mut self.bits, value) } #[inline] fn write_unsigned_counted( &mut self, count: BitCount, value: U, ) -> io::Result<()> where U: UnsignedInteger, { BitWrite::write_unsigned_counted::(&mut self.bits, count, value) } #[inline] fn write_signed_counted( &mut self, bits: impl TryInto>, value: S, ) -> io::Result<()> where S: SignedInteger, { BitWrite::write_signed_counted::(&mut self.bits, bits, value) } #[inline] fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive, { BitWrite::write_from(&mut self.bits, value) } #[inline] fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { BitWrite::write_as_from::(&mut self.bits, value) } #[inline] fn pad(&mut self, bits: u32) -> io::Result<()> { BitWrite::pad(&mut self.bits, bits) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { BitWrite::write_bytes(&mut self.bits, buf) } fn write_unary(&mut self, value: u32) -> io::Result<()> { BitWrite::write_unary::(&mut self.bits, value) } #[inline] fn byte_aligned(&self) -> bool { BitWrite::byte_aligned(&self.bits) } } #[cfg(feature = "alloc")] mod bit_recorder { use super::*; /// 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_var(1, 0b1u8).unwrap(); /// recorder.write_var(2, 0b01u8).unwrap(); /// recorder.write_var(5, 0b10111u8).unwrap(); /// assert_eq!(recorder.written(), 8); /// let mut writer = BitWriter::endian(Vec::new(), BigEndian); /// recorder.playback(&mut writer); /// assert_eq!(writer.into_writer(), [0b10110111]); /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] pub struct BitRecorder { writer: BitWriter, E>, phantom: PhantomData, } impl BitRecorder { /// Creates new recorder #[inline] pub fn new() -> Self { BitRecorder { writer: BitWriter::new(Vec::new()), phantom: PhantomData, } } /// Creates new recorder sized for the given number of bytes #[inline] pub fn with_capacity(bytes: usize) -> Self { BitRecorder { writer: BitWriter::new(Vec::with_capacity(bytes)), phantom: PhantomData, } } /// Creates new recorder with the given endianness #[inline] pub fn endian(endian: E) -> Self { BitRecorder { writer: BitWriter::endian(Vec::new(), endian), phantom: PhantomData, } } /// Returns number of bits written /// /// # Panics /// /// Panics if the number of bits written is /// larger than the maximum supported by the counter type. /// Use [`BitRecorder::written_checked`] for a non-panicking /// alternative. #[inline] pub fn written(&self) -> N { self.written_checked().unwrap() } /// Returns number of bits written /// /// # Errors /// /// Returns an error if the number of bits written overflows /// our counter type. #[inline] pub fn written_checked(&self) -> Result { let mut written = N::try_from(self.writer.writer.len()) .map_err(|_| Overflowed)? .checked_mul(8u8.into())?; written.checked_add_assign(N::try_from(self.writer.bits).map_err(|_| Overflowed)?)?; Ok(written) } /// Plays recorded writes to the given writer #[inline] pub fn playback(&self, writer: &mut W) -> io::Result<()> { writer.write_bytes(self.writer.writer.as_slice())?; writer.write_var(self.writer.bits, self.writer.value)?; Ok(()) } /// Clears recorder, removing all values #[inline] pub fn clear(&mut self) { self.writer = BitWriter::new({ let mut v = core::mem::take(&mut self.writer.writer); v.clear(); v }); } } impl Default for BitRecorder { #[inline] fn default() -> Self { Self::new() } } impl BitWrite for BitRecorder where E: Endianness, N: Counter, { #[inline] fn write_bit(&mut self, bit: bool) -> io::Result<()> { BitWrite::write_bit(&mut self.writer, bit) } #[inline] fn write(&mut self, value: I) -> io::Result<()> where I: Integer, { BitWrite::write::(&mut self.writer, value) } #[inline] fn write_const(&mut self) -> io::Result<()> { self.writer.write_const::() } #[inline] fn write_var(&mut self, bits: u32, value: I) -> io::Result<()> where I: Integer, { self.writer.write_var(bits, value) } #[inline] fn write_unsigned(&mut self, value: U) -> io::Result<()> where U: UnsignedInteger, { BitWrite::write_unsigned::(&mut self.writer, value) } #[inline] fn write_unsigned_var(&mut self, bits: u32, value: U) -> io::Result<()> where U: UnsignedInteger, { self.writer.write_unsigned_var(bits, value) } #[inline] fn write_signed(&mut self, value: S) -> io::Result<()> where S: SignedInteger, { BitWrite::write_signed::(&mut self.writer, value) } #[inline(always)] fn write_signed_var(&mut self, bits: u32, value: S) -> io::Result<()> where S: SignedInteger, { self.writer.write_signed_var(bits, value) } #[inline] fn write_count(&mut self, count: BitCount) -> io::Result<()> { self.writer.write_count::(count) } #[inline] fn write_counted( &mut self, bits: BitCount, value: I, ) -> io::Result<()> where I: Integer + Sized, { self.writer.write_counted::(bits, value) } #[inline] fn write_unsigned_counted( &mut self, bits: BitCount, value: U, ) -> io::Result<()> where U: UnsignedInteger, { self.writer.write_unsigned_counted::(bits, value) } #[inline] fn write_signed_counted( &mut self, bits: impl TryInto>, value: S, ) -> io::Result<()> where S: SignedInteger, { self.writer.write_signed_counted::(bits, value) } #[inline] fn write_from(&mut self, value: V) -> io::Result<()> where V: Primitive, { BitWrite::write_from::(&mut self.writer, value) } #[inline] fn write_as_from(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { BitWrite::write_as_from::(&mut self.writer, value) } #[inline] fn pad(&mut self, bits: u32) -> io::Result<()> { BitWrite::pad(&mut self.writer, bits) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { BitWrite::write_bytes(&mut self.writer, buf) } #[inline] fn write_unary(&mut self, value: u32) -> io::Result<()> { self.writer.write_unary::(value) } #[inline] fn build(&mut self, build: &T) -> Result<(), T::Error> { BitWrite::build(&mut self.writer, build) } #[inline] fn build_with<'a, T: ToBitStreamWith<'a>>( &mut self, build: &T, context: &T::Context, ) -> Result<(), T::Error> { BitWrite::build_with(&mut self.writer, build, context) } #[inline] fn byte_aligned(&self) -> bool { BitWrite::byte_aligned(&self.writer) } #[inline] fn byte_align(&mut self) -> io::Result<()> { BitWrite::byte_align(&mut self.writer) } #[inline] fn write_huffman(&mut self, value: T::Symbol) -> io::Result<()> where T: crate::huffman::ToBits, { BitWrite::write_huffman::(&mut self.writer, value) } } impl BitRecorder { /// Returns shortest option between ourself and candidate /// /// Executes fallible closure on emptied candidate recorder, /// compares the lengths of ourself and the candidate, /// and returns the shorter of the two. /// /// If the new candidate is shorter, we swap ourself and /// the candidate so any recorder capacity can be reused. /// /// # Example /// /// ``` /// use bitstream_io::{BitRecorder, BitWrite, BigEndian}; /// /// let mut best = BitRecorder::::new(); /// let mut candidate = BitRecorder::new(); /// /// // write an 8 bit value to our initial candidate /// best.write::<8, u8>(0); /// assert_eq!(best.written(), 8); /// /// // try another candidate which writes 4 bits /// best = best.best(&mut candidate, |w| { /// w.write::<4, u8>(0) /// }).unwrap(); /// /// // which becomes our new best candidate /// assert_eq!(best.written(), 4); /// /// // finally, try a not-so-best candidate /// // which writes 10 bits /// best = best.best(&mut candidate, |w| { /// w.write::<10, u16>(0) /// }).unwrap(); /// /// // so our best candidate remains 4 bits /// assert_eq!(best.written(), 4); /// ``` pub fn best( mut self, candidate: &mut Self, f: impl FnOnce(&mut Self) -> Result<(), F>, ) -> Result { candidate.clear(); f(candidate)?; if candidate.written() < self.written() { core::mem::swap(&mut self, candidate); } Ok(self) } } } #[inline] fn write_byte(mut writer: W, byte: u8) -> io::Result<()> where W: io::Write, { writer.write_all(core::slice::from_ref(&byte)) } /// 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<()>; /// Pads the stream by writing 0 over the given number of bytes. /// /// # Errors /// /// Passes along any I/O error from the underlying stream. fn pad(&mut self, bytes: u32) -> 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) } /// Builds and writes complex type with owned context fn build_using( &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, { self.writer.write_all(E::primitive_to_bytes(value).as_ref()) } #[inline] fn write_as(&mut self, value: V) -> io::Result<()> where F: Endianness, V: Primitive, { self.writer.write_all(F::primitive_to_bytes(value).as_ref()) } #[inline] fn pad(&mut self, mut bytes: u32) -> io::Result<()> { let buf = [0u8; 8]; while bytes > 0 { let to_write = bytes.min(8); self.write_bytes(&buf[0..to_write as usize])?; bytes -= to_write; } Ok(()) } #[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::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; /// Returns length of self in bits, if possible fn bits(&self) -> Result where Self: Sized, { let mut c: BitsWritten = BitsWritten::default(); self.to_writer(&mut c)?; Ok(c.into_written()) } /// Returns total length of self, if possible #[deprecated(since = "4.0.0", note = "use of bits() is preferred")] #[inline] fn bits_len(&self) -> Result where Self: Sized, { self.bits() } } /// 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; /// Returns length of self in bits, if possible fn bits(&self, context: &Self::Context) -> Result where Self: Sized, { let mut c: BitsWritten = BitsWritten::default(); self.to_writer(&mut c, context)?; Ok(c.into_written()) } /// Returns total length of self, if possible #[deprecated(since = "4.0.0", note = "use of len() is preferred")] #[inline] fn bits_len(&self, context: &Self::Context) -> Result where Self: Sized, { self.bits(context) } } /// Implemented by complex types that consume additional context /// to build themselves to a writer pub trait ToBitStreamUsing { /// Some context to consume when writing type Context; /// 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; /// Returns length of self in bits, if possible fn bits(&self, context: Self::Context) -> Result where Self: Sized, { let mut c: BitsWritten = BitsWritten::default(); self.to_writer(&mut c, context)?; Ok(c.into_written()) } } /// 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; /// Returns length of self in bytes, if possible fn bytes(&self) -> Result where Self: Sized, { let mut counter = ByteCount::default(); self.to_writer(&mut counter)?; Ok(counter.writer.count) } } /// 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; /// Returns length of self in bytes, if possible fn bytes(&self, context: &Self::Context) -> Result where Self: Sized, { let mut counter = ByteCount::default(); self.to_writer(&mut counter, context)?; Ok(counter.writer.count) } } /// Implemented by complex types that consume additional context /// to build themselves to a writer pub trait ToByteStreamUsing { /// Some context to consume when writing type Context; /// 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; /// Returns length of self in bytes, if possible fn bytes(&self, context: Self::Context) -> Result where Self: Sized, { let mut counter = ByteCount::default(); self.to_writer(&mut counter, context)?; Ok(counter.writer.count) } } #[derive(Default)] struct ByteCounterWriter { count: C, } impl io::Write for ByteCounterWriter { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.count .checked_add_assign(buf.len().try_into().map_err(|_| Overflowed)?)?; Ok(buf.len()) } #[inline] fn flush(&mut self) -> io::Result<()> { // nothing to do Ok(()) } } #[derive(Default)] struct ByteCount { writer: ByteCounterWriter, } impl ByteWrite for ByteCount { fn write(&mut self, _value: V) -> io::Result<()> { self.writer.count.checked_add_assign( V::buffer() .as_ref() .len() .try_into() .map_err(|_| Overflowed)?, )?; Ok(()) } fn write_as(&mut self, _value: V) -> io::Result<()> { self.writer.count.checked_add_assign( V::buffer() .as_ref() .len() .try_into() .map_err(|_| Overflowed)?, )?; Ok(()) } fn write_bytes(&mut self, buf: &[u8]) -> io::Result<()> { self.writer .count .checked_add_assign(buf.len().try_into().map_err(|_| Overflowed)?)?; Ok(()) } fn pad(&mut self, bytes: u32) -> io::Result<()> { self.writer .count .checked_add_assign(bytes.try_into().map_err(|_| Overflowed)?)?; Ok(()) } fn writer_ref(&mut self) -> &mut dyn io::Write { &mut self.writer } } bitstream-io-4.9.0/tests/huffman.rs000064400000000000000000000017451046102023000154000ustar 00000000000000#[test] fn test_huffman_values() { use bitstream_io::{define_huffman_tree, BigEndian, BitRead, BitReader}; let data = [0b10110001, 0b11101101]; define_huffman_tree!(Tree1 : i32 = [0, [1, [2, 5]]]); define_huffman_tree!(Tree2 : &'static str = ["foo", ["bar", ["baz", "kelp"]]]); let mut r = BitReader::endian(data.as_slice(), BigEndian); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 2); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 5); let mut r = BitReader::endian(data.as_slice(), BigEndian); assert_eq!(r.read_huffman::().unwrap(), "bar"); assert_eq!(r.read_huffman::().unwrap(), "baz"); assert_eq!(r.read_huffman::().unwrap(), "foo"); assert_eq!(r.read_huffman::().unwrap(), "foo"); assert_eq!(r.read_huffman::().unwrap(), "kelp"); } bitstream-io-4.9.0/tests/random-3be.bin000064400000000000000000000001771046102023000160250ustar 00000000000000“À÷l5¦rk¥n{LïÔûðœ’Q^ÛÃn»´zm¶Z÷î À‹Yp"~\EeõûðEC[ˆ¤lä|ë–?þ|ËàçÚ:>ïh£óg•¨¤ëÚ  C9;òæ×™Р]®Uä&¨¹ò¦˜8Á’Û«›BCKZ¡ ¤æ[¬„¯cÁbitstream-io-4.9.0/tests/random-3le.bin000064400000000000000000000001771046102023000160370ustar 00000000000000OÀk¼PÀ”Ö¹‰.¶}ø-­SÿÓo`FRie¯íÚî±IÔnÙ«?/bÍ…ài‘Õ÷Ìu-Ž¢‘ó±Sîøÿ9“cÿ註ÂM¾–¢sŠ&éìÄK{~DŸb¡V™—°ú‡jú`CDn«n )m*„Šs¹²’Ïbitstream-io-4.9.0/tests/random.bin000064400000000000000000000002001046102023000153410ustar 00000000000000x^〦´ÎMt±íÃoiúŸ~3’J+Ûxm×vM¢vË^ýÁxk.Oˈ¬¾¿`þ¨kqœrÇÿÏ™|ûGGÝí~lòµ{P4Hg'~\Úó#ú µÊ¼„Õ>TÓ"r[ushHikT!TœËu•ìx6bitstream-io-4.9.0/tests/read.rs000064400000000000000000001137741046102023000146750ustar 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. use std::io; #[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(actual_data.as_slice(), 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(actual_data.as_slice(), BigEndian); assert!(r.byte_aligned()); assert_eq!(r.read_var::(2).unwrap(), 2); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(3).unwrap(), 6); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(5).unwrap(), 7); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(3).unwrap(), 5); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(19).unwrap(), 0x53BC1); assert!(r.byte_aligned()); assert!(r.read_var::(1).is_err()); // reading const unsigned values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert!(r.byte_aligned()); assert_eq!(r.read::<2, u32>().unwrap(), 2); assert!(!r.byte_aligned()); assert_eq!(r.read::<3, u32>().unwrap(), 6); assert!(!r.byte_aligned()); assert_eq!(r.read::<5, u32>().unwrap(), 7); assert!(!r.byte_aligned()); assert_eq!(r.read::<3, u32>().unwrap(), 5); assert!(!r.byte_aligned()); assert_eq!(r.read::<19, u32>().unwrap(), 0x53BC1); assert!(r.byte_aligned()); assert!(r.read::<1, u32>().is_err()); // 16-bit values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read::<1, u8>().unwrap(), 1); assert_eq!(r.read::<14, u16>().unwrap(), 0b0110_0011_1101_10); assert_eq!(r.read::<16, u16>().unwrap(), 0b1001_1101_1110_0000); assert_eq!(r.read::<1, u8>().unwrap(), 1); // skipping bits let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_var::(2).unwrap(), 2); assert!(r.skip(3).is_ok()); assert_eq!(r.read_var::(5).unwrap(), 7); assert!(r.skip(3).is_ok()); assert_eq!(r.read_var::(19).unwrap(), 0x53BC1); // reading signed values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_signed_var::(2).unwrap(), -2); assert_eq!(r.read_signed_var::(3).unwrap(), -2); assert_eq!(r.read_signed_var::(5).unwrap(), 7); assert_eq!(r.read_signed_var::(3).unwrap(), -3); assert_eq!(r.read_signed_var::(19).unwrap(), -181311); // reading const signed values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_signed::<2, i32>().unwrap(), -2); assert_eq!(r.read_signed::<3, i32>().unwrap(), -2); assert_eq!(r.read_signed::<5, i32>().unwrap(), 7); assert_eq!(r.read_signed::<3, i32>().unwrap(), -3); assert_eq!(r.read_signed::<19, i32>().unwrap(), -181311); // reading unary 0 values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_unary::<0>().unwrap(), 1); assert_eq!(r.read_unary::<0>().unwrap(), 2); assert_eq!(r.read_unary::<0>().unwrap(), 0); assert_eq!(r.read_unary::<0>().unwrap(), 0); assert_eq!(r.read_unary::<0>().unwrap(), 4); // reading unary 1 values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_unary::<1>().unwrap(), 0); assert_eq!(r.read_unary::<1>().unwrap(), 1); assert_eq!(r.read_unary::<1>().unwrap(), 0); assert_eq!(r.read_unary::<1>().unwrap(), 3); assert_eq!(r.read_unary::<1>().unwrap(), 0); // reading unsigned vbr let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_unsigned_vbr::<4, u8>().unwrap(), 11); assert_eq!(r.read_unsigned_vbr::<4, u8>().unwrap(), 238); assert_eq!(r.read_unsigned_vbr::<4, u8>().unwrap(), 99); assert!(r.read_unsigned_vbr::<4, u8>().is_err()); // reading signed vbr let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_signed_vbr::<4, i8>().unwrap(), -6); assert_eq!(r.read_signed_vbr::<4, i8>().unwrap(), 119); assert_eq!(r.read_signed_vbr::<4, i8>().unwrap(), -50); assert!(r.read_signed_vbr::<4, i8>().is_err()); // byte aligning let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_var::(3).unwrap(), 5); r.byte_align(); assert_eq!(r.read_var::(3).unwrap(), 7); r.byte_align(); r.byte_align(); assert_eq!(r.read_var::(8).unwrap(), 59); r.byte_align(); assert_eq!(r.read_var::(4).unwrap(), 12); // reading bytes, aligned let mut r = BitReader::endian(actual_data.as_slice(), 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(actual_data.as_slice(), BigEndian); let mut sub_data = [0; 2]; assert_eq!(r.read_var::(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([255; 1].as_slice(), BigEndian); assert_eq!(r.read_var::(0).unwrap(), 0); assert_eq!(r.read_var::(0).unwrap(), 0); assert_eq!(r.read_var::(0).unwrap(), 0); assert_eq!(r.read_var::(0).unwrap(), 0); assert_eq!(r.read_var::(8).unwrap(), 255); let mut r = BitReader::endian([255; 1].as_slice(), BigEndian); assert_eq!(r.read::<0, u8>().unwrap(), 0); assert_eq!(r.read::<0, u16>().unwrap(), 0); assert_eq!(r.read::<0, u32>().unwrap(), 0); assert_eq!(r.read::<0, u64>().unwrap(), 0); assert_eq!(r.read::<8, u8>().unwrap(), 255); let mut r = BitReader::endian([255; 1].as_slice(), BigEndian); assert!(r.read_signed_var::(0).is_err()); assert!(r.read_signed_var::(0).is_err()); assert!(r.read_signed_var::(0).is_err()); assert!(r.read_signed_var::(0).is_err()); // unsigned 32 and 64-bit values let mut r = BitReader::endian(data.as_slice(), BigEndian); assert_eq!(r.read_var::(32).unwrap(), 0); assert_eq!(r.read_var::(32).unwrap(), 4294967295); assert_eq!(r.read_var::(32).unwrap(), 2147483648); assert_eq!(r.read_var::(32).unwrap(), 2147483647); assert_eq!(r.read_var::(64).unwrap(), 0); assert_eq!(r.read_var::(64).unwrap(), 0xFFFFFFFFFFFFFFFF); assert_eq!(r.read_var::(64).unwrap(), 9223372036854775808); assert_eq!(r.read_var::(64).unwrap(), 9223372036854775807); let mut r = BitReader::endian(data.as_slice(), BigEndian); assert_eq!(r.read::<32, u32>().unwrap(), 0); assert_eq!(r.read::<32, u32>().unwrap(), 4294967295); assert_eq!(r.read::<32, u32>().unwrap(), 2147483648); assert_eq!(r.read::<32, u32>().unwrap(), 2147483647); assert_eq!(r.read::<64, u64>().unwrap(), 0); assert_eq!(r.read::<64, u64>().unwrap(), 0xFFFFFFFFFFFFFFFF); assert_eq!(r.read::<64, u64>().unwrap(), 9223372036854775808); assert_eq!(r.read::<64, u64>().unwrap(), 9223372036854775807); // signed 32 and 64-bit values let mut r = BitReader::endian(data.as_slice(), BigEndian); assert_eq!(r.read_signed_var::(32).unwrap(), 0); assert_eq!(r.read_signed_var::(32).unwrap(), -1); assert_eq!(r.read_signed_var::(32).unwrap(), -2147483648); assert_eq!(r.read_signed_var::(32).unwrap(), 2147483647); assert_eq!(r.read_signed_var::(64).unwrap(), 0); assert_eq!(r.read_signed_var::(64).unwrap(), -1); assert_eq!(r.read_signed_var::(64).unwrap(), -9223372036854775808); assert_eq!(r.read_signed_var::(64).unwrap(), 9223372036854775807); let mut r = BitReader::endian(data.as_slice(), BigEndian); assert_eq!(r.read_signed::<32, i32>().unwrap(), 0); assert_eq!(r.read_signed::<32, i32>().unwrap(), -1); assert_eq!(r.read_signed::<32, i32>().unwrap(), -2147483648); assert_eq!(r.read_signed::<32, i32>().unwrap(), 2147483647); assert_eq!(r.read_signed::<64, i64>().unwrap(), 0); assert_eq!(r.read_signed::<64, i64>().unwrap(), -1); assert_eq!(r.read_signed::<64, i64>().unwrap(), -9223372036854775808); assert_eq!(r.read_signed::<64, i64>().unwrap(), 9223372036854775807); } #[test] fn test_reader_huffman_be() { use bitstream_io::define_huffman_tree; use bitstream_io::{BigEndian, BitRead, BitReader}; define_huffman_tree!(SomeTree : i32 = [[[4, 3], 2], [1, 0]]); let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 4); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 2); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 2); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 2); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 4); assert_eq!(r.read_huffman::().unwrap(), 2); } #[test] fn test_read_chunks_be() { use bitstream_io::{BigEndian, BitRead, BitReader}; let data: &[u8] = &[0b1011_0001, 0b1110_1101, 0b0011_1011, 0b1100_0001]; let mut chunk: [u8; 2] = [0; 2]; // test non-aligned chunk reading let mut r = BitReader::endian(data, BigEndian); assert_eq!(r.read::<2, u8>().unwrap(), 0b10); r.read_bytes(&mut chunk).unwrap(); assert_eq!(&chunk, &[0b11_0001_11, 0b10_1101_00]); assert_eq!(r.read::<14, u16>().unwrap(), 0b11_1011_1100_0001); // test the smallest chunk let mut chunk = 0; let mut r = BitReader::endian(data, BigEndian); assert_eq!(r.read::<2, u8>().unwrap(), 0b10); r.read_bytes(core::slice::from_mut(&mut chunk)).unwrap(); assert_eq!(chunk, 0b11_0001_11); r.read_bytes(core::slice::from_mut(&mut chunk)).unwrap(); assert_eq!(chunk, 0b10_1101_00); assert_eq!(r.read::<14, u16>().unwrap(), 0b11_1011_1100_0001); // test a larger chunk let data = include_bytes!("random.bin"); let mut chunk: [u8; 127] = [0; 127]; let mut r = BitReader::endian(data.as_slice(), BigEndian); assert_eq!(r.read::<3, u8>().unwrap(), 0b000); r.read_bytes(&mut chunk).unwrap(); assert_eq!( chunk.as_slice(), include_bytes!("random-3be.bin").as_slice() ); assert_eq!(r.read::<5, u8>().unwrap(), 0b10110); } #[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(actual_data.as_slice(), 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(actual_data.as_slice(), LittleEndian); assert!(r.byte_aligned()); assert_eq!(r.read_var::(2).unwrap(), 1); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(3).unwrap(), 4); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(5).unwrap(), 13); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(3).unwrap(), 3); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(19).unwrap(), 0x609DF); assert!(r.byte_aligned()); assert!(r.read_var::(1).is_err()); // reading const unsigned values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert!(r.byte_aligned()); assert_eq!(r.read::<2, u32>().unwrap(), 1); assert!(!r.byte_aligned()); assert_eq!(r.read::<3, u32>().unwrap(), 4); assert!(!r.byte_aligned()); assert_eq!(r.read::<5, u32>().unwrap(), 13); assert!(!r.byte_aligned()); assert_eq!(r.read::<3, u32>().unwrap(), 3); assert!(!r.byte_aligned()); assert_eq!(r.read::<19, u32>().unwrap(), 0x609DF); assert!(r.byte_aligned()); assert!(r.read::<1, u32>().is_err()); // 16-bit values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!(r.read::<1, u8>().unwrap(), 1); assert_eq!(r.read::<14, u16>().unwrap(), 0b1101_1011_0110_00); assert_eq!(r.read::<16, u16>().unwrap(), 0b1000_0010_0111_0111); assert_eq!(r.read::<1, u8>().unwrap(), 1); // skipping bits let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!(r.read_var::(2).unwrap(), 1); assert!(r.skip(3).is_ok()); assert_eq!(r.read_var::(5).unwrap(), 13); assert!(r.skip(3).is_ok()); assert_eq!(r.read_var::(19).unwrap(), 0x609DF); // reading signed values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!(r.read_signed_var::(2).unwrap(), 1); assert_eq!(r.read_signed_var::(3).unwrap(), -4); assert_eq!(r.read_signed_var::(5).unwrap(), 13); assert_eq!(r.read_signed_var::(3).unwrap(), 3); assert_eq!(r.read_signed_var::(19).unwrap(), -128545); // reading const signed values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!(r.read_signed::<2, i32>().unwrap(), 1); assert_eq!(r.read_signed::<3, i32>().unwrap(), -4); assert_eq!(r.read_signed::<5, i32>().unwrap(), 13); assert_eq!(r.read_signed::<3, i32>().unwrap(), 3); assert_eq!(r.read_signed::<19, i32>().unwrap(), -128545); // reading unary 0 values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!(r.read_unary::<0>().unwrap(), 1); assert_eq!(r.read_unary::<0>().unwrap(), 0); assert_eq!(r.read_unary::<0>().unwrap(), 0); assert_eq!(r.read_unary::<0>().unwrap(), 2); assert_eq!(r.read_unary::<0>().unwrap(), 2); // reading unary 1 values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!(r.read_unary::<1>().unwrap(), 0); assert_eq!(r.read_unary::<1>().unwrap(), 3); assert_eq!(r.read_unary::<1>().unwrap(), 0); assert_eq!(r.read_unary::<1>().unwrap(), 1); assert_eq!(r.read_unary::<1>().unwrap(), 0); // byte aligning let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!(r.read_var::(3).unwrap(), 1); r.byte_align(); assert_eq!(r.read_var::(3).unwrap(), 5); r.byte_align(); r.byte_align(); assert_eq!(r.read_var::(8).unwrap(), 59); r.byte_align(); assert_eq!(r.read_var::(4).unwrap(), 1); // reading bytes, aligned let mut r = BitReader::endian(actual_data.as_slice(), 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(actual_data.as_slice(), LittleEndian); let mut sub_data = [0; 2]; assert_eq!(r.read_var::(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([255; 1].as_slice(), LittleEndian); assert_eq!(r.read_var::(0).unwrap(), 0); assert_eq!(r.read_var::(0).unwrap(), 0); assert_eq!(r.read_var::(0).unwrap(), 0); assert_eq!(r.read_var::(0).unwrap(), 0); assert_eq!(r.read_var::(8).unwrap(), 255); let mut r = BitReader::endian([255; 1].as_slice(), LittleEndian); assert_eq!(r.read::<0, u8>().unwrap(), 0); assert_eq!(r.read::<0, u16>().unwrap(), 0); assert_eq!(r.read::<0, u32>().unwrap(), 0); assert_eq!(r.read::<0, u64>().unwrap(), 0); assert_eq!(r.read::<8, u8>().unwrap(), 255); let mut r = BitReader::endian([255; 1].as_slice(), LittleEndian); assert!(r.read_signed_var::(0).is_err()); assert!(r.read_signed_var::(0).is_err()); assert!(r.read_signed_var::(0).is_err()); assert!(r.read_signed_var::(0).is_err()); // unsigned 32 and 64-bit values let mut r = BitReader::endian(data.as_slice(), LittleEndian); assert_eq!(r.read_var::(32).unwrap(), 0); assert_eq!(r.read_var::(32).unwrap(), 4294967295); assert_eq!(r.read_var::(32).unwrap(), 2147483648); assert_eq!(r.read_var::(32).unwrap(), 2147483647); assert_eq!(r.read_var::(64).unwrap(), 0); assert_eq!(r.read_var::(64).unwrap(), 0xFFFFFFFFFFFFFFFF); assert_eq!(r.read_var::(64).unwrap(), 9223372036854775808); assert_eq!(r.read_var::(64).unwrap(), 9223372036854775807); let mut r = BitReader::endian(data.as_slice(), LittleEndian); assert_eq!(r.read::<32, u32>().unwrap(), 0); assert_eq!(r.read::<32, u32>().unwrap(), 4294967295); assert_eq!(r.read::<32, u32>().unwrap(), 2147483648); assert_eq!(r.read::<32, u32>().unwrap(), 2147483647); assert_eq!(r.read::<64, u64>().unwrap(), 0); assert_eq!(r.read::<64, u64>().unwrap(), 0xFFFFFFFFFFFFFFFF); assert_eq!(r.read::<64, u64>().unwrap(), 9223372036854775808); assert_eq!(r.read::<64, u64>().unwrap(), 9223372036854775807); let mut r = BitReader::endian(data.as_slice(), LittleEndian); assert_eq!(r.read_signed_var::(32).unwrap(), 0); assert_eq!(r.read_signed_var::(32).unwrap(), -1); assert_eq!(r.read_signed_var::(32).unwrap(), -2147483648); assert_eq!(r.read_signed_var::(32).unwrap(), 2147483647); assert_eq!(r.read_signed_var::(64).unwrap(), 0); assert_eq!(r.read_signed_var::(64).unwrap(), -1); assert_eq!(r.read_signed_var::(64).unwrap(), -9223372036854775808); assert_eq!(r.read_signed_var::(64).unwrap(), 9223372036854775807); let mut r = BitReader::endian(data.as_slice(), LittleEndian); assert_eq!(r.read_signed::<32, i32>().unwrap(), 0); assert_eq!(r.read_signed::<32, i32>().unwrap(), -1); assert_eq!(r.read_signed::<32, i32>().unwrap(), -2147483648); assert_eq!(r.read_signed::<32, i32>().unwrap(), 2147483647); assert_eq!(r.read_signed::<64, i64>().unwrap(), 0); assert_eq!(r.read_signed::<64, i64>().unwrap(), -1); assert_eq!(r.read_signed::<64, i64>().unwrap(), -9223372036854775808); assert_eq!(r.read_signed::<64, i64>().unwrap(), 9223372036854775807); } #[test] fn test_reader_huffman_le() { use bitstream_io::define_huffman_tree; use bitstream_io::{BitRead, BitReader, LittleEndian}; define_huffman_tree!(SomeTree : i32 = [[[4, 3], 2], [1, 0]]); let actual_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 3); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 2); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 0); assert_eq!(r.read_huffman::().unwrap(), 1); assert_eq!(r.read_huffman::().unwrap(), 2); assert_eq!(r.read_huffman::().unwrap(), 4); assert_eq!(r.read_huffman::().unwrap(), 3); } #[test] fn test_read_chunks_le() { use bitstream_io::{BitRead, BitReader, LittleEndian}; let data: &[u8] = &[0b1011_0001, 0b1110_1101, 0b0011_1011, 0b1100_0001]; let mut chunk: [u8; 2] = [0; 2]; // test non-aligned chunk reading let mut r = BitReader::endian(data, LittleEndian); assert_eq!(r.read::<2, u8>().unwrap(), 0b01); r.read_bytes(&mut chunk).unwrap(); assert_eq!(&chunk, &[0b01_1011_00, 0b11_1110_11]); assert_eq!(r.read::<14, u16>().unwrap(), 0b1100_0001_0011_10); // test the smallest chunk let mut chunk = 0; let mut r = BitReader::endian(data, LittleEndian); assert_eq!(r.read::<2, u8>().unwrap(), 0b01); r.read_bytes(core::slice::from_mut(&mut chunk)).unwrap(); assert_eq!(chunk, 0b01_1011_00); r.read_bytes(core::slice::from_mut(&mut chunk)).unwrap(); assert_eq!(chunk, 0b11_1110_11); assert_eq!(r.read::<14, u16>().unwrap(), 0b1100_0001_0011_10); // test a larger chunk let data = include_bytes!("random.bin"); let mut chunk: [u8; 127] = [0; 127]; let mut r = BitReader::endian(data.as_slice(), LittleEndian); assert_eq!(r.read::<3, u8>().unwrap(), 0b010); r.read_bytes(&mut chunk).unwrap(); assert_eq!( chunk.as_slice(), include_bytes!("random-3le.bin").as_slice() ); assert_eq!(r.read::<5, u8>().unwrap(), 0b00110); } #[test] fn test_reader_io_errors_be() { use bitstream_io::{BigEndian, BitRead, BitReader}; use io::ErrorKind; let actual_data: [u8; 1] = [0xB1]; // individual bits let mut r = BitReader::endian(actual_data.as_slice(), 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(actual_data.as_slice(), BigEndian); assert!(r.read_var::(7).is_ok()); assert_eq!(r.skip(5).unwrap_err().kind(), ErrorKind::UnexpectedEof); // signed values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert!(r.read_signed_var::(2).is_ok()); assert!(r.read_signed_var::(3).is_ok()); assert_eq!( r.read_signed_var::(5).unwrap_err().kind(), ErrorKind::UnexpectedEof ); let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert!(r.read_signed::<2, i32>().is_ok()); assert!(r.read_signed::<3, i32>().is_ok()); assert_eq!( r.read_signed::<5, i32>().unwrap_err().kind(), ErrorKind::UnexpectedEof ); // unary 0 values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert!(r.read_unary::<0>().is_ok()); assert!(r.read_unary::<0>().is_ok()); assert!(r.read_unary::<0>().is_ok()); assert!(r.read_unary::<0>().is_ok()); assert_eq!( r.read_unary::<0>().unwrap_err().kind(), ErrorKind::UnexpectedEof ); // unary 1 values let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert!(r.read_unary::<1>().is_ok()); assert!(r.read_unary::<1>().is_ok()); assert!(r.read_unary::<1>().is_ok()); assert!(r.read_unary::<1>().is_ok()); assert_eq!( r.read_unary::<1>().unwrap_err().kind(), ErrorKind::UnexpectedEof ); // reading bytes, aligned let mut r = BitReader::endian(actual_data.as_slice(), 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(actual_data.as_slice(), BigEndian); let mut sub_data = [0; 2]; assert!(r.read_var::(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 io::ErrorKind; let actual_data: [u8; 1] = [0xB1]; // individual bits let mut r = BitReader::endian(actual_data.as_slice(), 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(actual_data.as_slice(), LittleEndian); assert!(r.read_var::(7).is_ok()); assert_eq!(r.skip(5).unwrap_err().kind(), ErrorKind::UnexpectedEof); // signed values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert!(r.read_signed_var::(2).is_ok()); assert!(r.read_signed_var::(3).is_ok()); assert_eq!( r.read_signed_var::(5).unwrap_err().kind(), ErrorKind::UnexpectedEof ); let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert!(r.read_signed::<2, i32>().is_ok()); assert!(r.read_signed::<3, i32>().is_ok()); assert_eq!( r.read_signed::<5, i32>().unwrap_err().kind(), ErrorKind::UnexpectedEof ); // unary 0 values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert!(r.read_unary::<0>().is_ok()); assert!(r.read_unary::<0>().is_ok()); assert!(r.read_unary::<0>().is_ok()); assert!(r.read_unary::<0>().is_ok()); assert_eq!( r.read_unary::<0>().unwrap_err().kind(), ErrorKind::UnexpectedEof ); // unary 1 values let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert!(r.read_unary::<1>().is_ok()); assert!(r.read_unary::<1>().is_ok()); assert!(r.read_unary::<1>().is_ok()); assert!(r.read_unary::<1>().is_ok()); assert_eq!( r.read_unary::<1>().unwrap_err().kind(), ErrorKind::UnexpectedEof ); // reading bytes, aligned let mut r = BitReader::endian(actual_data.as_slice(), 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(actual_data.as_slice(), LittleEndian); let mut sub_data = [0; 2]; assert!(r.read_var::(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 io::ErrorKind; let actual_data = [0u8; 10]; let mut r = BitReader::endian(actual_data.as_slice(), BigEndian); assert_eq!( r.read_var::(9).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_var::(17).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_var::(33).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_var::(65).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed_var::(9).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed_var::(17).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed_var::(33).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed_var::(65).unwrap_err().kind(), ErrorKind::InvalidInput ); let mut r = BitReader::endian(actual_data.as_slice(), LittleEndian); assert_eq!( r.read_var::(9).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_var::(17).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_var::(33).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_var::(65).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed_var::(9).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed_var::(17).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed_var::(33).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( r.read_signed_var::(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(actual_data.as_slice(), BigEndian); assert!(r.byte_aligned()); assert_eq!(r.read_var::(4).unwrap(), 0xB); let mut r2 = r.clone(); assert!(!r.byte_aligned()); assert_eq!(r.read_var::(4).unwrap(), 0x1); assert_eq!(r.read_var::(8).unwrap(), 0xED); assert!(!r2.byte_aligned()); assert_eq!(r2.read_var::(4).unwrap(), 0x1); assert_eq!(r2.read_var::(8).unwrap(), 0xED); // Can still instantiate a BitReader when the backing std::io::Read is // !Clone. struct NotCloneRead<'a>(&'a [u8]); impl<'a> io::Read for NotCloneRead<'a> { fn read(&mut self, buf: &mut [u8]) -> 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(actual_data.as_slice(), 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(actual_data.as_slice(), LittleEndian); let read_data: [u8; 4] = r.read_to().unwrap(); assert_eq!(actual_data, read_data); } #[test] fn test_large_reads() { use bitstream_io::{BigEndian, BitRead, BitReader, ByteRead, ByteReader, LittleEndian}; for size in [0, 1, 4096, 4097, 10000] { let input = (0..255).cycle().take(size).collect::>(); assert_eq!(input.len(), size); let mut r = BitReader::endian(input.as_slice(), BigEndian); let output = r.read_to_vec(size).unwrap(); assert_eq!(input, output); let mut r = BitReader::endian(input.as_slice(), LittleEndian); let output = r.read_to_vec(size).unwrap(); assert_eq!(input, output); let mut r = ByteReader::endian(input.as_slice(), BigEndian); let output = r.read_to_vec(size).unwrap(); assert_eq!(input, output); let mut r = ByteReader::endian(input.as_slice(), LittleEndian); let output = r.read_to_vec(size).unwrap(); assert_eq!(input, output); } let input: [u8; 5] = [0, 0, 0, 0, 0]; let mut r = BitReader::endian(input.as_slice(), BigEndian); assert!(r.read_to_vec(usize::MAX).is_err()); let mut r = BitReader::endian(input.as_slice(), LittleEndian); assert!(r.read_to_vec(usize::MAX).is_err()); let mut r = ByteReader::endian(input.as_slice(), BigEndian); assert!(r.read_to_vec(usize::MAX).is_err()); let mut r = ByteReader::endian(input.as_slice(), LittleEndian); assert!(r.read_to_vec(usize::MAX).is_err()); } #[test] fn test_bitcount_read() { use bitstream_io::{BigEndian, BitCount, BitRead, BitReader}; // 1 bit count - reading 1 bit let bytes = &[0b1_1_000000]; let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); let count = reader.read_count::<0b1>().unwrap(); assert_eq!(count, BitCount::new::<1>()); assert_eq!(reader.read_counted::<1, u8>(count).unwrap(), 0b1); // 2 bits count - reading 3 bits let bytes = &[0b11_111_000]; let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); let count = reader.read_count::<0b11>().unwrap(); assert_eq!(count, BitCount::new::<0b11>()); assert_eq!(reader.read_counted::<0b11, u8>(count).unwrap(), 0b111); // 3 bits count - reading 7 bits let bytes = &[0b111_11111, 0b11_000000]; let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); let count = reader.read_count::<0b111>().unwrap(); assert_eq!(count, BitCount::new::<0b111>()); assert_eq!(reader.read_counted::<0b111, u8>(count).unwrap(), 0b11111_11); // 4 bits count - reading 15 bits let bytes = &[0b1111_1111, 0b11111111, 0b111_00000]; let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); let count = reader.read_count::<0b1111>().unwrap(); assert_eq!(count, BitCount::new::<0b1111>()); assert_eq!( reader.read_counted::<0b1111, u16>(count).unwrap(), 0b1111_11111111_111 ); // 5 bits count - reading 31 bits let bytes = &[0b11111_111, 0b11111111, 0b11111111, 0b11111111, 0b1111_0000]; let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); let count = reader.read_count::<0b11111>().unwrap(); assert_eq!(count, BitCount::new::<0b11111>()); assert_eq!( reader.read_counted::<0b11111, u32>(count).unwrap(), 0b111_11111111_11111111_11111111_1111, ); // 6 bits count - reading 63 bits let bytes = &[ 0b111111_11, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111_000, ]; let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); let count = reader.read_count::<0b111111>().unwrap(); assert_eq!(count, BitCount::new::<0b111111>()); assert_eq!( reader.read_counted::<0b111111, u64>(count).unwrap(), 0b11_11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111, ); // 7 bits count - reading 127 bits let bytes = &[ 0b1111111_1, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b111111_00, ]; let mut reader = BitReader::endian(bytes.as_slice(), BigEndian); let count = reader.read_count::<0b1111111>().unwrap(); assert_eq!(count, BitCount::new::<0b1111111>()); assert_eq!( reader.read_counted::<0b1111111, u128>(count).unwrap(), 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, ); // We have to stop here because no primitive type gets any larger. // So while BitCount technically extends out to 32 bits, // it's not practical to get anywhere near that. } #[test] fn test_nonzero_reads() { use bitstream_io::{BigEndian, BitRead, BitReader, LittleEndian}; use core::num::NonZero; let data: &[u8] = &[0b001_00000, 0]; assert_eq!( BitReader::endian(data, BigEndian).read::<3, u8>().unwrap(), 1, ); assert_eq!( BitReader::endian(data, BigEndian) .read::<3, NonZero>() .unwrap() .get(), 2, ); assert_eq!( BitReader::endian(data, BigEndian) .read_var::(3) .unwrap(), 1, ); assert_eq!( BitReader::endian(data, BigEndian) .read_var::>(3) .unwrap() .get(), 2, ); assert!(BitReader::endian(data, BigEndian) .read_var::>(8) .is_err()); let data: &[u8] = &[0b00000_001, 0]; assert_eq!( BitReader::endian(data, LittleEndian) .read::<3, u8>() .unwrap(), 1, ); assert_eq!( BitReader::endian(data, LittleEndian) .read::<3, NonZero>() .unwrap() .get(), 2, ); assert_eq!( BitReader::endian(data, LittleEndian) .read_var::(3) .unwrap(), 1, ); assert_eq!( BitReader::endian(data, LittleEndian) .read_var::>(3) .unwrap() .get(), 2, ); assert!(BitReader::endian(data, LittleEndian) .read_var::>(8) .is_err()); } bitstream-io-4.9.0/tests/read_seek.rs000064400000000000000000000076061046102023000157000ustar 00000000000000use bitstream_io::{BigEndian, BitRead, BitReader, Endianness, LittleEndian}; use std::io::{self, Cursor, SeekFrom}; #[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_var(5)?; assert_eq!(r.position_in_bits()?, 7); let _: u32 = r.read_var(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_var(9)?; assert_eq!(r.position_in_bits()?, 43); let _: i32 = r.read_signed_var(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_var(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-4.9.0/tests/roundtrip.rs000064400000000000000000000314251046102023000160000ustar 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. use bitstream_io::{ BigEndian, BitRead, BitReader, BitWrite, BitWriter, Endianness, Integer, LittleEndian, Primitive, }; fn roundtrip() { /*unsigned values*/ for bits in 1..17 { let max = 1 << bits; let mut output: Vec = Vec::with_capacity(max); { let mut writer = BitWriter::<_, E>::new(&mut output); for value in 0..max { writer.write_var(bits, value as u32).unwrap(); } writer.byte_align().unwrap(); } { let mut reader = BitReader::<_, E>::new(output.as_slice()); for value in 0..max { assert_eq!(reader.read_var::(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::<_, E>::new(&mut output); for value in min..max { writer.write_signed_var(bits, value as i32).unwrap(); } writer.byte_align().unwrap(); } { let mut reader = BitReader::<_, E>::new(output.as_slice()); for value in min..max { assert_eq!(reader.read_signed_var::(bits).unwrap(), value as i32); } } } } #[test] fn test_rountrip_be() { roundtrip::(); } #[test] fn test_roundtrip_le() { roundtrip::(); } fn wide_roundtrip(start: I, end: I, increment: I) where E: Endianness, I: Integer + Copy + std::fmt::Debug + std::ops::AddAssign + std::cmp::PartialEq + std::cmp::PartialOrd, { let mut w = BitWriter::, E>::new(vec![]); // add an extra bit to check non byte-aligned values w.write_bit(true).unwrap(); let mut v = start; while v < end { w.write::(v).unwrap(); v += increment; } w.byte_align().unwrap(); let vec = w.into_writer(); let mut r = BitReader::<_, E>::new(vec.as_slice()); assert_eq!(r.read_bit().unwrap(), true); let mut v = start; while v < end { assert_eq!(r.read::().unwrap(), v); v += increment; } } #[test] fn test_roundtrip_u7_be() { wide_roundtrip::<7, BigEndian, u8>(u8::MIN, u8::MAX / 2, 1); } #[test] fn test_roundtrip_u7_le() { wide_roundtrip::<7, LittleEndian, u8>(u8::MIN, u8::MAX / 2, 1); } #[test] fn test_roundtrip_u8_be() { wide_roundtrip::<8, BigEndian, u8>(u8::MIN, u8::MAX, 1); } #[test] fn test_roundtrip_u8_le() { wide_roundtrip::<8, LittleEndian, u8>(u8::MIN, u8::MAX, 1); } #[test] fn test_roundtrip_i8_be() { wide_roundtrip::<8, BigEndian, i8>(i8::MIN, i8::MAX, 1); } #[test] fn test_roundtrip_i8_le() { wide_roundtrip::<8, LittleEndian, i8>(i8::MIN, i8::MAX, 1); } #[test] fn test_roundtrip_u9_be() { wide_roundtrip::<9, BigEndian, u16>(u16::MIN, u8::MAX as u16 * 2, 1); } #[test] fn test_roundtrip_u9_le() { wide_roundtrip::<9, LittleEndian, u16>(u16::MIN, u8::MAX as u16 * 2, 1); } #[test] fn test_roundtrip_u15_be() { wide_roundtrip::<15, BigEndian, u16>(u16::MIN, u16::MAX / 2, 1); } #[test] fn test_roundtrip_u15_le() { wide_roundtrip::<15, LittleEndian, u16>(u16::MIN, u16::MAX / 2, 1); } #[test] fn test_roundtrip_u16_be() { wide_roundtrip::<16, BigEndian, u16>(u16::MIN, u16::MAX, 1); } #[test] fn test_roundtrip_u16_le() { wide_roundtrip::<16, LittleEndian, u16>(u16::MIN, u16::MAX, 1); } #[test] fn test_roundtrip_i16_be() { wide_roundtrip::<16, BigEndian, i16>(i16::MIN, i16::MAX, 1); } #[test] fn test_roundtrip_i16_le() { wide_roundtrip::<16, LittleEndian, i16>(i16::MIN, i16::MAX, 1); } #[test] fn test_roundtrip_u32_be() { wide_roundtrip::<32, BigEndian, u32>(u32::MIN, u32::MAX - 65536, 65536); } #[test] fn test_roundtrip_u32_le() { wide_roundtrip::<32, LittleEndian, u32>(u32::MIN, u32::MAX - 65536, 65536); } #[test] fn test_roundtrip_i32_be() { wide_roundtrip::<32, BigEndian, i32>(i32::MIN, i32::MAX - 65536, 65536); } #[test] fn test_roundtrip_i32_le() { wide_roundtrip::<32, LittleEndian, i32>(i32::MIN, i32::MAX - 65536, 65536); } #[test] fn test_roundtrip_u64_be() { wide_roundtrip::<64, BigEndian, u64>(u64::MIN, u64::MAX - u64::MAX / 65536, u64::MAX / 65536); } #[test] fn test_roundtrip_u64_le() { wide_roundtrip::<64, LittleEndian, u64>( u64::MIN, u64::MAX - u64::MAX / 65536, u64::MAX / 65536, ); } #[test] fn test_roundtrip_i64_be() { wide_roundtrip::<64, BigEndian, i64>(i64::MIN, i64::MAX - i64::MAX / 65536, i64::MAX / 65536); } #[test] fn test_roundtrip_i64_le() { wide_roundtrip::<64, LittleEndian, i64>( i64::MIN, i64::MAX - i64::MAX / 65536, i64::MAX / 65536, ); } #[test] fn test_roundtrip_u128_be() { wide_roundtrip::<128, BigEndian, u128>( u128::MIN, u128::MAX - u128::MAX / 65536, u128::MAX / 65536, ); } #[test] fn test_roundtrip_u128_le() { wide_roundtrip::<128, LittleEndian, u128>( u128::MIN, u128::MAX - u128::MAX / 65536, u128::MAX / 65536, ); } #[test] fn test_roundtrip_i128_be() { wide_roundtrip::<128, BigEndian, i128>( i128::MIN, i128::MAX - i128::MAX / 65536, i128::MAX / 65536, ); } #[test] fn test_roundtrip_i128_le() { wide_roundtrip::<128, LittleEndian, i128>( i128::MIN, i128::MAX - i128::MAX / 65536, i128::MAX / 65536, ); } fn unary() { let mut output: Vec = Vec::new(); { let mut writer = BitWriter::<_, E>::new(&mut output); for value in 0..1024 { writer.write_unary::<0>(value).unwrap(); } writer.byte_align().unwrap(); } { let mut c = output.as_slice(); let mut reader = BitReader::<_, E>::new(&mut c); for value in 0..1024 { assert_eq!(reader.read_unary::<0>().unwrap(), value); } } let mut output: Vec = Vec::new(); { let mut writer = BitWriter::<_, E>::new(&mut output); for value in 0..1024 { writer.write_unary::<1>(value).unwrap(); } writer.byte_align().unwrap(); } { let mut c = output.as_slice(); let mut reader = BitReader::<_, E>::new(&mut c); for value in 0..1024 { assert_eq!(reader.read_unary::<1>().unwrap(), value); } } } #[test] fn test_unary_roundtrip_be() { unary::() } #[test] fn test_unary_roundtrip_le() { unary::() } fn float() where E: Endianness, P: Primitive + From + core::fmt::Debug + core::cmp::PartialEq, { let mut output: Vec = Vec::new(); { let mut writer = BitWriter::<_, E>::new(&mut output); // these values should all be exact in floating-point for value in 0..1024 { writer.write_from(P::from(value)).unwrap(); } writer.byte_align().unwrap(); } { let mut c = output.as_slice(); let mut reader = BitReader::<_, E>::new(&mut c); for value in 0..1024 { assert_eq!(reader.read_to::

().unwrap(), P::from(value)); } } } #[test] fn test_f32_roundtrip_be() { float::() } #[test] fn test_f64_roundtrip_be() { float::() } #[test] fn test_f32_roundtrip_le() { float::() } #[test] fn test_f64_roundtrip_le() { float::() } #[test] fn test_auto_signedness() { use bitstream_io::{ BigEndian, BitRead, BitReader, BitWrite, BitWriter, Endianness, Integer, LittleEndian, SignedInteger, UnsignedInteger, }; macro_rules! define_roundtrip { ($n:ident, $i:ident, $w:ident, $r:ident) => { fn $n( mut start: I, end: I, bits: u32, ) { let mut w: BitWriter<_, E> = BitWriter::new(Vec::new()); w.write_bit(true).unwrap(); let mut i = start; while i < end { w.$w(bits, i).unwrap(); i += I::ONE; } w.$w(bits, end).unwrap(); w.byte_align().unwrap(); let v = w.into_writer(); let mut r: BitReader<_, E> = BitReader::new(v.as_slice()); assert_eq!(r.read_bit().unwrap(), true); while start < end { assert_eq!(r.$r::(bits).unwrap(), start); start += I::ONE; } assert_eq!(r.$r::(bits).unwrap(), end); } }; } define_roundtrip!( test_writer_unsigned, UnsignedInteger, write_var, read_unsigned_var ); test_writer_unsigned::<_, BigEndian>(u8::MIN, u8::MAX, 8); test_writer_unsigned::<_, LittleEndian>(u8::MIN, u8::MAX, 8); define_roundtrip!( test_writer_signed, SignedInteger, write_var, read_signed_var ); test_writer_signed::<_, BigEndian>(i8::MIN, i8::MAX, 8); test_writer_signed::<_, LittleEndian>(i8::MIN, i8::MAX, 8); define_roundtrip!( test_reader_unsigned, UnsignedInteger, write_unsigned_var, read_var ); test_reader_unsigned::<_, BigEndian>(u8::MIN, u8::MAX, 8); test_reader_unsigned::<_, LittleEndian>(u8::MIN, u8::MAX, 8); define_roundtrip!( test_reader_signed, SignedInteger, write_signed_var, read_var ); test_reader_signed::<_, BigEndian>(i8::MIN, i8::MAX, 8); test_reader_signed::<_, LittleEndian>(i8::MIN, i8::MAX, 8); } #[test] fn test_bit_count() { use bitstream_io::{BigEndian, BitRead, BitReader, BitWrite, BitWriter}; let data: &[u8] = &[0b1111_0000]; // read a count from a 4-bit field let count = BitReader::endian(data, BigEndian) .read_count::<0b1111>() .unwrap(); assert_eq!(u32::from(count), 0b1111); // increment it by 1 let count = count.try_map::<16, _>(|i| i.checked_add(1)).unwrap(); assert_eq!(u32::from(count), 0b1111 + 1); // decrement it by 1 let count = count.try_map::<0b1111, _>(|i| i.checked_sub(1)).unwrap(); assert_eq!(u32::from(count), 0b1111); // write the count back to disk let mut w = BitWriter::endian(vec![], BigEndian); w.write_count::<0b1111>(count).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), data); } fn test_primitives() { use bitstream_io::{BitRead, BitReader, BitWrite, BitWriter}; // try a lot of primitive values, shifted by 1 bit let mut w = BitWriter::, E>::new(vec![]); w.write_bit(true).unwrap(); w.write_from::(u8::MAX - 10).unwrap(); w.write_from::(u16::MAX - 10).unwrap(); w.write_from::(u32::MAX - 10).unwrap(); w.write_from::(u64::MAX - 10).unwrap(); w.write_from::(u128::MAX - 10).unwrap(); w.write_from::(i8::MAX - 10).unwrap(); w.write_from::(i16::MAX - 10).unwrap(); w.write_from::(i32::MAX - 10).unwrap(); w.write_from::(i64::MAX - 10).unwrap(); w.write_from::(i128::MAX - 10).unwrap(); w.write_from::(1.0).unwrap(); w.write_from::(2.0).unwrap(); w.write_from::<[u8; 3]>([9, 8, 7]).unwrap(); w.byte_align().unwrap(); let v = w.into_writer(); let mut r = BitReader::<&[u8], E>::new(v.as_slice()); assert_eq!(r.read_bit().unwrap(), true); assert_eq!(r.read_to::().unwrap(), u8::MAX - 10); assert_eq!(r.read_to::().unwrap(), u16::MAX - 10); assert_eq!(r.read_to::().unwrap(), u32::MAX - 10); assert_eq!(r.read_to::().unwrap(), u64::MAX - 10); assert_eq!(r.read_to::().unwrap(), u128::MAX - 10); assert_eq!(r.read_to::().unwrap(), i8::MAX - 10); assert_eq!(r.read_to::().unwrap(), i16::MAX - 10); assert_eq!(r.read_to::().unwrap(), i32::MAX - 10); assert_eq!(r.read_to::().unwrap(), i64::MAX - 10); assert_eq!(r.read_to::().unwrap(), i128::MAX - 10); assert_eq!(r.read_to::().unwrap(), 1.0); assert_eq!(r.read_to::().unwrap(), 2.0); assert_eq!(r.read_to::<[u8; 3]>().unwrap(), [9, 8, 7]); } #[test] fn test_primitives_be() { test_primitives::() } #[test] fn test_primitives_le() { test_primitives::() } bitstream-io-4.9.0/tests/write.rs000064400000000000000000002140701046102023000151030ustar 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. use bitstream_io::{BigEndian, BitWrite, BitWriter}; use std::io; #[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_var(2, 2u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 6u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(5, 7u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 5u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(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::<2, u32>(2).unwrap(); assert!(!w.byte_aligned()); w.write::<3, u32>(6).unwrap(); assert!(!w.byte_aligned()); w.write::<5, u32>(7).unwrap(); assert!(!w.byte_aligned()); w.write::<3, u32>(5).unwrap(); assert!(!w.byte_aligned()); w.write::<19, u32>(0x53BC1).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::<1, u8>(1).unwrap(); assert!(!w.byte_aligned()); w.write::<14, u16>(0b0110_0011_1101_10).unwrap(); assert!(!w.byte_aligned()); w.write::<16, u16>(0b1001_1101_1110_0000).unwrap(); assert!(!w.byte_aligned()); w.write::<1, u8>(1).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_var(2, -2).unwrap(); w.write_signed_var(3, -2).unwrap(); w.write_signed_var(5, 7).unwrap(); w.write_signed_var(3, -3).unwrap(); w.write_signed_var(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::<2, i32>(-2).unwrap(); w.write_signed::<3, i32>(-2).unwrap(); w.write_signed::<5, i32>(7).unwrap(); w.write_signed::<3, i32>(-3).unwrap(); w.write_signed::<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_unary::<0>(1).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(4).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(3).unwrap(); w.write_unary::<0>(4).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_var(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_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(3).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(2).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(5).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); // writing unsigned vbr let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write_unsigned_vbr::<4, _>(11u8).unwrap(); // 001 011 -> <1>011 <0>001 w.write_unsigned_vbr::<4, _>(238u8).unwrap(); // 011 101 110 -> <1>110 <1>101 <0>011 w.write_unsigned_vbr::<4, _>(99u8).unwrap(); // 001 100 011 -> <1>011 <1>100 <0>001 assert_eq!(w.into_writer().as_slice(), &final_data); // writing signed vbr let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write_signed_vbr::<4, _>(-6i16).unwrap(); // 001 011 -> <1>011 <0>001 w.write_signed_vbr::<4, _>(119i16).unwrap(); // 011 101 110 -> <1>110 <1>101 <0>011 w.write_signed_vbr::<4, _>(-50i16).unwrap(); // 001 100 011 -> <1>011 <1>100 <0>001 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_var(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write_var(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write_var(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write_var(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_var(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_var(0, 0u8).unwrap(); w.write_var(0, 0u16).unwrap(); w.write_var(0, 0u32).unwrap(); w.write_var(0, 0u64).unwrap(); assert!(w.into_writer().is_empty()); let mut w = BitWriter::endian(Vec::new(), BigEndian); assert!(w.write_signed_var(0, 0i8).is_err()); assert!(w.write_signed_var(0, 0i16).is_err()); assert!(w.write_signed_var(0, 0i32).is_err()); assert!(w.write_signed_var(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_var(32, 0u32).unwrap(); w.write_var(32, 4294967295u32).unwrap(); w.write_var(32, 2147483648u32).unwrap(); w.write_var(32, 2147483647u32).unwrap(); w.write_var(64, 0u64).unwrap(); w.write_var(64, 0xFFFFFFFFFFFFFFFFu64).unwrap(); w.write_var(64, 9223372036854775808u64).unwrap(); w.write_var(64, 9223372036854775807u64).unwrap(); assert_eq!(w.into_writer(), final_data); let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); w.write::<32, u32>(0).unwrap(); w.write::<32, u32>(4294967295).unwrap(); w.write::<32, u32>(2147483648).unwrap(); w.write::<32, u32>(2147483647).unwrap(); w.write::<64, u64>(0).unwrap(); w.write::<64, u64>(0xFFFFFFFFFFFFFFFF).unwrap(); w.write::<64, u64>(9223372036854775808).unwrap(); w.write::<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_signed_var(32, 0i32).unwrap(); w.write_signed_var(32, -1i32).unwrap(); w.write_signed_var(32, -2147483648i32).unwrap(); w.write_signed_var(32, 2147483647i32).unwrap(); w.write_signed_var(64, 0i64).unwrap(); w.write_signed_var(64, -1i64).unwrap(); w.write_signed_var(64, -9223372036854775808i64).unwrap(); w.write_signed_var(64, 9223372036854775807i64).unwrap(); assert_eq!(w.into_writer(), final_data); let mut w = BitWriter::endian(Vec::with_capacity(48), BigEndian); w.write_signed::<32, i32>(0).unwrap(); w.write_signed::<32, i32>(-1).unwrap(); w.write_signed::<32, i32>(-2147483648).unwrap(); w.write_signed::<32, i32>(2147483647).unwrap(); w.write_signed::<64, i64>(0).unwrap(); w.write_signed::<64, i64>(-1).unwrap(); w.write_signed::<64, i64>(-9223372036854775808).unwrap(); w.write_signed::<64, i64>(9223372036854775807).unwrap(); assert_eq!(w.into_writer(), final_data); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(8, core::i8::MAX) .unwrap(); } assert_eq!(bytes, core::i8::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(8, core::i8::MIN) .unwrap(); } assert_eq!(bytes, core::i8::MIN.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(16, core::i16::MAX) .unwrap(); } assert_eq!(bytes, core::i16::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(16, core::i16::MIN) .unwrap(); } assert_eq!(bytes, core::i16::MIN.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(32, core::i32::MAX) .unwrap(); } assert_eq!(bytes, core::i32::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(32, core::i32::MIN) .unwrap(); } assert_eq!(bytes, core::i32::MIN.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(64, core::i64::MAX) .unwrap(); } assert_eq!(bytes, core::i64::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(64, core::i64::MIN) .unwrap(); } assert_eq!(bytes, core::i64::MIN.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(128, core::i128::MAX) .unwrap(); } assert_eq!(bytes, core::i128::MAX.to_be_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, BigEndian) .write_signed_var(128, core::i128::MIN) .unwrap(); } assert_eq!(bytes, core::i128::MIN.to_be_bytes()); } #[test] fn test_writer_huffman_be() { use bitstream_io::define_huffman_tree; use bitstream_io::{BigEndian, BitWrite, BitWriter}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; define_huffman_tree!(TreeName : i32 = [[[4, 3], 2], [1, 0]]); let mut w = BitWriter::endian(Vec::with_capacity(4), BigEndian); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(2).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); } #[test] fn test_write_chunks_be() { use bitstream_io::{BigEndian, BitWrite, BitWriter}; let data: &[u8] = &[0b1011_0001, 0b1110_1101, 0b0011_1011, 0b1100_0001]; // test non-aligned chunk writing let mut w = BitWriter::endian(vec![], BigEndian); w.write::<2, u8>(0b10).unwrap(); w.write_bytes(&[0b11_0001_11, 0b10_1101_00]).unwrap(); w.write::<14, u16>(0b11_1011_1100_0001).unwrap(); assert_eq!(w.into_writer().as_slice(), data); // test the smallest chunk let mut w = BitWriter::endian(vec![], BigEndian); w.write::<2, u8>(0b10).unwrap(); w.write_bytes(core::slice::from_ref(&0b11_0001_11)).unwrap(); w.write_bytes(core::slice::from_ref(&0b10_1101_00)).unwrap(); w.write::<14, u16>(0b11_1011_1100_0001).unwrap(); assert_eq!(w.into_writer().as_slice(), data); // test a larger chunk let mut w = BitWriter::endian(vec![], BigEndian); w.write::<3, u8>(0b000).unwrap(); w.write_bytes(include_bytes!("random-3be.bin").as_slice()) .unwrap(); w.write::<5, u8>(0b10110).unwrap(); assert_eq!( w.into_writer().as_slice(), include_bytes!("random.bin").as_slice() ); } #[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_var(2, 1u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 4u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(5, 13u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 3u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(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::<2, u32>(1).unwrap(); assert!(!w.byte_aligned()); w.write::<3, u32>(4).unwrap(); assert!(!w.byte_aligned()); w.write::<5, u32>(13).unwrap(); assert!(!w.byte_aligned()); w.write::<3, u32>(3).unwrap(); assert!(!w.byte_aligned()); w.write::<19, u32>(0x609DF).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::<1, u8>(1).unwrap(); assert!(!w.byte_aligned()); w.write::<14, u16>(0b1101_1011_0110_00).unwrap(); assert!(!w.byte_aligned()); w.write::<16, u16>(0b1000_0010_0111_0111).unwrap(); assert!(!w.byte_aligned()); w.write::<1, u8>(1).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_var(2, 1).unwrap(); w.write_signed_var(3, -4).unwrap(); w.write_signed_var(5, 13).unwrap(); w.write_signed_var(3, 3).unwrap(); w.write_signed_var(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::<2, i32>(1).unwrap(); w.write_signed::<3, i32>(-4).unwrap(); w.write_signed::<5, i32>(13).unwrap(); w.write_signed::<3, i32>(3).unwrap(); w.write_signed::<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_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(5).unwrap(); w.write_unary::<0>(3).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_var(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_unary::<1>(0).unwrap(); w.write_unary::<1>(3).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(2).unwrap(); w.write_unary::<1>(5).unwrap(); w.write_unary::<1>(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_var(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write_var(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write_var(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write_var(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_var(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_var(0, 0u8).unwrap(); w.write_var(0, 0u16).unwrap(); w.write_var(0, 0u32).unwrap(); w.write_var(0, 0u64).unwrap(); assert!(w.into_writer().is_empty()); let mut w = BitWriter::endian(Vec::new(), LittleEndian); assert!(w.write_signed_var(0, 0i8).is_err()); assert!(w.write_signed_var(0, 0i16).is_err()); assert!(w.write_signed_var(0, 0i32).is_err()); assert!(w.write_signed_var(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_var(32, 0u32).unwrap(); w.write_var(32, 4294967295u32).unwrap(); w.write_var(32, 2147483648u32).unwrap(); w.write_var(32, 2147483647u32).unwrap(); w.write_var(64, 0u64).unwrap(); w.write_var(64, 0xFFFFFFFFFFFFFFFFu64).unwrap(); w.write_var(64, 9223372036854775808u64).unwrap(); w.write_var(64, 9223372036854775807u64).unwrap(); assert_eq!(w.into_writer(), final_data); let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); w.write::<32, u32>(0).unwrap(); w.write::<32, u32>(4294967295).unwrap(); w.write::<32, u32>(2147483648).unwrap(); w.write::<32, u32>(2147483647).unwrap(); w.write::<64, u64>(0).unwrap(); w.write::<64, u64>(0xFFFFFFFFFFFFFFFF).unwrap(); w.write::<64, u64>(9223372036854775808).unwrap(); w.write::<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_signed_var(32, 0i32).unwrap(); w.write_signed_var(32, -1i32).unwrap(); w.write_signed_var(32, -2147483648i32).unwrap(); w.write_signed_var(32, 2147483647i32).unwrap(); w.write_signed_var(64, 0i64).unwrap(); w.write_signed_var(64, -1i64).unwrap(); w.write_signed_var(64, -9223372036854775808i64).unwrap(); w.write_signed_var(64, 9223372036854775807i64).unwrap(); assert_eq!(w.into_writer(), final_data); let mut w = BitWriter::endian(Vec::with_capacity(48), LittleEndian); w.write_signed::<32, i32>(0).unwrap(); w.write_signed::<32, i32>(-1).unwrap(); w.write_signed::<32, i32>(-2147483648).unwrap(); w.write_signed::<32, i32>(2147483647).unwrap(); w.write_signed::<64, i64>(0).unwrap(); w.write_signed::<64, i64>(-1).unwrap(); w.write_signed::<64, i64>(-9223372036854775808).unwrap(); w.write_signed::<64, i64>(9223372036854775807).unwrap(); assert_eq!(w.into_writer(), final_data); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(8, core::i8::MAX) .unwrap(); } assert_eq!(bytes, core::i8::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(8, core::i8::MIN) .unwrap(); } assert_eq!(bytes, core::i8::MIN.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(16, core::i16::MAX) .unwrap(); } assert_eq!(bytes, core::i16::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(16, core::i16::MIN) .unwrap(); } assert_eq!(bytes, core::i16::MIN.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(32, core::i32::MAX) .unwrap(); } assert_eq!(bytes, core::i32::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(32, core::i32::MIN) .unwrap(); } assert_eq!(bytes, core::i32::MIN.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(64, core::i64::MAX) .unwrap(); } assert_eq!(bytes, core::i64::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(64, core::i64::MIN) .unwrap(); } assert_eq!(bytes, core::i64::MIN.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(128, core::i128::MAX) .unwrap(); } assert_eq!(bytes, core::i128::MAX.to_le_bytes()); let mut bytes = Vec::new(); { BitWriter::endian(&mut bytes, LittleEndian) .write_signed_var(128, core::i128::MIN) .unwrap(); } assert_eq!(bytes, core::i128::MIN.to_le_bytes()); } #[test] fn test_writer_huffman_le() { use bitstream_io::define_huffman_tree; use bitstream_io::{BitWrite, BitWriter, LittleEndian}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; define_huffman_tree!(TreeName : i32= [[[4, 3], 2], [1, 0]]); let mut w = BitWriter::endian(Vec::with_capacity(4), LittleEndian); w.write_huffman::(1).unwrap(); w.write_huffman::(3).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(3).unwrap(); w.write_var(1, 1u8).unwrap(); assert_eq!(w.into_writer().as_slice(), &final_data); } #[test] fn test_write_chunks_le() { use bitstream_io::{BitWrite, BitWriter, LittleEndian}; let data: &[u8] = &[0b1011_0001, 0b1110_1101, 0b0011_1011, 0b1100_0001]; // test non-aligned chunk writing let mut w = BitWriter::endian(vec![], LittleEndian); w.write::<2, u8>(0b01).unwrap(); w.write_bytes(&[0b01_1011_00, 0b11_1110_11]).unwrap(); w.write::<14, u16>(0b1100_0001_0011_10).unwrap(); assert_eq!(w.into_writer().as_slice(), data); // test the smallest chunk let mut w = BitWriter::endian(vec![], LittleEndian); w.write::<2, u8>(0b01).unwrap(); w.write_bytes(core::slice::from_ref(&0b01_1011_00)).unwrap(); w.write_bytes(core::slice::from_ref(&0b11_1110_11)).unwrap(); w.write::<14, u16>(0b1100_0001_0011_10).unwrap(); assert_eq!(w.into_writer().as_slice(), data); // test a larger chunk let mut w = BitWriter::endian(vec![], LittleEndian); w.write::<3, u8>(0b010).unwrap(); w.write_bytes(include_bytes!("random-3le.bin").as_slice()) .unwrap(); w.write::<5, u8>(0b00110).unwrap(); assert_eq!( w.into_writer().as_slice(), include_bytes!("random.bin").as_slice() ); } struct LimitedWriter { can_write: usize, } impl LimitedWriter { fn new(max_bytes: usize) -> LimitedWriter { LimitedWriter { can_write: max_bytes, } } } impl io::Write for LimitedWriter { fn write(&mut self, buf: &[u8]) -> Result { let to_write = buf.len().min(self.can_write); self.can_write -= to_write; Ok(to_write) } fn flush(&mut self) -> Result<(), io::Error> { Ok(()) } } #[test] fn test_writer_io_errors_be() { use bitstream_io::{BigEndian, BitWrite, BitWriter}; use 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_var(2, 2u32).is_ok()); assert!(w.write_var(3, 6u32).is_ok()); assert!(w.write_var(5, 7u32).is_ok()); assert!(w.write_var(3, 5u32).is_ok()); assert_eq!( w.write_var(19, 0x53BC1u32).unwrap_err().kind(), ErrorKind::WriteZero ); // signed values let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write_signed_var(2, -2).is_ok()); assert!(w.write_signed_var(3, -2).is_ok()); assert!(w.write_signed_var(5, 7).is_ok()); assert!(w.write_signed_var(3, -3).is_ok()); assert_eq!( w.write_signed_var(19, -181311).unwrap_err().kind(), ErrorKind::WriteZero ); // unary 0 values let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write_unary::<0>(1).is_ok()); assert!(w.write_unary::<0>(2).is_ok()); assert!(w.write_unary::<0>(0).is_ok()); assert!(w.write_unary::<0>(0).is_ok()); assert!(w.write_unary::<0>(4).is_ok()); assert!(w.write_unary::<0>(2).is_ok()); assert_eq!( w.write_unary::<0>(1).unwrap_err().kind(), ErrorKind::WriteZero ); // unary 1 values let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(1).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(3).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(1).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert_eq!( w.write_unary::<1>(1).unwrap_err().kind(), ErrorKind::WriteZero ); // byte aligning let mut w = BitWriter::endian(LimitedWriter::new(1), BigEndian); assert!(w.write_var::(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_var(4, 11u8).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 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_var(2, 1u32).is_ok()); assert!(w.write_var(3, 4u32).is_ok()); assert!(w.write_var(5, 13u32).is_ok()); assert!(w.write_var(3, 3u32).is_ok()); assert_eq!( w.write_var(19, 0x609DFu32).unwrap_err().kind(), ErrorKind::WriteZero ); // signed values let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write_signed_var(2, 1).is_ok()); assert!(w.write_signed_var(3, -4).is_ok()); assert!(w.write_signed_var(5, 13).is_ok()); assert!(w.write_signed_var(3, 3).is_ok()); assert_eq!( w.write_signed_var(19, -128545).unwrap_err().kind(), ErrorKind::WriteZero ); // unary 0 values let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write_unary::<0>(1).is_ok()); assert!(w.write_unary::<0>(0).is_ok()); assert!(w.write_unary::<0>(0).is_ok()); assert!(w.write_unary::<0>(2).is_ok()); assert!(w.write_unary::<0>(2).is_ok()); assert!(w.write_unary::<0>(2).is_ok()); assert_eq!( w.write_unary::<0>(5).unwrap_err().kind(), ErrorKind::WriteZero ); // unary 1 values let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(3).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(1).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(1).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert!(w.write_unary::<1>(1).is_ok()); assert!(w.write_unary::<1>(0).is_ok()); assert_eq!( w.write_unary::<1>(1).unwrap_err().kind(), ErrorKind::WriteZero ); // byte aligning let mut w = BitWriter::endian(LimitedWriter::new(1), LittleEndian); assert!(w.write_var::(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_var(4, 11u8).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 io::{sink, ErrorKind}; let mut w = BitWriter::endian(sink(), BigEndian); assert_eq!( w.write_var(9, 0u8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(17, 0u16).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(33, 0u32).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(65, 0u64).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(1, 0b10u8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(2, 0b100u8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(3, 0b1000u8).unwrap_err().kind(), ErrorKind::InvalidInput ); for bits in 1..8 { let val = 1u8 << bits; assert_eq!( w.write_var(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 8..16 { let val = 1u16 << bits; assert_eq!( w.write_var(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 16..32 { let val = 1u32 << bits; assert_eq!( w.write_var(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 32..64 { let val = 1u64 << bits; assert_eq!( w.write_var(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } assert_eq!( w.write_signed_var(9, 0i8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed_var(17, 0i16).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed_var(33, 0i32).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed_var(65, 0i64).unwrap_err().kind(), ErrorKind::InvalidInput ); let mut w = BitWriter::endian(sink(), LittleEndian); assert_eq!( w.write_var(9, 0u8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(17, 0u16).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(33, 0u32).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(65, 0u64).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(1, 0b10u8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(2, 0b100u8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_var(3, 0b1000u8).unwrap_err().kind(), ErrorKind::InvalidInput ); for bits in 1..8 { let val = 1u8 << bits; assert_eq!( w.write_var(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 8..16 { let val = 1u16 << bits; assert_eq!( w.write_var(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 16..32 { let val = 1u32 << bits; assert_eq!( w.write_var(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } for bits in 32..64 { let val = 1u64 << bits; assert_eq!( w.write_var(bits, val).unwrap_err().kind(), ErrorKind::InvalidInput ); } assert_eq!( w.write_signed_var(9, 0i8).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed_var(17, 0i16).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed_var(33, 0i32).unwrap_err().kind(), ErrorKind::InvalidInput ); assert_eq!( w.write_signed_var(65, 0i64).unwrap_err().kind(), ErrorKind::InvalidInput ); } #[test] fn test_counter_be() { use bitstream_io::{BitWrite, BitsWritten}; // writing individual bits let mut w: BitsWritten = BitsWritten::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: BitsWritten = BitsWritten::new(); assert!(w.byte_aligned()); w.write_var(2, 2u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 6u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(5, 7u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 5u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(19, 0x53BC1u32).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.written(), 32); // writing signed values let mut w: BitsWritten = BitsWritten::new(); w.write_signed_var(2, -2).unwrap(); w.write_signed_var(3, -2).unwrap(); w.write_signed_var(5, 7).unwrap(); w.write_signed_var(3, -3).unwrap(); w.write_signed_var(19, -181311).unwrap(); assert_eq!(w.written(), 32); // writing unary 0 values let mut w: BitsWritten = BitsWritten::new(); w.write_unary::<0>(1).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(4).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(3).unwrap(); w.write_unary::<0>(4).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_var(1, 1u32).unwrap(); assert_eq!(w.written(), 32); // writing unary 1 values let mut w: BitsWritten = BitsWritten::new(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(3).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(2).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(5).unwrap(); assert_eq!(w.written(), 32); // byte aligning let mut w: BitsWritten = BitsWritten::new(); w.write_var(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write_var(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write_var(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write_var(4, 12u32).unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 32); // writing bytes, aligned let mut w: BitsWritten = BitsWritten::new(); w.write_bytes(b"\xB1\xED").unwrap(); assert_eq!(w.written(), 16); // writing bytes, un-aligned let mut w: BitsWritten = BitsWritten::new(); w.write_var(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::define_huffman_tree; use bitstream_io::{BitWrite, BitsWritten}; define_huffman_tree!(TreeName : i32 = [[[4, 3], 2], [1, 0]]); let mut w: BitsWritten = BitsWritten::new(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(2).unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 32); } #[test] fn test_counter_le() { use bitstream_io::{BitWrite, BitsWritten}; // writing individual bits let mut w: BitsWritten = BitsWritten::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: BitsWritten = BitsWritten::new(); assert!(w.byte_aligned()); w.write_var(2, 1u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 4u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(5, 13u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 3u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(19, 0x609DFu32).unwrap(); assert!(w.byte_aligned()); assert_eq!(w.written(), 32); // writing signed values let mut w: BitsWritten = BitsWritten::new(); w.write_signed_var(2, 1).unwrap(); w.write_signed_var(3, -4).unwrap(); w.write_signed_var(5, 13).unwrap(); w.write_signed_var(3, 3).unwrap(); w.write_signed_var(19, -128545).unwrap(); assert_eq!(w.written(), 32); // writing unary 0 values let mut w: BitsWritten = BitsWritten::new(); w.write_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(5).unwrap(); w.write_unary::<0>(3).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_var(2, 3u32).unwrap(); assert_eq!(w.written(), 32); // writing unary 1 values let mut w: BitsWritten = BitsWritten::new(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(3).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(2).unwrap(); w.write_unary::<1>(5).unwrap(); w.write_unary::<1>(0).unwrap(); assert_eq!(w.written(), 32); // byte aligning let mut w: BitsWritten = BitsWritten::new(); w.write_var(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write_var(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write_var(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write_var(4, 12u32).unwrap(); w.byte_align().unwrap(); assert_eq!(w.written(), 32); // writing bytes, aligned let mut w: BitsWritten = BitsWritten::new(); w.write_bytes(b"\xB1\xED").unwrap(); assert_eq!(w.written(), 16); // writing bytes, un-aligned let mut w: BitsWritten = BitsWritten::new(); w.write_var(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::define_huffman_tree; use bitstream_io::{BitWrite, BitsWritten}; define_huffman_tree!(TreeName : i32= [[[4, 3], 2], [1, 0]]); let mut w: BitsWritten = BitsWritten::new(); w.write_huffman::(1).unwrap(); w.write_huffman::(3).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(3).unwrap(); w.write::<1, u8>(1).unwrap(); assert_eq!(w.written(), 32); } #[test] fn test_recorder_be() { use bitstream_io::{BigEndian, BitRecorder, BitWrite, BitWriter}; // partial writes let mut w: BitRecorder = BitRecorder::new(); w.write_bit(true).unwrap(); let mut w2 = BitWriter::endian(vec![], BigEndian); w.playback(&mut w2).unwrap(); w2.byte_align().unwrap(); let mut w3 = BitWriter::endian(vec![], BigEndian); w3.write_bit(true).unwrap(); w3.byte_align().unwrap(); assert_eq!(w2.into_writer(), w3.into_writer()); 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_var(2, 2u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 6u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(5, 7u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 5u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(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_var(2, -2).unwrap(); w.write_signed_var(3, -2).unwrap(); w.write_signed_var(5, 7).unwrap(); w.write_signed_var(3, -3).unwrap(); w.write_signed_var(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_unary::<0>(1).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(4).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(3).unwrap(); w.write_unary::<0>(4).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_var(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_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(3).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(2).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(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_var(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write_var(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write_var(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write_var(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_var(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::define_huffman_tree; use bitstream_io::{BigEndian, BitRecorder, BitWrite, BitWriter}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; define_huffman_tree!(TreeName : i32 = [[[4, 3], 2], [1, 0]]); let mut w: BitRecorder = BitRecorder::new(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(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}; // partial writes let mut w: BitRecorder = BitRecorder::new(); w.write_bit(true).unwrap(); let mut w2 = BitWriter::endian(vec![], LittleEndian); w.playback(&mut w2).unwrap(); w2.byte_align().unwrap(); let mut w3 = BitWriter::endian(vec![], LittleEndian); w3.write_bit(true).unwrap(); w3.byte_align().unwrap(); assert_eq!(w2.into_writer(), w3.into_writer()); 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_var(2, 1u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 4u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(5, 13u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(3, 3u32).unwrap(); assert!(!w.byte_aligned()); w.write_var(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_var(2, 1).unwrap(); w.write_signed_var(3, -4).unwrap(); w.write_signed_var(5, 13).unwrap(); w.write_signed_var(3, 3).unwrap(); w.write_signed_var(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_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(2).unwrap(); w.write_unary::<0>(5).unwrap(); w.write_unary::<0>(3).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(1).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_unary::<0>(0).unwrap(); w.write_var(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_unary::<1>(0).unwrap(); w.write_unary::<1>(3).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(1).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(0).unwrap(); w.write_unary::<1>(2).unwrap(); w.write_unary::<1>(5).unwrap(); w.write_unary::<1>(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_var(3, 5u32).unwrap(); w.byte_align().unwrap(); w.write_var(3, 7u32).unwrap(); w.byte_align().unwrap(); w.byte_align().unwrap(); w.write_var(8, 59u32).unwrap(); w.byte_align().unwrap(); w.write_var(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_var(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::define_huffman_tree; use bitstream_io::{BitRecorder, BitWrite, BitWriter, LittleEndian}; let final_data: [u8; 4] = [0xB1, 0xED, 0x3B, 0xC1]; define_huffman_tree!(TreeName : i32 = [[[4, 3], 2], [1, 0]]); let mut w: BitRecorder = BitRecorder::new(); w.write_huffman::(1).unwrap(); w.write_huffman::(3).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(0).unwrap(); w.write_huffman::(1).unwrap(); w.write_huffman::(2).unwrap(); w.write_huffman::(4).unwrap(); w.write_huffman::(3).unwrap(); w.write::<1, u8>(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); } #[test] fn test_pad() { use bitstream_io::{BigEndian, Endianness, LittleEndian}; fn test_pad_endian() { use bitstream_io::BitWriter; let mut plain: BitWriter<_, E> = BitWriter::new(Vec::new()); let mut padded: BitWriter<_, E> = BitWriter::new(Vec::new()); for bits in 1..64 { plain.write_bit(true).unwrap(); plain.write_var(bits, 0u64).unwrap(); padded.write_bit(true).unwrap(); padded.pad(bits).unwrap(); } // plain.write_from([0u8; 1024]).unwrap(); // plain.write_bit(true).unwrap(); // padded.pad(1024 * 8).unwrap(); // padded.write_bit(true).unwrap(); plain.byte_align().unwrap(); padded.byte_align().unwrap(); assert_eq!(plain.into_writer(), padded.into_writer()); } test_pad_endian::(); test_pad_endian::(); } #[test] fn test_counter_overflow() { use bitstream_io::BitsWritten; // overflow u8 with many small writes let mut counter: BitsWritten = BitsWritten::new(); for _ in 0..255 { assert!(counter.write_bit(false).is_ok()); } assert!(counter.write_bit(false).is_err()); // overflow u8 with one big write let mut counter: BitsWritten = BitsWritten::new(); assert!(counter.write_from([0u8; 31]).is_ok()); let mut counter: BitsWritten = BitsWritten::new(); assert!(counter.write_from([0u8; 32]).is_err()); } #[test] fn test_negative_write() { let mut bit_writer = BitWriter::endian(Vec::new(), BigEndian); assert!(bit_writer.write_bit(false).is_ok()); assert!(bit_writer.write_var(8, -1i8).is_ok()); assert!(bit_writer.write_var(7, 0u8).is_ok()); if let Some(writer) = bit_writer.writer() { assert_eq!(writer[0] >> 7, 0); } else { panic!("writer() returned None"); } } #[test] fn test_bitcount_write() { use bitstream_io::{BigEndian, BitCount, BitWrite, BitWriter}; // 1 bit count - writing 1 bit let bytes = vec![]; let mut writer = BitWriter::endian(bytes, BigEndian); let count = BitCount::<0b1>::new::<1>(); writer.write_count(count).unwrap(); writer.write_counted::<1, u8>(count, 0b1).unwrap(); writer.byte_align().unwrap(); assert_eq!(writer.into_writer(), &[0b1_1_000000]); // 2 bit count - writing 3 bits let bytes = vec![]; let mut writer = BitWriter::endian(bytes, BigEndian); let count = BitCount::<0b11>::new::<0b11>(); writer.write_count(count).unwrap(); writer.write_counted::<0b11, u8>(count, 0b111).unwrap(); writer.byte_align().unwrap(); assert_eq!(writer.into_writer(), &[0b11_111_000]); // 3 bit count - writing 7 bits let bytes = vec![]; let mut writer = BitWriter::endian(bytes, BigEndian); let count = BitCount::<0b111>::new::<0b111>(); writer.write_count(count).unwrap(); writer .write_counted::<0b111, u8>(count, 0b11111_11) .unwrap(); writer.byte_align().unwrap(); assert_eq!(writer.into_writer(), &[0b111_11111, 0b11_000000]); // 4 bit count - writing 15 bits let bytes = vec![]; let mut writer = BitWriter::endian(bytes, BigEndian); let count = BitCount::<0b1111>::new::<0b1111>(); writer.write_count(count).unwrap(); writer .write_counted::<0b1111, u16>(count, 0b1111_11111111_111) .unwrap(); writer.byte_align().unwrap(); assert_eq!( writer.into_writer(), &[0b1111_1111, 0b11111111, 0b111_00000] ); // 5 bits count - writing 31 bits let bytes = vec![]; let mut writer = BitWriter::endian(bytes, BigEndian); let count = BitCount::<0b11111>::new::<0b11111>(); writer.write_count(count).unwrap(); writer .write_counted::<0b11111, u32>(count, 0b111_11111111_11111111_11111111_1111) .unwrap(); writer.byte_align().unwrap(); assert_eq!( writer.into_writer(), &[0b11111_111, 0b11111111, 0b11111111, 0b11111111, 0b1111_0000] ); // 6 bits count - writing 63 bits let bytes = vec![]; let mut writer = BitWriter::endian(bytes, BigEndian); let count = BitCount::<0b111111>::new::<0b111111>(); writer.write_count(count).unwrap(); writer .write_counted::<0b111111, u64>( count, 0b11_11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111, ) .unwrap(); writer.byte_align().unwrap(); assert_eq!( writer.into_writer(), &[ 0b111111_11, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111_000 ] ); // 7 bits count - writing 127 bits let bytes = vec![]; let mut writer = BitWriter::endian(bytes, BigEndian); let count = BitCount::<0b1111111>::new::<0b1111111>(); writer.write_count(count).unwrap(); writer .write_counted::<0b1111111, u128>(count, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) .unwrap(); writer.byte_align().unwrap(); assert_eq!( writer.into_writer(), &[ 0b1111111_1, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b111111_00, ] ); } #[test] fn test_nonzero_writes() { use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian}; use core::num::NonZero; let mut w = BitWriter::endian(vec![], BigEndian); w.write::<3, u8>(1).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), &[0b001_00000]); let mut w = BitWriter::endian(vec![], BigEndian); w.write::<3, NonZero>(NonZero::new(2).unwrap()).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), &[0b001_00000]); let mut w = BitWriter::endian(vec![], BigEndian); w.write_var::(3, 1).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), &[0b001_00000]); let mut w = BitWriter::endian(vec![], BigEndian); w.write_var::>(3, NonZero::new(2).unwrap()) .unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), &[0b001_00000]); let mut w = BitWriter::endian(vec![], LittleEndian); w.write::<3, u8>(1).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), &[0b00000_001]); let mut w = BitWriter::endian(vec![], LittleEndian); w.write::<3, NonZero>(NonZero::new(2).unwrap()).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), &[0b00000_001]); let mut w = BitWriter::endian(vec![], LittleEndian); w.write_var::(3, 1).unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), &[0b00000_001]); let mut w = BitWriter::endian(vec![], LittleEndian); w.write_var::>(3, NonZero::new(2).unwrap()) .unwrap(); w.byte_align().unwrap(); assert_eq!(w.into_writer(), &[0b00000_001]); } #[test] fn test_const_writes() { use bitstream_io::{BigEndian, BitWrite, BitWriter, LittleEndian}; let mut w = BitWriter::endian(vec![], BigEndian); w.write_const::<0, 0b0>().unwrap(); w.write_const::<1, 0b1>().unwrap(); w.write_const::<2, 0b10>().unwrap(); w.write_const::<3, 0b100>().unwrap(); w.write_const::<4, 0b1000>().unwrap(); w.write_const::<5, 0b10000>().unwrap(); w.write_const::<6, 0b100000>().unwrap(); w.write_const::<7, 0b1000000>().unwrap(); w.write_const::<8, 0b10000000>().unwrap(); w.write_const::<9, 0b100000000>().unwrap(); w.write_const::<10, 0b1000000000>().unwrap(); w.byte_align().unwrap(); assert_eq!( w.into_writer(), &[ 0b1_10_100_10, 0b00_100001, 0b00000_100, 0b0000_1000, 0b0000_1000, 0b00000_100, 0b00000000 ] ); let mut w = BitWriter::endian(vec![], LittleEndian); w.write_const::<0, 0b0>().unwrap(); w.write_const::<1, 0b1>().unwrap(); w.write_const::<2, 0b10>().unwrap(); w.write_const::<3, 0b100>().unwrap(); w.write_const::<4, 0b1000>().unwrap(); w.write_const::<5, 0b10000>().unwrap(); w.write_const::<6, 0b100000>().unwrap(); w.write_const::<7, 0b1000000>().unwrap(); w.write_const::<8, 0b10000000>().unwrap(); w.write_const::<9, 0b100000000>().unwrap(); w.write_const::<10, 0b1000000000>().unwrap(); w.byte_align().unwrap(); assert_eq!( w.into_writer(), &[ 0b00_100_10_1, 0b0_10000_10, 0b000_10000, 0b0000_1000, 0b0000_1000, 0b000_10000, 0b0_1000000 ] ); } #[test] fn test_byte_count() { use bitstream_io::{ByteWrite, ToByteStream}; #[derive(Default)] struct Builder { a: u8, b: u16, c: u32, d: u64, e: u128, } impl ToByteStream for Builder { type Error = io::Error; fn to_writer(&self, w: &mut W) -> io::Result<()> { w.write(self.a)?; w.write(self.b)?; w.write(self.c)?; w.write(self.d)?; w.write(self.e)?; Ok(()) } } assert_eq!( Builder::default().bytes::().unwrap(), 1 + 2 + 4 + 8 + 16 ); }