diff options
Diffstat (limited to '')
-rw-r--r-- | rust/vendor/cipher/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | rust/vendor/cipher/CHANGELOG.md | 73 | ||||
-rw-r--r-- | rust/vendor/cipher/Cargo.toml | 37 | ||||
-rw-r--r-- | rust/vendor/cipher/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | rust/vendor/cipher/LICENSE-MIT | 25 | ||||
-rw-r--r-- | rust/vendor/cipher/README.md | 62 | ||||
-rw-r--r-- | rust/vendor/cipher/src/block.rs | 199 | ||||
-rw-r--r-- | rust/vendor/cipher/src/common.rs | 80 | ||||
-rw-r--r-- | rust/vendor/cipher/src/dev.rs | 2 | ||||
-rw-r--r-- | rust/vendor/cipher/src/dev/block.rs | 143 | ||||
-rw-r--r-- | rust/vendor/cipher/src/dev/stream.rs | 241 | ||||
-rw-r--r-- | rust/vendor/cipher/src/errors.rs | 50 | ||||
-rw-r--r-- | rust/vendor/cipher/src/lib.rs | 30 | ||||
-rw-r--r-- | rust/vendor/cipher/src/stream.rs | 133 |
14 files changed, 1277 insertions, 0 deletions
diff --git a/rust/vendor/cipher/.cargo-checksum.json b/rust/vendor/cipher/.cargo-checksum.json new file mode 100644 index 0000000..36d110f --- /dev/null +++ b/rust/vendor/cipher/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"4f42101ba3c45517867ba7a95a5c7ff7f46a1db51c91bf1411187f5d5ff9d645","Cargo.toml":"fe10b85cb33215e5255e89862f3b7ca6a229974a6adfec32c502dbbc12c6e209","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"5c7bd92d1f096f12203dc1b601e3cb17484fa1b023e30b6b8edcc80e416237ec","README.md":"cda2a9761889d7415b4acd843a765dae9f134ceb87ccaee52238b99011f141c0","src/block.rs":"2024369aee8b5acb29c6b4beb66ddc2fc447d755db172f155d3fab9c1562c86d","src/common.rs":"f0e3787ae05a3682acda7862585880c8ecb0eff7a8e8edbebdeb639d358210ee","src/dev.rs":"82e51f2d453c922ccd40f16e9e2353e7f0e4fe0db74b810a75410f375709f3d7","src/dev/block.rs":"160be9cf57e058936fca4a768d8b275cb7f7d39ed092c12ac9830bc66af9c75f","src/dev/stream.rs":"ec7bed6b8eec2ae7ac5bd7c2c248d1a0a8afc014fd0d47fe34677c922617df38","src/errors.rs":"641b729a52101f7d128a3e4faed5d80884616c1e27578cf9a1a57bcd41f38422","src/lib.rs":"d524d8c3519cfe93447097fc1b97be3fa0dd948971387d0cf28f618b69740a8d","src/stream.rs":"7dd1f37b79b41295dbbeab1bbd44121293a5fe4b29a7f04d881a72884c14a46f"},"package":"7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"}
\ No newline at end of file diff --git a/rust/vendor/cipher/CHANGELOG.md b/rust/vendor/cipher/CHANGELOG.md new file mode 100644 index 0000000..2c86e48 --- /dev/null +++ b/rust/vendor/cipher/CHANGELOG.md @@ -0,0 +1,73 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.3.0 (2021-04-29) +### Added +- Encrypt/decrypt-only block cipher traits ([#352]) +- Re-export `blobby` from root ([#435]) +- Block cipher trait blanket impls for refs ([#441]) + +### Changed +- Consolidate error types ([#373]) +- Change `SeekNum` impls to fit with the new `BlockBuffer` ([#435]) +- Reorganize modules ([#435]) +- Renamed `new_var` to `new_from_slice(s)` ([#442]) + +[#352]: https://github.com/RustCrypto/traits/pull/352 +[#373]: https://github.com/RustCrypto/traits/pull/373 +[#435]: https://github.com/RustCrypto/traits/pull/435 +[#441]: https://github.com/RustCrypto/traits/pull/441 +[#442]: https://github.com/RustCrypto/traits/pull/442 + +## 0.2.5 (2020-11-01) +### Fixed +- Nested macros used old deprecated names ([#360]) + +[#360]: https://github.com/RustCrypto/traits/pull/360 + +## 0.2.4 (2020-11-01) +### Fixed +- Macro expansion error ([#358]) + +[#358]: https://github.com/RustCrypto/traits/pull/358 + +## 0.2.3 (2020-11-01) [YANKED] +### Fixed +- Legacy macro wrappers ([#356]) + +[#356]: https://github.com/RustCrypto/traits/pull/356 + +## 0.2.2 (2020-11-01) [YANKED] +### Added +- `BlockCipher::{encrypt_slice, decrypt_slice}` methods ([#351]) + +### Changed +- Revamp macro names ([#350]) + +[#351]: https://github.com/RustCrypto/traits/pull/351 +[#350]: https://github.com/RustCrypto/traits/pull/350 + +## 0.2.1 (2020-10-16) +### Added +- Re-export `generic_array` from toplevel ([#343]) + +### Fixed +- `dev` macro imports ([#345]) + +[#343]: https://github.com/RustCrypto/traits/pull/343 +[#345]: https://github.com/RustCrypto/traits/pull/345 + +## 0.2.0 (2020-10-15) [YANKED] +### Changed +- Unify `block-cipher` and `stream-cipher` into `cipher` ([#337]) + +[#337]: https://github.com/RustCrypto/traits/pull/337 + +## 0.1.1 (2015-06-25) + +## 0.1.0 (2015-06-24) +- Initial release diff --git a/rust/vendor/cipher/Cargo.toml b/rust/vendor/cipher/Cargo.toml new file mode 100644 index 0000000..535e038 --- /dev/null +++ b/rust/vendor/cipher/Cargo.toml @@ -0,0 +1,37 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "cipher" +version = "0.3.0" +authors = ["RustCrypto Developers"] +description = "Traits for describing block ciphers and stream ciphers" +documentation = "https://docs.rs/cipher" +readme = "README.md" +keywords = ["crypto", "block-cipher", "stream-cipher", "trait"] +categories = ["cryptography", "no-std"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/RustCrypto/traits" +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] +[dependencies.blobby] +version = "0.3" +optional = true + +[dependencies.generic-array] +version = "0.14" + +[features] +dev = ["blobby"] +std = [] diff --git a/rust/vendor/cipher/LICENSE-APACHE b/rust/vendor/cipher/LICENSE-APACHE new file mode 100644 index 0000000..78173fa --- /dev/null +++ b/rust/vendor/cipher/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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. diff --git a/rust/vendor/cipher/LICENSE-MIT b/rust/vendor/cipher/LICENSE-MIT new file mode 100644 index 0000000..f3a832c --- /dev/null +++ b/rust/vendor/cipher/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2016-2020 RustCrypto Developers + +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. diff --git a/rust/vendor/cipher/README.md b/rust/vendor/cipher/README.md new file mode 100644 index 0000000..b2c33ab --- /dev/null +++ b/rust/vendor/cipher/README.md @@ -0,0 +1,62 @@ +# RustCrypto: Cipher Traits + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] +[![Build Status][build-image]][build-link] + +Traits which define the functionality of [block ciphers] and [stream ciphers]. + +See [RustCrypto/block-ciphers] and [RustCrypto/stream-ciphers] for algorithm +implementations which use these traits. + +[Documentation][docs-link] + +## Minimum Supported Rust Version + +Rust **1.41** or higher. + +Minimum supported Rust version can be changed in the future, but it will be +done with a minor version bump. + +## SemVer Policy + +- All on-by-default features of this library are covered by SemVer +- MSRV is considered exempt from SemVer as noted above + +## License + +Licensed under either of: + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/cipher.svg +[crate-link]: https://crates.io/crates/cipher +[docs-image]: https://docs.rs/cipher/badge.svg +[docs-link]: https://docs.rs/cipher/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260050-traits +[build-image]: https://github.com/RustCrypto/traits/workflows/cipher/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/traits/actions?query=workflow:cipher + +[//]: # (general links) + +[block ciphers]: https://en.wikipedia.org/wiki/Block_cipher +[stream ciphers]: https://en.wikipedia.org/wiki/Stream_cipher +[RustCrypto/block-ciphers]: https://github.com/RustCrypto/block-ciphers +[RustCrypto/stream-ciphers]: https://github.com/RustCrypto/stream-ciphers diff --git a/rust/vendor/cipher/src/block.rs b/rust/vendor/cipher/src/block.rs new file mode 100644 index 0000000..d38da8f --- /dev/null +++ b/rust/vendor/cipher/src/block.rs @@ -0,0 +1,199 @@ +//! Traits used to define functionality of [block ciphers][1]. +//! +//! # About block ciphers +//! +//! Block ciphers are keyed, deterministic permutations of a fixed-sized input +//! "block" providing a reversible transformation to/from an encrypted output. +//! They are one of the fundamental structural components of [symmetric cryptography][2]. +//! +//! [1]: https://en.wikipedia.org/wiki/Block_cipher +//! [2]: https://en.wikipedia.org/wiki/Symmetric-key_algorithm + +use crate::errors::InvalidLength; +use core::convert::TryInto; +use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; + +/// Key for an algorithm that implements [`NewBlockCipher`]. +pub type BlockCipherKey<B> = GenericArray<u8, <B as NewBlockCipher>::KeySize>; + +/// Block on which a [`BlockCipher`] operates. +pub type Block<B> = GenericArray<u8, <B as BlockCipher>::BlockSize>; + +/// Block on which a [`BlockCipher`] operates in parallel. +pub type ParBlocks<B> = GenericArray<Block<B>, <B as BlockCipher>::ParBlocks>; + +/// Instantiate a [`BlockCipher`] algorithm. +pub trait NewBlockCipher: Sized { + /// Key size in bytes with which cipher guaranteed to be initialized. + type KeySize: ArrayLength<u8>; + + /// Create new block cipher instance from key with fixed size. + fn new(key: &BlockCipherKey<Self>) -> Self; + + /// Create new block cipher instance from key with variable size. + /// + /// Default implementation will accept only keys with length equal to + /// `KeySize`, but some ciphers can accept range of key lengths. + fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> { + if key.len() != Self::KeySize::to_usize() { + Err(InvalidLength) + } else { + Ok(Self::new(GenericArray::from_slice(key))) + } + } +} + +/// Trait which marks a type as being a block cipher. +pub trait BlockCipher { + /// Size of the block in bytes + type BlockSize: ArrayLength<u8>; + + /// Number of blocks which can be processed in parallel by + /// cipher implementation + type ParBlocks: ArrayLength<Block<Self>>; +} + +/// Encrypt-only functionality for block ciphers. +pub trait BlockEncrypt: BlockCipher { + /// Encrypt block in-place + fn encrypt_block(&self, block: &mut Block<Self>); + + /// Encrypt several blocks in parallel using instruction level parallelism + /// if possible. + /// + /// If `ParBlocks` equals to 1 it's equivalent to `encrypt_block`. + #[inline] + fn encrypt_par_blocks(&self, blocks: &mut ParBlocks<Self>) { + for block in blocks.iter_mut() { + self.encrypt_block(block); + } + } + + /// Encrypt a slice of blocks, leveraging parallelism when available. + #[inline] + fn encrypt_blocks(&self, mut blocks: &mut [Block<Self>]) { + let pb = Self::ParBlocks::to_usize(); + + if pb > 1 { + let mut iter = blocks.chunks_exact_mut(pb); + + for chunk in &mut iter { + self.encrypt_par_blocks(chunk.try_into().unwrap()) + } + + blocks = iter.into_remainder(); + } + + for block in blocks { + self.encrypt_block(block); + } + } +} + +/// Decrypt-only functionality for block ciphers. +pub trait BlockDecrypt: BlockCipher { + /// Decrypt block in-place + fn decrypt_block(&self, block: &mut Block<Self>); + + /// Decrypt several blocks in parallel using instruction level parallelism + /// if possible. + /// + /// If `ParBlocks` equals to 1 it's equivalent to `decrypt_block`. + #[inline] + fn decrypt_par_blocks(&self, blocks: &mut ParBlocks<Self>) { + for block in blocks.iter_mut() { + self.decrypt_block(block); + } + } + + /// Decrypt a slice of blocks, leveraging parallelism when available. + #[inline] + fn decrypt_blocks(&self, mut blocks: &mut [Block<Self>]) { + let pb = Self::ParBlocks::to_usize(); + + if pb > 1 { + let mut iter = blocks.chunks_exact_mut(pb); + + for chunk in &mut iter { + self.decrypt_par_blocks(chunk.try_into().unwrap()) + } + + blocks = iter.into_remainder(); + } + + for block in blocks { + self.decrypt_block(block); + } + } +} + +/// Encrypt-only functionality for block ciphers with mutable access to `self`. +/// +/// The main use case for this trait is hardware encryption engines which +/// require `&mut self` access to an underlying hardware peripheral. +pub trait BlockEncryptMut: BlockCipher { + /// Encrypt block in-place + fn encrypt_block_mut(&mut self, block: &mut Block<Self>); +} + +/// Decrypt-only functionality for block ciphers with mutable access to `self`. +/// +/// The main use case for this trait is hardware encryption engines which +/// require `&mut self` access to an underlying hardware peripheral. +pub trait BlockDecryptMut: BlockCipher { + /// Decrypt block in-place + fn decrypt_block_mut(&mut self, block: &mut Block<Self>); +} + +impl<Alg: BlockEncrypt> BlockEncryptMut for Alg { + fn encrypt_block_mut(&mut self, block: &mut Block<Self>) { + self.encrypt_block(block); + } +} + +impl<Alg: BlockDecrypt> BlockDecryptMut for Alg { + fn decrypt_block_mut(&mut self, block: &mut Block<Self>) { + self.decrypt_block(block); + } +} + +// Impls of block cipher traits for reference types + +impl<Alg: BlockCipher> BlockCipher for &Alg { + type BlockSize = Alg::BlockSize; + type ParBlocks = Alg::ParBlocks; +} + +impl<Alg: BlockEncrypt> BlockEncrypt for &Alg { + #[inline] + fn encrypt_block(&self, block: &mut Block<Self>) { + Alg::encrypt_block(self, block); + } + + #[inline] + fn encrypt_par_blocks(&self, blocks: &mut ParBlocks<Self>) { + Alg::encrypt_par_blocks(self, blocks); + } + + #[inline] + fn encrypt_blocks(&self, blocks: &mut [Block<Self>]) { + Alg::encrypt_blocks(self, blocks); + } +} + +impl<Alg: BlockDecrypt> BlockDecrypt for &Alg { + #[inline] + fn decrypt_block(&self, block: &mut Block<Self>) { + Alg::decrypt_block(self, block); + } + + #[inline] + fn decrypt_par_blocks(&self, blocks: &mut ParBlocks<Self>) { + Alg::decrypt_par_blocks(self, blocks); + } + + #[inline] + fn decrypt_blocks(&self, blocks: &mut [Block<Self>]) { + Alg::decrypt_blocks(self, blocks); + } +} diff --git a/rust/vendor/cipher/src/common.rs b/rust/vendor/cipher/src/common.rs new file mode 100644 index 0000000..cd97524 --- /dev/null +++ b/rust/vendor/cipher/src/common.rs @@ -0,0 +1,80 @@ +use crate::{errors::InvalidLength, BlockCipher, NewBlockCipher}; +use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; + +/// Key for an algorithm that implements [`NewCipher`]. +pub type CipherKey<C> = GenericArray<u8, <C as NewCipher>::KeySize>; + +/// Nonce for an algorithm that implements [`NewCipher`]. +pub type Nonce<C> = GenericArray<u8, <C as NewCipher>::NonceSize>; + +/// Cipher creation trait. +/// +/// It can be used for creation of block modes, synchronous and asynchronous stream ciphers. +pub trait NewCipher: Sized { + /// Key size in bytes + type KeySize: ArrayLength<u8>; + + /// Nonce size in bytes + type NonceSize: ArrayLength<u8>; + + /// Create new stream cipher instance from key and nonce arrays. + fn new(key: &CipherKey<Self>, nonce: &Nonce<Self>) -> Self; + + /// Create new stream cipher instance from variable length key and nonce + /// given as byte slices. + #[inline] + fn new_from_slices(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidLength> { + let kl = Self::KeySize::to_usize(); + let nl = Self::NonceSize::to_usize(); + if key.len() != kl || nonce.len() != nl { + Err(InvalidLength) + } else { + let key = GenericArray::from_slice(key); + let nonce = GenericArray::from_slice(nonce); + Ok(Self::new(key, nonce)) + } + } +} + +/// Trait for types which can be initialized from a block cipher and nonce. +pub trait FromBlockCipher { + /// Block cipher + type BlockCipher: BlockCipher; + /// Nonce size in bytes + type NonceSize: ArrayLength<u8>; + + /// Instantiate a stream cipher from a block cipher + fn from_block_cipher( + cipher: Self::BlockCipher, + nonce: &GenericArray<u8, Self::NonceSize>, + ) -> Self; +} + +impl<C> NewCipher for C +where + C: FromBlockCipher, + C::BlockCipher: NewBlockCipher, +{ + type KeySize = <<Self as FromBlockCipher>::BlockCipher as NewBlockCipher>::KeySize; + type NonceSize = <Self as FromBlockCipher>::NonceSize; + + fn new(key: &CipherKey<Self>, nonce: &Nonce<Self>) -> C { + C::from_block_cipher( + <<Self as FromBlockCipher>::BlockCipher as NewBlockCipher>::new(key), + nonce, + ) + } + + fn new_from_slices(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidLength> { + if nonce.len() != Self::NonceSize::USIZE { + Err(InvalidLength) + } else { + C::BlockCipher::new_from_slice(key) + .map_err(|_| InvalidLength) + .map(|cipher| { + let nonce = GenericArray::from_slice(nonce); + Self::from_block_cipher(cipher, nonce) + }) + } + } +} diff --git a/rust/vendor/cipher/src/dev.rs b/rust/vendor/cipher/src/dev.rs new file mode 100644 index 0000000..6bedbe9 --- /dev/null +++ b/rust/vendor/cipher/src/dev.rs @@ -0,0 +1,2 @@ +mod block; +mod stream; diff --git a/rust/vendor/cipher/src/dev/block.rs b/rust/vendor/cipher/src/dev/block.rs new file mode 100644 index 0000000..fc53b94 --- /dev/null +++ b/rust/vendor/cipher/src/dev/block.rs @@ -0,0 +1,143 @@ +//! Development-related functionality + +pub use blobby; + +/// Define block cipher test +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! block_cipher_test { + ($name:ident, $test_name:expr, $cipher:ty) => { + #[test] + fn $name() { + use cipher::generic_array::{typenum::Unsigned, GenericArray}; + use cipher::{ + blobby::Blob3Iterator, BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher, + }; + + fn run_test(key: &[u8], pt: &[u8], ct: &[u8]) -> bool { + let state = <$cipher as NewBlockCipher>::new_from_slice(key).unwrap(); + + let mut block = GenericArray::clone_from_slice(pt); + state.encrypt_block(&mut block); + if ct != block.as_slice() { + return false; + } + + state.decrypt_block(&mut block); + if pt != block.as_slice() { + return false; + } + + true + } + + fn run_par_test(key: &[u8], pt: &[u8]) -> bool { + type ParBlocks = <$cipher as BlockCipher>::ParBlocks; + type BlockSize = <$cipher as BlockCipher>::BlockSize; + type Block = GenericArray<u8, BlockSize>; + type ParBlock = GenericArray<Block, ParBlocks>; + + let state = <$cipher as NewBlockCipher>::new_from_slice(key).unwrap(); + + let block = Block::clone_from_slice(pt); + let mut blocks1 = ParBlock::default(); + for (i, b) in blocks1.iter_mut().enumerate() { + *b = block; + b[0] = b[0].wrapping_add(i as u8); + } + let mut blocks2 = blocks1.clone(); + + // check that `encrypt_blocks` and `encrypt_block` + // result in the same ciphertext + state.encrypt_blocks(&mut blocks1); + for b in blocks2.iter_mut() { + state.encrypt_block(b); + } + if blocks1 != blocks2 { + return false; + } + + // check that `encrypt_blocks` and `encrypt_block` + // result in the same plaintext + state.decrypt_blocks(&mut blocks1); + for b in blocks2.iter_mut() { + state.decrypt_block(b); + } + if blocks1 != blocks2 { + return false; + } + + true + } + + let pb = <$cipher as BlockCipher>::ParBlocks::to_usize(); + let data = include_bytes!(concat!("data/", $test_name, ".blb")); + for (i, row) in Blob3Iterator::new(data).unwrap().enumerate() { + let [key, pt, ct] = row.unwrap(); + if !run_test(key, pt, ct) { + panic!( + "\n\ + Failed test №{}\n\ + key:\t{:?}\n\ + plaintext:\t{:?}\n\ + ciphertext:\t{:?}\n", + i, key, pt, ct, + ); + } + + // test parallel blocks encryption/decryption + if pb != 1 { + if !run_par_test(key, pt) { + panic!( + "\n\ + Failed parallel test №{}\n\ + key:\t{:?}\n\ + plaintext:\t{:?}\n\ + ciphertext:\t{:?}\n", + i, key, pt, ct, + ); + } + } + } + // test if cipher can be cloned + let key = Default::default(); + let _ = <$cipher as NewBlockCipher>::new(&key).clone(); + } + }; +} + +/// Define block cipher benchmark +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! block_cipher_bench { + ($cipher:path, $key_len:expr) => { + extern crate test; + + use cipher::{BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher}; + use test::Bencher; + + #[bench] + pub fn encrypt(bh: &mut Bencher) { + let state = <$cipher>::new_from_slice(&[1u8; $key_len]).unwrap(); + let mut block = Default::default(); + + bh.iter(|| { + state.encrypt_block(&mut block); + test::black_box(&block); + }); + bh.bytes = block.len() as u64; + } + + #[bench] + pub fn decrypt(bh: &mut Bencher) { + let state = <$cipher>::new_from_slice(&[1u8; $key_len]).unwrap(); + let mut block = Default::default(); + + bh.iter(|| { + state.decrypt_block(&mut block); + test::black_box(&block); + }); + bh.bytes = block.len() as u64; + } + }; +} diff --git a/rust/vendor/cipher/src/dev/stream.rs b/rust/vendor/cipher/src/dev/stream.rs new file mode 100644 index 0000000..43757ff --- /dev/null +++ b/rust/vendor/cipher/src/dev/stream.rs @@ -0,0 +1,241 @@ +//! Development-related functionality + +/// Test core functionality of synchronous stream cipher +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! stream_cipher_test { + ($name:ident, $cipher:ty, $test_name:expr) => { + #[test] + fn $name() { + use cipher::generic_array::GenericArray; + use cipher::{blobby::Blob4Iterator, NewCipher, StreamCipher}; + + let data = include_bytes!(concat!("data/", $test_name, ".blb")); + for (i, row) in Blob4Iterator::new(data).unwrap().enumerate() { + let [key, iv, pt, ct] = row.unwrap(); + + for chunk_n in 1..256 { + let mut mode = <$cipher>::new_from_slices(key, iv).unwrap(); + let mut pt = pt.to_vec(); + for chunk in pt.chunks_mut(chunk_n) { + mode.apply_keystream(chunk); + } + if pt != &ct[..] { + panic!( + "Failed main test №{}, chunk size: {}\n\ + key:\t{:?}\n\ + iv:\t{:?}\n\ + plaintext:\t{:?}\n\ + ciphertext:\t{:?}\n", + i, chunk_n, key, iv, pt, ct, + ); + } + } + } + } + }; +} + +/// Test stream synchronous stream cipher seeking capabilities +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! stream_cipher_seek_test { + ($name:ident, $cipher:ty) => { + #[test] + fn $name() { + use cipher::generic_array::GenericArray; + use cipher::{NewCipher, StreamCipher, StreamCipherSeek}; + + fn get_cipher() -> $cipher { + <$cipher>::new(&Default::default(), &Default::default()) + } + + const MAX_SEEK: usize = 512; + + let mut ct = [0u8; MAX_SEEK]; + get_cipher().apply_keystream(&mut ct[..]); + + for n in 0..MAX_SEEK { + let mut cipher = get_cipher(); + assert_eq!(cipher.current_pos::<usize>(), 0); + cipher.seek(n); + assert_eq!(cipher.current_pos::<usize>(), n); + let mut buf = [0u8; MAX_SEEK]; + cipher.apply_keystream(&mut buf[n..]); + assert_eq!(cipher.current_pos::<usize>(), MAX_SEEK); + assert_eq!(&buf[n..], &ct[n..]); + } + + const MAX_CHUNK: usize = 128; + const MAX_LEN: usize = 1024; + + let mut buf = [0u8; MAX_CHUNK]; + let mut cipher = get_cipher(); + assert_eq!(cipher.current_pos::<usize>(), 0); + cipher.apply_keystream(&mut []); + assert_eq!(cipher.current_pos::<usize>(), 0); + for n in 1..MAX_CHUNK { + assert_eq!(cipher.current_pos::<usize>(), 0); + for m in 1.. { + cipher.apply_keystream(&mut buf[..n]); + assert_eq!(cipher.current_pos::<usize>(), n * m); + if n * m > MAX_LEN { + break; + } + } + cipher.seek(0); + } + } + }; +} + +/// Test core functionality of asynchronous stream cipher +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! stream_cipher_async_test { + ($name:ident, $test_name:expr, $cipher:ty) => { + #[test] + fn $name() { + use cipher::generic_array::GenericArray; + use cipher::{blobby::Blob4Iterator, AsyncStreamCipher, NewCipher}; + + fn run_test( + key: &[u8], + iv: &[u8], + plaintext: &[u8], + ciphertext: &[u8], + ) -> Option<&'static str> { + for n in 1..=plaintext.len() { + let mut mode = <$cipher>::new_from_slices(key, iv).unwrap(); + let mut buf = plaintext.to_vec(); + for chunk in buf.chunks_mut(n) { + mode.encrypt(chunk); + } + if buf != &ciphertext[..] { + return Some("encrypt"); + } + } + + for n in 1..=plaintext.len() { + let mut mode = <$cipher>::new_from_slices(key, iv).unwrap(); + let mut buf = ciphertext.to_vec(); + for chunk in buf.chunks_mut(n) { + mode.decrypt(chunk); + } + if buf != &plaintext[..] { + return Some("decrypt"); + } + } + + None + } + + let data = include_bytes!(concat!("data/", $test_name, ".blb")); + + for (i, row) in Blob4Iterator::new(data).unwrap().enumerate() { + let [key, iv, pt, ct] = row.unwrap(); + if let Some(desc) = run_test(key, iv, pt, ct) { + panic!( + "\n\ + Failed test №{}: {}\n\ + key:\t{:?}\n\ + iv:\t{:?}\n\ + plaintext:\t{:?}\n\ + ciphertext:\t{:?}\n", + i, desc, key, iv, pt, ct, + ); + } + } + } + }; +} + +/// Create synchronous stream cipher benchmarks +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! stream_cipher_sync_bench { + ($name:ident, $cipher:path, $data_len:expr) => { + #[bench] + pub fn $name(bh: &mut Bencher) { + let key = Default::default(); + let nonce = Default::default(); + let mut cipher = <$cipher>::new(&key, &nonce); + let mut data = get_data($data_len); + + bh.iter(|| { + cipher.apply_keystream(&mut data); + test::black_box(&data); + }); + bh.bytes = data.len() as u64; + } + }; + ($cipher:path) => { + extern crate test; + + use cipher::{generic_array::GenericArray, NewCipher, StreamCipher}; + use test::Bencher; + + #[inline(never)] + fn get_data(n: usize) -> Vec<u8> { + vec![77; n] + } + + $crate::stream_cipher_sync_bench!(bench1_10, $cipher, 10); + $crate::stream_cipher_sync_bench!(bench2_100, $cipher, 100); + $crate::stream_cipher_sync_bench!(bench3_1000, $cipher, 1000); + $crate::stream_cipher_sync_bench!(bench4_10000, $cipher, 10000); + $crate::stream_cipher_sync_bench!(bench5_100000, $cipher, 100000); + }; +} + +/// Create asynchronous stream cipher benchmarks +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "dev")))] +macro_rules! stream_cipher_async_bench { + ($enc_name:ident, $dec_name:ident, $cipher:path, $data_len:expr) => { + #[bench] + pub fn $enc_name(bh: &mut Bencher) { + let key = Default::default(); + let nonce = Default::default(); + let mut cipher = <$cipher>::new(&key, &nonce); + let mut data = get_data($data_len); + + bh.iter(|| { + cipher.encrypt(&mut data); + test::black_box(&data); + }); + bh.bytes = data.len() as u64; + } + + #[bench] + pub fn $dec_name(bh: &mut Bencher) { + let key = Default::default(); + let nonce = Default::default(); + let mut cipher = <$cipher>::new(&key, &nonce); + let mut data = get_data($data_len); + + bh.iter(|| { + cipher.decrypt(&mut data); + test::black_box(&data); + }); + bh.bytes = data.len() as u64; + } + }; + ($cipher:path) => { + extern crate test; + + use cipher::{generic_array::GenericArray, AsyncStreamCipher, NewCipher}; + use test::Bencher; + + #[inline(never)] + fn get_data(n: usize) -> Vec<u8> { + vec![77; n] + } + + $crate::stream_cipher_async_bench!(encrypt_10, decrypt_10, $cipher, 10); + $crate::stream_cipher_async_bench!(encrypt_100, decrypt_100, $cipher, 100); + $crate::stream_cipher_async_bench!(encrypt_1000, decrypt_1000, $cipher, 1000); + $crate::stream_cipher_async_bench!(encrypt_10000, decrypt_10000, $cipher, 10000); + $crate::stream_cipher_async_bench!(encrypt_100000, decrypt_100000, $cipher, 100000); + }; +} diff --git a/rust/vendor/cipher/src/errors.rs b/rust/vendor/cipher/src/errors.rs new file mode 100644 index 0000000..f527365 --- /dev/null +++ b/rust/vendor/cipher/src/errors.rs @@ -0,0 +1,50 @@ +//! Error types. + +use core::fmt; + +/// The error type returned when stream cipher has reached the end of a keystream. +#[derive(Copy, Clone, Debug)] +pub struct LoopError; + +impl fmt::Display for LoopError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str("Loop Error") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for LoopError {} + +/// The error type returned when key and/or nonce used in stream cipher +/// initialization had an invalid length. +#[derive(Copy, Clone, Debug)] +pub struct InvalidLength; + +impl fmt::Display for InvalidLength { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str("Loop Error") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for InvalidLength {} + +/// The error type returned when a cipher position can not be represented +/// by the requested type. +#[derive(Copy, Clone, Debug)] +pub struct OverflowError; + +impl fmt::Display for OverflowError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str("Overflow Error") + } +} + +impl From<OverflowError> for LoopError { + fn from(_: OverflowError) -> LoopError { + LoopError + } +} + +#[cfg(feature = "std")] +impl std::error::Error for OverflowError {} diff --git a/rust/vendor/cipher/src/lib.rs b/rust/vendor/cipher/src/lib.rs new file mode 100644 index 0000000..d0766d8 --- /dev/null +++ b/rust/vendor/cipher/src/lib.rs @@ -0,0 +1,30 @@ +//! This crate defines a set of traits which describe the functionality of +//! [block ciphers][1] and [stream ciphers][2]. +//! +//! [1]: https://en.wikipedia.org/wiki/Block_cipher +//! [2]: https://en.wikipedia.org/wiki/Stream_cipher + +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" +)] +#![forbid(unsafe_code)] +#![warn(missing_docs, rust_2018_idioms)] + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "dev")] +pub use blobby; + +mod block; +mod common; +#[cfg(feature = "dev")] +mod dev; +pub mod errors; +mod stream; + +pub use crate::{block::*, common::*, stream::*}; +pub use generic_array::{self, typenum::consts}; diff --git a/rust/vendor/cipher/src/stream.rs b/rust/vendor/cipher/src/stream.rs new file mode 100644 index 0000000..3bea728 --- /dev/null +++ b/rust/vendor/cipher/src/stream.rs @@ -0,0 +1,133 @@ +//! Traits which define functionality of stream ciphers. +//! +//! See [RustCrypto/stream-ciphers](https://github.com/RustCrypto/stream-ciphers) +//! for ciphers implementation. + +use crate::errors::{LoopError, OverflowError}; +use core::convert::{TryFrom, TryInto}; + +/// Synchronous stream cipher core trait. +pub trait StreamCipher { + /// Apply keystream to the data. + /// + /// It will XOR generated keystream with the data, which can be both + /// encryption and decryption. + /// + /// # Panics + /// If end of the keystream will be reached with the given data length, + /// method will panic without modifying the provided `data`. + #[inline] + fn apply_keystream(&mut self, data: &mut [u8]) { + self.try_apply_keystream(data).unwrap(); + } + + /// Apply keystream to the data, but return an error if end of a keystream + /// will be reached. + /// + /// If end of the keystream will be achieved with the given data length, + /// method will return `Err(LoopError)` without modifying provided `data`. + fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError>; +} + +/// Trait for seekable stream ciphers. +/// +/// Methods of this trait are generic over the [`SeekNum`] trait, which is +/// implemented for primitive numeric types, i.e.: `i/u8`, `i/u16`, `i/u32`, +/// `i/u64`, `i/u128`, and `i/usize`. +pub trait StreamCipherSeek { + /// Try to get current keystream position + /// + /// Returns [`LoopError`] if position can not be represented by type `T` + fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError>; + + /// Try to seek to the given position + /// + /// Returns [`LoopError`] if provided position value is bigger than + /// keystream length. + fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError>; + + /// Get current keystream position + /// + /// # Panics + /// If position can not be represented by type `T` + fn current_pos<T: SeekNum>(&self) -> T { + self.try_current_pos().unwrap() + } + + /// Seek to the given position + /// + /// # Panics + /// If provided position value is bigger than keystream leangth + fn seek<T: SeekNum>(&mut self, pos: T) { + self.try_seek(pos).unwrap() + } +} + +/// Asynchronous stream cipher core trait. +pub trait AsyncStreamCipher { + /// Encrypt data in place. + fn encrypt(&mut self, data: &mut [u8]); + + /// Decrypt data in place. + fn decrypt(&mut self, data: &mut [u8]); +} + +impl<C: StreamCipher> StreamCipher for &mut C { + #[inline] + fn apply_keystream(&mut self, data: &mut [u8]) { + C::apply_keystream(self, data); + } + + #[inline] + fn try_apply_keystream(&mut self, data: &mut [u8]) -> Result<(), LoopError> { + C::try_apply_keystream(self, data) + } +} + +/// Trait implemented for numeric types which can be used with the +/// [`StreamCipherSeek`] trait. +/// +/// This trait is implemented for primitive numeric types, i.e. `i/u8`, +/// `u16`, `u32`, `u64`, `u128`, `usize`, and `i32`. It is not intended +/// to be implemented in third-party crates. +#[rustfmt::skip] +pub trait SeekNum: + Sized + + TryInto<u8> + TryFrom<u8> + TryInto<i8> + TryFrom<i8> + + TryInto<u16> + TryFrom<u16> + TryInto<i16> + TryFrom<i16> + + TryInto<u32> + TryFrom<u32> + TryInto<i32> + TryFrom<i32> + + TryInto<u64> + TryFrom<u64> + TryInto<i64> + TryFrom<i64> + + TryInto<u128> + TryFrom<u128> + TryInto<i128> + TryFrom<i128> + + TryInto<usize> + TryFrom<usize> + TryInto<isize> + TryFrom<isize> +{ + /// Try to get position for block number `block`, byte position inside + /// block `byte`, and block size `bs`. + fn from_block_byte<T: SeekNum>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError>; + + /// Try to get block number and bytes position for given block size `bs`. + fn to_block_byte<T: SeekNum>(self, bs: u8) -> Result<(T, u8), OverflowError>; +} + +macro_rules! impl_seek_num { + {$($t:ty )*} => { + $( + impl SeekNum for $t { + fn from_block_byte<T: TryInto<Self>>(block: T, byte: u8, bs: u8) -> Result<Self, OverflowError> { + debug_assert!(byte < bs); + let block = block.try_into().map_err(|_| OverflowError)?; + let pos = block.checked_mul(bs as Self).ok_or(OverflowError)? + (byte as Self); + Ok(pos) + } + + fn to_block_byte<T: TryFrom<Self>>(self, bs: u8) -> Result<(T, u8), OverflowError> { + let bs = bs as Self; + let byte = self % bs; + let block = T::try_from(self/bs).map_err(|_| OverflowError)?; + Ok((block, byte as u8)) + } + } + )* + }; +} + +impl_seek_num! { u8 u16 u32 u64 u128 usize i32 } |