core2-0.4.0/.cargo_vcs_info.json0000644000000001360000000000100120470ustar { "git": { "sha1": "545e84bcb0f235b12e21351e0c69767958efe2a7" }, "path_in_vcs": "" }core2-0.4.0/.github/workflows/ci.yml000064400000000000000000000050450072674642500154060ustar 00000000000000name: CI on: [push, pull_request] jobs: test-nightly: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] rust: [nightly] steps: - uses: actions/checkout@v2 - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust }} override: true - name: Run tests (no_std) uses: actions-rs/cargo@v1 with: command: test args: --tests --no-default-features --features nightly - name: Run tests (std) uses: actions-rs/cargo@v1 with: command: test args: --tests --no-default-features --features std,nightly - name: Run tests (alloc) uses: actions-rs/cargo@v1 with: command: test args: --tests --no-default-features --features alloc,nightly test-stable: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] rust: [stable] steps: - uses: actions/checkout@v2 - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust }} override: true - name: Run tests (no_std) uses: actions-rs/cargo@v1 with: command: test args: --no-default-features - name: Run tests (std) uses: actions-rs/cargo@v1 with: command: test args: --no-default-features --features std - name: Run tests (alloc) uses: actions-rs/cargo@v1 with: command: test args: --no-default-features --features alloc test-msrv: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] rust: [1.47] steps: - uses: actions/checkout@v2 - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust }} override: true - name: Run tests (no_std) uses: actions-rs/cargo@v1 with: command: test args: --no-default-features - name: Run tests (std) uses: actions-rs/cargo@v1 with: command: test args: --no-default-features --features std - name: Run tests (alloc) uses: actions-rs/cargo@v1 with: command: test args: --no-default-features --features alloc core2-0.4.0/.gitignore000064400000000000000000000001370072674642500126600ustar 00000000000000/target #Added by cargo # #already existing elements were commented out #/target Cargo.lock core2-0.4.0/Cargo.toml0000644000000016700000000000100100510ustar # 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" name = "core2" version = "0.4.0" authors = ["Brendan Molloy "] description = "The bare essentials of std::io for use in no_std. Alloc support is optional." categories = ["no-std"] license = "Apache-2.0 OR MIT" repository = "https://github.com/bbqsrc/core2" [package.metadata.docs.rs] features = ["nightly"] [dependencies.memchr] version = "2" default-features = false [features] alloc = [] default = ["std"] nightly = [] std = ["alloc"] core2-0.4.0/Cargo.toml.orig000064400000000000000000000007560072674642500135660ustar 00000000000000[package] name = "core2" version = "0.4.0" authors = ["Brendan Molloy "] description = "The bare essentials of std::io for use in no_std. Alloc support is optional." license = "Apache-2.0 OR MIT" edition = "2018" repository = "https://github.com/bbqsrc/core2" categories = ["no-std"] [dependencies] memchr = { version = "2", default-features = false } [features] default = ["std"] std = ["alloc"] alloc = [] nightly = [] [package.metadata.docs.rs] features = ["nightly"] core2-0.4.0/LICENSE-APACHE000064400000000000000000000261360072674642500126230ustar 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. core2-0.4.0/LICENSE-MIT000064400000000000000000000020750072674642500123270ustar 00000000000000Copyright (c) 2020-2021 Brendan Molloy 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. core2-0.4.0/README.md000064400000000000000000000056220072674642500121530ustar 00000000000000# core2 [![Actions Status](https://github.com/bbqsrc/core2/workflows/CI/badge.svg)](https://github.com/bbqsrc/core2/actions) [![Documentation](https://docs.rs/core2/badge.svg)](https://docs.rs/core2) ![Minimum Supported Rust Version (MSRV)](https://img.shields.io/badge/rust-v1.47.0+-blue) Ever wanted a `Cursor` or the `Error` trait in `no_std`? Well now you can have it. A 'fork' of Rust's `std` modules for `no_std` environments, with the added benefit of optionally taking advantage of `alloc`. The goal of this crate is to provide a stable interface for building I/O and error trait functionality in `no_std` environments. The current code corresponds to the most recent stable API of Rust 1.47.0. It is also a goal to achieve a true alloc-less experience, with opt-in alloc support. This crate works on `stable` with some limitations in functionality, and `nightly` without limitations by adding the relevant feature flag. This crate is `std` by default -- use no default features to get `no_std` mode. ## Usage ```toml [dependencies] core2 = "0.3" ``` Add the crate, use the things you would usually want from `std::io`, but instead from `core2::io`, and use `core2::error::Error` in place of `std::error::Error`. ### Features - **std**: enables `std` pass-throughs for the polyfilled types, but allows accessing the new types - **alloc**: enable aspects of the `Read` and `Write` traits that require `alloc` support (WIP) - **nightly**: enables **nightly**-only features, such as `BufReader` and `BufWriter` with const generic buffers. ### Differences to `std::io` - No `std::io::Error`, so we have our own copy without any `Os` error functions - `IoSlice` and the `*_vectored` family of functions are not implemented. - `BufReader` and `BufWriter` have a different signature, as they now use a const generic bounded array for the internal buffer. (Requires **nightly** feature) Other than items perhaps being entirely missing or certain functions unavailable on some traits, no function signatures have been changed. ### Limitations - Using the buffer types currently requires **nightly** due to the use of const generics. - Using `copy` or the buffer types with `std` support currently requires **nightly** due to the `initializer` API. ## Where is it used? All of the below are works in progress, but should help with demonstrating how to use this crate. - [thiserror_core2](https://github.com/bbqsrc/thiserror-core2): fork of `thiserror` using the `core2::error::Error` trait. ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. --- Almost all of the code in this repository is a copy of the [Rust language codebase](https://github.com/rust-lang/rust) with minor modifications. For attributions, see https://thanks.rust-lang.org/. core2-0.4.0/src/error.rs000064400000000000000000000336230072674642500131640ustar 00000000000000//! Traits for working with Errors. // A note about crates and the facade: // // Originally, the `Error` trait was defined in libcore, and the impls // were scattered about. However, coherence objected to this // arrangement, because to create the blanket impls for `Box` required // knowing that `&str: !Error`, and we have no means to deal with that // sort of conflict just now. Therefore, for the time being, we have // moved the `Error` trait into libstd. As we evolve a sol'n to the // coherence challenge (e.g., specialization, neg impls, etc) we can // reconsider what crate these items belong in. #[allow(deprecated)] use core::alloc::LayoutErr; use core::any::TypeId; use core::fmt::{Debug, Display}; #[cfg(feature = "alloc")] use alloc::{string::String, borrow::Cow, boxed::Box}; /// `Error` is a trait representing the basic expectations for error values, /// i.e., values of type `E` in [`Result`]. Errors must describe /// themselves through the [`Display`] and [`Debug`] traits, and may provide /// cause chain information: /// /// [`Error::source()`] is generally used when errors cross /// "abstraction boundaries". If one module must report an error that is caused /// by an error from a lower-level module, it can allow accessing that error /// via [`Error::source()`]. This makes it possible for the high-level /// module to provide its own errors while also revealing some of the /// implementation for debugging via `source` chains. /// /// [`Result`]: Result pub trait Error: Debug + Display { /// The lower-level source of this error, if any. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::fmt; /// /// #[derive(Debug)] /// struct SuperError { /// side: SuperErrorSideKick, /// } /// /// impl fmt::Display for SuperError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "SuperError is here!") /// } /// } /// /// impl Error for SuperError { /// fn source(&self) -> Option<&(dyn Error + 'static)> { /// Some(&self.side) /// } /// } /// /// #[derive(Debug)] /// struct SuperErrorSideKick; /// /// impl fmt::Display for SuperErrorSideKick { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f, "SuperErrorSideKick is here!") /// } /// } /// /// impl Error for SuperErrorSideKick {} /// /// fn get_super_error() -> Result<(), SuperError> { /// Err(SuperError { side: SuperErrorSideKick }) /// } /// /// fn main() { /// match get_super_error() { /// Err(e) => { /// println!("Error: {}", e); /// println!("Caused by: {}", e.source().unwrap()); /// } /// _ => println!("No error"), /// } /// } /// ``` fn source(&self) -> Option<&(dyn Error + 'static)> { None } /// Gets the `TypeId` of `self`. #[doc(hidden)] fn type_id(&self, _: private::Internal) -> TypeId where Self: 'static, { TypeId::of::() } } mod private { // This is a hack to prevent `type_id` from being overridden by `Error` // implementations, since that can enable unsound downcasting. #[derive(Debug)] pub struct Internal; } #[cfg(feature = "alloc")] impl<'a, E: Error + 'a> From for Box { /// Converts a type of [`Error`] into a box of dyn [`Error`]. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::fmt; /// use std::mem; /// /// #[derive(Debug)] /// struct AnError; /// /// impl fmt::Display for AnError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f , "An error") /// } /// } /// /// impl Error for AnError {} /// /// let an_error = AnError; /// assert!(0 == mem::size_of_val(&an_error)); /// let a_boxed_error = Box::::from(an_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: E) -> Box { Box::new(err) } } #[cfg(feature = "alloc")] impl<'a, E: Error + Send + Sync + 'a> From for Box { /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of /// dyn [`Error`] + [`Send`] + [`Sync`]. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::fmt; /// use std::mem; /// /// #[derive(Debug)] /// struct AnError; /// /// impl fmt::Display for AnError { /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// write!(f , "An error") /// } /// } /// /// impl Error for AnError {} /// /// unsafe impl Send for AnError {} /// /// unsafe impl Sync for AnError {} /// /// let an_error = AnError; /// assert!(0 == mem::size_of_val(&an_error)); /// let a_boxed_error = Box::::from(an_error); /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: E) -> Box { Box::new(err) } } #[cfg(feature = "alloc")] impl From for Box { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// /// let a_string_error = "a string error".to_string(); /// let a_boxed_error = Box::::from(a_string_error); /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` #[inline] fn from(err: String) -> Box { struct StringError(String); impl Error for StringError {} impl Display for StringError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { Display::fmt(&self.0, f) } } // Purposefully skip printing "StringError(..)" impl Debug for StringError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { Debug::fmt(&self.0, f) } } Box::new(StringError(err)) } } #[cfg(feature = "alloc")] impl From for Box { /// Converts a [`String`] into a box of dyn [`Error`]. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// /// let a_string_error = "a string error".to_string(); /// let a_boxed_error = Box::::from(a_string_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(str_err: String) -> Box { let err1: Box = From::from(str_err); let err2: Box = err1; err2 } } #[cfg(feature = "alloc")] impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// [`str`]: prim@str /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// /// let a_str_error = "a str error"; /// let a_boxed_error = Box::::from(a_str_error); /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` #[inline] fn from(err: &str) -> Box { From::from(String::from(err)) } } #[cfg(feature = "alloc")] impl From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// /// [`str`]: prim@str /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// /// let a_str_error = "a str error"; /// let a_boxed_error = Box::::from(a_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: &str) -> Box { From::from(String::from(err)) } } #[cfg(feature = "alloc")] impl<'a, 'b> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// use std::borrow::Cow; /// /// let a_cow_str_error = Cow::from("a str error"); /// let a_boxed_error = Box::::from(a_cow_str_error); /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } } #[cfg(feature = "alloc")] impl<'a> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`]. /// /// # Examples /// /// ``` /// use std::error::Error; /// use std::mem; /// use std::borrow::Cow; /// /// let a_cow_str_error = Cow::from("a str error"); /// let a_boxed_error = Box::::from(a_cow_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: Cow<'a, str>) -> Box { From::from(String::from(err)) } } // #[unstable(feature = "never_type", issue = "35121")] #[cfg(feature = "nightly")] impl Error for ! {} #[allow(deprecated)] impl Error for LayoutErr {} impl Error for core::str::ParseBoolError {} impl Error for core::str::Utf8Error {} impl Error for core::num::ParseIntError {} impl Error for core::num::TryFromIntError {} impl Error for core::array::TryFromSliceError {} impl Error for core::num::ParseFloatError {} #[cfg(feature = "alloc")] impl Error for alloc::string::FromUtf8Error {} #[cfg(feature = "alloc")] impl Error for alloc::string::FromUtf16Error {} #[cfg(feature = "alloc")] impl Error for Box { fn source(&self) -> Option<&(dyn Error + 'static)> { Error::source(&**self) } } // Copied from `any.rs`. impl dyn Error + 'static { /// Returns `true` if the boxed type is the same as `T` #[inline] pub fn is(&self) -> bool { // Get `TypeId` of the type this function is instantiated with. let t = TypeId::of::(); // Get `TypeId` of the type in the trait object. let boxed = self.type_id(private::Internal); // Compare both `TypeId`s on equality. t == boxed } /// Returns some reference to the boxed value if it is of type `T`, or /// `None` if it isn't. #[inline] pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { unsafe { Some(&*(self as *const dyn Error as *const T)) } } else { None } } /// Returns some mutable reference to the boxed value if it is of type `T`, or /// `None` if it isn't. #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { if self.is::() { unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) } } else { None } } } impl dyn Error + 'static + Send { /// Forwards to the method defined on the type `dyn Error`. #[inline] pub fn is(&self) -> bool { ::is::(self) } /// Forwards to the method defined on the type `dyn Error`. #[inline] pub fn downcast_ref(&self) -> Option<&T> { ::downcast_ref::(self) } /// Forwards to the method defined on the type `dyn Error`. #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { ::downcast_mut::(self) } } impl dyn Error + 'static + Send + Sync { /// Forwards to the method defined on the type `dyn Error`. #[inline] pub fn is(&self) -> bool { ::is::(self) } /// Forwards to the method defined on the type `dyn Error`. #[inline] pub fn downcast_ref(&self) -> Option<&T> { ::downcast_ref::(self) } /// Forwards to the method defined on the type `dyn Error`. #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { ::downcast_mut::(self) } } #[cfg(feature = "alloc")] impl dyn Error { #[inline] /// Attempts to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { if self.is::() { unsafe { let raw: *mut dyn Error = Box::into_raw(self); Ok(Box::from_raw(raw as *mut T)) } } else { Err(self) } } } #[cfg(feature = "alloc")] impl dyn Error + Send { #[inline] /// Attempts to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; ::downcast(err).map_err(|s| unsafe { // Reapply the `Send` marker. core::mem::transmute::, Box>(s) }) } } #[cfg(feature = "alloc")] impl dyn Error + Send + Sync { #[inline] /// Attempts to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; ::downcast(err).map_err(|s| unsafe { // Reapply the `Send + Sync` marker. core::mem::transmute::, Box>(s) }) } } core2-0.4.0/src/io/buffered.rs000064400000000000000000001114610072674642500142210ustar 00000000000000//! Buffering wrappers for I/O traits use crate::io::{BufRead, Error, ErrorKind, Read, Result, Seek, SeekFrom, Write}; use core::{cmp, fmt}; /// The `BufReader` struct adds buffering to any reader. /// /// It can be excessively inefficient to work directly with a [`Read`] instance. /// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`] /// results in a system call. A `BufReader` performs large, infrequent reads on /// the underlying [`Read`] and maintains an in-memory buffer of the results. /// /// `BufReader` can improve the speed of programs that make *small* and /// *repeated* read calls to the same file or network socket. It does not /// help when reading very large amounts at once, or reading just one or a few /// times. It also provides no advantage when reading from a source that is /// already in memory, like a [`Vec`]``. /// /// When the `BufReader` is dropped, the contents of its buffer will be /// discarded. Creating multiple instances of a `BufReader` on the same /// stream can cause data loss. Reading from the underlying reader after /// unwrapping the `BufReader` with [`BufReader::into_inner`] can also cause /// data loss. /// /// [`TcpStream::read`]: Read::read /// [`TcpStream`]: crate::net::TcpStream /// /// # Examples /// /// ```no_run /// use std::prelude::*; /// use core2::io::BufReader; /// use std::fs::File; /// /// fn main() -> core::result::Result<()> { /// let f = File::open("log.txt")?; /// let mut reader = BufReader::new(f); /// /// let mut line = String::new(); /// let len = reader.read_line(&mut line)?; /// println!("First line is {} bytes long", len); /// Ok(()) /// } /// ``` pub struct BufReader { inner: R, buf: [u8; S], pos: usize, cap: usize, } impl BufReader { /// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB, /// but may change in the future. /// /// # Examples /// /// ```no_run /// use core2::io::BufReader; /// use std::fs::File; /// /// fn main() -> core::result::Result<()> { /// let f = File::open("log.txt")?; /// let reader = BufReader::new(f); /// Ok(()) /// } /// ``` pub fn new(inner: R) -> BufReader { BufReader { inner, buf: [0; S], pos: 0, cap: 0, } } } impl BufReader { /// Gets a reference to the underlying reader. /// /// It is inadvisable to directly read from the underlying reader. /// /// # Examples /// /// ```no_run /// use core2::io::BufReader; /// use std::fs::File; /// /// fn main() -> core::result::Result<()> { /// let f1 = File::open("log.txt")?; /// let reader = BufReader::new(f1); /// /// let f2 = reader.get_ref(); /// Ok(()) /// } /// ``` pub fn get_ref(&self) -> &R { &self.inner } /// Gets a mutable reference to the underlying reader. /// /// It is inadvisable to directly read from the underlying reader. /// /// # Examples /// /// ```no_run /// use core2::io::BufReader; /// use std::fs::File; /// /// fn main() -> core::result::Result<()> { /// let f1 = File::open("log.txt")?; /// let mut reader = BufReader::new(f1); /// /// let f2 = reader.get_mut(); /// Ok(()) /// } /// ``` pub fn get_mut(&mut self) -> &mut R { &mut self.inner } /// Returns a reference to the internally buffered data. /// /// Unlike [`fill_buf`], this will not attempt to fill the buffer if it is empty. /// /// [`fill_buf`]: BufRead::fill_buf /// /// # Examples /// /// ```no_run /// use std::{BufReader, BufRead}; /// use std::fs::File; /// /// fn main() -> core::result::Result<()> { /// let f = File::open("log.txt")?; /// let mut reader = BufReader::new(f); /// assert!(reader.buffer().is_empty()); /// /// if reader.fill_buf()?.len() > 0 { /// assert!(!reader.buffer().is_empty()); /// } /// Ok(()) /// } /// ``` pub fn buffer(&self) -> &[u8] { &self.buf[self.pos..self.cap] } /// Returns the number of bytes the internal buffer can hold at once. /// /// # Examples /// /// ```no_run /// use std::{BufReader, BufRead}; /// use std::fs::File; /// /// fn main() -> core::result::Result<()> { /// let f = File::open("log.txt")?; /// let mut reader = BufReader::new(f); /// /// let capacity = reader.capacity(); /// let buffer = reader.fill_buf()?; /// assert!(buffer.len() <= capacity); /// Ok(()) /// } /// ``` pub fn capacity(&self) -> usize { S } /// Unwraps this `BufReader`, returning the underlying reader. /// /// Note that any leftover data in the internal buffer is lost. Therefore, /// a following read from the underlying reader may lead to data loss. /// /// # Examples /// /// ```no_run /// use core2::io::BufReader; /// use std::fs::File; /// /// fn main() -> core::result::Result<()> { /// let f1 = File::open("log.txt")?; /// let reader = BufReader::new(f1); /// /// let f2 = reader.into_inner(); /// Ok(()) /// } /// ``` pub fn into_inner(self) -> R { self.inner } /// Invalidates all data in the internal buffer. #[inline] fn discard_buffer(&mut self) { self.pos = 0; self.cap = 0; } } impl Read for BufReader { fn read(&mut self, buf: &mut [u8]) -> Result { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer // entirely. if self.pos == self.cap && buf.len() >= S { self.discard_buffer(); return self.inner.read(buf); } let nread = { let mut rem = self.fill_buf()?; rem.read(buf)? }; self.consume(nread); Ok(nread) } } impl BufRead for BufReader { fn fill_buf(&mut self) -> Result<&[u8]> { // If we've reached the end of our internal buffer then we need to fetch // some more data from the underlying reader. // Branch using `>=` instead of the more correct `==` // to tell the compiler that the pos..cap slice is always valid. if self.pos >= self.cap { debug_assert!(self.pos == self.cap); self.cap = self.inner.read(&mut self.buf)?; self.pos = 0; } Ok(&self.buf[self.pos..self.cap]) } fn consume(&mut self, amt: usize) { self.pos = cmp::min(self.pos + amt, self.cap); } } impl fmt::Debug for BufReader where R: fmt::Debug, { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("BufReader") .field("reader", &self.inner) .field("buffer", &format_args!("{}/{}", self.cap - self.pos, S)) .finish() } } impl Seek for BufReader { /// Seek to an offset, in bytes, in the underlying reader. /// /// The position used for seeking with [`SeekFrom::Current`]`(_)` is the /// position the underlying reader would be at if the `BufReader` had no /// internal buffer. /// /// Seeking always discards the internal buffer, even if the seek position /// would otherwise fall within it. This guarantees that calling /// [`BufReader::into_inner()`] immediately after a seek yields the underlying reader /// at the same position. /// /// To seek without discarding the internal buffer, use [`BufReader::seek_relative`]. /// /// See [`std::Seek`] for more details. /// /// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)` /// where `n` minus the internal buffer length overflows an `i64`, two /// seeks will be performed instead of one. If the second seek returns /// [`Err`], the underlying reader will be left at the same position it would /// have if you called `seek` with [`SeekFrom::Current`]`(0)`. /// /// [`std::Seek`]: Seek fn seek(&mut self, pos: SeekFrom) -> Result { let result: u64; if let SeekFrom::Current(n) = pos { let remainder = (self.cap - self.pos) as i64; // it should be safe to assume that remainder fits within an i64 as the alternative // means we managed to allocate 8 exbibytes and that's absurd. // But it's not out of the realm of possibility for some weird underlying reader to // support seeking by i64::MIN so we need to handle underflow when subtracting // remainder. if let Some(offset) = n.checked_sub(remainder) { result = self.inner.seek(SeekFrom::Current(offset))?; } else { // seek backwards by our remainder, and then by the offset self.inner.seek(SeekFrom::Current(-remainder))?; self.discard_buffer(); result = self.inner.seek(SeekFrom::Current(n))?; } } else { // Seeking with Start/End doesn't care about our buffer length. result = self.inner.seek(pos)?; } self.discard_buffer(); Ok(result) } } /// Wraps a writer and buffers its output. /// /// It can be excessively inefficient to work directly with something that /// implements [`Write`]. For example, every call to /// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A /// `BufWriter` keeps an in-memory buffer of data and writes it to an underlying /// writer in large, infrequent batches. /// /// `BufWriter` can improve the speed of programs that make *small* and /// *repeated* write calls to the same file or network socket. It does not /// help when writing very large amounts at once, or writing just one or a few /// times. It also provides no advantage when writing to a destination that is /// in memory, like a [`Vec`]`. /// /// It is critical to call [`flush`] before `BufWriter` is dropped. Though /// dropping will attempt to flush the contents of the buffer, any errors /// that happen in the process of dropping will be ignored. Calling [`flush`] /// ensures that the buffer is empty and thus dropping will not even attempt /// file operations. /// /// # Examples /// /// Let's write the numbers one through ten to a [`TcpStream`]: /// /// ```no_run /// use std::prelude::*; /// use std::net::TcpStream; /// /// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap(); /// /// for i in 0..10 { /// stream.write(&[i+1]).unwrap(); /// } /// ``` /// /// Because we're not buffering, we write each one in turn, incurring the /// overhead of a system call per byte written. We can fix this with a /// `BufWriter`: /// /// ```no_run /// use std::prelude::*; /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// for i in 0..10 { /// stream.write(&[i+1]).unwrap(); /// } /// stream.flush().unwrap(); /// ``` /// /// By wrapping the stream with a `BufWriter`, these ten writes are all grouped /// together by the buffer and will all be written out in one system call when /// the `stream` is flushed. /// /// [`TcpStream::write`]: Write::write /// [`TcpStream`]: crate::net::TcpStream /// [`flush`]: Write::flush pub struct BufWriter { inner: Option, buf: [u8; S], len: usize, // #30888: If the inner writer panics in a call to write, we don't want to // write the buffered data a second time in BufWriter's destructor. This // flag tells the Drop impl if it should skip the flush. panicked: bool, } /// An error returned by [`BufWriter::into_inner`] which combines an error that /// happened while writing out the buffer, and the buffered writer object /// which may be used to recover from the condition. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// // do stuff with the stream /// /// // we want to get our `TcpStream` back, so let's try: /// /// let stream = match stream.into_inner() { /// Ok(s) => s, /// Err(e) => { /// // Here, e is an IntoInnerError /// panic!("An error occurred"); /// } /// }; /// ``` #[derive(Debug)] pub struct IntoInnerError(W, Error); impl BufWriter where W: Write, { /// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB, /// but may change in the future. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// ``` pub fn new(inner: W) -> BufWriter { BufWriter { inner: Some(inner), buf: [0; S], len: 0, panicked: false, } } /// Send data in our local buffer into the inner writer, looping as /// necessary until either it's all been sent or an error occurs. /// /// Because all the data in the buffer has been reported to our owner as /// "successfully written" (by returning nonzero success values from /// `write`), any 0-length writes from `inner` must be reported as i/o /// errors from this method. fn flush_buf(&mut self) -> Result<()> { /// Helper struct to ensure the buffer is updated after all the writes /// are complete. It tracks the number of written bytes and drains them /// all from the front of the buffer when dropped. struct BufGuard<'a, const S: usize> { buffer: &'a mut [u8; S], written: usize, } impl<'a, const S: usize> BufGuard<'a, S> { fn new(buffer: &'a mut [u8; S]) -> Self { Self { buffer, written: 0 } } /// The unwritten part of the buffer fn remaining(&self) -> &[u8] { &self.buffer[self.written..] } /// Flag some bytes as removed from the front of the buffer fn consume(&mut self, amt: usize) { self.written += amt; } /// true if all of the bytes have been written fn done(&self) -> bool { self.written >= self.buffer.len() } } impl Drop for BufGuard<'_, S> { fn drop(&mut self) { if self.written > 0 { let mut new_buf = [0; S]; new_buf.copy_from_slice(&self.buffer[self.written..]); *self.buffer = new_buf; } } } let mut guard = BufGuard::new(&mut self.buf); let inner = self.inner.as_mut().unwrap(); while !guard.done() { self.panicked = true; let r = inner.write(guard.remaining()); self.panicked = false; match r { Ok(0) => { return Err(Error::new( ErrorKind::WriteZero, "failed to write the buffered data", )); } Ok(n) => guard.consume(n), Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } } Ok(()) } /// Buffer some data without flushing it, regardless of the size of the /// data. Writes as much as possible without exceeding capacity. Returns /// the number of bytes written. fn write_to_buf(&mut self, buf: &[u8]) -> usize { let available = S - self.len; let amt_to_buffer = available.min(buf.len()); (&mut self.buf[available..]).copy_from_slice(&buf[..amt_to_buffer]); self.len += amt_to_buffer; amt_to_buffer } /// Gets a reference to the underlying writer. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// // we can use reference just like buffer /// let reference = buffer.get_ref(); /// ``` pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() } /// Gets a mutable reference to the underlying writer. /// /// It is inadvisable to directly write to the underlying writer. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// // we can use reference just like buffer /// let reference = buffer.get_mut(); /// ``` pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } /// Returns a reference to the internally buffered data. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// // See how many bytes are currently buffered /// let bytes_buffered = buf_writer.buffer().len(); /// ``` pub fn buffer(&self) -> &[u8] { &self.buf } /// Returns the number of bytes the internal buffer can hold without flushing. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// // Check the capacity of the inner buffer /// let capacity = buf_writer.capacity(); /// // Calculate how many bytes can be written without flushing /// let without_flush = capacity - buf_writer.buffer().len(); /// ``` pub fn capacity(&self) -> usize { S } /// Unwraps this `BufWriter`, returning the underlying writer. /// /// The buffer is written out before returning the writer. /// /// # Errors /// /// An [`Err`] will be returned if an error occurs while flushing the buffer. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// // unwrap the TcpStream and flush the buffer /// let stream = buffer.into_inner().unwrap(); /// ``` pub fn into_inner(mut self) -> core::result::Result>> { match self.flush_buf() { Err(e) => Err(IntoInnerError(self, e)), Ok(()) => Ok(self.inner.take().unwrap()), } } } impl Write for BufWriter { fn write(&mut self, buf: &[u8]) -> Result { if self.len + buf.len() > S { self.flush_buf()?; } // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919 if buf.len() >= S { self.panicked = true; let r = self.get_mut().write(buf); self.panicked = false; r } else { self.buf.copy_from_slice(buf); Ok(buf.len()) } } fn write_all(&mut self, buf: &[u8]) -> Result<()> { // Normally, `write_all` just calls `write` in a loop. We can do better // by calling `self.get_mut().write_all()` directly, which avoids // round trips through the buffer in the event of a series of partial // writes in some circumstances. if self.len + buf.len() > S { self.flush_buf()?; } // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919 if buf.len() >= S { self.panicked = true; let r = self.get_mut().write_all(buf); self.panicked = false; r } else { self.buf.copy_from_slice(buf); Ok(()) } } fn flush(&mut self) -> Result<()> { self.flush_buf().and_then(|()| self.get_mut().flush()) } } impl fmt::Debug for BufWriter where W: fmt::Debug, { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("BufWriter") .field("writer", &self.inner.as_ref().unwrap()) .field("buffer", &format_args!("{}/{}", self.buf.len(), S)) .finish() } } impl Seek for BufWriter { /// Seek to the offset, in bytes, in the underlying writer. /// /// Seeking always writes out the internal buffer before seeking. fn seek(&mut self, pos: SeekFrom) -> Result { self.flush_buf()?; self.get_mut().seek(pos) } } impl Drop for BufWriter { fn drop(&mut self) { if self.inner.is_some() && !self.panicked { // dtors should not panic, so we ignore a failed flush let _r = self.flush_buf(); } } } impl IntoInnerError { /// Returns the error which caused the call to [`BufWriter::into_inner()`] /// to fail. /// /// This error was returned when attempting to write the internal buffer. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// // do stuff with the stream /// /// // we want to get our `TcpStream` back, so let's try: /// /// let stream = match stream.into_inner() { /// Ok(s) => s, /// Err(e) => { /// // Here, e is an IntoInnerError, let's log the inner error. /// // /// // We'll just 'log' to stdout for this example. /// println!("{}", e.error()); /// /// panic!("An unexpected error occurred."); /// } /// }; /// ``` pub fn error(&self) -> &Error { &self.1 } /// Returns the buffered writer instance which generated the error. /// /// The returned object can be used for error recovery, such as /// re-inspecting the buffer. /// /// # Examples /// /// ```no_run /// use core2::io::BufWriter; /// use std::net::TcpStream; /// /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); /// /// // do stuff with the stream /// /// // we want to get our `TcpStream` back, so let's try: /// /// let stream = match stream.into_inner() { /// Ok(s) => s, /// Err(e) => { /// // Here, e is an IntoInnerError, let's re-examine the buffer: /// let buffer = e.into_inner(); /// /// // do stuff to try to recover /// /// // afterwards, let's just return the stream /// buffer.into_inner().unwrap() /// } /// }; /// ``` pub fn into_inner(self) -> W { self.0 } } impl From> for Error { fn from(iie: IntoInnerError) -> Error { iie.1 } } impl fmt::Display for IntoInnerError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.error().fmt(f) } } /// Private helper struct for implementing the line-buffered writing logic. /// This shim temporarily wraps a BufWriter, and uses its internals to /// implement a line-buffered writer (specifically by using the internal /// methods like write_to_buf and flush_buf). In this way, a more /// efficient abstraction can be created than one that only had access to /// `write` and `flush`, without needlessly duplicating a lot of the /// implementation details of BufWriter. This also allows existing /// `BufWriters` to be temporarily given line-buffering logic; this is what /// enables Stdout to be alternately in line-buffered or block-buffered mode. #[derive(Debug)] pub(super) struct LineWriterShim<'a, W: Write, const S: usize> { buffer: &'a mut BufWriter, } impl<'a, W: Write, const S: usize> LineWriterShim<'a, W, S> { pub fn new(buffer: &'a mut BufWriter) -> Self { Self { buffer } } /// Get a mutable reference to the inner writer (that is, the writer /// wrapped by the BufWriter). Be careful with this writer, as writes to /// it will bypass the buffer. fn inner_mut(&mut self) -> &mut W { self.buffer.get_mut() } /// Get the content currently buffered in self.buffer fn buffered(&self) -> &[u8] { self.buffer.buffer() } /// Flush the buffer iff the last byte is a newline (indicating that an /// earlier write only succeeded partially, and we want to retry flushing /// the buffered line before continuing with a subsequent write) fn flush_if_completed_line(&mut self) -> Result<()> { match self.buffered().last().copied() { Some(b'\n') => self.buffer.flush_buf(), _ => Ok(()), } } } impl<'a, W: Write, const S: usize> Write for LineWriterShim<'a, W, S> { /// Write some data into this BufReader with line buffering. This means /// that, if any newlines are present in the data, the data up to the last /// newline is sent directly to the underlying writer, and data after it /// is buffered. Returns the number of bytes written. /// /// This function operates on a "best effort basis"; in keeping with the /// convention of `Write::write`, it makes at most one attempt to write /// new data to the underlying writer. If that write only reports a partial /// success, the remaining data will be buffered. /// /// Because this function attempts to send completed lines to the underlying /// writer, it will also flush the existing buffer if it ends with a /// newline, even if the incoming data does not contain any newlines. fn write(&mut self, buf: &[u8]) -> Result { let newline_idx = match memchr::memrchr(b'\n', buf) { // If there are no new newlines (that is, if this write is less than // one line), just do a regular buffered write (which may flush if // we exceed the inner buffer's size) None => { self.flush_if_completed_line()?; return self.buffer.write(buf); } // Otherwise, arrange for the lines to be written directly to the // inner writer. Some(newline_idx) => newline_idx + 1, }; // Flush existing content to prepare for our write. We have to do this // before attempting to write `buf` in order to maintain consistency; // if we add `buf` to the buffer then try to flush it all at once, // we're obligated to return Ok(), which would mean suppressing any // errors that occur during flush. self.buffer.flush_buf()?; // This is what we're going to try to write directly to the inner // writer. The rest will be buffered, if nothing goes wrong. let lines = &buf[..newline_idx]; // Write `lines` directly to the inner writer. In keeping with the // `write` convention, make at most one attempt to add new (unbuffered) // data. Because this write doesn't touch the BufWriter state directly, // and the buffer is known to be empty, we don't need to worry about // self.buffer.panicked here. let flushed = self.inner_mut().write(lines)?; // If buffer returns Ok(0), propagate that to the caller without // doing additional buffering; otherwise we're just guaranteeing // an "ErrorKind::WriteZero" later. if flushed == 0 { return Ok(0); } // Now that the write has succeeded, buffer the rest (or as much of // the rest as possible). If there were any unwritten newlines, we // only buffer out to the last unwritten newline that fits in the // buffer; this helps prevent flushing partial lines on subsequent // calls to LineWriterShim::write. // Handle the cases in order of most-common to least-common, under // the presumption that most writes succeed in totality, and that most // writes are smaller than the buffer. // - Is this a partial line (ie, no newlines left in the unwritten tail) // - If not, does the data out to the last unwritten newline fit in // the buffer? // - If not, scan for the last newline that *does* fit in the buffer let tail = if flushed >= newline_idx { &buf[flushed..] } else if newline_idx - flushed <= self.buffer.capacity() { &buf[flushed..newline_idx] } else { let scan_area = &buf[flushed..]; let scan_area = &scan_area[..self.buffer.capacity()]; match memchr::memrchr(b'\n', scan_area) { Some(newline_idx) => &scan_area[..newline_idx + 1], None => scan_area, } }; let buffered = self.buffer.write_to_buf(tail); Ok(flushed + buffered) } fn flush(&mut self) -> Result<()> { self.buffer.flush() } /// Write some data into this BufReader with line buffering. This means /// that, if any newlines are present in the data, the data up to the last /// newline is sent directly to the underlying writer, and data after it /// is buffered. /// /// Because this function attempts to send completed lines to the underlying /// writer, it will also flush the existing buffer if it contains any /// newlines, even if the incoming data does not contain any newlines. fn write_all(&mut self, buf: &[u8]) -> Result<()> { match memchr::memrchr(b'\n', buf) { // If there are no new newlines (that is, if this write is less than // one line), just do a regular buffered write (which may flush if // we exceed the inner buffer's size) None => { self.flush_if_completed_line()?; self.buffer.write_all(buf) } Some(newline_idx) => { let (lines, tail) = buf.split_at(newline_idx + 1); if self.buffered().is_empty() { self.inner_mut().write_all(lines)?; } else { // If there is any buffered data, we add the incoming lines // to that buffer before flushing, which saves us at least // one write call. We can't really do this with `write`, // since we can't do this *and* not suppress errors *and* // report a consistent state to the caller in a return // value, but here in write_all it's fine. self.buffer.write_all(lines)?; self.buffer.flush_buf()?; } self.buffer.write_all(tail) } } } } /// Wraps a writer and buffers output to it, flushing whenever a newline /// (`0x0a`, `'\n'`) is detected. /// /// The [`BufWriter`] struct wraps a writer and buffers its output. /// But it only does this batched write when it goes out of scope, or when the /// internal buffer is full. Sometimes, you'd prefer to write each line as it's /// completed, rather than the entire buffer at once. Enter `LineWriter`. It /// does exactly that. /// /// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the /// `LineWriter` goes out of scope or when its internal buffer is full. /// /// If there's still a partial line in the buffer when the `LineWriter` is /// dropped, it will flush those contents. /// /// # Examples /// /// We can use `LineWriter` to write one line at a time, significantly /// reducing the number of actual writes to the file. /// /// ```no_run /// use std::fs::{self, File}; /// use std::prelude::*; /// use core2::io::LineWriter; /// /// fn main() -> core::result::Result<()> { /// let road_not_taken = b"I shall be telling this with a sigh /// Somewhere ages and ages hence: /// Two roads diverged in a wood, and I - /// I took the one less traveled by, /// And that has made all the difference."; /// /// let file = File::create("poem.txt")?; /// let mut file = LineWriter::new(file); /// /// file.write_all(b"I shall be telling this with a sigh")?; /// /// // No bytes are written until a newline is encountered (or /// // the internal buffer is filled). /// assert_eq!(fs::read_to_string("poem.txt")?, ""); /// file.write_all(b"\n")?; /// assert_eq!( /// fs::read_to_string("poem.txt")?, /// "I shall be telling this with a sigh\n", /// ); /// /// // Write the rest of the poem. /// file.write_all(b"Somewhere ages and ages hence: /// Two roads diverged in a wood, and I - /// I took the one less traveled by, /// And that has made all the difference.")?; /// /// // The last line of the poem doesn't end in a newline, so /// // we have to flush or drop the `LineWriter` to finish /// // writing. /// file.flush()?; /// /// // Confirm the whole poem was written. /// assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]); /// Ok(()) /// } /// ``` pub struct LineWriter { inner: BufWriter, } impl LineWriter { /// Creates a new `LineWriter`. /// /// # Examples /// /// ```no_run /// use std::fs::File; /// use core2::io::LineWriter; /// /// fn main() -> core::result::Result<()> { /// let file = File::create("poem.txt")?; /// let file = LineWriter::new(file); /// Ok(()) /// } /// ``` pub fn new(inner: W) -> LineWriter { LineWriter { inner: BufWriter::new(inner), } } /// Gets a reference to the underlying writer. /// /// # Examples /// /// ```no_run /// use std::fs::File; /// use core2::io::LineWriter; /// /// fn main() -> core::result::Result<()> { /// let file = File::create("poem.txt")?; /// let file = LineWriter::new(file); /// /// let reference = file.get_ref(); /// Ok(()) /// } /// ``` pub fn get_ref(&self) -> &W { self.inner.get_ref() } /// Gets a mutable reference to the underlying writer. /// /// Caution must be taken when calling methods on the mutable reference /// returned as extra writes could corrupt the output stream. /// /// # Examples /// /// ```no_run /// use std::fs::File; /// use core2::io::LineWriter; /// /// fn main() -> core::result::Result<()> { /// let file = File::create("poem.txt")?; /// let mut file = LineWriter::new(file); /// /// // we can use reference just like file /// let reference = file.get_mut(); /// Ok(()) /// } /// ``` pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } /// Unwraps this `LineWriter`, returning the underlying writer. /// /// The internal buffer is written out before returning the writer. /// /// # Errors /// /// An [`Err`] will be returned if an error occurs while flushing the buffer. /// /// # Examples /// /// ```no_run /// use std::fs::File; /// use core2::io::LineWriter; /// /// fn main() -> core::result::Result<()> { /// let file = File::create("poem.txt")?; /// /// let writer: LineWriter = LineWriter::new(file); /// /// let file: File = writer.into_inner()?; /// Ok(()) /// } /// ``` pub fn into_inner(self) -> core::result::Result>> { self.inner .into_inner() .map_err(|IntoInnerError(buf, e)| IntoInnerError(LineWriter { inner: buf }, e)) } } impl Write for LineWriter { fn write(&mut self, buf: &[u8]) -> Result { LineWriterShim::new(&mut self.inner).write(buf) } fn flush(&mut self) -> Result<()> { self.inner.flush() } fn write_all(&mut self, buf: &[u8]) -> Result<()> { LineWriterShim::new(&mut self.inner).write_all(buf) } fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { LineWriterShim::new(&mut self.inner).write_fmt(fmt) } } impl fmt::Debug for LineWriter where W: fmt::Debug, { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("LineWriter") .field("writer", &self.inner.inner) .field("buffer", &format_args!("{}/{}", self.inner.len, S)) .finish() } } core2-0.4.0/src/io/cursor.rs000064400000000000000000000162610072674642500137560ustar 00000000000000use super::{BufRead, Error, ErrorKind, Read, Result, Seek, SeekFrom, Write}; use core::cmp; /// A `Cursor` wraps an in-memory buffer and provides it with a /// [`Seek`] implementation. /// /// `Cursor`s are used with in-memory buffers, anything implementing /// [`AsRef`]`<[u8]>`, to allow them to implement [`Read`] and/or [`Write`], /// allowing these buffers to be used anywhere you might use a reader or writer /// that does actual I/O. /// /// The standard library implements some I/O traits on various types which /// are commonly used as a buffer, like `Cursor<`[`Vec`]`>` and /// `Cursor<`[`&[u8]`][bytes]`>`. /// /// # Examples /// /// We may want to write bytes to a [`File`] in our production /// code, but use an in-memory buffer in our tests. We can do this with /// `Cursor`: /// /// [bytes]: crate::slice /// [`File`]: crate::fs::File /// /// ``` /// use std::io::prelude::*; /// use core2::io::{self, Seek, SeekFrom, Write}; /// use std::fs::File; /// /// // a library function we've written /// fn write_ten_bytes_at_end(writer: &mut W) -> io::Result<()> { /// writer.seek(SeekFrom::End(-10))?; /// /// for i in 0..10 { /// writer.write(&[i])?; /// } /// /// // all went well /// Ok(()) /// } /// /// # #[cfg(feature = "std")] /// # fn foo() -> io::Result<()> { /// // Here's some code that uses this library function. /// // /// // We might want to use a BufReader here for efficiency, but let's /// // keep this example focused. /// let mut file = File::create("foo.txt").map_err(|e| io::Error::from(e))?; /// /// write_ten_bytes_at_end(&mut file)?; /// # Ok(()) /// # } /// /// // now let's write a test /// #[test] /// fn test_writes_bytes() { /// // setting up a real File is much slower than an in-memory buffer, /// // let's use a cursor instead /// use core2::io::Cursor; /// let mut buff = Cursor::new(vec![0; 15]); /// /// write_ten_bytes_at_end(&mut buff).unwrap(); /// /// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// } /// ``` #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Cursor { inner: T, pos: u64, } impl Cursor { /// Creates a new cursor wrapping the provided underlying in-memory buffer. /// /// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`]) /// is not empty. So writing to cursor starts with overwriting [`Vec`] /// content, not with appending to it. /// /// # Examples /// /// ``` /// use core2::io::Cursor; /// /// let buff = Cursor::new(Vec::new()); /// # fn force_inference(_: &Cursor>) {} /// # force_inference(&buff); /// ``` pub fn new(inner: T) -> Cursor { Cursor { pos: 0, inner } } /// Consumes this cursor, returning the underlying value. /// /// # Examples /// /// ``` /// use core2::io::Cursor; /// /// let buff = Cursor::new(Vec::new()); /// # fn force_inference(_: &Cursor>) {} /// # force_inference(&buff); /// /// let vec = buff.into_inner(); /// ``` pub fn into_inner(self) -> T { self.inner } /// Gets a reference to the underlying value in this cursor. /// /// # Examples /// /// ``` /// use core2::io::Cursor; /// /// let buff = Cursor::new(Vec::new()); /// # fn force_inference(_: &Cursor>) {} /// # force_inference(&buff); /// /// let reference = buff.get_ref(); /// ``` pub fn get_ref(&self) -> &T { &self.inner } /// Gets a mutable reference to the underlying value in this cursor. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying value as it may corrupt this cursor's position. /// /// # Examples /// /// ``` /// use core2::io::Cursor; /// /// let mut buff = Cursor::new(Vec::new()); /// # fn force_inference(_: &Cursor>) {} /// # force_inference(&buff); /// /// let reference = buff.get_mut(); /// ``` pub fn get_mut(&mut self) -> &mut T { &mut self.inner } /// Returns the current position of this cursor. /// /// # Examples /// /// ``` /// use core2::io::{Cursor, Seek, SeekFrom}; /// use std::io::prelude::*; /// /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); /// /// assert_eq!(buff.position(), 0); /// /// buff.seek(SeekFrom::Current(2)).unwrap(); /// assert_eq!(buff.position(), 2); /// /// buff.seek(SeekFrom::Current(-1)).unwrap(); /// assert_eq!(buff.position(), 1); /// ``` pub fn position(&self) -> u64 { self.pos } /// Sets the position of this cursor. /// /// # Examples /// /// ``` /// use core2::io::Cursor; /// /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); /// /// assert_eq!(buff.position(), 0); /// /// buff.set_position(2); /// assert_eq!(buff.position(), 2); /// /// buff.set_position(4); /// assert_eq!(buff.position(), 4); /// ``` pub fn set_position(&mut self, pos: u64) { self.pos = pos; } } impl Seek for Cursor where T: AsRef<[u8]>, { fn seek(&mut self, style: SeekFrom) -> Result { let (base_pos, offset) = match style { SeekFrom::Start(n) => { self.pos = n; return Ok(n); } SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), SeekFrom::Current(n) => (self.pos, n), }; let new_pos = if offset >= 0 { base_pos.checked_add(offset as u64) } else { base_pos.checked_sub((offset.wrapping_neg()) as u64) }; match new_pos { Some(n) => { self.pos = n; Ok(self.pos) } None => Err(Error::new( ErrorKind::InvalidInput, "invalid seek to a negative or overflowing position", )), } } } impl Read for Cursor where T: AsRef<[u8]>, { fn read(&mut self, buf: &mut [u8]) -> Result { let n = Read::read(&mut self.fill_buf()?, buf)?; self.pos += n as u64; Ok(n) } fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { let n = buf.len(); Read::read_exact(&mut self.fill_buf()?, buf)?; self.pos += n as u64; Ok(()) } } impl BufRead for Cursor where T: AsRef<[u8]>, { fn fill_buf(&mut self) -> Result<&[u8]> { let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64); Ok(&self.inner.as_ref()[(amt as usize)..]) } fn consume(&mut self, amt: usize) { self.pos += amt as u64; } } // Non-resizing write implementation #[inline] fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> Result { let pos = cmp::min(*pos_mut, slice.len() as u64); let amt = (&mut slice[(pos as usize)..]).write(buf)?; *pos_mut += amt as u64; Ok(amt) } impl Write for Cursor<&mut [u8]> { #[inline] fn write(&mut self, buf: &[u8]) -> Result { slice_write(&mut self.pos, self.inner, buf) } #[inline] fn flush(&mut self) -> Result<()> { Ok(()) } } core2-0.4.0/src/io/error.rs000064400000000000000000000363300072674642500135710ustar 00000000000000use core::{convert::From, fmt, result}; /// A specialized [`Result`] type for I/O operations. /// /// This type is broadly used across [`std::io`] for any operation which may /// produce an error. /// /// This typedef is generally used to avoid writing out [`io::Error`] directly and /// is otherwise a direct mapping to [`Result`]. /// /// While usual Rust style is to import types directly, aliases of [`Result`] /// often are not, to make it easier to distinguish between them. [`Result`] is /// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias /// will generally use `io::Result` instead of shadowing the [prelude]'s import /// of [`std::result::Result`][`Result`]. /// /// [`std::io`]: crate::io /// [`io::Error`]: Error /// [`Result`]: crate::result::Result /// [prelude]: crate::prelude /// /// # Examples /// /// A convenience function that bubbles an `io::Result` to its caller: /// /// ``` /// use core2::io; /// /// #[cfg(feature = "std")] /// fn get_string() -> io::Result { /// let mut buffer = String::new(); /// /// std::io::stdin().read_line(&mut buffer).map_err(|e| io::Error::from(e))?; /// /// Ok(buffer) /// } /// ``` pub type Result = result::Result; /// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and /// associated traits. /// /// Errors mostly originate from the underlying OS, but custom instances of /// `Error` can be created with crafted error messages and a particular value of /// [`ErrorKind`]. /// /// [`Read`]: crate::io::Read /// [`Write`]: crate::io::Write /// [`Seek`]: crate::io::Seek pub struct Error { repr: Repr, } impl crate::error::Error for Error {} impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.repr, f) } } enum Repr { Simple(ErrorKind), Custom(Custom), } #[derive(Debug)] struct Custom { kind: ErrorKind, error: &'static str, } /// A list specifying general categories of I/O error. /// /// This list is intended to grow over time and it is not recommended to /// exhaustively match against it. /// /// It is used with the [`io::Error`] type. /// /// [`io::Error`]: Error #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] // #[allow(deprecated)] #[non_exhaustive] pub enum ErrorKind { /// An entity was not found, often a file. NotFound, /// The operation lacked the necessary privileges to complete. PermissionDenied, /// The connection was refused by the remote server. ConnectionRefused, /// The connection was reset by the remote server. ConnectionReset, /// The connection was aborted (terminated) by the remote server. ConnectionAborted, /// The network operation failed because it was not connected yet. NotConnected, /// A socket address could not be bound because the address is already in /// use elsewhere. AddrInUse, /// A nonexistent interface was requested or the requested address was not /// local. AddrNotAvailable, /// The operation failed because a pipe was closed. BrokenPipe, /// An entity already exists, often a file. AlreadyExists, /// The operation needs to block to complete, but the blocking operation was /// requested to not occur. WouldBlock, /// A parameter was incorrect. InvalidInput, /// Data not valid for the operation were encountered. /// /// Unlike [`InvalidInput`], this typically means that the operation /// parameters were valid, however the error was caused by malformed /// input data. /// /// For example, a function that reads a file into a string will error with /// `InvalidData` if the file's contents are not valid UTF-8. /// /// [`InvalidInput`]: ErrorKind::InvalidInput InvalidData, /// The I/O operation's timeout expired, causing it to be canceled. TimedOut, /// An error returned when an operation could not be completed because a /// call to [`write`] returned [`Ok(0)`]. /// /// This typically means that an operation could only succeed if it wrote a /// particular number of bytes but only a smaller number of bytes could be /// written. /// /// [`write`]: crate::io::Write::write /// [`Ok(0)`]: Ok WriteZero, /// This operation was interrupted. /// /// Interrupted operations can typically be retried. Interrupted, /// Any I/O error not part of this list. /// /// Errors that are `Other` now may move to a different or a new /// [`ErrorKind`] variant in the future. It is not recommended to match /// an error against `Other` and to expect any additional characteristics, /// e.g., a specific [`Error::raw_os_error`] return value. Other, /// An error returned when an operation could not be completed because an /// "end of file" was reached prematurely. /// /// This typically means that an operation could only succeed if it read a /// particular number of bytes but only a smaller number of bytes could be /// read. UnexpectedEof, /// Any I/O error from the standard library that's not part of this list. /// /// Errors that are `Uncategorized` now may move to a different or a new /// [`ErrorKind`] variant in the future. It is not recommended to match /// an error against `Uncategorized`; use a wildcard match (`_`) instead. #[doc(hidden)] Uncategorized, } impl ErrorKind { pub(crate) fn as_str(&self) -> &'static str { match *self { ErrorKind::NotFound => "entity not found", ErrorKind::PermissionDenied => "permission denied", ErrorKind::ConnectionRefused => "connection refused", ErrorKind::ConnectionReset => "connection reset", ErrorKind::ConnectionAborted => "connection aborted", ErrorKind::NotConnected => "not connected", ErrorKind::AddrInUse => "address in use", ErrorKind::AddrNotAvailable => "address not available", ErrorKind::BrokenPipe => "broken pipe", ErrorKind::AlreadyExists => "entity already exists", ErrorKind::WouldBlock => "operation would block", ErrorKind::InvalidInput => "invalid input parameter", ErrorKind::InvalidData => "invalid data", ErrorKind::TimedOut => "timed out", ErrorKind::WriteZero => "write zero", ErrorKind::Interrupted => "operation interrupted", ErrorKind::Other => "other os error", ErrorKind::UnexpectedEof => "unexpected end of file", ErrorKind::Uncategorized => "uncategorized", } } } #[cfg(feature = "std")] impl From for ErrorKind { /// Converts an [`std::io::ErrorKind`] into an [`ErrorKind`]. /// /// This conversion allocates a new error with a simple representation of error kind. /// /// # Examples /// /// ``` /// use core2::io::{Error, ErrorKind}; /// /// let not_found = ErrorKind::from(std::io::ErrorKind::NotFound); /// let err: Error = not_found.into(); /// assert_eq!("entity not found", format!("{}", err)); /// ``` fn from(k: std::io::ErrorKind) -> Self { match k { std::io::ErrorKind::NotFound => ErrorKind::NotFound, std::io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied, std::io::ErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused, std::io::ErrorKind::ConnectionReset => ErrorKind::ConnectionReset, std::io::ErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted, std::io::ErrorKind::NotConnected => ErrorKind::NotConnected, std::io::ErrorKind::AddrInUse => ErrorKind::AddrInUse, std::io::ErrorKind::AddrNotAvailable => ErrorKind::AddrNotAvailable, std::io::ErrorKind::BrokenPipe => ErrorKind::BrokenPipe, std::io::ErrorKind::AlreadyExists => ErrorKind::AlreadyExists, std::io::ErrorKind::WouldBlock => ErrorKind::WouldBlock, std::io::ErrorKind::InvalidInput => ErrorKind::InvalidInput, std::io::ErrorKind::InvalidData => ErrorKind::InvalidData, std::io::ErrorKind::TimedOut => ErrorKind::TimedOut, std::io::ErrorKind::WriteZero => ErrorKind::WriteZero, std::io::ErrorKind::Interrupted => ErrorKind::Interrupted, std::io::ErrorKind::Other => ErrorKind::Other, std::io::ErrorKind::UnexpectedEof => ErrorKind::UnexpectedEof, _ => ErrorKind::Uncategorized, } } } /// Intended for use for errors not exposed to the user, where allocating onto /// the heap (for normal construction via Error::new) is too costly. impl From for Error { /// Converts an [`ErrorKind`] into an [`Error`]. /// /// This conversion allocates a new error with a simple representation of error kind. /// /// # Examples /// /// ``` /// use core2::io::{Error, ErrorKind}; /// /// let not_found = ErrorKind::NotFound; /// let error = Error::from(not_found); /// assert_eq!("entity not found", format!("{}", error)); /// ``` #[inline] fn from(kind: ErrorKind) -> Error { Error { repr: Repr::Simple(kind), } } } #[cfg(feature = "std")] impl From for Error { /// Converts an [`std::io::ErrorKind`] into an [`Error`]. /// /// This conversion allocates a new error with a simple representation of error kind. /// /// # Examples /// /// ``` /// use core2::io::{Error, ErrorKind}; /// /// let not_found = std::io::Error::from(std::io::ErrorKind::NotFound); /// let error = Error::from(not_found); /// assert_eq!("entity not found", format!("{}", error)); /// ``` #[inline] fn from(err: std::io::Error) -> Self { Self::from(ErrorKind::from(err.kind())) } } impl Error { /// Creates a new I/O error from a known kind of error as well as an /// arbitrary error payload. /// /// This function is used to generically create I/O errors which do not /// originate from the OS itself. The `error` argument is an arbitrary /// payload which will be contained in this [`Error`]. /// /// # Examples /// /// ``` /// use core2::io::{Error, ErrorKind}; /// /// // errors can be created from strings /// let custom_error = Error::new(ErrorKind::Other, "oh no!"); /// /// // errors can also be created from other errors /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error.into_inner().unwrap()); /// ``` pub fn new(kind: ErrorKind, error: &'static str) -> Error { Self::_new(kind, error.into()) } fn _new(kind: ErrorKind, error: &'static str) -> Error { Error { repr: Repr::Custom(Custom { kind, error }), } } /// Returns a reference to the inner error wrapped by this error (if any). /// /// If this [`Error`] was constructed via [`new`] then this function will /// return [`Some`], otherwise it will return [`None`]. /// /// [`new`]: Error::new /// /// # Examples /// /// ``` /// use core2::io::{Error, ErrorKind}; /// /// fn print_error(err: &Error) { /// if let Some(inner_err) = err.get_ref() { /// println!("Inner error: {:?}", inner_err); /// } else { /// println!("No inner error"); /// } /// } /// /// #[cfg(feature = "std")] /// fn emit_error() { /// // Will print "No inner error". /// print_error(&Error::from(std::io::Error::last_os_error())); /// // Will print "Inner error: ...". /// print_error(&Error::new(ErrorKind::Other, "oh no!")); /// } /// /// #[cfg(not(feature = "std"))] /// fn emit_error() { /// // Will print "No inner error". /// print_error(&ErrorKind::Other.into()); /// // Will print "Inner error: ...". /// print_error(&Error::new(ErrorKind::Other, "oh no!")); /// } /// /// fn main() { /// emit_error(); /// } /// ``` pub fn get_ref(&self) -> Option<&&'static str> { match self.repr { Repr::Simple(..) => None, Repr::Custom(ref c) => Some(&c.error), } } /// Consumes the `Error`, returning its inner error (if any). /// /// If this [`Error`] was constructed via [`new`] then this function will /// return [`Some`], otherwise it will return [`None`]. /// /// [`new`]: Error::new /// /// # Examples /// /// ``` /// use core2::io::{Error, ErrorKind}; /// /// fn print_error(err: Error) { /// if let Some(inner_err) = err.into_inner() { /// println!("Inner error: {}", inner_err); /// } else { /// println!("No inner error"); /// } /// } /// /// #[cfg(feature = "std")] /// fn emit_error() { /// // Will print "No inner error". /// print_error(std::io::Error::last_os_error().into()); /// // Will print "Inner error: ...". /// print_error(Error::new(ErrorKind::Other, "oh no!")); /// } /// /// #[cfg(not(feature = "std"))] /// fn emit_error() { /// // Will print "No inner error". /// print_error(ErrorKind::Other.into()); /// // Will print "Inner error: ...". /// print_error(Error::new(ErrorKind::Other, "oh no!")); /// } /// /// fn main() { /// emit_error(); /// } /// ``` pub fn into_inner(self) -> Option<&'static str> { match self.repr { Repr::Simple(..) => None, Repr::Custom(c) => Some(c.error), } } /// Returns the corresponding [`ErrorKind`] for this error. /// /// # Examples /// /// ``` /// use core2::io::{Error, ErrorKind}; /// /// fn print_error(err: Error) { /// println!("{:?}", err.kind()); /// } /// /// #[cfg(feature = "std")] /// fn emit_error() { /// // Will print "Other". /// print_error(std::io::Error::last_os_error().into()); /// // Will print "AddrInUse". /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); /// } /// /// #[cfg(not(feature = "std"))] /// fn emit_error() { /// // Will print "Other". /// print_error(ErrorKind::Other.into()); /// // Will print "AddrInUse". /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!")); /// } /// /// fn main() { /// emit_error(); /// } /// ``` pub fn kind(&self) -> ErrorKind { match self.repr { Repr::Custom(ref c) => c.kind, Repr::Simple(kind) => kind, } } } impl fmt::Debug for Repr { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt), Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), } } } impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self.repr { Repr::Custom(ref c) => c.error.fmt(fmt), Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()), } } } fn _assert_error_is_sync_send() { fn _is_sync_send() {} _is_sync_send::(); } core2-0.4.0/src/io/impls.rs000064400000000000000000000106600072674642500135620ustar 00000000000000use super::error::{Error, ErrorKind, Result}; use super::traits::{BufRead, Read, Seek, SeekFrom, Write}; use core::{cmp, fmt, mem}; // ============================================================================= // Forwarding implementations impl Read for &mut R { #[inline] fn read(&mut self, buf: &mut [u8]) -> Result { (**self).read(buf) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { (**self).read_exact(buf) } } impl Write for &mut W { #[inline] fn write(&mut self, buf: &[u8]) -> Result { (**self).write(buf) } #[inline] fn flush(&mut self) -> Result<()> { (**self).flush() } #[inline] fn write_all(&mut self, buf: &[u8]) -> Result<()> { (**self).write_all(buf) } #[inline] fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { (**self).write_fmt(fmt) } } impl Seek for &mut S { #[inline] fn seek(&mut self, pos: SeekFrom) -> Result { (**self).seek(pos) } } impl BufRead for &mut B { #[inline] fn fill_buf(&mut self) -> Result<&[u8]> { (**self).fill_buf() } #[inline] fn consume(&mut self, amt: usize) { (**self).consume(amt) } } // ============================================================================= // In-memory buffer implementations /// Read is implemented for `&[u8]` by copying from the slice. /// /// Note that reading updates the slice to point to the yet unread part. /// The slice will be empty when EOF is reached. impl Read for &[u8] { #[inline] fn read(&mut self, buf: &mut [u8]) -> Result { let amt = cmp::min(buf.len(), self.len()); let (a, b) = self.split_at(amt); // First check if the amount of bytes we want to read is small: // `copy_from_slice` will generally expand to a call to `memcpy`, and // for a single byte the overhead is significant. if amt == 1 { buf[0] = a[0]; } else { buf[..amt].copy_from_slice(a); } *self = b; Ok(amt) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> { if buf.len() > self.len() { return Err(Error::new( ErrorKind::UnexpectedEof, "failed to fill whole buffer", )); } let (a, b) = self.split_at(buf.len()); // First check if the amount of bytes we want to read is small: // `copy_from_slice` will generally expand to a call to `memcpy`, and // for a single byte the overhead is significant. if buf.len() == 1 { buf[0] = a[0]; } else { buf.copy_from_slice(a); } *self = b; Ok(()) } } impl BufRead for &[u8] { #[inline] fn fill_buf(&mut self) -> Result<&[u8]> { Ok(*self) } #[inline] fn consume(&mut self, amt: usize) { *self = &self[amt..]; } } /// Write is implemented for `&mut [u8]` by copying into the slice, overwriting /// its data. /// /// Note that writing updates the slice to point to the yet unwritten part. /// The slice will be empty when it has been completely overwritten. impl Write for &mut [u8] { #[inline] fn write(&mut self, data: &[u8]) -> Result { let amt = cmp::min(data.len(), self.len()); let (a, b) = mem::replace(self, &mut []).split_at_mut(amt); a.copy_from_slice(&data[..amt]); *self = b; Ok(amt) } #[inline] fn write_all(&mut self, data: &[u8]) -> Result<()> { if self.write(data)? == data.len() { Ok(()) } else { Err(Error::new( ErrorKind::WriteZero, "failed to write whole buffer", )) } } #[inline] fn flush(&mut self) -> Result<()> { Ok(()) } } /// Write is implemented for `Vec` by appending to the vector. /// The vector will grow as needed. #[cfg(feature = "alloc")] impl Write for alloc::vec::Vec { #[inline] fn write(&mut self, buf: &[u8]) -> Result { self.extend_from_slice(buf); Ok(buf.len()) } #[inline] fn write_all(&mut self, buf: &[u8]) -> Result<()> { self.extend_from_slice(buf); Ok(()) } #[inline] fn flush(&mut self) -> Result<()> { Ok(()) } } core2-0.4.0/src/io/mod.rs000064400000000000000000000012260072674642500132130ustar 00000000000000#[cfg(feature = "nightly")] mod buffered; mod cursor; mod error; mod impls; mod traits; mod util; #[cfg(not(feature = "std"))] pub use cursor::Cursor; #[cfg(not(feature = "std"))] pub use error::{Error, ErrorKind, Result}; #[cfg(not(feature = "std"))] pub use traits::{BufRead, Bytes, Chain, Read, Seek, SeekFrom, Take, Write}; #[cfg(feature = "std")] pub use std::io::{ BufRead, Bytes, Chain, Cursor, Error, ErrorKind, Read, Result, Seek, SeekFrom, Take, Write, }; // Use this crate's implementation on both std and no_std #[cfg(feature = "nightly")] pub use buffered::{BufReader, BufWriter, LineWriter}; #[cfg(feature = "nightly")] pub use util::copy; core2-0.4.0/src/io/traits.rs000064400000000000000000001227460072674642500137550ustar 00000000000000use super::error::{Error, ErrorKind, Result}; use core::{cmp, fmt, slice}; #[cfg(feature = "alloc")] pub use alloc::vec::Vec; #[cfg(feature = "alloc")] struct Guard<'a> { buf: &'a mut Vec, len: usize, } #[cfg(feature = "alloc")] impl Drop for Guard<'_> { fn drop(&mut self) { unsafe { self.buf.set_len(self.len); } } } // This uses an adaptive system to extend the vector when it fills. We want to // avoid paying to allocate and zero a huge chunk of memory if the reader only // has 4 bytes while still making large reads if the reader does have a ton // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every // time is 4,500 times (!) slower than a default reservation size of 32 if the // reader has a very small amount of data to return. // // Because we're extending the buffer with uninitialized data for trusted // readers, we need to make sure to truncate that if any of this panics. #[cfg(feature = "alloc")] fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { read_to_end_with_reservation(r, buf, |_| 32) } #[cfg(feature = "alloc")] fn read_to_end_with_reservation( r: &mut R, buf: &mut Vec, mut reservation_size: F, ) -> Result where R: Read + ?Sized, F: FnMut(&R) -> usize, { let start_len = buf.len(); let mut g = Guard { len: buf.len(), buf, }; loop { if g.len == g.buf.len() { unsafe { // FIXME(danielhenrymantilla): #42788 // // - This creates a (mut) reference to a slice of // _uninitialized_ integers, which is **undefined behavior** // // - Only the standard library gets to soundly "ignore" this, // based on its privileged knowledge of unstable rustc // internals; g.buf.reserve(reservation_size(r)); let capacity = g.buf.capacity(); g.buf.set_len(capacity); r.initializer().initialize(&mut g.buf[g.len..]); } } let buf = &mut g.buf[g.len..]; match r.read(buf) { Ok(0) => return Ok(g.len - start_len), Ok(n) => { // We can't allow bogus values from read. If it is too large, the returned vec could have its length // set past its capacity, or if it overflows the vec could be shortened which could create an invalid // string if this is called via read_to_string. assert!(n <= buf.len()); g.len += n; } Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } } } /// The `Read` trait allows for reading bytes from a source. /// /// Implementors of the `Read` trait are called 'readers'. /// /// Readers are defined by one required method, [`read()`]. Each call to [`read()`] /// will attempt to pull bytes from this source into a provided buffer. A /// number of other methods are implemented in terms of [`read()`], giving /// implementors a number of ways to read bytes while only needing to implement /// a single method. /// /// Readers are intended to be composable with one another. Many implementors /// throughout [`std::io`] take and provide types which implement the `Read` /// trait. /// /// Please note that each call to [`read()`] may involve a system call, and /// therefore, using something that implements [`BufRead`], such as /// [`BufReader`], will be more efficient. /// /// # Examples /// /// [`File`]s implement `Read`: /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut f = File::open("foo.txt")?; /// let mut buffer = [0; 10]; /// /// // read up to 10 bytes /// f.read(&mut buffer)?; /// /// let mut buffer = Vec::new(); /// // read the whole file /// f.read_to_end(&mut buffer)?; /// /// // read into a String, so that you don't need to do the conversion. /// let mut buffer = String::new(); /// f.read_to_string(&mut buffer)?; /// /// // and more! See the other methods for more details. /// Ok(()) /// } /// ``` /// /// Read from [`&str`] because [`&[u8]`][slice] implements `Read`: /// /// ```no_run /// # use std::io; /// use std::io::prelude::*; /// /// fn main() -> io::Result<()> { /// let mut b = "This string will be read".as_bytes(); /// let mut buffer = [0; 10]; /// /// // read up to 10 bytes /// b.read(&mut buffer)?; /// /// // etc... it works exactly as a File does! /// Ok(()) /// } /// ``` /// /// [`read()`]: Read::read /// [`&str`]: prim@str /// [`std::io`]: self /// [`File`]: crate::fs::File /// [slice]: ../../std/primitive.slice.html pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. /// /// This function does not provide any guarantees about whether it blocks /// waiting for data, but if an object needs to block for a read and cannot, /// it will typically signal this via an [`Err`] return value. /// /// If the return value of this method is [`Ok(n)`], then it must be /// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates /// that the buffer `buf` has been filled in with `n` bytes of data from this /// source. If `n` is `0`, then it can indicate one of two scenarios: /// /// 1. This reader has reached its "end of file" and will likely no longer /// be able to produce bytes. Note that this does not mean that the /// reader will *always* no longer be able to produce bytes. /// 2. The buffer specified was 0 bytes in length. /// /// It is not an error if the returned value `n` is smaller than the buffer size, /// even when the reader is not at the end of the stream yet. /// This may happen for example because fewer bytes are actually available right now /// (e. g. being close to end-of-file) or because read() was interrupted by a signal. /// /// No guarantees are provided about the contents of `buf` when this /// function is called, implementations cannot rely on any property of the /// contents of `buf` being true. It is recommended that *implementations* /// only write data to `buf` instead of reading its contents. /// /// Correspondingly, however, *callers* of this method may not assume any guarantees /// about how the implementation uses `buf`. The trait is safe to implement, /// so it is possible that the code that's supposed to write to the buffer might also read /// from it. It is your responsibility to make sure that `buf` is initialized /// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one /// obtains via [`MaybeUninit`]) is not safe, and can lead to undefined behavior. /// /// [`MaybeUninit`]: crate::mem::MaybeUninit /// /// # Errors /// /// If this function encounters any form of I/O or other error, an error /// variant will be returned. If an error is returned then it must be /// guaranteed that no bytes were read. /// /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read /// operation should be retried if there is nothing else to do. /// /// # Examples /// /// [`File`]s implement `Read`: /// /// [`Ok(n)`]: Ok /// [`File`]: crate::fs::File /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut f = File::open("foo.txt")?; /// let mut buffer = [0; 10]; /// /// // read up to 10 bytes /// let n = f.read(&mut buffer[..])?; /// /// println!("The bytes: {:?}", &buffer[..n]); /// Ok(()) /// } /// ``` fn read(&mut self, buf: &mut [u8]) -> Result; /// Read all bytes until EOF in this source, placing them into `buf`. /// /// All bytes read from this source will be appended to the specified buffer /// `buf`. This function will continuously call [`read()`] to append more data to /// `buf` until [`read()`] returns either [`Ok(0)`] or an error of /// non-[`ErrorKind::Interrupted`] kind. /// /// If successful, this function will return the total number of bytes read. /// /// # Errors /// /// If this function encounters an error of the kind /// [`ErrorKind::Interrupted`] then the error is ignored and the operation /// will continue. /// /// If any other read error is encountered then this function immediately /// returns. Any bytes which have already been read will be appended to /// `buf`. /// /// # Examples /// /// [`File`]s implement `Read`: /// /// [`read()`]: Read::read /// [`Ok(0)`]: Ok /// [`File`]: crate::fs::File /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut f = File::open("foo.txt")?; /// let mut buffer = Vec::new(); /// /// // read the whole file /// f.read_to_end(&mut buffer)?; /// Ok(()) /// } /// ``` /// /// (See also the [`std::fs::read`] convenience function for reading from a /// file.) /// /// [`std::fs::read`]: crate::fs::read #[cfg(feature = "alloc")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { read_to_end(self, buf) } /// Determines if this `Read`er can work with buffers of uninitialized /// memory. /// /// The default implementation returns an initializer which will zero /// buffers. /// /// If a `Read`er guarantees that it can work properly with uninitialized /// memory, it should call [`Initializer::nop()`]. See the documentation for /// [`Initializer`] for details. /// /// The behavior of this method must be independent of the state of the /// `Read`er - the method only takes `&self` so that it can be used through /// trait objects. /// /// # Safety /// /// This method is unsafe because a `Read`er could otherwise return a /// non-zeroing `Initializer` from another `Read` type without an `unsafe` /// block. #[inline] unsafe fn initializer(&self) -> Initializer { Initializer::zeroing() } /// Read the exact number of bytes required to fill `buf`. /// /// This function reads as many bytes as necessary to completely fill the /// specified buffer `buf`. /// /// No guarantees are provided about the contents of `buf` when this /// function is called, implementations cannot rely on any property of the /// contents of `buf` being true. It is recommended that implementations /// only write data to `buf` instead of reading its contents. The /// documentation on [`read`] has a more detailed explanation on this /// subject. /// /// # Errors /// /// If this function encounters an error of the kind /// [`ErrorKind::Interrupted`] then the error is ignored and the operation /// will continue. /// /// If this function encounters an "end of file" before completely filling /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. /// The contents of `buf` are unspecified in this case. /// /// If any other read error is encountered then this function immediately /// returns. The contents of `buf` are unspecified in this case. /// /// If this function returns an error, it is unspecified how many bytes it /// has read, but it will never read more than would be necessary to /// completely fill the buffer. /// /// # Examples /// /// [`File`]s implement `Read`: /// /// [`read`]: Read::read /// [`File`]: crate::fs::File /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut f = File::open("foo.txt")?; /// let mut buffer = [0; 10]; /// /// // read exactly 10 bytes /// f.read_exact(&mut buffer)?; /// Ok(()) /// } /// ``` fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { while !buf.is_empty() { match self.read(buf) { Ok(0) => break, Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; } Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } } if !buf.is_empty() { Err(Error::new( ErrorKind::UnexpectedEof, "failed to fill whole buffer", )) } else { Ok(()) } } /// Creates a "by reference" adaptor for this instance of `Read`. /// /// The returned adaptor also implements `Read` and will simply borrow this /// current reader. /// /// # Examples /// /// [`File`]s implement `Read`: /// /// [`File`]: crate::fs::File /// /// ```no_run /// use std::io; /// use std::io::Read; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut f = File::open("foo.txt")?; /// let mut buffer = Vec::new(); /// let mut other_buffer = Vec::new(); /// /// { /// let reference = f.by_ref(); /// /// // read at most 5 bytes /// reference.take(5).read_to_end(&mut buffer)?; /// /// } // drop our &mut reference so we can use f again /// /// // original file still usable, read the rest /// f.read_to_end(&mut other_buffer)?; /// Ok(()) /// } /// ``` fn by_ref(&mut self) -> &mut Self where Self: Sized, { self } /// Transforms this `Read` instance to an [`Iterator`] over its bytes. /// /// The returned type implements [`Iterator`] where the `Item` is /// [`Result`]`<`[`u8`]`, `[`io::Error`]`>`. /// The yielded item is [`Ok`] if a byte was successfully read and [`Err`] /// otherwise. EOF is mapped to returning [`None`] from this iterator. /// /// # Examples /// /// [`File`]s implement `Read`: /// /// [`File`]: crate::fs::File /// [`Result`]: crate::result::Result /// [`io::Error`]: self::Error /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut f = File::open("foo.txt")?; /// /// for byte in f.bytes() { /// println!("{}", byte.unwrap()); /// } /// Ok(()) /// } /// ``` fn bytes(self) -> Bytes where Self: Sized, { Bytes { inner: self } } /// Creates an adaptor which will chain this stream with another. /// /// The returned `Read` instance will first read all bytes from this object /// until EOF is encountered. Afterwards the output is equivalent to the /// output of `next`. /// /// # Examples /// /// [`File`]s implement `Read`: /// /// [`File`]: crate::fs::File /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut f1 = File::open("foo.txt")?; /// let mut f2 = File::open("bar.txt")?; /// /// let mut handle = f1.chain(f2); /// let mut buffer = String::new(); /// /// // read the value into a String. We could use any Read method here, /// // this is just one example. /// handle.read_to_string(&mut buffer)?; /// Ok(()) /// } /// ``` fn chain(self, next: R) -> Chain where Self: Sized, { Chain { first: self, second: next, done_first: false, } } /// Creates an adaptor which will read at most `limit` bytes from it. /// /// This function returns a new instance of `Read` which will read at most /// `limit` bytes, after which it will always return EOF ([`Ok(0)`]). Any /// read errors will not count towards the number of bytes read and future /// calls to [`read()`] may succeed. /// /// # Examples /// /// [`File`]s implement `Read`: /// /// [`File`]: crate::fs::File /// [`Ok(0)`]: Ok /// [`read()`]: Read::read /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut f = File::open("foo.txt")?; /// let mut buffer = [0; 5]; /// /// // read at most five bytes /// let mut handle = f.take(5); /// /// handle.read(&mut buffer)?; /// Ok(()) /// } /// ``` fn take(self, limit: u64) -> Take where Self: Sized, { Take { inner: self, limit } } } /// A type used to conditionally initialize buffers passed to `Read` methods. #[derive(Debug)] pub struct Initializer(bool); impl Initializer { /// Returns a new `Initializer` which will zero out buffers. #[inline] pub fn zeroing() -> Initializer { Initializer(true) } /// Returns a new `Initializer` which will not zero out buffers. /// /// # Safety /// /// This may only be called by `Read`ers which guarantee that they will not /// read from buffers passed to `Read` methods, and that the return value of /// the method accurately reflects the number of bytes that have been /// written to the head of the buffer. #[inline] pub unsafe fn nop() -> Initializer { Initializer(false) } /// Indicates if a buffer should be initialized. #[inline] pub fn should_initialize(&self) -> bool { self.0 } /// Initializes a buffer if necessary. #[inline] pub fn initialize(&self, buf: &mut [u8]) { if self.should_initialize() { unsafe { core::ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) } } } } /// A trait for objects which are byte-oriented sinks. /// /// Implementors of the `Write` trait are sometimes called 'writers'. /// /// Writers are defined by two required methods, [`write`] and [`flush`]: /// /// * The [`write`] method will attempt to write some data into the object, /// returning how many bytes were successfully written. /// /// * The [`flush`] method is useful for adaptors and explicit buffers /// themselves for ensuring that all buffered data has been pushed out to the /// 'true sink'. /// /// Writers are intended to be composable with one another. Many implementors /// throughout [`std::io`] take and provide types which implement the `Write` /// trait. /// /// [`write`]: Write::write /// [`flush`]: Write::flush /// [`std::io`]: self /// /// # Examples /// /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { /// let data = b"some bytes"; /// /// let mut pos = 0; /// let mut buffer = File::create("foo.txt")?; /// /// while pos < data.len() { /// let bytes_written = buffer.write(&data[pos..])?; /// pos += bytes_written; /// } /// Ok(()) /// } /// ``` /// /// The trait also provides convenience methods like [`write_all`], which calls /// `write` in a loop until its entire input has been written. /// /// [`write_all`]: Write::write_all pub trait Write { /// Write a buffer into this writer, returning how many bytes were written. /// /// This function will attempt to write the entire contents of `buf`, but /// the entire write may not succeed, or the write may also generate an /// error. A call to `write` represents *at most one* attempt to write to /// any wrapped object. /// /// Calls to `write` are not guaranteed to block waiting for data to be /// written, and a write which would otherwise block can be indicated through /// an [`Err`] variant. /// /// If the return value is [`Ok(n)`] then it must be guaranteed that /// `n <= buf.len()`. A return value of `0` typically means that the /// underlying object is no longer able to accept bytes and will likely not /// be able to in the future as well, or that the buffer provided is empty. /// /// # Errors /// /// Each call to `write` may generate an I/O error indicating that the /// operation could not be completed. If an error is returned then no bytes /// in the buffer were written to this writer. /// /// It is **not** considered an error if the entire buffer could not be /// written to this writer. /// /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the /// write operation should be retried if there is nothing else to do. /// /// # Examples /// /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { /// let mut buffer = File::create("foo.txt")?; /// /// // Writes some prefix of the byte string, not necessarily all of it. /// buffer.write(b"some bytes")?; /// Ok(()) /// } /// ``` /// /// [`Ok(n)`]: Ok fn write(&mut self, buf: &[u8]) -> Result; /// Flush this output stream, ensuring that all intermediately buffered /// contents reach their destination. /// /// # Errors /// /// It is considered an error if not all bytes could be written due to /// I/O errors or EOF being reached. /// /// # Examples /// /// ```no_run /// use std::io::prelude::*; /// use std::io::BufWriter; /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { /// let mut buffer = BufWriter::new(File::create("foo.txt")?); /// /// buffer.write_all(b"some bytes")?; /// buffer.flush()?; /// Ok(()) /// } /// ``` fn flush(&mut self) -> Result<()>; /// Attempts to write an entire buffer into this writer. /// /// This method will continuously call [`write`] until there is no more data /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is /// returned. This method will not return until the entire buffer has been /// successfully written or such an error occurs. The first error that is /// not of [`ErrorKind::Interrupted`] kind generated from this method will be /// returned. /// /// If the buffer contains no data, this will never call [`write`]. /// /// # Errors /// /// This function will return the first error of /// non-[`ErrorKind::Interrupted`] kind that [`write`] returns. /// /// [`write`]: Write::write /// /// # Examples /// /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { /// let mut buffer = File::create("foo.txt")?; /// /// buffer.write_all(b"some bytes")?; /// Ok(()) /// } /// ``` fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { while !buf.is_empty() { match self.write(buf) { Ok(0) => { return Err(Error::new( ErrorKind::WriteZero, "failed to write whole buffer", )); } Ok(n) => buf = &buf[n..], Err(ref e) if e.kind() == ErrorKind::Interrupted => {} Err(e) => return Err(e), } } Ok(()) } /// Writes a formatted string into this writer, returning any error /// encountered. /// /// This method is primarily used to interface with the /// [`format_args!()`] macro, but it is rare that this should /// explicitly be called. The [`write!()`] macro should be favored to /// invoke this method instead. /// /// This function internally uses the [`write_all`] method on /// this trait and hence will continuously write data so long as no errors /// are received. This also means that partial writes are not indicated in /// this signature. /// /// [`write_all`]: Write::write_all /// /// # Errors /// /// This function will return any I/O error reported while formatting. /// /// # Examples /// /// ```no_run /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { /// let mut buffer = File::create("foo.txt")?; /// /// // this call /// write!(buffer, "{:.*}", 2, 1.234567)?; /// // turns into this: /// buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))?; /// Ok(()) /// } /// ``` fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { // Create a shim which translates a Write to a fmt::Write and saves // off I/O errors. instead of discarding them struct Adaptor<'a, T: ?Sized + 'a> { inner: &'a mut T, error: Result<()>, } impl fmt::Write for Adaptor<'_, T> { fn write_str(&mut self, s: &str) -> fmt::Result { match self.inner.write_all(s.as_bytes()) { Ok(()) => Ok(()), Err(e) => { self.error = Err(e); Err(fmt::Error) } } } } let mut output = Adaptor { inner: self, error: Ok(()), }; match fmt::write(&mut output, fmt) { Ok(()) => Ok(()), Err(..) => { // check if the error came from the underlying `Write` or not if output.error.is_err() { output.error } else { Err(Error::new(ErrorKind::Other, "formatter error")) } } } } /// Creates a "by reference" adaptor for this instance of `Write`. /// /// The returned adaptor also implements `Write` and will simply borrow this /// current writer. /// /// # Examples /// /// ```no_run /// use std::io::Write; /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { /// let mut buffer = File::create("foo.txt")?; /// /// let reference = buffer.by_ref(); /// /// // we can use reference just like our original buffer /// reference.write_all(b"some bytes")?; /// Ok(()) /// } /// ``` fn by_ref(&mut self) -> &mut Self where Self: Sized, { self } } /// The `Seek` trait provides a cursor which can be moved within a stream of /// bytes. /// /// The stream typically has a fixed size, allowing seeking relative to either /// end or the current offset. /// /// # Examples /// /// [`File`]s implement `Seek`: /// /// [`File`]: crate::fs::File /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// use std::io::SeekFrom; /// /// fn main() -> io::Result<()> { /// let mut f = File::open("foo.txt")?; /// /// // move the cursor 42 bytes from the start of the file /// f.seek(SeekFrom::Start(42))?; /// Ok(()) /// } /// ``` pub trait Seek { /// Seek to an offset, in bytes, in a stream. /// /// A seek beyond the end of a stream is allowed, but behavior is defined /// by the implementation. /// /// If the seek operation completed successfully, /// this method returns the new position from the start of the stream. /// That position can be used later with [`SeekFrom::Start`]. /// /// # Errors /// /// Seeking to a negative offset is considered an error. fn seek(&mut self, pos: SeekFrom) -> Result; } /// Enumeration of possible methods to seek within an I/O object. /// /// It is used by the [`Seek`] trait. #[derive(Copy, PartialEq, Eq, Clone, Debug)] pub enum SeekFrom { /// Sets the offset to the provided number of bytes. Start(u64), /// Sets the offset to the size of this object plus the specified number of /// bytes. /// /// It is possible to seek beyond the end of an object, but it's an error to /// seek before byte 0. End(i64), /// Sets the offset to the current position plus the specified number of /// bytes. /// /// It is possible to seek beyond the end of an object, but it's an error to /// seek before byte 0. Current(i64), } /// An iterator over `u8` values of a reader. /// /// This struct is generally created by calling [`bytes`] on a reader. /// Please see the documentation of [`bytes`] for more details. /// /// [`bytes`]: Read::bytes #[derive(Debug)] pub struct Bytes { inner: R, } impl Iterator for Bytes { type Item = Result; fn next(&mut self) -> Option> { let mut byte = 0; loop { return match self.inner.read(slice::from_mut(&mut byte)) { Ok(0) => None, Ok(..) => Some(Ok(byte)), Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => Some(Err(e)), }; } } } /// A `BufRead` is a type of `Read`er which has an internal buffer, allowing it /// to perform extra ways of reading. /// /// For example, reading line-by-line is inefficient without using a buffer, so /// if you want to read by line, you'll need `BufRead`, which includes a /// [`read_line`] method as well as a [`lines`] iterator. /// /// # Examples /// /// A locked standard input implements `BufRead`: /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// /// let stdin = io::stdin(); /// for line in stdin.lock().lines() { /// println!("{}", line.unwrap()); /// } /// ``` /// /// If you have something that implements [`Read`], you can use the [`BufReader` /// type][`BufReader`] to turn it into a `BufRead`. /// /// For example, [`File`] implements [`Read`], but not `BufRead`. /// [`BufReader`] to the rescue! /// /// [`File`]: crate::fs::File /// [`read_line`]: BufRead::read_line /// [`lines`]: BufRead::lines /// /// ```no_run /// use std::io::{self, BufReader}; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let f = File::open("foo.txt")?; /// let f = BufReader::new(f); /// /// for line in f.lines() { /// println!("{}", line.unwrap()); /// } /// /// Ok(()) /// } /// ``` pub trait BufRead: Read { /// Returns the contents of the internal buffer, filling it with more data /// from the inner reader if it is empty. /// /// This function is a lower-level call. It needs to be paired with the /// [`consume`] method to function properly. When calling this /// method, none of the contents will be "read" in the sense that later /// calling `read` may return the same contents. As such, [`consume`] must /// be called with the number of bytes that are consumed from this buffer to /// ensure that the bytes are never returned twice. /// /// [`consume`]: BufRead::consume /// /// An empty buffer returned indicates that the stream has reached EOF. /// /// # Errors /// /// This function will return an I/O error if the underlying reader was /// read, but returned an error. /// /// # Examples /// /// A locked standard input implements `BufRead`: /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// /// let stdin = io::stdin(); /// let mut stdin = stdin.lock(); /// /// let buffer = stdin.fill_buf().unwrap(); /// /// // work with buffer /// println!("{:?}", buffer); /// /// // ensure the bytes we worked with aren't returned again later /// let length = buffer.len(); /// stdin.consume(length); /// ``` fn fill_buf(&mut self) -> Result<&[u8]>; /// Tells this buffer that `amt` bytes have been consumed from the buffer, /// so they should no longer be returned in calls to `read`. /// /// This function is a lower-level call. It needs to be paired with the /// [`fill_buf`] method to function properly. This function does /// not perform any I/O, it simply informs this object that some amount of /// its buffer, returned from [`fill_buf`], has been consumed and should /// no longer be returned. As such, this function may do odd things if /// [`fill_buf`] isn't called before calling it. /// /// The `amt` must be `<=` the number of bytes in the buffer returned by /// [`fill_buf`]. /// /// # Examples /// /// Since `consume()` is meant to be used with [`fill_buf`], /// that method's example includes an example of `consume()`. /// /// [`fill_buf`]: BufRead::fill_buf fn consume(&mut self, amt: usize); } /// Adaptor to chain together two readers. /// /// This struct is generally created by calling [`chain`] on a reader. /// Please see the documentation of [`chain`] for more details. /// /// [`chain`]: Read::chain pub struct Chain { first: T, second: U, done_first: bool, } impl Chain { /// Consumes the `Chain`, returning the wrapped readers. /// /// # Examples /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut foo_file = File::open("foo.txt")?; /// let mut bar_file = File::open("bar.txt")?; /// /// let chain = foo_file.chain(bar_file); /// let (foo_file, bar_file) = chain.into_inner(); /// Ok(()) /// } /// ``` pub fn into_inner(self) -> (T, U) { (self.first, self.second) } /// Gets references to the underlying readers in this `Chain`. /// /// # Examples /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut foo_file = File::open("foo.txt")?; /// let mut bar_file = File::open("bar.txt")?; /// /// let chain = foo_file.chain(bar_file); /// let (foo_file, bar_file) = chain.get_ref(); /// Ok(()) /// } /// ``` pub fn get_ref(&self) -> (&T, &U) { (&self.first, &self.second) } /// Gets mutable references to the underlying readers in this `Chain`. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying readers as doing so may corrupt the internal state of this /// `Chain`. /// /// # Examples /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut foo_file = File::open("foo.txt")?; /// let mut bar_file = File::open("bar.txt")?; /// /// let mut chain = foo_file.chain(bar_file); /// let (foo_file, bar_file) = chain.get_mut(); /// Ok(()) /// } /// ``` pub fn get_mut(&mut self) -> (&mut T, &mut U) { (&mut self.first, &mut self.second) } } impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Chain") .field("t", &self.first) .field("u", &self.second) .finish() } } impl Read for Chain { fn read(&mut self, buf: &mut [u8]) -> Result { if !self.done_first { match self.first.read(buf)? { 0 if !buf.is_empty() => self.done_first = true, n => return Ok(n), } } self.second.read(buf) } unsafe fn initializer(&self) -> Initializer { let initializer = self.first.initializer(); if initializer.should_initialize() { initializer } else { self.second.initializer() } } } impl BufRead for Chain { fn fill_buf(&mut self) -> Result<&[u8]> { if !self.done_first { match self.first.fill_buf()? { buf if buf.is_empty() => { self.done_first = true; } buf => return Ok(buf), } } self.second.fill_buf() } fn consume(&mut self, amt: usize) { if !self.done_first { self.first.consume(amt) } else { self.second.consume(amt) } } } /// Reader adaptor which limits the bytes read from an underlying reader. /// /// This struct is generally created by calling [`take`] on a reader. /// Please see the documentation of [`take`] for more details. /// /// [`take`]: Read::take #[derive(Debug)] pub struct Take { inner: T, limit: u64, } impl Take { /// Returns the number of bytes that can be read before this instance will /// return EOF. /// /// # Note /// /// This instance may reach `EOF` after reading fewer bytes than indicated by /// this method if the underlying [`Read`] instance reaches EOF. /// /// # Examples /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let f = File::open("foo.txt")?; /// /// // read at most five bytes /// let handle = f.take(5); /// /// println!("limit: {}", handle.limit()); /// Ok(()) /// } /// ``` pub fn limit(&self) -> u64 { self.limit } /// Sets the number of bytes that can be read before this instance will /// return EOF. This is the same as constructing a new `Take` instance, so /// the amount of bytes read and the previous limit value don't matter when /// calling this method. /// /// # Examples /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let f = File::open("foo.txt")?; /// /// // read at most five bytes /// let mut handle = f.take(5); /// handle.set_limit(10); /// /// assert_eq!(handle.limit(), 10); /// Ok(()) /// } /// ``` pub fn set_limit(&mut self, limit: u64) { self.limit = limit; } /// Consumes the `Take`, returning the wrapped reader. /// /// # Examples /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut file = File::open("foo.txt")?; /// /// let mut buffer = [0; 5]; /// let mut handle = file.take(5); /// handle.read(&mut buffer)?; /// /// let file = handle.into_inner(); /// Ok(()) /// } /// ``` pub fn into_inner(self) -> T { self.inner } /// Gets a reference to the underlying reader. /// /// # Examples /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut file = File::open("foo.txt")?; /// /// let mut buffer = [0; 5]; /// let mut handle = file.take(5); /// handle.read(&mut buffer)?; /// /// let file = handle.get_ref(); /// Ok(()) /// } /// ``` pub fn get_ref(&self) -> &T { &self.inner } /// Gets a mutable reference to the underlying reader. /// /// Care should be taken to avoid modifying the internal I/O state of the /// underlying reader as doing so may corrupt the internal limit of this /// `Take`. /// /// # Examples /// /// ```no_run /// use std::io; /// use std::io::prelude::*; /// use std::fs::File; /// /// fn main() -> io::Result<()> { /// let mut file = File::open("foo.txt")?; /// /// let mut buffer = [0; 5]; /// let mut handle = file.take(5); /// handle.read(&mut buffer)?; /// /// let file = handle.get_mut(); /// Ok(()) /// } /// ``` pub fn get_mut(&mut self) -> &mut T { &mut self.inner } } impl Read for Take { fn read(&mut self, buf: &mut [u8]) -> Result { // Don't call into inner reader at all at EOF because it may still block if self.limit == 0 { return Ok(0); } let max = cmp::min(buf.len() as u64, self.limit) as usize; let n = self.inner.read(&mut buf[..max])?; self.limit -= n as u64; Ok(n) } unsafe fn initializer(&self) -> Initializer { self.inner.initializer() } #[cfg(feature = "alloc")] fn read_to_end(&mut self, buf: &mut Vec) -> Result { // Pass in a reservation_size closure that respects the current value // of limit for each read. If we hit the read limit, this prevents the // final zero-byte read from allocating again. read_to_end_with_reservation(self, buf, |self_| cmp::min(self_.limit, 32) as usize) } } impl BufRead for Take { fn fill_buf(&mut self) -> Result<&[u8]> { // Don't call into inner reader at all at EOF because it may still block if self.limit == 0 { return Ok(&[]); } let buf = self.inner.fill_buf()?; let cap = cmp::min(buf.len() as u64, self.limit) as usize; Ok(&buf[..cap]) } fn consume(&mut self, amt: usize) { // Don't let callers reset the limit by passing an overlarge value let amt = cmp::min(amt as u64, self.limit) as usize; self.limit -= amt as u64; self.inner.consume(amt); } } core2-0.4.0/src/io/util.rs000064400000000000000000000022150072674642500134100ustar 00000000000000#[cfg(feature = "nightly")] use core::mem::MaybeUninit; #[cfg(feature = "nightly")] use crate::io::{ErrorKind, Read, Write}; #[cfg(feature = "nightly")] pub fn copy( reader: &mut R, writer: &mut W, ) -> crate::io::Result where R: Read, W: Write, { let mut buf = MaybeUninit::<[u8; S]>::uninit(); // FIXME: #42788 // // - This creates a (mut) reference to a slice of // _uninitialized_ integers, which is **undefined behavior** // // - Only the standard library gets to soundly "ignore" this, // based on its privileged knowledge of unstable rustc // internals; unsafe { reader.initializer().initialize(buf.assume_init_mut()); } let mut written = 0; loop { let len = match reader.read(unsafe { buf.assume_init_mut() }) { Ok(0) => return Ok(written), Ok(len) => len, Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), }; writer.write_all(unsafe { &buf.assume_init_ref()[..len] })?; written += len as u64; } } core2-0.4.0/src/lib.rs000064400000000000000000000010160072674642500125700ustar 00000000000000#![cfg_attr(feature = "nightly", feature(maybe_uninit_ref))] #![cfg_attr(feature = "nightly", feature(never_type))] #![cfg_attr(all(feature = "std", feature = "nightly"), feature(read_initializer))] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(feature = "std", allow(dead_code))] #[cfg(not(feature = "std"))] pub mod error; #[cfg(feature = "std")] pub use std::error as error; #[cfg(not(feature = "std"))] pub mod io; #[cfg(feature = "std")] pub use std::io as io; #[cfg(feature = "alloc")] extern crate alloc; core2-0.4.0/tests/tests.rs000064400000000000000000000373620072674642500135540ustar 00000000000000use core::cmp; use core2::io::{self as io, BufRead, Cursor, Read, Write}; // #[test] // #[cfg_attr(target_os = "emscripten", ignore)] // fn read_until() { // let mut buf = Cursor::new(&b"12"[..]); // let mut v = Vec::new(); // assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2); // assert_eq!(v, b"12"); // let mut buf = Cursor::new(&b"1233"[..]); // let mut v = Vec::new(); // assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3); // assert_eq!(v, b"123"); // v.truncate(0); // assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1); // assert_eq!(v, b"3"); // v.truncate(0); // assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0); // assert_eq!(v, []); // } // #[test] // fn split() { // let buf = Cursor::new(&b"12"[..]); // let mut s = buf.split(b'3'); // assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); // assert!(s.next().is_none()); // let buf = Cursor::new(&b"1233"[..]); // let mut s = buf.split(b'3'); // assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); // assert_eq!(s.next().unwrap().unwrap(), vec![]); // assert!(s.next().is_none()); // } // #[test] // fn read_line() { // let mut buf = Cursor::new(&b"12"[..]); // let mut v = String::new(); // assert_eq!(buf.read_line(&mut v).unwrap(), 2); // assert_eq!(v, "12"); // let mut buf = Cursor::new(&b"12\n\n"[..]); // let mut v = String::new(); // assert_eq!(buf.read_line(&mut v).unwrap(), 3); // assert_eq!(v, "12\n"); // v.truncate(0); // assert_eq!(buf.read_line(&mut v).unwrap(), 1); // assert_eq!(v, "\n"); // v.truncate(0); // assert_eq!(buf.read_line(&mut v).unwrap(), 0); // assert_eq!(v, ""); // } // #[test] // fn lines() { // let buf = Cursor::new(&b"12\r"[..]); // let mut s = buf.lines(); // assert_eq!(s.next().unwrap().unwrap(), "12\r".to_string()); // assert!(s.next().is_none()); // let buf = Cursor::new(&b"12\r\n\n"[..]); // let mut s = buf.lines(); // assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); // assert_eq!(s.next().unwrap().unwrap(), "".to_string()); // assert!(s.next().is_none()); // } // #[test] // fn read_to_end() { // let mut c = Cursor::new(&b""[..]); // let mut v = Vec::new(); // assert_eq!(c.read_to_end(&mut v).unwrap(), 0); // assert_eq!(v, []); // let mut c = Cursor::new(&b"1"[..]); // let mut v = Vec::new(); // assert_eq!(c.read_to_end(&mut v).unwrap(), 1); // assert_eq!(v, b"1"); // let cap = 1024 * 1024; // let data = (0..cap).map(|i| (i / 3) as u8).collect::>(); // let mut v = Vec::new(); // let (a, b) = data.split_at(data.len() / 2); // assert_eq!(Cursor::new(a).read_to_end(&mut v).unwrap(), a.len()); // assert_eq!(Cursor::new(b).read_to_end(&mut v).unwrap(), b.len()); // assert_eq!(v, data); // } // #[test] // fn read_to_string() { // let mut c = Cursor::new(&b""[..]); // let mut v = String::new(); // assert_eq!(c.read_to_string(&mut v).unwrap(), 0); // assert_eq!(v, ""); // let mut c = Cursor::new(&b"1"[..]); // let mut v = String::new(); // assert_eq!(c.read_to_string(&mut v).unwrap(), 1); // assert_eq!(v, "1"); // let mut c = Cursor::new(&b"\xff"[..]); // let mut v = String::new(); // assert!(c.read_to_string(&mut v).is_err()); // } #[test] fn read_exact() { let mut buf = [0; 4]; let mut c = Cursor::new(&b""[..]); assert_eq!( c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof ); let mut c = Cursor::new(&b"123"[..]).chain(Cursor::new(&b"456789"[..])); c.read_exact(&mut buf).unwrap(); assert_eq!(&buf, b"1234"); c.read_exact(&mut buf).unwrap(); assert_eq!(&buf, b"5678"); assert_eq!( c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof ); } #[test] fn read_exact_slice() { let mut buf = [0; 4]; let mut c = &b""[..]; assert_eq!( c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof ); let mut c = &b"123"[..]; assert_eq!( c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof ); // make sure the optimized (early returning) method is being used assert_eq!(&buf, &[0; 4]); let mut c = &b"1234"[..]; c.read_exact(&mut buf).unwrap(); assert_eq!(&buf, b"1234"); let mut c = &b"56789"[..]; c.read_exact(&mut buf).unwrap(); assert_eq!(&buf, b"5678"); assert_eq!(c, b"9"); } #[test] fn take_eof() { struct R; impl Read for R { fn read(&mut self, _: &mut [u8]) -> io::Result { Err(io::Error::new(io::ErrorKind::Other, "")) } } impl BufRead for R { fn fill_buf(&mut self) -> io::Result<&[u8]> { Err(io::Error::new(io::ErrorKind::Other, "")) } fn consume(&mut self, _amt: usize) {} } let mut buf = [0; 1]; assert_eq!(0, R.take(0).read(&mut buf).unwrap()); assert_eq!(b"", R.take(0).fill_buf().unwrap()); } fn cmp_bufread(mut br1: Br1, mut br2: Br2, exp: &[u8]) { let mut cat = Vec::new(); loop { let consume = { let buf1 = br1.fill_buf().unwrap(); let buf2 = br2.fill_buf().unwrap(); let minlen = if buf1.len() < buf2.len() { buf1.len() } else { buf2.len() }; assert_eq!(buf1[..minlen], buf2[..minlen]); cat.extend_from_slice(&buf1[..minlen]); minlen }; if consume == 0 { break; } br1.consume(consume); br2.consume(consume); } assert_eq!(br1.fill_buf().unwrap().len(), 0); assert_eq!(br2.fill_buf().unwrap().len(), 0); assert_eq!(&cat[..], &exp[..]) } #[test] fn chain_bufread() { let testdata = b"ABCDEFGHIJKL"; let chain1 = (&testdata[..3]) .chain(&testdata[3..6]) .chain(&testdata[6..9]) .chain(&testdata[9..]); let chain2 = (&testdata[..4]) .chain(&testdata[4..8]) .chain(&testdata[8..]); cmp_bufread(chain1, chain2, &testdata[..]); } // #[test] // fn chain_zero_length_read_is_not_eof() { // let a = b"A"; // let b = b"B"; // let mut s = String::new(); // let mut chain = (&a[..]).chain(&b[..]); // chain.read(&mut []).unwrap(); // chain.read_to_string(&mut s).unwrap(); // assert_eq!("AB", s); // } // #[bench] // #[cfg_attr(target_os = "emscripten", ignore)] // fn bench_read_to_end(b: &mut test::Bencher) { // b.iter(|| { // let mut lr = repeat(1).take(10000000); // let mut vec = Vec::with_capacity(1024); // super::read_to_end(&mut lr, &mut vec) // }); // } // #[test] // fn seek_len() -> io::Result<()> { // let mut c = Cursor::new(vec![0; 15]); // assert_eq!(c.stream_len()?, 15); // c.seek(SeekFrom::End(0))?; // let old_pos = c.stream_position()?; // assert_eq!(c.stream_len()?, 15); // assert_eq!(c.stream_position()?, old_pos); // c.seek(SeekFrom::Start(7))?; // c.seek(SeekFrom::Current(2))?; // let old_pos = c.stream_position()?; // assert_eq!(c.stream_len()?, 15); // assert_eq!(c.stream_position()?, old_pos); // Ok(()) // } // #[test] // fn seek_position() -> io::Result<()> { // // All `asserts` are duplicated here to make sure the method does not // // change anything about the seek state. // let mut c = Cursor::new(vec![0; 15]); // assert_eq!(c.stream_position()?, 0); // assert_eq!(c.stream_position()?, 0); // c.seek(SeekFrom::End(0))?; // assert_eq!(c.stream_position()?, 15); // assert_eq!(c.stream_position()?, 15); // c.seek(SeekFrom::Start(7))?; // c.seek(SeekFrom::Current(2))?; // assert_eq!(c.stream_position()?, 9); // assert_eq!(c.stream_position()?, 9); // c.seek(SeekFrom::End(-3))?; // c.seek(SeekFrom::Current(1))?; // c.seek(SeekFrom::Current(-5))?; // assert_eq!(c.stream_position()?, 8); // assert_eq!(c.stream_position()?, 8); // Ok(()) // } // A simple example reader which uses the default implementation of // read_to_end. struct ExampleSliceReader<'a> { slice: &'a [u8], } impl<'a> Read for ExampleSliceReader<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result { let len = cmp::min(self.slice.len(), buf.len()); buf[..len].copy_from_slice(&self.slice[..len]); self.slice = &self.slice[len..]; Ok(len) } } // #[test] // fn test_read_to_end_capacity() -> io::Result<()> { // let input = &b"foo"[..]; // // read_to_end() generally needs to over-allocate, both for efficiency // // and so that it can distinguish EOF. Assert that this is the case // // with this simple ExampleSliceReader struct, which uses the default // // implementation of read_to_end. Even though vec1 is allocated with // // exactly enough capacity for the read, read_to_end will allocate more // // space here. // let mut vec1 = Vec::with_capacity(input.len()); // ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?; // assert_eq!(vec1.len(), input.len()); // assert!(vec1.capacity() > input.len(), "allocated more"); // // However, std::io::Take includes an implementation of read_to_end // // that will not allocate when the limit has already been reached. In // // this case, vec2 never grows. // let mut vec2 = Vec::with_capacity(input.len()); // ExampleSliceReader { slice: input }.take(input.len() as u64).read_to_end(&mut vec2)?; // assert_eq!(vec2.len(), input.len()); // assert_eq!(vec2.capacity(), input.len(), "did not allocate more"); // Ok(()) // } // #[test] // fn io_slice_mut_advance() { // let mut buf1 = [1; 8]; // let mut buf2 = [2; 16]; // let mut buf3 = [3; 8]; // let mut bufs = &mut [ // IoSliceMut::new(&mut buf1), // IoSliceMut::new(&mut buf2), // IoSliceMut::new(&mut buf3), // ][..]; // // Only in a single buffer.. // bufs = IoSliceMut::advance(bufs, 1); // assert_eq!(bufs[0].deref(), [1; 7].as_ref()); // assert_eq!(bufs[1].deref(), [2; 16].as_ref()); // assert_eq!(bufs[2].deref(), [3; 8].as_ref()); // // Removing a buffer, leaving others as is. // bufs = IoSliceMut::advance(bufs, 7); // assert_eq!(bufs[0].deref(), [2; 16].as_ref()); // assert_eq!(bufs[1].deref(), [3; 8].as_ref()); // // Removing a buffer and removing from the next buffer. // bufs = IoSliceMut::advance(bufs, 18); // assert_eq!(bufs[0].deref(), [3; 6].as_ref()); // } // #[test] // fn io_slice_mut_advance_empty_slice() { // let empty_bufs = &mut [][..]; // // Shouldn't panic. // IoSliceMut::advance(empty_bufs, 1); // } // #[test] // fn io_slice_mut_advance_beyond_total_length() { // let mut buf1 = [1; 8]; // let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..]; // // Going beyond the total length should be ok. // bufs = IoSliceMut::advance(bufs, 9); // assert!(bufs.is_empty()); // } // #[test] // fn io_slice_advance() { // let buf1 = [1; 8]; // let buf2 = [2; 16]; // let buf3 = [3; 8]; // let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..]; // // Only in a single buffer.. // bufs = IoSlice::advance(bufs, 1); // assert_eq!(bufs[0].deref(), [1; 7].as_ref()); // assert_eq!(bufs[1].deref(), [2; 16].as_ref()); // assert_eq!(bufs[2].deref(), [3; 8].as_ref()); // // Removing a buffer, leaving others as is. // bufs = IoSlice::advance(bufs, 7); // assert_eq!(bufs[0].deref(), [2; 16].as_ref()); // assert_eq!(bufs[1].deref(), [3; 8].as_ref()); // // Removing a buffer and removing from the next buffer. // bufs = IoSlice::advance(bufs, 18); // assert_eq!(bufs[0].deref(), [3; 6].as_ref()); // } // #[test] // fn io_slice_advance_empty_slice() { // let empty_bufs = &mut [][..]; // // Shouldn't panic. // IoSlice::advance(empty_bufs, 1); // } // #[test] // fn io_slice_advance_beyond_total_length() { // let buf1 = [1; 8]; // let mut bufs = &mut [IoSlice::new(&buf1)][..]; // // Going beyond the total length should be ok. // bufs = IoSlice::advance(bufs, 9); // assert!(bufs.is_empty()); // } /// Create a new writer that reads from at most `n_bufs` and reads /// `per_call` bytes (in total) per call to write. fn test_writer() -> TestWriter { TestWriter { written: Vec::new(), per_call: 2, } } struct TestWriter { written: Vec, per_call: usize, } impl Write for TestWriter { fn write(&mut self, buf: &[u8]) -> io::Result { let n = self.per_call.min(buf.len()); self.written.extend_from_slice(&buf[..n]); Ok(n) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } #[test] fn test_writer_read_from_one_buf() { let mut writer = test_writer(); assert_eq!(writer.write(&[]).unwrap(), 0); // assert_eq!(writer.write_vectored(&[]).unwrap(), 0); // Read at most 2 bytes. assert_eq!(writer.write(&[1, 1, 1]).unwrap(), 2); assert_eq!(writer.write(&[2, 2, 2]).unwrap(), 2); // Only read from first buf. assert_eq!(writer.write(&[3]).unwrap(), 1); assert_eq!(writer.written, &[1, 1, 2, 2, 3]); } // #[test] // fn test_writer_read_from_multiple_bufs() { // let mut writer = test_writer(3, 3); // // Read at most 3 bytes from two buffers. // let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])]; // assert_eq!(writer.write_vectored(bufs).unwrap(), 3); // // Read at most 3 bytes from three buffers. // let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])]; // assert_eq!(writer.write_vectored(bufs).unwrap(), 3); // assert_eq!(writer.written, &[1, 2, 2, 3, 4, 5]); // } // #[test] // fn test_write_all_vectored() { // #[rustfmt::skip] // Becomes unreadable otherwise. // let tests: Vec<(_, &'static [u8])> = vec![ // (vec![], &[]), // (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]), // (vec![IoSlice::new(&[1])], &[1]), // (vec![IoSlice::new(&[1, 2])], &[1, 2]), // (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]), // (vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]), // (vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]), // (vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]), // (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2])], &[1, 2, 2]), // (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]), // (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]), // (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]), // (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]), // (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 2, 2, 2, 2]), // (vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]), // (vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]), // (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]), // (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 2, 2, 3, 3, 3]), // (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]), // ]; // let writer_configs = &[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]; // for (n_bufs, per_call) in writer_configs.iter().copied() { // for (mut input, wanted) in tests.clone().into_iter() { // let mut writer = test_writer(n_bufs, per_call); // assert!(writer.write_all_vectored(&mut *input).is_ok()); // assert_eq!(&*writer.written, &*wanted); // } // } // }