├── .cargo └── config ├── .gitignore ├── Cargo.toml ├── LICENSE ├── LICENSE-APACHE ├── LICENSE-ZLIB ├── Makefile ├── README.md ├── src ├── as_maybe_uninit.rs ├── extension_traits │ ├── as_out.rs │ ├── boxed.rs │ ├── manually_drop_mut.rs │ ├── maybe_uninit.rs │ ├── mod.rs │ ├── transpose.rs │ └── vec.rs ├── lib.rs ├── out_ref.rs ├── read │ ├── impls.rs │ └── mod.rs └── utils │ ├── macros.rs │ ├── mod.rs │ └── prelude.rs └── tests └── docs.rs /.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | rustdocflags = [ 3 | "-C", "opt-level=2", 4 | ] 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target 4 | 5 | # https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries 6 | /Cargo.lock 7 | 8 | # These are backup files generated by rustfmt 9 | **/*.rs.bk 10 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "uninit" 3 | version = "0.6.2" 4 | authors = [ 5 | "Daniel Henry-Mantilla ", 6 | "Alyssa Haroldsen ", 7 | ] 8 | edition = "2021" 9 | rust-version = "1.56" 10 | documentation = "https://docs.rs/uninit" 11 | homepage = "https://crates.io/crates/uninit" 12 | repository = "https://github.com/danielhenrymantilla/rust-uninit" 13 | 14 | description = "A collection of tools for a safer usage of uninitialized memory" 15 | keywords = ["uninit", "sound", "unsafe", "read", "MaybeUninit"] 16 | categories = ["memory-management", "rust-patterns"] 17 | 18 | readme = "README.md" 19 | license = "Zlib OR MIT OR Apache-2.0" 20 | 21 | [dependencies] 22 | zerocopy = { version = ">=0.1,<0.8", default-features = false, optional = true } 23 | 24 | [features] 25 | default = ["std"] 26 | 27 | std = ["alloc"] 28 | alloc = [] 29 | 30 | better-docs = ["nightly"] 31 | nightly = [] 32 | specialization = ["nightly"] 33 | 34 | chain = [] 35 | 36 | [package.metadata.docs.rs] 37 | all-features = true 38 | rustc-args = ["-C", "opt-level=2"] 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Daniel Henry-Mantilla 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 Daniel Henry-Mantilla 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-ZLIB: -------------------------------------------------------------------------------- 1 | zlib License 2 | 3 | (C) 2020 Daniel Henry-Mantilla 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test publish clean 2 | 3 | test: 4 | cargo clean && cargo miri test --features nightly 5 | cargo clean && cargo test --features nightly 6 | cargo check --no-default-features --target thumbv6m-none-eabi 7 | 8 | publish: test 9 | cargo publish --dry-run 10 | 11 | clean: 12 | cargo clean 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `::uninit` 2 | 3 | > A collection of tools for a safer usage of uninitialized memory. 4 | 5 | [![Latest version](https://img.shields.io/crates/v/uninit.svg)](https://crates.io/crates/uninit) 6 | [![Documentation](https://docs.rs/uninit/badge.svg)](https://docs.rs/uninit) 7 | ![License](https://img.shields.io/crates/l/uninit.svg) 8 | ![MSRV](https://img.shields.io/badge/MSRV-1.56-blue) 9 | ___ 10 | 11 | Many crates out there try to replicate C "optimization" patterns such as 12 | handling uninitialized memory without taking into account that Rust types 13 | carry semantics much more subtle than those of C. 14 | 15 | For instance, the following code is _Undefined Behavior_! 16 | 17 | ```rust 18 | use ::core::mem; 19 | 20 | let mut array: [u8; 256] = unsafe { mem::uninitialized() }; 21 | for (i, x) in array.iter_mut().enumerate() { 22 | *x = i as u8; 23 | } 24 | ``` 25 | 26 | Indeed, it creates `u8`s with uninitialized memory, which currently 27 | has **no defined behavior** in the Rust model (see [_"What The Hardware Does" 28 | is not What Your Program Does: Uninitialized Memory_, by Ralf Jung]( 29 | https://www.ralfj.de/blog/2019/07/14/uninit.html)), and then creates Rust 30 | references to these invalid `u8`s, which become in turn invalid too. 31 | 32 | ## Do not use [`mem::uninitialized`]! 33 | 34 | In hindsight, offering a [`mem::uninitialized`] function in the [`core` 35 | library](https://doc.rust-lang.org/core) of Rust (even if it was marked 36 | `unsafe`), has been of the worst mistakes of the language. Indeed, the function 37 | is generic and only bounded by `Sized`, and it turns out that, except for 38 | zero-sized types or the later introduced [`MaybeUninit`]``, **all the other 39 | calls to this function are unsound** (instant UB). 40 | 41 | Note that there are other ways to trigger this UB without explicitely using 42 | [`mem::uninitialized`]`::()`, such as: 43 | 44 | - ```rust 45 | use ::core::mem::MaybeUninit; 46 | type T = u8; // for the example 47 | 48 | unsafe { 49 | MaybeUninit::::uninit() // Uninitialized `MaybeUninit` => Fine 50 | .assume_init() // Back to an uninitialized `T` => UB 51 | }; 52 | ``` 53 | 54 | - this is exactly equivalent to calling `mem::uninitialized::()`, 55 | which breaks the _validity_ invariant of `T` and thus causes 56 | "instant UB". 57 | 58 | There currently only two exceptions / _valid_ use cases: 59 | 60 | - either [`type T = [MaybeUninit; N]`][`uninit_array!`], 61 | 62 | - or `T` is an inhabited ZST (this may, however, break safety 63 | invariants associated with the properties of the type, causing UB 64 | once such broken invariant is witnessed). 65 | 66 | - yes, using [`MaybeUninit`] is more subtle than just changing a function 67 | call. 68 | 69 | - ```rust 70 | let mut vec: Vec = Vec::with_capacity(100); // Fine 71 | unsafe { 72 | vec.set_len(100); // we have an uninitialized [u8; 100] in the heap 73 | // This has broken the _safety_ invariant of `Vec`, but is not yet UB 74 | // since no code has witnessed the broken state 75 | } 76 | let heap_bytes: &[u8] = &*vec; // Witness the broken safety invariant: UB! 77 | ``` 78 | 79 | ## Instead, (you can) use [`MaybeUninit`] 80 | 81 | So, the solution to manipulating uninitialized memory is to use 82 | [`MaybeUninit`]: the special type `MaybeUninit` does not assume that its 83 | backing memory has been initialized / **the behavior of an uninitialized 84 | `MaybeUninit` is well-defined, no matter the `T`**. 85 | 86 | ### How to correctly use [`MaybeUninit`] 87 | 88 | It is all about the _**delayed** initialization pattern_: 89 | 90 | 1. **Creation** 91 | 92 | A `MaybeUninit` is created, with, for instance, 93 | `MaybeUninit::::uninit()`: 94 | 95 | ```rust 96 | use ::core::mem::MaybeUninit; 97 | 98 | let mut x = MaybeUninit::::uninit(); 99 | ``` 100 | 101 | 2. **(Delayed) Initialization** 102 | 103 | With great care to avoid accidentally creating (even if only for an 104 | instant) a `&T`, `&mut T`, or even a `T` while the memory has not been 105 | initialized yet (which would be UB), we can write to (and thus initialize) the 106 | uninitialized memory through a `&mut MaybeUninit`: 107 | 108 | - either directly, for instance: 109 | 110 | ```rust 111 | use ::core::mem::MaybeUninit; 112 | let mut x = MaybeUninit::::uninit(); 113 | 114 | x = MaybeUninit::new(42); 115 | assert_eq!(42, unsafe { x.assume_init() }); 116 | ``` 117 | 118 | - or through a raw `*mut T` pointer (contrary to Rust references, 119 | raw pointers do not assume that the memory they point to is 120 | valid). For instance: 121 | 122 | ```rust 123 | use ::core::mem::MaybeUninit; 124 | let mut x = MaybeUninit::::uninit(); 125 | 126 | unsafe { 127 | x.as_mut_ptr().write(42); 128 | assert_eq!(x.assume_init(), 42); 129 | } 130 | ``` 131 | 132 | - or, if you use the tools of this crate, by upgrading the 133 | `&mut MaybeUninit` into a "`&out T`" type called 134 | [`Out`]``: 135 | 136 | ```rust 137 | #![forbid(unsafe_code)] // no unsafe! 138 | use ::core::mem::MaybeUninit; 139 | use ::uninit::prelude::*; 140 | 141 | let mut x = MaybeUninit::uninit(); 142 | let at_init_x: &i32 = x.as_out().write(42); 143 | assert_eq!(at_init_x, &42); 144 | ``` 145 | 146 | 3. **Type-level upgrade** 147 | 148 | Once we know, for sure, that the memory has been initialized, we can 149 | upgrade the `MaybeUninit` type to the fully-fledged `T` type: 150 | 151 | - By value (`MaybeUninit -> T`): [`.assume_init()`]( 152 | https://doc.rust-lang.org/core/mem/union.MaybeUninit.html#method.assume_init) 153 | 154 | - By shared reference (`&MaybeUninit -> &T`): 155 | [`.assume_init_by_ref()`] 156 | 157 | - By unique reference (`&mut MaybeUninit -> &mut T`): 158 | [`.assume_init_by_mut()`] 159 | 160 | ## The problem 161 | 162 | As you can see, manipulating [`MaybeUninit`] to initialize its contents is 163 | done through restrictive and unergonomic types 164 | (`&mut MaybeUninit` / `*mut T`). 165 | 166 | > So most APIs **do not** offer a way to output / write into uninitialized memory. 167 | 168 | This is what ends up leading many people to do the step `.3` before the 169 | step `.2`: it is oh so much ergonomic to work with a `&mut T` than a 170 | `*mut T`, especially when arrays, slices and vectors are involved. Thus 171 | people end up doing UB. 172 | 173 | ### One of the worst offenders of this situation is the [`Read`] trait 174 | 175 | ```rust 176 | use ::std::io; 177 | 178 | pub trait Read { 179 | fn read (&mut self, buf: &mut [u8]) -> Result; 180 | // ... 181 | } 182 | ``` 183 | 184 | that is, there is no way to `.read()` into an uninitialized buffer (it would 185 | require an api taking either a `(*mut u8, usize)` pair, or, equivalently and 186 | by the way more ergonomically, a [`&out [u8]`][`crate::prelude::Out`]). 187 | 188 | # Enter `::uninit` 189 | 190 | So, the objective of this crate is double: 191 | 192 | - it offers ergonomic ways to create uninitialized buffers. 193 | 194 | For instance: 195 | 196 | - [`uninit_array!`] 197 | 198 | - [`Vec::reserve_uninit`] 199 | 200 | - it tries to offer APIs that are equivalent to pervasive APIs, 201 | such as `Read`'s, but that are able to work with such uninitialized buffers. 202 | 203 | For instance: 204 | 205 | - [`ReadIntoUninit`] 206 | 207 | - [Initialize an uninitialized buffer with `.copy_from_slice()`] 208 | 209 | ### `#![no_std]` friendly 210 | 211 | Simply disable the default-enabled `"std"` feature in your `Cargo.toml` file: 212 | 213 | ```toml 214 | [dependencies] 215 | uninit = { version = "x.y.z", default-features = false } 216 | ``` 217 | 218 | [`Read`]: https://doc.rust-lang.org/1.36.0/std/io/trait.Read.html 219 | [`mem::uninitialized`]: https://doc.rust-lang.org/core/mem/fn.uninitialized.html 220 | [`MaybeUninit`]: https://doc.rust-lang.org/core/mem/union.MaybeUninit.html 221 | [`.assume_init_by_ref()`]: https://docs.rs/uninit/0.3.0/uninit/extension_traits/trait.MaybeUninitExt.html#tymethod.assume_init_by_ref 222 | [`.assume_init_by_mut()`]: https://docs.rs/uninit/0.3.0/uninit/extension_traits/trait.MaybeUninitExt.html#tymethod.assume_init_by_mut 223 | [`uninit_array!`]: https://docs.rs/uninit/0.3.0/uninit/macro.uninit_array.html 224 | [`Vec::reserve_uninit`]: https://docs.rs/uninit/0.3.0/uninit/extension_traits/trait.VecCapacity.html#tymethod.reserve_uninit 225 | [`Out`]: https://docs.rs/uninit/0.3.0/uninit/out_ref/struct.Out.html 226 | [Initialize an uninitialized buffer with `.copy_from_slice()`]: https://docs.rs/uninit/0.3.0/uninit/out_ref/struct.Out.html#method.copy_from_slice 227 | [`ReadIntoUninit`]: https://docs.rs/uninit/0.3.0/uninit/read/trait.ReadIntoUninit.html 228 | -------------------------------------------------------------------------------- /src/as_maybe_uninit.rs: -------------------------------------------------------------------------------- 1 | use_prelude!(); 2 | 3 | use crate::extension_traits::MaybeUninitExt; 4 | use core::mem::MaybeUninit; 5 | 6 | /// Converts a reference into its maybe-initialized form. 7 | /// 8 | /// This trait allows you to use a unified API for `MaybeUninit` 9 | /// on sized and unsized types. 10 | /// 11 | /// You probably don't need to implement this trait yourself: 12 | /// it is automatically implemented for all `T: Sized` and `[T]`. 13 | /// 14 | /// # Safety 15 | /// - `Uninit` must have the same layout as `Self` but with no requirement on its contents. 16 | /// See the [`MaybeUninit` layout](https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#layout-1). 17 | /// - All methods return pointers that point to the same memory as their input. 18 | pub unsafe trait AsMaybeUninit { 19 | /// This type in its maybe-uninitialized form. 20 | type Uninit: ?Sized + MaybeUninitExt; 21 | 22 | /// The largest `Sized` element in `Self`, used to check for the absence 23 | /// of [drop glue][core::mem::needs_drop] via a `Copy` bound. 24 | /// 25 | /// For `Self: Sized`, this equals `Self`, but for `[T]` it is `T`. 26 | type SizedPart: Sized; 27 | 28 | /// Converts a `&self` to its maybe-initialized equivalent. 29 | fn as_ref_uninit(&self) -> &Self::Uninit; 30 | 31 | /// Converts a `&mut T` to its maybe-initialized equivalent. 32 | /// 33 | /// This converts a read-write-valid-values-only reference to a write-anything reference. 34 | /// 35 | /// # Safety 36 | /// 37 | /// The same requirements as [`Out::as_mut_uninit`]. 38 | /// Care should be taken with usage of the output - uninitialized garbage must not be written. 39 | /// 40 | /// [`Out::as_mut_uninit`]: crate::out_ref::Out::as_mut_uninit 41 | unsafe fn as_mut_uninit(&mut self) -> &mut Self::Uninit; 42 | 43 | /// Converts a raw pointer to a reference to maybe-uninit. 44 | /// 45 | /// # Safety 46 | /// 47 | /// This has the same requirements as `&*(raw as *const Self::Uninit)`. 48 | /// 49 | /// - `raw` must point to a readable allocated memory for `'a` for the size of `T` 50 | /// - `raw` must be aligned for `T` 51 | unsafe fn raw_as_uninit<'a>(raw: *const Self) -> &'a Self::Uninit; 52 | 53 | /// Converts a raw mutable pointer to a mutable reference to maybe-uninit. 54 | /// 55 | /// # Safety 56 | /// 57 | /// This has the same requirements as `&mut *(raw as *mut Self::Uninit)`. 58 | /// 59 | /// - `raw` must point to a readable and writeable allocated object for `'a` for the size of `T` 60 | /// - The pointer must not alias any other mutable references for `'a` 61 | /// - `raw` must be aligned for `T` 62 | unsafe fn raw_mut_as_uninit<'a>(raw: *mut Self) -> &'a mut Self::Uninit; 63 | } 64 | 65 | // SAFETY: 66 | // - `MaybeUninit` has the same layout as `T` but with no requirements on its contents. 67 | // - `as_ref_uninit` and `as_mut_uninit` return the same address as their input. 68 | unsafe impl AsMaybeUninit for T { 69 | type Uninit = MaybeUninit; 70 | type SizedPart = T; 71 | 72 | #[inline] 73 | fn as_ref_uninit(&self) -> &Self::Uninit { 74 | unsafe { &*(self as *const T).cast() } 75 | } 76 | 77 | #[inline] 78 | unsafe fn as_mut_uninit(&mut self) -> &mut Self::Uninit { 79 | // SAFETY: Uninit will not be written to the output as promised by the caller. 80 | unsafe { &mut *(self as *mut T).cast() } 81 | } 82 | 83 | #[inline] 84 | unsafe fn raw_as_uninit<'a>(raw: *const Self) -> &'a Self::Uninit { 85 | // SAFETY: The pointer is aligned and readable for `'a` as promised by the caller. 86 | unsafe { &*(raw as *const MaybeUninit) } 87 | } 88 | 89 | #[inline] 90 | unsafe fn raw_mut_as_uninit<'a>(raw: *mut Self) -> &'a mut Self::Uninit { 91 | // SAFETY: The pointer is aligned and read-writeable for `'a` as promised by the caller. 92 | unsafe { &mut *(raw as *mut MaybeUninit) } 93 | } 94 | } 95 | 96 | // Unfortunately this cannot `impl AsMaybeUninit for ManuallyDrop` as 97 | // that would conflict with the `Sized` blanket impl. 98 | 99 | // SAFETY: 100 | // - `[MaybeUninit]` has the same layout as `[T]` but with no requirements on its contents. 101 | // - `as_ref_uninit` and `as_mut_uninit` return the same address as their input. 102 | unsafe impl AsMaybeUninit for [T] { 103 | type Uninit = [MaybeUninit]; 104 | type SizedPart = T; 105 | 106 | #[inline] 107 | fn as_ref_uninit(&self) -> &Self::Uninit { 108 | unsafe { &*(self as *const [T] as *const [MaybeUninit]) } 109 | } 110 | 111 | #[inline] 112 | unsafe fn as_mut_uninit(&mut self) -> &mut Self::Uninit { 113 | // SAFETY: Uninit will not be written to the output as promised by the caller. 114 | unsafe { &mut *(self as *mut [T] as *mut [MaybeUninit]) } 115 | } 116 | 117 | #[inline] 118 | unsafe fn raw_as_uninit<'a>(raw: *const Self) -> &'a Self::Uninit { 119 | // SAFETY: The pointer is aligned and readable for `'a` as promised by the caller. 120 | unsafe { &*(raw as *const [MaybeUninit]) } 121 | } 122 | 123 | #[inline] 124 | unsafe fn raw_mut_as_uninit<'a>(raw: *mut Self) -> &'a mut Self::Uninit { 125 | // SAFETY: The pointer is aligned and read-writeable for `'a` as promised by the caller. 126 | unsafe { &mut *(raw as *mut [MaybeUninit]) } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/extension_traits/as_out.rs: -------------------------------------------------------------------------------- 1 | use_prelude!(); 2 | 3 | use crate::extension_traits::Transpose; 4 | use ::core::mem::ManuallyDrop; 5 | 6 | /// Extension trait to convert a `&mut _` into a `&out _` by calling 7 | /// `.as_out()` on it. 8 | /// 9 | /// By autoref, this means that you can even just extract a `&out T` reference 10 | /// out of a `mut` element simply by calling `.as_out()` on it. 11 | /// 12 | /// There is, however, one restriction: to be able to call `.as_out()` on 13 | /// something, it needs to be either `Copy`, or a value wrapped in a 14 | /// [`MaybeUninit`] / a [`ManuallyDrop`]. 15 | /// 16 | /// This is by design. Indeed, [`Out`] references do not call the destructor 17 | /// of the overwritten element (since it may not be initialized). 18 | /// This could cause memory leaks when there is an initialized element with 19 | /// [drop glue][core::mem::needs_drop]. 20 | /// 21 | /// To solve this limitation, one must explicitly call 22 | /// [`.manually_drop_mut()`][`crate::ManuallyDropMut::manually_drop_mut`] 23 | /// to automagically transmute the `&mut _` reference into a 24 | /// `&mut ManuallyDrop<_>`. 25 | /// 26 | /// # Examples 27 | /// 28 | /// ```rust 29 | /// use ::uninit::prelude::*; 30 | /// 31 | /// let mut x = 0; 32 | /// x.as_out().write(42); 33 | /// 34 | /// let mut y = ::core::mem::MaybeUninit::uninit(); 35 | /// y.as_out().write(42); 36 | /// let y = unsafe { y.assume_init() }; 37 | /// 38 | /// assert_eq!(x, y); 39 | /// ``` 40 | pub trait AsOut { 41 | #[allow(missing_docs)] 42 | fn as_out<'out>(self: &'out mut Self) -> Out<'out, Pointee>; 43 | } 44 | 45 | impl AsOut for MaybeUninit { 46 | #[inline] 47 | fn as_out<'out>(self: &'out mut MaybeUninit) -> Out<'out, T> { 48 | self.into() 49 | } 50 | } 51 | 52 | impl AsOut for T 53 | where 54 | T: Copy, 55 | { 56 | #[inline] 57 | fn as_out<'out>(self: &'out mut T) -> Out<'out, T> { 58 | self.into() 59 | } 60 | } 61 | 62 | impl AsOut<[T]> for [MaybeUninit] { 63 | #[inline] 64 | fn as_out<'out>(self: &'out mut [MaybeUninit]) -> Out<'out, [T]> { 65 | self.into() 66 | } 67 | } 68 | 69 | impl AsOut<[T]> for [T] 70 | where 71 | T: Copy, 72 | { 73 | #[inline] 74 | fn as_out<'out>(self: &'out mut [T]) -> Out<'out, [T]> { 75 | self.into() 76 | } 77 | } 78 | 79 | impl AsOut for ManuallyDrop { 80 | #[inline] 81 | fn as_out<'out>(self: &'out mut ManuallyDrop) -> Out<'out, T> { 82 | self.into() 83 | } 84 | } 85 | 86 | impl AsOut<[T]> for [ManuallyDrop] { 87 | #[inline] 88 | fn as_out<'out>(self: &'out mut [ManuallyDrop]) -> Out<'out, [T]> { 89 | self.into() 90 | } 91 | } 92 | 93 | impl AsOut<[T]> for MaybeUninit<[T; N]> { 94 | #[inline] 95 | fn as_out<'out>(self: &'out mut Self) -> Out<'out, [T]> { 96 | From::from(&mut self.transpose()[..]) 97 | } 98 | } 99 | 100 | impl AsOut<[T]> for [MaybeUninit; N] { 101 | #[inline] 102 | fn as_out<'out>(self: &'out mut Self) -> Out<'out, [T]> { 103 | From::from(&mut self[..]) 104 | } 105 | } 106 | 107 | impl AsOut<[T]> for [T; N] 108 | where 109 | T: Copy, 110 | { 111 | #[inline] 112 | fn as_out<'out>(self: &'out mut Self) -> Out<'out, [T]> { 113 | From::from(&mut self[..]) 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/extension_traits/boxed.rs: -------------------------------------------------------------------------------- 1 | use_prelude!(); 2 | cfg_alloc! { 3 | 4 | mod private { 5 | use_prelude!(); 6 | 7 | pub trait Sealed : Sized {} 8 | impl Sealed for Box<::core::mem::MaybeUninit> 9 | {} 10 | } 11 | 12 | /// Extension trait for uninitalized `Box` allocations and 13 | /// the optimized delayed-initialization pattern. 14 | /// 15 | /// # Optimized in-place heap initialization 16 | /// 17 | /// The `Box::uninit().init(...)` delayed-initialization pattern is suprisingly 18 | /// effective in helping the optimizer inline the creation of the value directly 19 | /// into the heap. 20 | /// 21 | /// - In other words, this bundles [`::copyless`](https://docs.rs/copyless) 22 | /// functionality. 23 | /// 24 | /// - For those wondering why `Box::new(...)` could not be made as efficient, 25 | /// the answer lies in temporaries: the `...` temporary when calling 26 | /// `Box::new()` is created _before_ attempting the allocation, and given 27 | /// that this allocation can fail / have side-effects, the optimizer is not 28 | /// allowed to reorder the creation of the temporary after the allocation, 29 | /// since it can change the semantics of the code for these corner (but 30 | /// not unreachable) cases. It is hence illegal for the optimizer to inline 31 | /// the creation of `...` directly into the heap. 32 | /// 33 | /// Whereas `Box::uninit().init(...)` only creates the temporary after 34 | /// the allocation attempted in `uninit()` has succeeded, at which point 35 | /// it should be trivial for the optimizer to inline its creation directly 36 | /// into the heap. 37 | /// 38 | /// - Note, however, that this property cannot be guaranteed from a library 39 | /// perspective; for instance, **the heap-inlined initialization does not 40 | /// seem to happen when the optimization level (`opt-level`) is less than 41 | /// `2`. Inversely, the author has observed that the heap-inlined 42 | /// initialization does seem to kick in when compiling with `-C 43 | /// opt-level=2`** (or `3`), _e.g._, when running on `--release`. 44 | /// 45 | /// 46 | /// ### Example 47 | /// 48 | /// ```rust 49 | /// use ::uninit::prelude::*; 50 | /// 51 | /// let ft: Box = Box::uninit().init(42); 52 | /// assert_eq!(*ft, 42); 53 | /// ``` 54 | /// 55 | /// This optimization can even allow creating arrays too big to fit in the 56 | /// stack. 57 | /// 58 | /// - For instance, the following implementation panics: 59 | /// 60 | /// ```rust,should_panic 61 | /// fn alloc_big_boxed_array () -> Box<[u64; 10_000_000]> 62 | /// { 63 | /// // This can panic because of the `[0; 10_000_000]` stack 64 | /// // temporary overflowing the stack. 65 | /// Box::new([0; 10_000_000]) 66 | /// } 67 | /// # println!("Address: {:p}", alloc_big_boxed_array()); 68 | /// # panic!(); 69 | /// ``` 70 | /// 71 | /// - Whereas the following one does not 72 | /// (doc-tested with `RUSTDOCFLAGS=-Copt-level=2`): 73 | /// 74 | /// ```rust 75 | /// # use ::uninit::prelude::*; 76 | /// fn alloc_big_boxed_array () -> Box<[u64; 10_000_000]> 77 | /// { 78 | /// // But this works fine, since there is no stack temporary! 79 | /// Box::uninit().init([0; 10_000_000]) 80 | /// } 81 | /// # println!("Address: {:p}", alloc_big_boxed_array()); 82 | /// ``` 83 | /// 84 | /// # Handling allocation failure 85 | /// 86 | /// A neat side-effect of this implementation is to expose the intermediate 87 | /// state of `Box::try_alloc()`, which yields an `Option>>` 88 | /// depending on whether the attempted allocation succeeded or not. 89 | /// 90 | /// ### Example 91 | /// 92 | /// ```rust,no_run 93 | /// use ::uninit::prelude::*; 94 | /// 95 | /// let buf: Box<[u8; ::core::i32::MAX as _]> = match Box::try_alloc() { 96 | /// | Some(uninit) => uninit.init([0; ::core::i32::MAX as _]), 97 | /// | None => { 98 | /// panic!("Failed to allocate 2GB of memory"); 99 | /// } 100 | /// }; 101 | /// # let _ = buf; 102 | /// ``` 103 | impl BoxUninit for Box> { 104 | type T = T; 105 | 106 | /// Idiomatic allocation-failure unwrapping of [`BoxUninit::try_alloc`]`()`. 107 | #[inline] 108 | fn uninit () 109 | -> Box> 110 | { 111 | let layout = alloc::Layout::new::(); 112 | if let Some(it) = Self::try_alloc() { it } else { 113 | alloc::handle_alloc_error(layout); 114 | } 115 | } 116 | 117 | /// Attempts to `Box`-allocate memory for `T`, without initializing it. 118 | /// 119 | /// Returns `None` when the allocation fails. 120 | #[inline] 121 | fn try_alloc () 122 | -> Option>> 123 | {Some({ 124 | if ::core::mem::size_of::() == 0 { 125 | Self::new(MaybeUninit::uninit()) 126 | } else { 127 | unsafe { 128 | // Safety: we have guarded against ZST 129 | let layout = alloc::Layout::new::(); 130 | Self::from_raw( 131 | ptr::NonNull::new(alloc::alloc(layout))? 132 | .as_ptr() 133 | .cast() 134 | 135 | ) 136 | } 137 | } 138 | })} 139 | 140 | /// Safely initialize a `Box::MaybeUninit` by providing a `value: T` 141 | /// (that can be inlined into the `Box`), and safely return the ergonomic 142 | /// `Box` witness of that initialization. 143 | #[inline(always)] 144 | fn init (mut self: Box>, value: T) 145 | -> Box 146 | { 147 | *self = MaybeUninit::new(value); 148 | unsafe { 149 | // Safety: `self` has just been initialized. 150 | Box::from_raw(Box::into_raw(self).cast()) 151 | } 152 | } 153 | } 154 | /// Extension trait for uninitalized `Box` allocations and 155 | /// the optimized delayed-initialization pattern. 156 | #[allow(missing_docs)] 157 | pub 158 | trait BoxUninit : private::Sealed { 159 | type T; 160 | fn uninit () 161 | -> Self 162 | ; 163 | fn init (self, value: Self::T) 164 | -> Box 165 | ; 166 | fn try_alloc () 167 | -> Option 168 | ; 169 | } 170 | 171 | mod private2 { 172 | use_prelude!(); 173 | 174 | pub trait Sealed {} 175 | impl Sealed for Box<[::core::mem::MaybeUninit]> 176 | {} 177 | impl Sealed for Box<::core::mem::MaybeUninit> 178 | {} 179 | } 180 | 181 | impl BoxAssumeInit for Box<[MaybeUninit]> { 182 | #[allow(missing_docs)] 183 | type Ret = [T]; 184 | 185 | 186 | /// Allows to "`.assume_init()`" a boxed `[MaybeUninit]`. 187 | /// 188 | /// # Safety 189 | /// 190 | /// - This has the same safety requirements as 191 | /// [`.assume_init()`][`MaybeUninit::assume_init`]. 192 | #[inline] 193 | unsafe fn assume_init (self: Box<[MaybeUninit]>) 194 | -> Box<[T]> 195 | { 196 | let len = self.len(); 197 | let ptr = Box::leak(self).as_mut_ptr(); 198 | // SAFETY: 199 | // - `T` and `MaybeUninit` have the same layout 200 | // - The `T` are initialized as promised by the caller 201 | unsafe { 202 | Box::from_raw(slice::from_raw_parts_mut( 203 | ptr.cast(), len, 204 | )) 205 | } 206 | } 207 | } 208 | 209 | impl BoxAssumeInit for Box> { 210 | type Ret = T; 211 | 212 | /// Allows to "`.assume_init()`" a boxed `MaybeUninit`. 213 | /// 214 | /// # Safety 215 | /// 216 | /// - This has the same safety requirements as 217 | /// [`.assume_init()`][`MaybeUninit::assume_init`]. 218 | #[inline] 219 | unsafe fn assume_init (self: Box>) 220 | -> Box 221 | { 222 | // SAFETY: 223 | // - `T` and `MaybeUninit` have the same layout 224 | // - The `T` are initialized as promised by the caller 225 | unsafe { 226 | Box::from_raw(Box::into_raw(self).cast()) 227 | } 228 | } 229 | } 230 | 231 | /// Extension trait to `.assume_init()` through a `Box`. 232 | /// 233 | /// This is a compatibility helper trait. For versions of Rust where the 234 | /// `feature(box_uninit)` is unstable, this trait enables the feature in stable 235 | /// Rust. This may trigger an `unstable_name_collisions` lint, but this is fine, 236 | /// since the implementation is the same. You can dismiss that lint with: 237 | /// 238 | /// ```rust 239 | /// #![allow(unstable_name_collisions)] 240 | /// ``` 241 | #[allow(missing_docs)] 242 | pub 243 | trait BoxAssumeInit : private2::Sealed { 244 | type Ret : ?Sized; 245 | 246 | unsafe fn assume_init (self: Self) 247 | -> Box 248 | ; 249 | } 250 | 251 | pub use new_uninit_slice::*; 252 | mod new_uninit_slice { 253 | #![allow(missing_docs)] 254 | use super::*; 255 | 256 | pub trait BoxNewUninitSlice: Sized { 257 | /// Constructs a new boxed slice with uninitialized contents. 258 | /// 259 | /// ## Example 260 | /// 261 | /// ``` 262 | /// use ::uninit::prelude::*; 263 | /// 264 | /// let mut values = Box::<[u32]>::new_uninit_slice(3); 265 | /// 266 | /// let values = unsafe { 267 | /// // Deferred initialization: 268 | /// values[0].as_mut_ptr().write(1); 269 | /// values[1].as_mut_ptr().write(2); 270 | /// values[2].as_mut_ptr().write(3); 271 | /// values.assume_init() 272 | /// }; 273 | /// 274 | /// assert_eq!(*values, [1, 2, 3]); 275 | /// ``` 276 | fn new_uninit_slice(len: usize) 277 | -> Box<[MaybeUninit]>; 278 | } 279 | 280 | impl BoxNewUninitSlice for Box<[T]> { 281 | #[inline] 282 | fn new_uninit_slice (len: usize) 283 | -> Box<[MaybeUninit]> 284 | { 285 | Vec::with_capacity(len).into_backing_buffer_forget_elems() 286 | } 287 | } 288 | } 289 | 290 | } // cfg_alloc! 291 | -------------------------------------------------------------------------------- /src/extension_traits/manually_drop_mut.rs: -------------------------------------------------------------------------------- 1 | use ::core::mem::ManuallyDrop; 2 | 3 | #[cfg(doc)] 4 | use crate::Out; 5 | 6 | /// Extension trait providing a cast to the [`ManuallyDrop`] type. 7 | /// 8 | /// This is useful if you want to use an [`Out`] reference to something that 9 | /// is not `Copy` (potentially because it has drop glue, in which case you 10 | /// either don't mind leaking / skipping that drop glue, or you know you will 11 | /// be manually handling it). 12 | /// 13 | /// ⚠️ **Misusage of this function can thus lead to memory leaks** ⚠️ 14 | /// 15 | /// # Example 16 | /// 17 | /// The following fails to compile because of the missing `Copy` bound: 18 | /// 19 | /// ```rust,compile_fail 20 | /// use ::uninit::prelude::*; 21 | /// use ::core::cell::Cell; 22 | /// 23 | /// let mut cell = Cell::new(0); 24 | /// cell.as_out().write(Cell::new(42)); // Error, not `Copy` 25 | /// assert_eq!(cell.get(), 42); 26 | /// ``` 27 | /// 28 | /// We see here that the `Copy` bound can be too restrictive. By calling 29 | /// `.manually_drop_mut()`, we no longer need to satisfy this `Copy` bound; but 30 | /// then we need to be careful with memory leaks. 31 | /// 32 | /// Since `::core::mem::needs_drop::>() == false`, there is nothing to 33 | /// worry about: 34 | /// 35 | /// ```rust 36 | /// use ::uninit::prelude::*; 37 | /// use ::core::cell::Cell; 38 | /// 39 | /// let mut cell = Cell::new(0); 40 | /// cell.manually_drop_mut().as_out().write(Cell::new(42)); // OK 41 | /// assert_eq!(cell.get(), 42); 42 | /// ``` 43 | /// 44 | /// # Counterexample 45 | /// 46 | /// ```rust 47 | /// use ::uninit::prelude::*; 48 | /// use ::std::rc::Rc; 49 | /// 50 | /// let rc = Rc::new(()); 51 | /// assert_eq!(Rc::strong_count(&rc), 1); 52 | /// let mut rc2 = Some(Rc::clone(&rc)); 53 | /// assert_eq!(Rc::strong_count(&rc), 2); 54 | /// // This overwrites `rc2` without running any destructor whatsoever, hence 55 | /// // leaking the `rc` clone. 56 | /// rc2.manually_drop_mut().as_out().write(None); 57 | /// assert_eq!(Rc::strong_count(&rc), 2); 58 | /// assert!(Rc::try_unwrap(rc).is_err()); 59 | /// ``` 60 | #[allow(missing_docs)] 61 | pub trait ManuallyDropMut { 62 | type Ret: ?Sized; 63 | 64 | fn manually_drop_mut(self: &'_ mut Self) -> &'_ mut Self::Ret; 65 | } 66 | 67 | impl ManuallyDropMut for [T] { 68 | type Ret = [ManuallyDrop]; 69 | 70 | #[inline] 71 | fn manually_drop_mut<'__>(self: &'__ mut [T]) -> &'__ mut [ManuallyDrop] { 72 | let len = self.len(); 73 | unsafe { 74 | // Safety: `ManuallyDrop` is `#[repr(transparent)]` 75 | ::core::slice::from_raw_parts_mut(self.as_mut_ptr().cast(), len) 76 | } 77 | } 78 | } 79 | 80 | impl ManuallyDropMut for T { 81 | type Ret = ManuallyDrop; 82 | 83 | #[inline] 84 | fn manually_drop_mut<'__>(self: &'__ mut T) -> &'__ mut ManuallyDrop { 85 | unsafe { 86 | // Safety: `ManuallyDrop` is `#[repr(transparent)]` 87 | ::core::mem::transmute(self) 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/extension_traits/maybe_uninit.rs: -------------------------------------------------------------------------------- 1 | use_prelude!(); 2 | 3 | /// Extension trait providing tranformations between init and uninit. 4 | /// 5 | /// # `from_mut`? 6 | /// 7 | /// This is provided by [`AsMaybeUninit::as_mut_uninit`]. 8 | /// 9 | /// The conversion from `&mut T` to `&mut MaybeUninit` is `unsafe`, since there 10 | /// are restrictions on what safe code can do with the output. These are the same 11 | /// requirements as [`Out::as_mut_uninit`]. 12 | /// 13 | /// Specifically, nothing must overwrite an initialized pointee 14 | /// with `MaybeUninit::uninit()` data, _i.e._, an 15 | /// uninitialised (and thus garbage) value, even though the API of `&mut T` 16 | /// allows this safely. This is similar to `Pin::get_mut_unchecked`. 17 | /// 18 | /// The correct way to convert `&mut T` into a maybe-initialized reference is through 19 | /// [the `&out` reference abstraction][`crate::out_ref`]. 20 | /// 21 | /// [`AsMaybeUninit::as_mut_uninit`]: crate::AsMaybeUninit::as_mut_uninit 22 | /// [`Out::as_mut_uninit`]: crate::out_ref::Out::as_mut_uninit 23 | pub trait MaybeUninitExt { 24 | /// The inner type that may be initialized. 25 | /// 26 | /// - For `MaybeUninit`, this is `T`. 27 | /// - For `[MaybeUninit]`, this is `[T]`. 28 | type T: ?Sized; 29 | 30 | /// Gets a raw pointer to the inner type. 31 | fn as_ptr(&self) -> *const Self::T; 32 | 33 | /// Gets a raw mutable pointer to the inner type. 34 | fn as_mut_ptr(&mut self) -> *mut Self::T; 35 | 36 | /// Converts a `&MaybeUninit<_>` to a `& _`. 37 | /// 38 | /// # Safety 39 | /// 40 | /// Don't be lured by the reference: this has the same safety requirements 41 | /// that [`.assume_init`][`MaybeUninit::assume_init`] does. Mainly: 42 | /// 43 | /// - The `Self::T` that `self` points to must be initialized. 44 | unsafe fn assume_init_by_ref(&self) -> &Self::T; 45 | 46 | /// Converts a `&mut MaybeUninit<_>` to a `&mut _`. 47 | /// 48 | /// # Safety 49 | /// 50 | /// Don't be lured by the `mut` reference: this has the same safety 51 | /// requirements that [`.assume_init`][`MaybeUninit::assume_init`] does. 52 | /// Mainly: 53 | /// 54 | /// - The `Self::T` that `self` points to must be initialized. 55 | unsafe fn assume_init_by_mut(&mut self) -> &mut Self::T; 56 | 57 | /// Downgrades a `& _` to a `&MaybeUninit<_>`. Rarely useful. 58 | #[deprecated = "Use `AsUninit::as_ref_uninit` instead"] 59 | fn from_ref(init_ref: &'_ Self::T) -> &'_ Self; 60 | } 61 | 62 | impl MaybeUninitExt for MaybeUninit { 63 | type T = T; 64 | 65 | #[inline] 66 | fn as_ptr(&self) -> *const Self::T { 67 | self.as_ptr() 68 | } 69 | 70 | #[inline] 71 | fn as_mut_ptr(&mut self) -> *mut Self::T { 72 | self.as_mut_ptr() 73 | } 74 | 75 | #[inline] 76 | unsafe fn assume_init_by_ref(self: &'_ Self) -> &'_ Self::T { 77 | unsafe { 78 | // # Safety 79 | // 80 | // - Same memory layout, bounded lifetimes, same mut-ness 81 | &*(self as *const _ as *const Self::T) 82 | } 83 | } 84 | 85 | #[inline] 86 | unsafe fn assume_init_by_mut(self: &'_ mut Self) -> &'_ mut Self::T { 87 | unsafe { 88 | // # Safety 89 | // 90 | // - Same memory layout, bounded lifetimes, same mut-ness 91 | &mut *(self as *mut _ as *mut Self::T) 92 | } 93 | } 94 | 95 | #[inline] 96 | fn from_ref(some_ref: &'_ Self::T) -> &'_ Self { 97 | unsafe { 98 | // # Safety 99 | // 100 | // - Same memory layout, bounded lifetimes, same mut-ness 101 | mem::transmute(some_ref) 102 | } 103 | } 104 | } 105 | 106 | impl MaybeUninitExt for [MaybeUninit] { 107 | type T = [T]; 108 | 109 | #[inline] 110 | fn as_ptr(&self) -> *const Self::T { 111 | self as *const _ as *const Self::T 112 | } 113 | 114 | #[inline] 115 | fn as_mut_ptr(&mut self) -> *mut Self::T { 116 | self as *mut _ as *mut Self::T 117 | } 118 | 119 | #[inline] 120 | unsafe fn assume_init_by_ref(self: &'_ Self) -> &'_ Self::T { 121 | unsafe { 122 | // # Safety 123 | // 124 | // - Same memory layout, bounded lifetimes, same mut-ness 125 | let len = self.len(); 126 | slice::from_raw_parts(self.as_ptr().cast(), len) 127 | } 128 | } 129 | 130 | #[inline] 131 | unsafe fn assume_init_by_mut(self: &'_ mut Self) -> &'_ mut Self::T { 132 | unsafe { 133 | // # Safety 134 | // 135 | // - Same memory layout, bounded lifetimes, same mut-ness 136 | let len = self.len(); 137 | slice::from_raw_parts_mut(self.as_mut_ptr().cast(), len) 138 | } 139 | } 140 | 141 | #[inline] 142 | fn from_ref(slice: &'_ Self::T) -> &'_ Self { 143 | unsafe { 144 | // # Safety 145 | // 146 | // - Same memory layout, bounded lifetimes, same mut-ness 147 | let len = slice.len(); 148 | slice::from_raw_parts(slice.as_ptr().cast(), len) 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/extension_traits/mod.rs: -------------------------------------------------------------------------------- 1 | //! Extension traits to enhance external types with useful methods. 2 | 3 | pub use self::as_out::AsOut; 4 | mod as_out; 5 | 6 | pub use self::manually_drop_mut::ManuallyDropMut; 7 | mod manually_drop_mut; 8 | 9 | pub use self::maybe_uninit::MaybeUninitExt; 10 | mod maybe_uninit; 11 | 12 | pub use self::transpose::Transpose; 13 | mod transpose; 14 | 15 | cfg_alloc! { 16 | pub use self::boxed::{ 17 | BoxAssumeInit, 18 | BoxNewUninitSlice, 19 | BoxUninit, 20 | }; 21 | mod boxed; 22 | 23 | pub use self::vec::{ 24 | VecCapacity, 25 | }; 26 | mod vec; 27 | } 28 | 29 | cfg_std! { 30 | pub use self::vec::{ 31 | VecExtendFromReader, 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /src/extension_traits/transpose.rs: -------------------------------------------------------------------------------- 1 | use_prelude!(); 2 | 3 | /// Extension trait to transform between `[MaybeUninit; N]` and `MaybeUninit<[T; N]>`, 4 | /// as well as between references to each. 5 | /// 6 | /// # Examples 7 | /// 8 | /// ## Initializing an array element-by-element 9 | /// 10 | /// This example [adapted from the standard library][stdlib-mu-array-init] needs less 11 | /// `unsafe` and no `transmute`s. 12 | /// 13 | /// ``` 14 | /// use std::mem::{self, MaybeUninit}; 15 | /// use uninit::extension_traits::Transpose; 16 | /// 17 | /// let data = { 18 | /// // Create an uninitialized array of `MaybeUninit`. 19 | /// // The initial `uninit` constructs a `MaybeUninit<[Vec; 1000]>`, 20 | /// // and the `transpose` exposes individual elements. 21 | /// let mut data: [MaybeUninit>; 1000] = MaybeUninit::uninit().transpose(); 22 | /// 23 | /// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, 24 | /// // we have a memory leak, but there is no memory safety issue. 25 | /// for elem in &mut data[..] { 26 | /// elem.write(vec![42]); 27 | /// } 28 | /// 29 | /// // Everything is initialized. 30 | /// // Transpose back into a `MaybeUninit` of an array and `assume_init` it. 31 | /// unsafe { data.transpose().assume_init() } 32 | /// }; 33 | /// 34 | /// assert_eq!(&data[0], &[42]); 35 | /// ``` 36 | /// 37 | /// [stdlib-mu-array-init]: https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element 38 | /// 39 | pub trait Transpose { 40 | /// `Self` but with the array and `MaybeUninit` parts swapped. 41 | /// 42 | /// | `Self` | `Self::Transposed` | 43 | /// | ------ | ------------------ | 44 | /// | `[MaybeUninit; N]` | `MaybeUninit<[T; N]>` | 45 | /// | `MaybeUninit<[T; N]>` | `[MaybeUninit; N]` | 46 | /// | `&'a [MaybeUninit; N]` | `&'a MaybeUninit<[T; N]>` | 47 | /// | `&'a MaybeUninit<[T; N]>` | `&'a [MaybeUninit; N]` | 48 | /// | `&'a mut [MaybeUninit; N]` | `&'a mut MaybeUninit<[T; N]>` | 49 | /// | `&'a mut MaybeUninit<[T; N]>` | `&'a mut [MaybeUninit; N]` | 50 | /// 51 | /// Like with [`Result::transpose`] and [`Option::transpose`], 52 | /// `x.transpose().transpose()` is a no-op. 53 | type Transposed: Transpose; 54 | 55 | /// Transpose between an array-of-`MaybeUninit` and a `MaybeUninit` of an array. 56 | /// 57 | /// # Example 58 | /// 59 | /// ``` 60 | /// use std::mem::MaybeUninit; 61 | /// use uninit::extension_traits::Transpose; 62 | /// 63 | /// let mut uninit_of_array: MaybeUninit<[u32; 4]> = MaybeUninit::new([1,2,3,4]); 64 | /// 65 | /// // `transpose` of an array consumes, copying if the array element is `Copy`. 66 | /// let mut array_of_uninit: [MaybeUninit; 4] = uninit_of_array.transpose(); 67 | /// 68 | /// array_of_uninit[0].write(10); 69 | /// 70 | /// // `transpose` of a reference does not copy. 71 | /// let uoa_ref = (&uninit_of_array).transpose(); 72 | /// 73 | /// // SAFETY: the first element of `uninit_of_array` has been initialized 74 | /// assert_eq!(unsafe { uoa_ref[0].assume_init() }, 1); 75 | /// 76 | /// // SAFETY: the first element of `array_of_uninit` has been initialized 77 | /// assert_eq!(unsafe { array_of_uninit[0].assume_init() }, 10); 78 | /// 79 | /// // `transpose` can also go the other way and be used to mutate. 80 | /// let aou_mut: &mut MaybeUninit<[u32; 4]> = (&mut array_of_uninit).transpose(); 81 | /// aou_mut.write([5,6,7,8]); 82 | /// assert_eq!(unsafe { array_of_uninit[0].assume_init() }, 5); 83 | /// ``` 84 | fn transpose(self) -> Self::Transposed; 85 | 86 | /// An alternate way to spell `(&self).transpose()`. 87 | /// 88 | /// This explicitly communicates this is a conversion between references. 89 | /// 90 | /// # Example 91 | /// 92 | /// ``` 93 | /// use std::mem::MaybeUninit; 94 | /// use uninit::extension_traits::Transpose; 95 | /// 96 | /// let uninit_of_array: MaybeUninit<[u32; 4]> = MaybeUninit::new([4,5,6,7]); 97 | /// 98 | /// // SAFETY: the second element of `uninit_of_array` has been initialized 99 | /// assert_eq!(unsafe { uninit_of_array.transpose_ref()[1].assume_init() }, 5); 100 | /// ``` 101 | fn transpose_ref<'a>(&'a self) -> &'a Self::Transposed 102 | where 103 | &'a Self: Transpose, 104 | { 105 | self.transpose() 106 | } 107 | 108 | /// An alternate way to spell `(&mut self).transpose()`. 109 | /// 110 | /// This explicitly communicates this is a conversion between references. 111 | /// 112 | /// # Example 113 | /// 114 | /// ``` 115 | /// use std::mem::MaybeUninit; 116 | /// use uninit::extension_traits::Transpose; 117 | /// 118 | /// let mut uninit_of_array: MaybeUninit<[u32; 4]> = MaybeUninit::uninit(); 119 | /// 120 | /// let array_of_uninit_mut = uninit_of_array.transpose_mut(); 121 | /// array_of_uninit_mut[0].write(10); 122 | /// array_of_uninit_mut[1].write(20); 123 | /// array_of_uninit_mut[2].write(30); 124 | /// array_of_uninit_mut[3].write(40); 125 | /// 126 | /// // SAFETY: all of the elements of `uninit_of_array` have been initialized 127 | /// assert_eq!(unsafe { uninit_of_array.assume_init_ref() }, &[10, 20, 30, 40]); 128 | /// ``` 129 | fn transpose_mut<'a>(&'a mut self) -> &'a mut Self::Transposed 130 | where 131 | &'a mut Self: Transpose, 132 | { 133 | self.transpose() 134 | } 135 | } 136 | 137 | impl Transpose for [MaybeUninit; N] { 138 | type Transposed = MaybeUninit<[T; N]>; 139 | 140 | fn transpose(self) -> Self::Transposed { 141 | // This does not use `mem::transmute` because the compiler's special 142 | // identical-size check does not function for generic code of this kind. 143 | 144 | // SAFETY: 145 | // - Neither `Self` nor `Self::Transposed` have drop glue, 146 | // since they're composed of only `MaybeUninit`. 147 | // - `T` and `MaybeUninit` are guaranteed to have the same layout. 148 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` both have no 149 | // requirement for initialization for their entire memory span. 150 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` are guaranteed to have 151 | // the same layout. This isn't universally applicable to types containing 152 | // `MaybeUninit` vs. `T`, but is true for arrays, which have a size of 153 | // `size_of::() * N` and the align of `T`. 154 | unsafe { core::mem::transmute_copy(&self) } 155 | } 156 | } 157 | 158 | impl Transpose for MaybeUninit<[T; N]> { 159 | type Transposed = [MaybeUninit; N]; 160 | 161 | fn transpose(self) -> Self::Transposed { 162 | // This does not use `mem::transmute` because the compiler's special 163 | // identical-size check does not function for generic code of this kind. 164 | 165 | // SAFETY: 166 | // - Neither `Self` nor `Self::Transposed` have drop glue, 167 | // since they're composed of only `MaybeUninit`. 168 | // - `T` and `MaybeUninit` are guaranteed to have the same layout. 169 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` both have no 170 | // requirement for initialization for their entire memory span. 171 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` are guaranteed to have 172 | // the same layout. This isn't universally applicable to types containing 173 | // `MaybeUninit` vs. `T`, but is true for arrays, which have a size of 174 | // `size_of::() * N` and the align of `T`. 175 | unsafe { core::mem::transmute_copy(&self) } 176 | } 177 | } 178 | 179 | impl<'a, T: 'a, const N: usize> Transpose for &'a [MaybeUninit; N] { 180 | type Transposed = &'a MaybeUninit<[T; N]>; 181 | 182 | fn transpose(self) -> Self::Transposed { 183 | // SAFETY: 184 | // - `T` and `MaybeUninit` are guaranteed to have the same layout. 185 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` both have no 186 | // requirement for initialization for their entire memory span. 187 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` are guaranteed to have 188 | // the same layout. This isn't universally applicable to types containing 189 | // `MaybeUninit` vs. `T`, but is true for arrays, which have a size of 190 | // `size_of::() * N` and the align of `T`. 191 | unsafe { &*(self as *const [MaybeUninit; N] as *const MaybeUninit<[T; N]>) } 192 | } 193 | } 194 | 195 | impl<'a, T: 'a, const N: usize> Transpose for &'a MaybeUninit<[T; N]> { 196 | type Transposed = &'a [MaybeUninit; N]; 197 | 198 | fn transpose(self) -> Self::Transposed { 199 | // SAFETY: 200 | // - `T` and `MaybeUninit` are guaranteed to have the same layout. 201 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` both have no 202 | // requirement for initialization for their entire memory span. 203 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` are guaranteed to have 204 | // the same layout. This isn't universally applicable to types containing 205 | // `MaybeUninit` vs. `T`, but is true for arrays, which have a size of 206 | // `size_of::() * N` and the align of `T`. 207 | unsafe { &*(self as *const MaybeUninit<[T; N]> as *const [MaybeUninit; N]) } 208 | } 209 | } 210 | 211 | impl<'a, T: 'a, const N: usize> Transpose for &'a mut [MaybeUninit; N] { 212 | type Transposed = &'a mut MaybeUninit<[T; N]>; 213 | 214 | fn transpose(self) -> Self::Transposed { 215 | // SAFETY: 216 | // - `T` and `MaybeUninit` are guaranteed to have the same layout. 217 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` both have no 218 | // requirement for initialization for their entire memory span. 219 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` are guaranteed to have 220 | // the same layout. This isn't universally applicable to types containing 221 | // `MaybeUninit` vs. `T`, but is true for arrays, which have a size of 222 | // `size_of::() * N` and the align of `T`. 223 | unsafe { &mut *(self as *mut [MaybeUninit; N] as *mut MaybeUninit<[T; N]>) } 224 | } 225 | } 226 | 227 | impl<'a, T: 'a, const N: usize> Transpose for &'a mut MaybeUninit<[T; N]> { 228 | type Transposed = &'a mut [MaybeUninit; N]; 229 | 230 | fn transpose(self) -> Self::Transposed { 231 | // SAFETY: 232 | // - `T` and `MaybeUninit` are guaranteed to have the same layout. 233 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` both have no 234 | // requirement for initialization for their entire memory span. 235 | // - `[MaybeUninit; N]` and `MaybeUninit<[T; N]>` are guaranteed to have 236 | // the same layout. This isn't universally applicable to types containing 237 | // `MaybeUninit` vs. `T`, but is true for arrays, which have a size of 238 | // `size_of::() * N` and the align of `T`. 239 | unsafe { &mut *(self as *mut MaybeUninit<[T; N]> as *mut [MaybeUninit; N]) } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /src/extension_traits/vec.rs: -------------------------------------------------------------------------------- 1 | cfg_alloc! { 2 | use crate::*; 3 | use ::core::slice; 4 | 5 | /// Extension trait for [`Vec`], allowing a non-`unsafe` API to interact 6 | /// with the backing buffer / allocation. 7 | #[allow(missing_docs)] 8 | pub 9 | trait VecCapacity : Sealed { 10 | type Item; 11 | 12 | /// See ↓ below ↓. 13 | fn split_at_extra_cap (self: &'_ mut Self) 14 | -> (&'_ mut [Self::Item], &'_ mut [MaybeUninit]) 15 | ; 16 | 17 | /// See ↓ below ↓. 18 | fn spare_cap (self: &'_ mut Self) 19 | -> &'_ mut [MaybeUninit] 20 | ; 21 | 22 | /// See ↓ below ↓. 23 | fn reserve_uninit (self: &'_ mut Self, additional: usize) 24 | -> &'_ mut [MaybeUninit] 25 | ; 26 | 27 | /// See ↓ below ↓. 28 | fn get_backing_buffer (self: &'_ mut Self) 29 | -> Out<'_, [Self::Item]> 30 | where 31 | Self::Item : Copy, // Opinionated stance against accidental memory leaks 32 | ; 33 | 34 | /// See ↓ below ↓. 35 | fn into_backing_buffer (self: Self) 36 | -> Box<[MaybeUninit]> 37 | where 38 | Self::Item : Copy, // Opinionated stance against accidental memory leaks 39 | ; 40 | 41 | /// See ↓ below ↓. 42 | fn get_backing_buffer_with_leaking_writes (self: &'_ mut Self) 43 | -> Out<'_, [Self::Item]> 44 | ; 45 | 46 | /// See ↓ below ↓. 47 | fn into_backing_buffer_forget_elems (self: Self) 48 | -> Box<[MaybeUninit]> 49 | ; 50 | } 51 | 52 | mod private { pub trait Sealed : Sized {} } use private::Sealed; 53 | 54 | impl Sealed for Vec {} 55 | impl VecCapacity for Vec { 56 | #[allow(missing_docs)] 57 | type Item = T; 58 | 59 | /// Same as `.split_at_extra_cap().1`, but for not invalidating 60 | /// —_w.r.t._ aliasing / Stacked Borrows— pointers to the initialized area 61 | /// of this `Vec`: 62 | /// 63 | /// ```rust 64 | /// use ::uninit::prelude::*; 65 | /// 66 | /// let mut v = Vec::with_capacity(2); // len = 0 && 2 uninit 67 | /// v.push(0); // len = 1 && 1 uninit 68 | /// let at_fst = v.as_mut_ptr(); 69 | /// v.spare_cap()[0] = MaybeUninit::new(27); // len = 1 && 1 init 70 | /// unsafe { 71 | /// v.set_len(2); // len = 2 72 | /// *at_fst += 42; // OK, neither `spare_cap()` nor the `len` interactions invalidated this. 73 | /// } 74 | /// assert_eq!(v.iter().sum::(), 42 + 27); 75 | /// ``` 76 | fn spare_cap (self: &'_ mut Vec) 77 | -> &'_ mut [MaybeUninit] 78 | { 79 | let len = self.len(); 80 | let cap = self.capacity(); 81 | unsafe { 82 | // Safety: 83 | // - The `.add()` is valid per invariants of `Vec`. 84 | // - Per `Vec`'s guarantees, the `len.. cap` range of its backing 85 | // buffer does contain `cap - len` contiguous `MaybeUninit`s. 86 | // - the `.as_mut_ptr()` ptr has RW provenance over the whole 87 | // `0.. cap` range, _a fortiori_ over `len.. cap`. 88 | ::core::slice::from_raw_parts_mut( 89 | self.as_mut_ptr().add(len).cast::>(), 90 | cap - len, 91 | ) 92 | } 93 | } 94 | 95 | /// Splits the `Vec`'s 96 | /// [backing buffer][`VecCapacity::get_backing_buffer`] into two slices of 97 | /// initialized and uninitialized elements. 98 | /// 99 | /// Imagine this as doing 100 | /// `self.get_backing_buffer().split_at_out(self.len())` 101 | /// while upgrading the first half to `&mut [T]`. 102 | /// 103 | /// # Guarantees (that `unsafe` code may rely on) 104 | /// 105 | /// Given a vector `v`, and `let (xs, extra) = v.split_at_extra_cap()`, 106 | /// then: 107 | /// 108 | /// - `xs` _is_ `v.as_slice()`, so: 109 | /// 110 | /// - `xs.len() == v.len()`, 111 | /// 112 | /// - `xs.as_ptr() == v.as_ptr()`, 113 | /// 114 | /// - `extra.len() == (v.capacity() - v.len())`; 115 | /// 116 | /// - if `.split_at_extra_cap()` is called right after a call to 117 | /// `.reserve(n)`, then `v.capacity() ≥ v.len() + n`, and thus 118 | /// **`extra.len() ≥ n`**. 119 | /// 120 | /// For the `extra.len() == n` equality to hold, one must subslice 121 | /// `extra`: 122 | /// 123 | /// - `extra = extra.get_out(.. n).unwrap();`. 124 | /// 125 | /// And given the aformentioned guarantees, one can even: 126 | /// 127 | /// - `extra = extra.get_unchecked_out(.. n);` 128 | /// 129 | /// This last idiom is covered by 130 | /// [`.reserve_uninit(n)`][`VecCapacity::reserve_uninit`]. 131 | /// 132 | /// - `extra.as_ptr() == v.as_ptr().add(v.len())`. 133 | /// 134 | /// - Thus, only after initializing the first `k` elements of `extra`, 135 | /// is it sound to `v.set_len(v.len() + k);`. 136 | /// 137 | /// # Example 138 | /// 139 | /// Making a palindrome `Vec`: 140 | /// 141 | /// ```rust 142 | /// use ::uninit::prelude::*; 143 | /// 144 | /// fn make_palindrome (v: &'_ mut Vec) 145 | /// { 146 | /// let len = v.len(); 147 | /// v.reserve(len); 148 | /// let (xs, extra) = v.split_at_extra_cap(); 149 | /// for (&x, at_dst) in xs.iter().rev().zip(extra.as_out()) { 150 | /// at_dst.write(x); 151 | /// } 152 | /// unsafe { 153 | /// // Safety: the first `len` elements of `extra` have been initialized. 154 | /// v.set_len(2 * len); 155 | /// } 156 | /// } 157 | /// 158 | /// let mut v = vec![1, 2, 3]; 159 | /// make_palindrome(&mut v); 160 | /// assert_eq!(v, [1, 2, 3, 3, 2, 1]); 161 | /// ``` 162 | #[inline] 163 | fn split_at_extra_cap (self: &'_ mut Vec) 164 | -> (&'_ mut [T], &'_ mut [MaybeUninit]) 165 | { 166 | let len = self.len(); 167 | let backing_buffer = self.get_backing_buffer_with_leaking_writes(); 168 | let (mut xs, extra) = backing_buffer.split_at_out(len); 169 | ( 170 | unsafe { 171 | // Safety: the first `len` elements are initialized (safety 172 | // invariant of `Vec`). 173 | &mut *xs.as_mut_ptr() 174 | }, 175 | unsafe { 176 | // Safety: that part is indeed uninit and garbage can be written 177 | // to it. 178 | extra.as_mut_uninit() 179 | }, 180 | ) 181 | } 182 | 183 | /// [Reserves][`Vec::reserve`] extra (uninitialized) memory for it, 184 | /// **returning a mutable handle to those extra (uninitialized) elements**. 185 | /// 186 | /// # Example 187 | /// 188 | /// ```rust 189 | /// # use ::core::mem::MaybeUninit; 190 | /// use ::uninit::prelude::*; 191 | /// 192 | /// let mut vec = b"Hello, ".to_vec(); 193 | /// const WORLD: &[u8] = b"World!"; 194 | /// 195 | /// let mut extra: Out<'_, [u8]> = vec.reserve_uninit(WORLD.len()).as_out(); 196 | /// extra.r().copy_from_slice(WORLD); 197 | /// 198 | /// // `.reserve_uninit()` guarantees the following properties: 199 | /// assert_eq!(extra.len(), WORLD.len()); 200 | /// let extra_start: *mut u8 = extra.r().as_mut_ptr().cast(); 201 | /// let uninit_start: *mut u8 = vec.as_mut_ptr().wrapping_add(vec.len()); 202 | /// assert_eq!(extra_start, uninit_start); 203 | /// 204 | /// unsafe { 205 | /// // # Safety 206 | /// // 207 | /// // - `.copy_from_slice()` contract guarantees initialization 208 | /// // of `extra`, which, in turn, from `reserve_uninit`'s contract, 209 | /// // leads to the `vec` extra capacity having been initialized. 210 | /// vec.set_len(vec.len() + WORLD.len()); 211 | /// } 212 | /// assert_eq!( 213 | /// vec, 214 | /// b"Hello, World!", 215 | /// ); 216 | /// ``` 217 | #[inline] 218 | fn reserve_uninit (self: &'_ mut Vec, additional: usize) 219 | -> &'_ mut [MaybeUninit] 220 | { 221 | self.reserve(additional); 222 | let extra = self.spare_cap(); 223 | unsafe { 224 | // Safety: `Vec` guarantees that `cap >= len + additional` and 225 | // thus that `cap - len >= additional`. 226 | extra.get_unchecked_mut(.. additional) 227 | } 228 | } 229 | 230 | /// Gets an [`&out [T]`][`Out`] slice (of `self.capacity()` elements) 231 | /// to the backing buffer. 232 | #[inline] 233 | fn get_backing_buffer (self: &'_ mut Vec) 234 | -> Out<'_, [T]> 235 | where 236 | T : Copy, // Opinionated stance against accidental memory leaks 237 | { 238 | self.get_backing_buffer_with_leaking_writes() 239 | } 240 | 241 | /// Same as [`.get_backing_buffer()`][`VecCapacity::get_backing_buffer`] 242 | /// but without the `Copy` bound. 243 | /// 244 | /// This means that extra care should be taken if 245 | /// `mem::needs_drop::()`. Indeed, if the `OutSlice` is used to 246 | /// overwrite initialized elements, then such elements will be destroyed 247 | /// without their `.drop()` glue / destructors ever being run. 248 | /// 249 | /// ⚠️ **Misusage of this function can thus lead to memory leaks** ⚠️ 250 | /// 251 | /// # Counter-example 252 | /// 253 | /// ```rust 254 | /// use ::uninit::prelude::*; 255 | /// use ::std::rc::Rc; 256 | /// 257 | /// let rc = Rc::new(()); 258 | /// assert_eq!(Rc::strong_count(&rc), 1); 259 | /// let mut v = vec![ Some(Rc::clone(&rc)) ]; 260 | /// assert_eq!(Rc::strong_count(&rc), 2); 261 | /// // This overwrites the `rc` clone without running any destructor 262 | /// // whatsoever, hence leaking it. 263 | /// v .get_backing_buffer_with_leaking_writes() 264 | /// .get_out(0) 265 | /// .unwrap() 266 | /// .write(None) // the `rc` clone is not freed 267 | /// ; 268 | /// assert_eq!(Rc::strong_count(&rc), 2); 269 | /// assert!(Rc::try_unwrap(rc).is_err()); 270 | /// ``` 271 | /// 272 | /// # Example 273 | /// 274 | /// ```rust 275 | /// use ::uninit::prelude::*; 276 | /// use ::std::cell::Cell; 277 | /// 278 | /// let mut v = vec![Cell::new(0)]; 279 | /// v .get_backing_buffer_with_leaking_writes() // No drop glue, so this is fine 280 | /// .get_out(0) 281 | /// .unwrap() 282 | /// .write(Cell::new(42)) 283 | /// ; 284 | /// assert_eq!(v[0].get(), 42); 285 | /// ``` 286 | #[inline] 287 | fn get_backing_buffer_with_leaking_writes (self: &'_ mut Vec) 288 | -> Out<'_, [T]> 289 | { 290 | let capacity = self.capacity(); 291 | unsafe { 292 | // # Safety 293 | // 294 | // - `Vec` safety invariant / layout guarantees state that 295 | // it owns a `Box<[MaybeUninit]` of length `self.capacity()` 296 | // and starting at `self.as_mut_ptr()`. 297 | slice::from_raw_parts_mut( 298 | self.as_mut_ptr().cast::>(), 299 | capacity, 300 | ).as_out() 301 | } 302 | } 303 | 304 | /// Extracts an owned handle to the backing buffer. 305 | #[inline] 306 | fn into_backing_buffer (self: Vec) 307 | -> Box<[MaybeUninit]> 308 | where 309 | T : Copy, // Opinionated stance against accidental memory leaks 310 | { 311 | self.into_backing_buffer_forget_elems() 312 | } 313 | 314 | /// Same as [`.into_backing_buffer()`][ 315 | /// `VecCapacity::into_backing_buffer`] but without the `Copy` bound. 316 | /// 317 | /// This means that extra care should be taken if 318 | /// `mem::needs_drop::()`. Indeed, the returned boxed slice 319 | /// will not run the destructor of its initialized elements (since it no 320 | /// longer knows which are). 321 | /// 322 | /// ⚠️ **Misusage of this function can thus lead to memory leaks** ⚠️ 323 | /// 324 | /// # Counter-example 325 | /// 326 | /// ```rust 327 | /// use ::uninit::prelude::*; 328 | /// use ::std::rc::Rc; 329 | /// 330 | /// let rc = Rc::new(()); 331 | /// assert_eq!(Rc::strong_count(&rc), 1); 332 | /// let mut v = vec![ Some(Rc::clone(&rc)) ]; 333 | /// assert_eq!(Rc::strong_count(&rc), 2); 334 | /// // This leaks the `rc` clone (but not the heap-allocated array containing it) 335 | /// let _ = v.into_backing_buffer_forget_elems(); 336 | /// assert_eq!(Rc::strong_count(&rc), 2); 337 | /// assert!(Rc::try_unwrap(rc).is_err()); 338 | /// ``` 339 | /// 340 | /// # Example 341 | /// 342 | /// ```rust 343 | /// use ::uninit::prelude::*; 344 | /// 345 | /// let mut v = vec![String::from("Hello!")]; 346 | /// // Good practice: before calling `.into_backing_buffer_forget_elems()` 347 | /// // one ought to `.clear()` the `Vec`: 348 | /// v.clear(); // drops `"Hello!"` 349 | /// let mut strings_buffer: Box<[MaybeUninit]> = 350 | /// v.into_backing_buffer_forget_elems() 351 | /// ; 352 | /// strings_buffer[0] = MaybeUninit::new(String::from("Greetings!")); 353 | /// let strings_buffer: Box<[String]> = unsafe { 354 | /// Box::assume_init(strings_buffer) 355 | /// }; 356 | /// assert_eq!(&*strings_buffer[0], "Greetings!"); 357 | /// // This does free the contained "Greetings!" `String`. 358 | /// drop(strings_buffer); 359 | /// ``` 360 | #[inline] 361 | fn into_backing_buffer_forget_elems (self: Vec) 362 | -> Box<[MaybeUninit]> 363 | { 364 | // We need to go through an intermediate max-capacity `Vec` because 365 | // there is no official guarantee that a `Vec`'s backing allocation 366 | // matches that of a boxed slice. 367 | let this: Vec> = unsafe { 368 | // Safety: 369 | // 370 | // - same layout; 371 | // 372 | // - `MaybeUninit>` is sound to `.assume_init()`; 373 | // 374 | // - init -> uninit conversion is sound by "covariance of ownership". 375 | let mut this = mem::ManuallyDrop::new(self); 376 | let capacity = this.capacity(); 377 | Vec::from_raw_parts( 378 | this.as_mut_ptr().cast::>(), 379 | capacity, 380 | capacity, 381 | ) 382 | }; 383 | this.into_boxed_slice() // hopefully a no-op 384 | } 385 | } 386 | 387 | cfg_std! { 388 | /// Extension trait for [`Vec`], that grows the vec by a _bounded_ amount of 389 | /// bytes, obtained when reading from `R`. 390 | /// 391 | /// This guarantees that the allocated memory starts uninitialized (before 392 | /// being initialized by the read), for maximum performance. 393 | /// 394 | /// # Example 395 | /// 396 | /// ```rust 397 | /// use ::uninit::read::VecExtendFromReader; 398 | /// 399 | /// let mut reader = &b"World!"[..]; 400 | /// let mut vec = b"Greetings, ".to_vec(); 401 | /// vec.extend_from_reader_exact(6, &mut reader).unwrap(); 402 | /// assert_eq!( 403 | /// vec, 404 | /// b"Greetings, World!", 405 | /// ); 406 | /// ``` 407 | pub 408 | trait VecExtendFromReader { 409 | /// Tries to extends the `Vec` with up to `max_count` bytes read from 410 | /// `reader`. 411 | fn extend_from_reader ( 412 | self: &'_ mut Self, 413 | max_count: usize, 414 | reader: R, 415 | ) -> io::Result 416 | ; 417 | /// Tries to extends the `Vec` with exactly `exact_count` bytes read from 418 | /// `reader`. 419 | fn extend_from_reader_exact ( 420 | self: &'_ mut Self, 421 | exact_count: usize, 422 | reader: R, 423 | ) -> io::Result<()> 424 | ; 425 | } 426 | 427 | macro_rules! make_extend {( 428 | name = $fname:ident, 429 | count_name = $count_param:ident, 430 | read_into_buf = |$reader:ident, $buf:ident| $read_into_buf:expr, 431 | ret_of_count = |$count:ident| -> $Ret:ty { $ret_of_count:expr }, 432 | ) => ( 433 | #[inline] 434 | fn $fname ( 435 | self: &'_ mut Self, 436 | $count_param: usize, 437 | mut $reader: R, 438 | ) -> io::Result<$Ret> 439 | { 440 | let $buf: Out<'_, [u8]> = self.reserve_uninit($count_param).as_out(); 441 | let buf: &mut [u8] = $read_into_buf?; 442 | let $count: usize = buf.len(); 443 | debug_assert_eq!( 444 | buf.as_mut_ptr(), 445 | self.as_mut_ptr() 446 | .wrapping_add(self.len()) 447 | , 448 | "This is a bug and a soundness issue. Please submit an issue ASAP", 449 | ); 450 | let new_len = self.len().checked_add($count); 451 | debug_assert!( 452 | new_len 453 | .map(|new_len| new_len <= self.capacity()) 454 | .unwrap_or(false) 455 | , 456 | "This is a bug and a soundness issue. Please submit an issue ASAP", 457 | ); 458 | unsafe { 459 | // # Safety 460 | // 461 | // - `buf: &mut [u8]` has been a witness of the initialization of 462 | // the bytes in the `len .. len + count` range. 463 | self.set_len( 464 | new_len.unwrap_or_else(|| hint::unreachable_unchecked()) 465 | ); 466 | } 467 | Ok($ret_of_count) 468 | } 469 | )} 470 | 471 | impl VecExtendFromReader for Vec { 472 | make_extend! { 473 | name = extend_from_reader, 474 | count_name = max_count, 475 | read_into_buf = |reader, buf| reader.read_into_uninit(buf), 476 | ret_of_count = |count| -> usize { count }, 477 | } 478 | make_extend! { 479 | name = extend_from_reader_exact, 480 | count_name = exact_count, 481 | read_into_buf = |reader, buf| reader.read_into_uninit_exact(buf), 482 | ret_of_count = |count| -> () { () }, 483 | } 484 | } 485 | } // cfg_std! 486 | 487 | 488 | } // cfg_alloc! 489 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(feature = "better-docs", 2 | feature(doc_cfg, decl_macro), 3 | cfg_attr(all(), doc = include_str!("../README.md")), 4 | )] 5 | //! 6 | #![cfg_attr(feature = "specialization", feature(specialization))] 7 | #![cfg_attr(feature = "specialization", allow(incomplete_features))] 8 | #![allow(unused_attributes)] 9 | #![deny( 10 | elided_lifetimes_in_paths, 11 | missing_docs, 12 | missing_copy_implementations, 13 | missing_debug_implementations, 14 | unsafe_op_in_unsafe_fn, 15 | unused_must_use 16 | )] 17 | #![no_std] 18 | 19 | #[doc(hidden)] 20 | pub use ::core; 21 | 22 | pub use as_maybe_uninit::AsMaybeUninit; 23 | 24 | #[cfg(feature = "alloc")] 25 | #[doc(hidden)] 26 | /// Not part of the public API 27 | pub extern crate alloc; 28 | 29 | #[cfg(feature = "std")] 30 | #[doc(hidden)] 31 | /// Not part of the public API 32 | pub extern crate std; 33 | 34 | #[macro_use] 35 | mod utils; 36 | pub mod prelude { 37 | //! Reexports of pervasive items. 38 | #[doc(no_inline)] 39 | pub use crate::{ 40 | extension_traits::{AsOut, ManuallyDropMut}, 41 | out_ref::Out, 42 | uninit_array, 43 | }; 44 | cfg_alloc! { 45 | #[doc(no_inline)] 46 | pub use crate::extension_traits::{ 47 | BoxAssumeInit, 48 | BoxNewUninitSlice, 49 | BoxUninit, 50 | VecCapacity, 51 | }; 52 | } 53 | pub use ::core::mem::MaybeUninit; 54 | } 55 | 56 | use_prelude!(); 57 | 58 | mod as_maybe_uninit; 59 | pub mod extension_traits; 60 | #[cfg(feature = "std")] 61 | #[cfg_attr(feature = "nightly", doc(cfg(feature = "std")))] 62 | pub mod read; 63 | 64 | pub mod out_ref; 65 | 66 | /// Sets up an inline / stack-allocated array of 67 | /// [uninitialized][`MaybeUninit`] elements. 68 | /// 69 | /// # Example 70 | /// 71 | /// ```rust 72 | /// use ::uninit::{prelude::*, read::ReadIntoUninit}; 73 | /// 74 | /// let mut reader = &b"Hello, World!"[..]; 75 | /// let mut backing_array = uninit_array![u8; 4]; // : [MaybeUninit; 4] 76 | /// let buf = backing_array.as_out(); 77 | /// assert_eq!( 78 | /// reader.read_into_uninit_exact(buf).unwrap(), 79 | /// b"Hell", 80 | /// ); 81 | /// ``` 82 | #[macro_export] 83 | macro_rules! uninit_array { 84 | ( 85 | $T:ty ; $count:expr 86 | ) => {{ 87 | use $crate::core::mem::MaybeUninit; 88 | const __UNINIT_ARRAY_COUNT__: usize = $count; 89 | unsafe { 90 | // # Safety 91 | // 92 | // - `mem::uninitialized::<[MaybeUninit<_>; _]>()` is sound. 93 | MaybeUninit::<[MaybeUninit<$T>; __UNINIT_ARRAY_COUNT__]>::uninit().assume_init() 94 | } 95 | }}; 96 | } 97 | -------------------------------------------------------------------------------- /src/out_ref.rs: -------------------------------------------------------------------------------- 1 | //! `&out _` references in stable Rust! 2 | //! 3 | //! An [`Out<'a, T>`][Out] (`&out T`) is a _write-only reference_. 4 | //! 5 | //! Its name is inspired by [`out` parameters][out-csharp] from various languages. 6 | //! It functions like `&'a mut MaybeUninit`, except: 7 | //! 8 | //! - It can be safely constructed from a `&mut T`, since its API forbids writing `MaybeUninit::uninit()`. 9 | //! - To avoid accidental memory leaks, `T` must be either `Copy` or wrapped in `ManuallyDrop`. 10 | //! - It supports `Out<[T]>`, whereas `MaybeUninit<[T]>` is currently invalid 11 | //! and must be written as `[MaybeUninit]`. 12 | //! 13 | //! Much like `&mut MaybeUninit`, you can safely [`write`][crate::out_ref::Out::write] 14 | //! to an `Out` and get a `&mut T` back - also without running any drop glue. 15 | //! Since it's proven to be initialized, you can read and write through that reference 16 | //! without issue. 17 | //! 18 | //! ## Interior Mutability 19 | //! 20 | //! The whole design of `Out` references is to forbid any non-unsafe API 21 | //! that would allow writing `MaybeUninit::uninit()` garbage into the 22 | //! pointee. So, for instance, this crate does not offer any API like: 23 | //! 24 | //! ```rust 25 | //! use ::core::{cell::Cell, mem::MaybeUninit}; 26 | //! 27 | //! // /!\ This is UNSOUND when combined with the `::uninit` crate! 28 | //! fn swap_mb_uninit_and_cell ( 29 | //! p: &'_ MaybeUninit>, 30 | //! ) -> &'_ Cell> 31 | //! { 32 | //! unsafe { 33 | //! // Safety: both `Cell` and `MaybeUninit` are `#[repr(transparent)]` 34 | //! ::core::mem::transmute(p) 35 | //! } 36 | //! } 37 | //! ``` 38 | //! 39 | //! Indeed, if both such non-`unsafe` API and the `uninit` crate were 40 | //! present, then one could trigger UB with: 41 | //! 42 | //! ```rust,ignore 43 | //! let mut x = [Cell::new(42)]; 44 | //! let at_mb_uninit_cell: &'_ MaybeUninit> = 45 | //! &x.as_out().as_ref_uninit()[0] 46 | //! ; 47 | //! swap_mb_uninit_and_cell(at_mb_uninit_cell) 48 | //! .set(MaybeUninit::uninit()) // UB! 49 | //! ; 50 | //! ``` 51 | //! 52 | //! The author of the crate believes that such UB is the responsibility of 53 | //! the one who defined `swap_mb_uninit_and_cell`, and that in general that 54 | //! function is unsound: **`MaybeUninit`-ness and interior mutability do 55 | //! not commute!** 56 | //! 57 | //! - the `Safety` annotation in the given example only justifies that 58 | //! it is not breaking any layout-based validity invariants, 59 | //! but it is actually impossible to semantically prove that it is safe 60 | //! for these properties to commute. 61 | //! 62 | //! If you are strongly convinced of the opposite, please file an issue (if 63 | //! there isn't already one: since this question is not that clear the 64 | //! author is very likely to create an issue themself). 65 | //! 66 | //! [out-csharp]: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/method-parameters#out-parameter-modifier 67 | 68 | use crate::{ 69 | extension_traits::{AsOut, Transpose}, 70 | AsMaybeUninit, 71 | }; 72 | use ::core::{ 73 | mem::{self, ManuallyDrop, MaybeUninit}, 74 | slice, 75 | }; 76 | use core::{marker::PhantomData, ptr::NonNull}; 77 | 78 | /// A write-only reference to a maybe-uninitialized `T` 79 | /// 80 | /// See the [module][crate::out_ref] documentation for more details. 81 | /// 82 | /// This means that the reference may point to uninitialized memory (or not), 83 | /// and thus that writes to the pointee will not call the `.drop()` destructor. 84 | /// 85 | /// This type can be [trivially constructed][`crate::AsOut`] from: 86 | /// 87 | /// - a `&'out mut MaybeUninit` (main point of the type), 88 | /// 89 | /// - a `&'out mut T` (to keep the ergonomics of being able to overwrite an 90 | /// already initialized value). 91 | /// 92 | /// - To avoid "accidentally" leaking memory in this second case, 93 | /// either `T` must be `Copy` (sufficient condition to prove there is 94 | /// no drop glue), or you must first call 95 | /// [`.manually_drop_mut()`][`crate::ManuallyDropMut`] 96 | /// before the [`.as_out()`][`crate::AsOut`] "coercion". 97 | #[derive(Debug)] 98 | #[repr(transparent)] 99 | pub struct Out<'out, T: 'out + ?Sized>( 100 | /// Storing a raw pointer instead of `&'a mut T::Uninit` allows the `Out` 101 | /// struct to not have any trait bounds in its definition and many of its `impls`, 102 | /// while transparently providing access requiring `AsMaybeUninit` where needed. 103 | /// 104 | /// Safety invariants enforced locally by this module: 105 | /// 106 | /// - Garbage (`MaybeUninit::uninit`) must not be written through this pointer. 107 | /// - This has the same safety requirements as `&'a mut T::Uninit`: it must be aligned, 108 | /// non-aliasing, and mutably dereferencable for `'a`. 109 | NonNull, 110 | PhantomData<&'out mut T>, 111 | ); 112 | 113 | // SAFETY: 114 | // 115 | // `Send`/`Sync` safety is related to mutation, so in that regard there is no 116 | // difference between `Out<'_, T>` and `&'_ mut T` (in other words: 117 | // `MaybeUninit` plays no role in that regard). 118 | // 119 | // Thus `Out` is `{Send,Sync}` if and only if `&mut` is. 120 | unsafe impl<'out, T: ?Sized + 'out> Send for Out<'out, T> where &'out mut T: Send {} 121 | unsafe impl<'out, T: ?Sized + 'out> Sync for Out<'out, T> where &'out mut T: Sync {} 122 | 123 | impl<'out, T: 'out> From<&'out mut MaybeUninit> for Out<'out, T> { 124 | #[inline] 125 | fn from(p: &'out mut MaybeUninit) -> Out<'out, T> { 126 | Out(NonNull::from(p).cast(), PhantomData) 127 | } 128 | } 129 | 130 | impl<'out, T> From<&'out mut T> for Out<'out, T> 131 | where 132 | T: ?Sized + AsMaybeUninit + 'out, 133 | T::SizedPart: Copy, // prevent accidentally leaking memory 134 | { 135 | #[inline] 136 | fn from(p: &'out mut T) -> Out<'out, T> { 137 | // SAFETY: Uninit cannot be written into as an invariant of the module 138 | Out(NonNull::from(p), PhantomData) 139 | } 140 | } 141 | 142 | #[cfg(doc)] 143 | use crate::extension_traits::ManuallyDropMut; 144 | 145 | /// For non-`Copy` types, explicitly transmuting the `mut` reference into one 146 | /// that points to a `ManuallyDrop` is required, so as to express how likely it 147 | /// is that memory be leaked. This can be safely achieved by using the 148 | /// [`ManuallyDropMut`] helper. 149 | impl<'out, T> From<&'out mut ManuallyDrop> for Out<'out, T> 150 | where 151 | T: ?Sized + 'out, 152 | { 153 | #[inline] 154 | fn from(p: &'out mut ManuallyDrop) -> Out<'out, T> { 155 | // SAFETY: Uninit cannot be written into as an invariant of the module 156 | Out(NonNull::from(&mut **p), PhantomData) 157 | } 158 | } 159 | 160 | impl<'out, T: 'out> From<&'out mut [ManuallyDrop]> for Out<'out, [T]> { 161 | #[inline] 162 | fn from(slice: &'out mut [ManuallyDrop]) -> Out<'out, [T]> { 163 | // SAFETY: 164 | // - Uninit cannot be written into as an invariant of the module 165 | // - `[ManuallyDrop]` has the same layout as `[MaybeUninit]` 166 | // - References are always non-null. 167 | unsafe { 168 | Out( 169 | NonNull::new_unchecked(slice as *mut _ as *mut [T]), 170 | PhantomData, 171 | ) 172 | } 173 | } 174 | } 175 | 176 | impl<'out, T: 'out> From<&'out mut [MaybeUninit]> for Out<'out, [T]> { 177 | #[inline] 178 | fn from(slice: &'out mut [MaybeUninit]) -> Out<'out, [T]> { 179 | // SAFETY: 180 | // - References are always non-null 181 | unsafe { 182 | Out( 183 | NonNull::new_unchecked(slice as *mut _ as *mut [T]), 184 | PhantomData, 185 | ) 186 | } 187 | } 188 | } 189 | 190 | impl<'out, T: 'out, const N: usize> From> for Out<'out, [T]> { 191 | /// Converts from `&out [T; N]` to `&out [T]`. 192 | /// 193 | /// # Example 194 | /// ``` 195 | /// use uninit::out_ref::Out; 196 | /// 197 | /// let mut data = [1,2,3]; 198 | /// 199 | /// let mut x: Out<[i32; 3]> = Out::from(&mut data); 200 | /// let mut y: Out<[i32]> = x.into(); 201 | /// y.fill_with_iter(5..); 202 | /// 203 | /// assert_eq!(data, [5, 6, 7]); 204 | /// ``` 205 | #[inline] 206 | fn from(value: Out<'out, [T; N]>) -> Self { 207 | // SAFETY: immediate conversion to `Out` means uninit can't be written. 208 | let slice: &mut [MaybeUninit] = unsafe { value.as_mut_uninit().transpose() }; 209 | slice.into() 210 | } 211 | } 212 | 213 | impl<'out, T: 'out, const N: usize> TryFrom> for Out<'out, [T; N]> { 214 | type Error = core::array::TryFromSliceError; 215 | 216 | /// Tries to create a `&out [T; N]` from a `&out [T]`. 217 | /// 218 | /// Succeeds if the length of the `&out [_]` is equal to `N`. 219 | /// 220 | /// # Example 221 | /// ``` 222 | /// use uninit::prelude::Out; 223 | /// 224 | /// let mut data = [1, 2, 3]; 225 | /// let mut out_slice: Out<[i32]> = Out::from(&mut data).into(); 226 | /// 227 | /// assert!(Out::<[i32; 2]>::try_from(out_slice.r()).is_err()); 228 | /// assert!(Out::<[i32; 4]>::try_from(out_slice.r()).is_err()); 229 | /// let out_array: Out<[i32; 3]> = out_slice.try_into().unwrap(); 230 | /// out_array.write([4, 5, 6]); 231 | /// 232 | /// assert_eq!(data, [4, 5, 6]); 233 | /// ``` 234 | fn try_from(value: Out<'out, [T]>) -> Result { 235 | // SAFETY: immediate conversion to `Out` means uninit can't be written. 236 | let array: &mut [MaybeUninit; N] = unsafe { value.as_mut_uninit() }.try_into()?; 237 | Ok(array.transpose().into()) 238 | } 239 | } 240 | 241 | impl<'out, T: 'out + ?Sized> Out<'out, T> 242 | where 243 | T: AsMaybeUninit, 244 | { 245 | /// Construct an `&out _` from a raw pointer. 246 | /// 247 | /// # Safety 248 | /// - `raw` must be aligned, dereferencable, writeable, and non-aliasing for `'out` as `T` 249 | /// - `raw` does not need to point to an initialized `T` 250 | /// - It must be sound to write an initialized `T` without dropping 251 | pub unsafe fn from_raw(raw: *mut T) -> Self { 252 | // SAFETY: 253 | // - `raw` is non-null (because it is dereferencable) as promised by the caller. 254 | // - `raw` satisfies the invarianst for the field as promised by the caller. 255 | unsafe { Out(NonNull::new_unchecked(raw), PhantomData) } 256 | } 257 | 258 | /// Reborrows the `&out _` reference for a shorter lifetime. 259 | #[inline] 260 | pub fn reborrow<'reborrow>(self: &'reborrow mut Out<'out, T>) -> Out<'reborrow, T> 261 | where 262 | 'out: 'reborrow, 263 | { 264 | Out(self.0, PhantomData) 265 | } 266 | 267 | /// Shorthand for [`.reborrow()`][`Out::reborrow`]. 268 | #[inline] 269 | pub fn r<'reborrow>(self: &'reborrow mut Out<'out, T>) -> Out<'reborrow, T> 270 | where 271 | 'out: 'reborrow, 272 | { 273 | self.reborrow() 274 | } 275 | 276 | /// Returns a raw mutable pointer to the pointee. 277 | /// 278 | /// # Guarantees (that `unsafe` code may rely on) 279 | /// 280 | /// - The returned pointer does point to the pointee, meaning that if 281 | /// such returned pointer is used to [`.write()`][`::core::ptr::write`] 282 | /// to the pointee, then it is safe to `assume_init()` it. 283 | /// 284 | /// - The returned pointer is non null, well-aligned, and writeable. 285 | /// 286 | /// It is also technically readable: 287 | /// 288 | /// - you can read a `MaybeUninit` out of it after `.cast()`ing it, 289 | /// 290 | /// - otherwise, except when sound to `assume_init()`, the obtained 291 | /// pointer cannot be used to read the value `: T` of the pointee! 292 | #[inline] 293 | pub fn as_mut_ptr(self: &'_ mut Out<'out, T>) -> *mut T { 294 | self.0.as_ptr() 295 | } 296 | 297 | /// Upgrades the `&out _` (write-only) reference to a read-writeable 298 | /// `&mut _`. 299 | /// 300 | /// # Safety 301 | /// 302 | /// Don't be lured by the `&mut` reference: Rust validity invariants 303 | /// imply that an `&mut` reference is only sound to produce if it points 304 | /// to an initialized value; it is otherwise instant UB. See 305 | /// [`MaybeUninit::assume_init`] for more info about it. Thus: 306 | /// 307 | /// - The pointee must have been initialized. 308 | /// 309 | /// This is a **validity invariant**, meaning that UB does happen from just 310 | /// calling that function to produce an ill-formed reference, even if the 311 | /// obtained reference is "never actually used". 312 | /// 313 | /// ## Counterexample 314 | /// 315 | /// The following program exhibits Undefined Behavior: 316 | /// 317 | /// ```rust,no_run 318 | /// use ::uninit::prelude::*; 319 | /// 320 | /// let mut x = MaybeUninit::uninit(); 321 | /// let _unused: &mut u8 = unsafe { 322 | /// x .as_out() 323 | /// .assume_init() // UB! 324 | /// }; 325 | /// ``` 326 | #[inline] 327 | pub unsafe fn assume_init(mut self: Out<'out, T>) -> &'out mut T { 328 | // SAFETY: 329 | // - `.0` is dereferencable for `'out` as an invariant of the type. 330 | // - The caller has promised that the pointee is initialized. 331 | unsafe { &mut *self.as_mut_ptr() } 332 | } 333 | 334 | /// _Upgrades_ the `&out _` (write-valid-values-only) reference to a 335 | /// `&mut MaybeUninit<_>` (write-anything) reference. 336 | /// 337 | /// # Safety 338 | /// 339 | /// - The obtained reference cannot be used to write garbage 340 | /// (`MaybeUninit::uninit()`) into the pointee. 341 | /// 342 | /// This means that it can thus **not be fed to opaque APIs!!** 343 | /// 344 | /// - Exception: if the given `&out` reference has originated from a 345 | /// `&mut MaybeUninit<_>`, then calling `.as_mut_uninit()` is a sound 346 | /// way to make the trip back. 347 | /// 348 | /// This is a **safety invariant** (_i.e._, even if it is never "instant" 349 | /// UB to produce such a value, it does break the safety invariant of 350 | /// `&mut MaybeUninit<_>` (that of being allowed to write 351 | /// `MaybeUninit::uninit()` garbage into the pointee), so UB can happen 352 | /// afterwards). This is different than `.assume_init()` soundness relying 353 | /// on a validity invariant, meaning that UB does happen from just calling 354 | /// that function to produce an ill-formed reference, even if the obtained 355 | /// reference is never actually used. 356 | /// 357 | /// # Counter-example 358 | /// 359 | /// The following code is Undefined Behavior: 360 | /// 361 | /// ```rust,no_run 362 | /// use ::uninit::prelude::*; 363 | /// 364 | /// let mut my_box = Box::new(42); 365 | /// let at_my_box: Out<'_, Box> = 366 | /// my_box 367 | /// .manually_drop_mut() 368 | /// .as_out() 369 | /// ; 370 | /// // Overwrite `my_box` with uninitialized bytes / garbage content. 371 | /// unsafe { 372 | /// *at_my_box.as_mut_uninit() = MaybeUninit::uninit(); 373 | /// } 374 | /// // Runs the destructor for a `Box` using a garbage pointer that 375 | /// // may thus point anywhere in memory! 376 | /// drop(my_box) 377 | /// ``` 378 | /// 379 | /// A function from an external library must always be seen as opaque 380 | /// (unless its documentation makes implementation-detail guarantees, such 381 | /// as this very crate does), so one cannot rely on its implementation 382 | /// (unless the lib is open source AND you pin-point to that version of the 383 | /// crate, either through `version = "=x.y.z"` or through `git = ..., 384 | /// rev = ...` in `Cargo.toml`). 385 | /// 386 | /// ```rust,ignore 387 | /// // `fn zeroize (out: &'_ mut MaybeUninit) -> &'_ mut u8;` 388 | /// // The author of the crate says it uses that `out` reference to write 389 | /// // `0` to the pointee. 390 | /// use ::some_lib::zeroize; 391 | /// 392 | /// let mut x = 42; 393 | /// let at_x = x.as_out(); 394 | /// // Unsound! The lib implementation is free to write 395 | /// // `MaybeUninit::uninit()` garbage to the pointee! 396 | /// zeroize(unsafe { at_x.as_mut_uninit() }); 397 | /// ``` 398 | #[inline] 399 | pub unsafe fn as_mut_uninit(self: Out<'out, T>) -> &'out mut T::Uninit { 400 | // SAFETY: sound as guaranteed by struct invariants 401 | unsafe { T::raw_mut_as_uninit(self.0.as_ptr()) } 402 | } 403 | 404 | /// Downgrades the `Out<'_, T>` value into a `&MaybeUninit`. 405 | /// 406 | /// In practice, calling this function explicitly is rarely needed given 407 | /// that `Out<'_, [T]> : Deref]`, so one can do: 408 | /// 409 | /// ```rust 410 | /// use ::uninit::prelude::*; 411 | /// 412 | /// let mut backing_array = uninit_array![_; 42]; 413 | /// let buf: Out<'_, [u8]> = backing_array.as_out(); 414 | /// assert_eq!(buf.len(), 42); // no need to `r().as_ref_uninit()` 415 | /// ``` 416 | #[inline] 417 | pub fn as_ref_uninit(self: Out<'out, T>) -> &'out T::Uninit { 418 | // SAFETY: sound as guaranteed by struct invariants 419 | unsafe { T::raw_as_uninit(self.0.as_ptr()) } 420 | } 421 | 422 | #[cfg(feature = "zerocopy")] 423 | #[cfg_attr(feature = "nightly", doc(cfg(feature = "zerocopy")))] 424 | /// Accesses the bytes of an `&out T` as an `&out [u8]` 425 | /// 426 | /// This is safe due to the `T: FromBytes` bound: any data written 427 | /// to the output will not cause `T` to have invalid contents. 428 | /// 429 | /// # Guarantees 430 | /// 431 | /// The returned `Out` has the same address as the input, and its `len` is the size of the `T` value. 432 | /// Therefore, if you fully initialize all of the elements of the returned `Out<[u8]>`, 433 | /// it is sound to treat the `self` as initialized. 434 | /// 435 | /// # Example 436 | /// ``` 437 | /// use std::mem::MaybeUninit; 438 | /// use uninit::prelude::{AsOut, Out}; 439 | /// 440 | /// let mut data: MaybeUninit<[u32; 2]> = MaybeUninit::uninit(); 441 | /// let u32_out: Out<[u32]> = data.as_out(); 442 | /// let bytes_out = u32_out.as_bytes_out(); 443 | /// bytes_out.fill(1); 444 | /// 445 | /// // SAFETY: the full memory span in `data` has been initialized 446 | /// assert_eq!(unsafe { data.assume_init() }, [0x01010101, 0x01010101]); 447 | /// ``` 448 | #[inline] 449 | pub fn as_bytes_out(mut self: Out<'out, T>) -> Out<'out, [u8]> 450 | where 451 | T: zerocopy::FromBytes, 452 | { 453 | let size = mem::size_of_val(self.r().as_ref_uninit()); 454 | let p: *mut u8 = self.as_mut_ptr().cast(); 455 | 456 | unsafe { 457 | // SAFETY: 458 | Out::slice_from_raw_parts(p, size) 459 | } 460 | } 461 | } 462 | 463 | impl<'out, T: 'out> Out<'out, T> { 464 | /// Write a `value` into the pointee, returning an `.assume_init()`-ed 465 | /// reference to it. 466 | /// 467 | /// This overwrites any previous value without dropping it, 468 | /// so be careful not to use this twice unless you want to skip running the destructor. 469 | /// This also returns a mutable reference to the (now safely initialized) contents of self. 470 | /// The return value behaves like any other mutable reference would, 471 | /// so assigning a new value to it will drop the old content. 472 | /// 473 | /// # Guarantees (that `unsafe` code may rely on) 474 | /// 475 | /// After the function returns, the pointee is guaranteed to have been 476 | /// initialized; it is thus sound to use that property to manually 477 | /// `assume_init()` it or any chunk of such items. 478 | /// 479 | /// # Examples 480 | /// 481 | /// Correct usage of this method: 482 | /// 483 | /// ``` 484 | /// use uninit::prelude::{AsOut, Out}; 485 | /// use std::mem::MaybeUninit; 486 | /// let mut storage = MaybeUninit::>::uninit(); 487 | /// 488 | /// let mut out_ref: Out> = storage.as_out(); 489 | /// { 490 | /// let hello = out_ref.write((&b"Hello, world!").to_vec()); 491 | /// // Setting hello does not leak prior allocations, but drops them 492 | /// *hello = (&b"Hello").to_vec(); 493 | /// hello[0] = 'h' as u8; 494 | /// } 495 | /// // x is initialized now: 496 | /// let s = unsafe { storage.assume_init() }; 497 | /// assert_eq!(b"hello", s.as_slice()); 498 | /// ``` 499 | /// 500 | /// This usage of the method causes a leak: 501 | /// 502 | /// ``` 503 | /// use uninit::prelude::{AsOut, Out}; 504 | /// use std::mem::MaybeUninit; 505 | /// let mut storage = MaybeUninit::::uninit(); 506 | /// let mut out_ref: Out = storage.as_out(); 507 | /// 508 | /// // reborrow to call multiple mutating methods 509 | /// out_ref.r().write("Hello".to_string()); 510 | /// // This leaks the contained string: 511 | /// out_ref.write("hello".to_string()); 512 | /// // storage is initialized now: 513 | /// assert_eq!(&unsafe { storage.assume_init() }, "hello"); 514 | /// ``` 515 | #[inline] 516 | pub fn write(self: Out<'out, T>, value: T) -> &'out mut T { 517 | unsafe { 518 | // SAFETY: 519 | // - The validity of `self.0` is an invariant of the type 520 | // - This writes an initialized value to the pointee 521 | self.0.as_ptr().write(value); 522 | self.assume_init() 523 | } 524 | } 525 | 526 | /// Similar to [`.write()`][`Out::write`], but getting the previous value 527 | /// back. Such previous value may or may not be initialized. 528 | /// 529 | /// # Guarantees (that `unsafe` code may rely on) 530 | /// 531 | /// - After the function returns, the pointee is guaranteed to have been 532 | /// initialized; it is thus sound to use that property to manually 533 | /// `assume_init()` it or any chunk of such items. 534 | /// 535 | /// - there is **no such guarantee** regarding the previous value, which 536 | /// is thus only sound to `assume_init()` if the pointee already was 537 | /// (before the call to `.replace()`). 538 | #[inline] 539 | pub fn replace(mut self: Out<'out, T>, value: T) -> (MaybeUninit, &'out mut T) { 540 | unsafe { 541 | // # Safety 542 | // 543 | // - This: 544 | // 545 | // 1. writes a valid value to the pointee, 546 | // 547 | // 2. extracts the previous value as a now owned `MaybeUninit` 548 | // 549 | // Thus it does not not `assume_init()` the pointee nor write 550 | // garbage to it. 551 | // 552 | // - Thanks to write the pointee is known to be initialized. 553 | ( 554 | mem::replace(self.r().as_mut_uninit(), MaybeUninit::new(value)), 555 | self.assume_init(), 556 | ) 557 | } 558 | } 559 | } 560 | 561 | /// This can be useful to get a `Out<'long ...>` out of a 562 | /// `&'short mut Out<'long ...>` by [`mem::replace`]-ing with a `Out::default()` 563 | /// (_e.g._, to implement an [`Iterator`]). 564 | impl<'out, T: 'out> Default for Out<'out, [T]> { 565 | #[inline] 566 | fn default() -> Self { 567 | <&mut [MaybeUninit]>::into(&mut []) 568 | } 569 | } 570 | 571 | impl<'out, T: 'out> Out<'out, [T]> { 572 | /// Converts a single item out reference into a `1`-long out slice. 573 | /// 574 | /// This is the `&out` version of 575 | /// [`slice::from_ref`] and [`slice::from_mut`]. 576 | #[inline] 577 | pub fn from_out(out: Out<'out, T>) -> Out<'out, [T]> { 578 | unsafe { slice::from_mut(out.as_mut_uninit()).as_out() } 579 | } 580 | 581 | /// Main indexing operation on an `&out [_]`. 582 | /// 583 | /// The type `Index` of `idx` may be: 584 | /// 585 | /// - a `usize`, and then `Index::Output` is a `Out` reference to a 586 | /// single element. 587 | /// 588 | /// - a `Range` (_e.g._, `a .. b`), and then `Index::Output` is 589 | /// a `Out<[T]>` reference to a subslice. 590 | /// 591 | /// # Example 592 | /// 593 | /// ```rust 594 | /// use ::uninit::prelude::*; 595 | /// 596 | /// let src: &[u8] = b"Hello, World!"; 597 | /// // Stack-allocate an uninitialized buffer. 598 | /// let mut buf = uninit_array![u8; 256]; 599 | /// // copy `src` into this stack allocated buffer, effectively initializing it. 600 | /// let buf: &mut [u8] = 601 | /// // buf[.. src.len()].as_out() 602 | /// buf.as_out().get_out(.. src.len()).unwrap() 603 | /// .copy_from_slice(src) 604 | /// ; 605 | /// assert_eq!(buf, b"Hello, World!"); 606 | /// buf[7 ..].copy_from_slice(b"Earth!"); 607 | /// assert_eq!(buf, b"Hello, Earth!"); 608 | /// ``` 609 | #[inline] 610 | pub fn get_out(self: Out<'out, [T]>, idx: Index) -> Option 611 | where 612 | Index: UsizeOrRange<'out, T>, // renamed for the documentation 613 | { 614 | macro_rules! impl_SliceIndex {( 615 | $($Range:ty),+ $(,)? 616 | ) => ( 617 | $( 618 | impl<'out, T : 'out> SliceIndex<'out, T> for $Range { 619 | type Output = Out<'out, [T]>; 620 | 621 | #[inline] 622 | fn idx (self: Self, slice: Out<'out, [T]>) 623 | -> Option> 624 | { 625 | unsafe { 626 | // Safety: this goes through an ephemeral 627 | // `&mut [MaybeUninit<_>]` reference to be able to 628 | // use slice indexing, but immediately downgrades 629 | // it back to an `Out` reference, so no danger 630 | // of writing garbage data. 631 | slice.as_mut_uninit() 632 | .get_mut(self) 633 | .map(Out::from) 634 | } 635 | } 636 | } 637 | )* 638 | )} 639 | impl<'out, T: 'out> SliceIndex<'out, T> for usize { 640 | type Output = Out<'out, T>; 641 | 642 | #[inline] 643 | fn idx(self: usize, slice: Out<'out, [T]>) -> Option> { 644 | unsafe { 645 | // Safety: ditto 646 | slice.as_mut_uninit().get_mut(self).map(Out::from) 647 | } 648 | } 649 | } 650 | impl_SliceIndex! { 651 | // a .. b 652 | ::core::ops::Range, 653 | // a ..= b 654 | ::core::ops::RangeInclusive, 655 | // a .. 656 | ::core::ops::RangeFrom, 657 | // .. b 658 | ::core::ops::RangeTo, 659 | // ..= b 660 | ::core::ops::RangeToInclusive, 661 | // .. 662 | ::core::ops::RangeFull, 663 | } 664 | 665 | idx.idx(self) 666 | } 667 | 668 | /// Same as `.get_out()`, but with the bound check being elided. 669 | /// 670 | /// # Safety 671 | /// 672 | /// The given `idx` mut be in bounds: 673 | /// 674 | /// - if `idx: usize`, then `idx` must be `< self.len()`. 675 | /// 676 | /// - if `idx` is an upper-bounded range (_e.g._, `.. b`, `a ..= b`), 677 | /// then the upper bound (`b` in the example) must be `< self.len()`. 678 | /// 679 | /// - _etc_. 680 | /// 681 | /// See [`.get_unchecked_mut()`]( 682 | /// https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked_mut) 683 | /// for more info about the safety of such call. 684 | #[inline] 685 | pub unsafe fn get_unchecked_out(self: Out<'out, [T]>, idx: Index) -> Index::Output 686 | where 687 | Index: UsizeOrRange<'out, T>, // renamed for the documentation 688 | { 689 | self.get_out(idx).unwrap_or_else(|| { 690 | if cfg!(debug_assertions) { 691 | panic!(concat!( 692 | "Attempted to index out of bounds through unchecked ", 693 | "indexing (this was detected thanks to a check still ", 694 | "being present in debug mode).\n", 695 | r"/!\ THIS IS A BUG AND A SOUNDNESS ISSUE /!\", 696 | "\n", 697 | "Please submit an issue ASAP.", 698 | )); 699 | } else { 700 | // SAFETY: unreachable as promised by the caller 701 | unsafe { ::core::hint::unreachable_unchecked() } 702 | } 703 | }) 704 | } 705 | 706 | /// Initialize the buffer with a copy from another (already initialized) 707 | /// buffer. 708 | /// 709 | /// It returns a read-writable slice to the initialized bytes for 710 | /// convenience (automatically 711 | /// [`assume_init`][`Out::assume_init`]-ed). 712 | /// 713 | /// # Panic 714 | /// 715 | /// The function panics if the slices' lengths are not equal. 716 | /// 717 | /// # Guarantees (that `unsafe` code may rely on) 718 | /// 719 | /// A non-`panic!`king return from this function **guarantees that the input 720 | /// slice has been (successfully) initialized**, and that it is thus then 721 | /// sound to `.assume_init()`. 722 | /// 723 | /// It also guarantees that the returned slice does correspond to the input 724 | /// slice (_e.g._, for [`crate::ReadIntoUninit`]'s safety guarantees). 725 | /// 726 | /// # Example 727 | /// 728 | /// ```rust 729 | /// # use ::core::mem::{self, MaybeUninit}; 730 | /// use ::uninit::prelude::*; 731 | /// 732 | /// let mut array = uninit_array![_; 13]; 733 | /// assert_eq!( 734 | /// array.as_out().copy_from_slice(b"Hello, World!"), 735 | /// b"Hello, World!", 736 | /// ); 737 | /// // we can thus soundly `assume_init` our array: 738 | /// let array = unsafe { 739 | /// mem::transmute::< 740 | /// [MaybeUninit; 13], 741 | /// [ u8 ; 13], 742 | /// >(array) 743 | /// }; 744 | /// assert_eq!( 745 | /// array, 746 | /// *b"Hello, World!", 747 | /// ); 748 | /// ``` 749 | pub fn copy_from_slice(mut self: Out<'out, [T]>, source_slice: &'_ [T]) -> &'out mut [T] 750 | where 751 | T: Copy, 752 | { 753 | unsafe { 754 | // # Safety 755 | // 756 | // - Writing to `self.0` is fine since `source_slice` only 757 | // contains initialized elements. 758 | // 759 | // - the `copy_nonoverlapping()` call guarantees that the buffer 760 | // has been initialized. 761 | self.r() 762 | .as_mut_uninit() 763 | .copy_from_slice(source_slice.as_ref_uninit()); 764 | self.assume_init() 765 | } 766 | } 767 | 768 | /// Fills `self` with elements by cloning `value`. 769 | /// 770 | /// The fully initialized slice is returned for your convenience. 771 | /// 772 | /// # Guarantees (that `unsafe` code may rely on) 773 | /// 774 | /// After this function returns without a panic, 775 | /// all elements that `self` points to are initialized. 776 | /// 777 | /// # Example 778 | /// ``` 779 | /// use std::mem::MaybeUninit; 780 | /// use uninit::prelude::{AsOut, Out}; 781 | /// 782 | /// let mut data: MaybeUninit<[u8; 4]> = MaybeUninit::uninit(); 783 | /// let mut out: Out<[u8]> = data.as_out(); 784 | /// 785 | /// assert_eq!(out.fill(2), &[2, 2, 2, 2]); 786 | /// 787 | /// // SAFETY: the array has been fully initialized 788 | /// let _ = unsafe { data.assume_init() }; 789 | /// ``` 790 | #[inline] 791 | pub fn fill(self, value: T) -> &'out mut [T] 792 | where 793 | T: Clone, 794 | { 795 | self.fill_with(move || value.clone()) 796 | } 797 | 798 | /// Fills `self` with elements returned by calling a closure repeatedly. 799 | /// 800 | /// The fully initialized slice is returned for your convenience. 801 | /// 802 | /// This method uses a closure to create new values in order. 803 | /// If you’d rather `Clone` a given value, use [`Out::fill`]. 804 | /// If you want to use the `Default` trait to generate values, you can pass `Default::default` as the argument. 805 | /// 806 | /// # Guarantees (that `unsafe` code may rely on) 807 | /// 808 | /// After this function returns without a panic, 809 | /// all elements that `self` points to are initialized. 810 | /// 811 | /// # Example 812 | /// 813 | /// ``` 814 | /// use std::mem::MaybeUninit; 815 | /// use uninit::prelude::{AsOut, Out}; 816 | /// 817 | /// let mut data: MaybeUninit<[u32; 20]> = MaybeUninit::uninit(); 818 | /// let mut out: Out<[u32]> = data.as_out(); 819 | /// 820 | /// let mut a = 0; 821 | /// let mut b = 1; 822 | /// let fib = out.fill_with(move || { 823 | /// let o = a; 824 | /// let c = a + b; 825 | /// a = b; 826 | /// b = c; 827 | /// o 828 | /// }); 829 | /// 830 | /// assert_eq!(fib, &[ 831 | /// 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 832 | /// 55, 89, 144, 233, 377, 610, 987, 833 | /// 1597, 2584, 4181 834 | /// ]); 835 | /// 836 | /// // SAFETY: the array has been fully initialized 837 | /// let _ = unsafe { data.assume_init() }; 838 | /// ``` 839 | #[inline] 840 | pub fn fill_with(mut self, mut f: impl FnMut() -> T) -> &'out mut [T] { 841 | for out in self.iter_out() { 842 | out.write(f()); 843 | } 844 | unsafe { 845 | // SAFETY: the entire slice has been iterated over and initialized 846 | self.assume_init() 847 | } 848 | } 849 | 850 | /// Fills the buffer with values from up to the first `self.len()` 851 | /// elements of an `iterable`. 852 | /// 853 | /// The elements of the slice that have been initialized is returned. 854 | /// Unlike `fill` and `fill_with`, this method does not have to 855 | /// fully initalize the slice. 856 | /// 857 | /// # Guarantees (that `unsafe` code may rely on) 858 | /// 859 | /// A non-panicking return from this function guarantees that the first `k` 860 | /// values of the buffer have been initialized and are thus sound to 861 | /// `.assume_init()`, where `k`, the numbers of elements that `iterable` 862 | /// has yielded (capped at `self.len()`), is the length of the returned 863 | /// buffer. 864 | /// 865 | /// # Example 866 | /// 867 | /// ``` 868 | /// use std::mem::MaybeUninit; 869 | /// use uninit::out_ref::Out; 870 | /// use uninit::extension_traits::{AsOut, Transpose}; 871 | /// 872 | /// let mut data: MaybeUninit<[u32; 16]> = MaybeUninit::uninit(); 873 | /// let mut out: Out<[u32]> = data.as_out(); 874 | /// 875 | /// assert_eq!(out.fill_with_iter(2..10), &[2, 3, 4, 5, 6, 7, 8, 9]); 876 | /// 877 | /// // SAFETY: the first 8 array elements have been fully initialized 878 | /// // We welcome suggestions for improving the ergonomics of the below. 879 | /// let initialized_part: &[u32; 8] = unsafe { 880 | /// <&[MaybeUninit; 8]>::try_from( 881 | /// data.transpose_ref().get(..8).unwrap() 882 | /// ).unwrap().transpose().assume_init_ref() 883 | /// }; 884 | /// assert_eq!(initialized_part, &[2, 3, 4, 5, 6, 7, 8, 9]); 885 | /// 886 | /// let mut out: Out<[u32]> = data.as_out(); 887 | /// assert_eq!(out.fill_with_iter(1..), &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); 888 | /// ``` 889 | #[inline] 890 | pub fn fill_with_iter( 891 | mut self: Out<'out, [T]>, 892 | iterable: impl IntoIterator, 893 | ) -> &'out mut [T] { 894 | let mut iter = iterable.into_iter(); 895 | let mut n = 0; 896 | // Avoids significant iterator combinators due to code size concerns. 897 | for out in self.iter_out() { 898 | if let Some(val) = iter.next() { 899 | out.write(val); 900 | n += 1; 901 | } else { 902 | break; 903 | } 904 | } 905 | unsafe { 906 | // SAFETY: `n` values of the buffer have been initialized 907 | self.get_unchecked_out(..n).assume_init() 908 | } 909 | } 910 | 911 | /// Fills the buffer with values from up to the first `self.len()` 912 | /// elements of an `iterable`. 913 | /// 914 | /// # Guarantees (that `unsafe` code may rely on) 915 | /// 916 | /// A non-panicking return from this function guarantees that the first `k` 917 | /// values of the buffer have been initialized and are thus sound to 918 | /// `.assume_init()`, where `k`, the numbers of elements that `iterable` 919 | /// has yielded (capped at `self.len()`), is the length of the returned 920 | /// buffer. 921 | #[inline] 922 | #[deprecated = "use `fill_with_iter` instead"] 923 | pub fn init_with(self: Out<'out, [T]>, iterable: impl IntoIterator) -> &'out mut [T] { 924 | self.fill_with_iter(iterable) 925 | } 926 | 927 | /// `.reborrow().into_iter()` 928 | #[inline] 929 | pub fn iter_out<'reborrow>(self: &'reborrow mut Out<'out, [T]>) -> iter::IterOut<'reborrow, T> { 930 | self.into_iter() 931 | } 932 | 933 | /// Same as [`.split_at_mut()`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at_mut 934 | /// ), but with `&out [_]` references. 935 | /// 936 | /// # Panic 937 | /// 938 | /// Panics if `idx > len`. 939 | #[inline] 940 | pub fn split_at_out(self: Out<'out, [T]>, idx: usize) -> (Out<'out, [T]>, Out<'out, [T]>) { 941 | let (left, right) = unsafe { self.as_mut_uninit() }.split_at_mut(idx); 942 | (left.as_out(), right.as_out()) 943 | } 944 | 945 | /// Constructs an `&out [T]` from a `*mut T` and length. 946 | /// 947 | /// # Safety 948 | /// - `data` must be [valid] for both reads and writes for `len * mem::size_of::()` many bytes, 949 | /// and it must be properly aligned. 950 | /// - The memory referenced by the returned `Out` must not be accessed through any other pointer 951 | /// (not derived from the return value) for the duration of lifetime `'out`. 952 | /// Both read and write accesses are forbidden. 953 | /// - It must be valid to write aligned elements of `T` into `data`. 954 | /// - The total size `len * mem::size_of::()` of the slice must be no larger than `isize::MAX`, 955 | /// and adding that size to `data` must not "wrap around" the address space. 956 | /// See the safety documentation of [`<*mut T>::offset`]. 957 | /// 958 | /// [valid]: core::ptr#safety 959 | /// [`NonNull::dangling()`]: core::ptr::NonNull::dangling 960 | /// [`<*mut T>::offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset 961 | /// 962 | /// # Example 963 | /// 964 | /// ``` 965 | /// use uninit::out_ref::Out; 966 | /// 967 | /// // Writes the values 0,1,2,...,len-1 to `data` 968 | /// #[no_mangle] 969 | /// pub unsafe extern "C" fn write_increasing(data: *mut u8, len: usize) { 970 | /// Out::slice_from_raw_parts(data, len).fill_with_iter(0..); 971 | /// } 972 | /// ``` 973 | pub unsafe fn slice_from_raw_parts(data: *mut T, len: usize) -> Out<'out, [T]> { 974 | // SAFETY: 975 | // - `data` is mutably dereferencable for `len` elements as promised by the caller. 976 | // - `MaybeUninit` has the same layout as `T`. 977 | // - The elements can be overwritten with any valid `T` as promised by the caller. 978 | let mu_slice: &mut [MaybeUninit] = 979 | unsafe { slice::from_raw_parts_mut(data.cast(), len) }; 980 | mu_slice.into() 981 | } 982 | 983 | /// Constructs an `&out [T]` with a zero length. 984 | /// 985 | /// Like the expression `&mut []`, the returned value may point 986 | /// to dangling memory that is aligned for `T`. 987 | /// 988 | /// # Example 989 | /// 990 | /// ``` 991 | /// use uninit::out_ref::Out; 992 | /// let x: Out<[u32]> = Out::empty(); 993 | /// assert!(x.is_empty()); 994 | /// ``` 995 | pub fn empty() -> Out<'static, [T]> { 996 | let data: &mut [ManuallyDrop] = &mut []; 997 | data.into() 998 | } 999 | } 1000 | 1001 | impl<'out, T: 'out, const N: usize> Out<'out, [T; N]> { 1002 | /// Returns true if this `&out [T; N]` is empty. 1003 | pub fn is_empty(&self) -> bool { 1004 | N == 0 1005 | } 1006 | 1007 | /// Returns the number of elements in the array. 1008 | pub fn len(&self) -> usize { 1009 | N 1010 | } 1011 | 1012 | /// Converts from `Out<[T; N]>` to `Out<[T]>` with a dynamic length. 1013 | /// 1014 | /// At the moment, more functionality is available for `Out<[T; N]>` 1015 | /// which `Out<[T; N]>` doesn't implicitly have access to. 1016 | /// 1017 | /// # Example 1018 | /// 1019 | /// ``` 1020 | /// use std::mem::MaybeUninit; 1021 | /// use uninit::out_ref::Out; 1022 | /// 1023 | /// let mut data: MaybeUninit<[i32; 3]> = MaybeUninit::uninit(); 1024 | /// let mut out = Out::from(&mut data); 1025 | /// // `r[eborrow]()` so `out` isn't consumed. 1026 | /// assert_eq!(out.r().as_slice_out().fill_with_iter(1..), &[1, 2, 3]); 1027 | /// assert_eq!(out.as_slice_out().fill_with_iter(10..), &[10, 11, 12]); 1028 | /// // SAFETY: fully initialized 1029 | /// assert_eq!(unsafe { data.assume_init() }, [10, 11, 12]); 1030 | /// ``` 1031 | pub fn as_slice_out(self) -> Out<'out, [T]> { 1032 | self.into() 1033 | } 1034 | } 1035 | 1036 | /// `Deref` into `[MaybeUninit]` to get access to the slice length related 1037 | /// getters. 1038 | impl<'out, T: 'out> ::core::ops::Deref for Out<'out, [T]> { 1039 | type Target = [MaybeUninit]; 1040 | 1041 | #[inline] 1042 | fn deref(&self) -> &[MaybeUninit] { 1043 | // SAFETY: 1044 | // - Sound as guaranteed by the invariants of the type. 1045 | // - `[T]` has the same layout as `[MaybeUninit]`. 1046 | unsafe { &*(self.0.as_ptr() as *const [MaybeUninit]) } 1047 | } 1048 | } 1049 | 1050 | use private::{SliceIndex, SliceIndex as UsizeOrRange}; 1051 | mod private { 1052 | use super::*; 1053 | 1054 | pub trait SliceIndex<'out, T> { 1055 | type Output: 'out; 1056 | 1057 | fn idx(self: Self, slice: Out<'out, [T]>) -> Option; 1058 | } 1059 | } 1060 | 1061 | /// `&out [_]` slice iteration logic. 1062 | pub mod iter { 1063 | use super::*; 1064 | 1065 | /// The value obtained when calling `.into_iter()` on a `Out<'out, [T]>`. 1066 | /// 1067 | /// An iterator over single value `Out<'out, T>` references. 1068 | #[allow(missing_debug_implementations)] 1069 | pub struct IterOut<'out, T: 'out> { 1070 | slice: Out<'out, [T]>, 1071 | } 1072 | 1073 | impl<'out, T: 'out> IterOut<'out, T> { 1074 | /// Extracts an `Out<[T]>` slice reference pointing to the elements not 1075 | /// yet yielded by the iterator. 1076 | #[inline] 1077 | pub fn remaining(self: IterOut<'out, T>) -> Out<'out, [T]> { 1078 | self.slice 1079 | } 1080 | } 1081 | 1082 | impl<'out, T: 'out> IntoIterator for Out<'out, [T]> { 1083 | type Item = Out<'out, T>; 1084 | type IntoIter = IterOut<'out, T>; 1085 | 1086 | fn into_iter(self: Out<'out, [T]>) -> IterOut<'out, T> { 1087 | IterOut { slice: self } 1088 | } 1089 | } 1090 | 1091 | impl<'out, 'inner: 'out, T: 'inner> IntoIterator for &'out mut Out<'inner, [T]> { 1092 | type Item = Out<'out, T>; 1093 | type IntoIter = IterOut<'out, T>; 1094 | 1095 | #[inline] 1096 | fn into_iter(self: &'out mut Out<'inner, [T]>) -> IterOut<'out, T> { 1097 | self.reborrow().into_iter() 1098 | } 1099 | } 1100 | 1101 | impl<'out, T: 'out> Iterator for IterOut<'out, T> { 1102 | type Item = Out<'out, T>; 1103 | 1104 | #[inline] 1105 | fn next(self: &'_ mut IterOut<'out, T>) -> Option> { 1106 | if self.slice.is_empty() { 1107 | return None; 1108 | } 1109 | let slice = mem::replace(&mut self.slice, Out::default()); 1110 | let (first, rest) = slice.split_at_out(1); 1111 | self.slice = rest; 1112 | Some(unsafe { first.get_unchecked_out(0) }) 1113 | } 1114 | } 1115 | } 1116 | -------------------------------------------------------------------------------- /src/read/impls.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[cfg(feature = "specialization")] 4 | #[doc(cfg(feature = "specialization"))] 5 | default unsafe impl ReadIntoUninit for R { 6 | #[inline] 7 | default fn read_into_uninit<'buf>( 8 | self: &'_ mut Self, 9 | buf: Out<'buf, [u8]>, 10 | ) -> io::Result<&'buf mut [u8]> { 11 | let buf = buf.fill_with_iter(::core::iter::repeat(0)); 12 | self.read(buf).map(move |n| &mut buf[..n]) 13 | } 14 | 15 | #[inline] 16 | default fn read_into_uninit_exact<'buf>( 17 | self: &'_ mut Self, 18 | buf: Out<'buf, [u8]>, 19 | ) -> io::Result<&'buf mut [u8]> { 20 | let buf = buf.fill_with_iter(::core::iter::repeat(0)); 21 | self.read_exact(buf).map(|()| buf) 22 | } 23 | } 24 | 25 | // # Safety: 26 | // 27 | // - basic delegation 28 | // 29 | // - `read_into_uninit_exact` is not overriden 30 | unsafe impl ReadIntoUninit for &'_ mut R { 31 | #[inline] 32 | fn read_into_uninit<'buf>( 33 | self: &'_ mut Self, 34 | buf: Out<'buf, [u8]>, 35 | ) -> io::Result<&'buf mut [u8]> { 36 | (**self).read_into_uninit(buf) 37 | } 38 | } 39 | 40 | // # Safety 41 | // 42 | // - `read_into_uninit` does return a prefix slice on success; 43 | // 44 | // - `read_into_uninit_exact` is not overriden 45 | unsafe impl ReadIntoUninit for &'_ [u8] { 46 | #[inline] 47 | fn read_into_uninit<'buf>( 48 | self: &'_ mut Self, 49 | buf: Out<'buf, [u8]>, 50 | ) -> io::Result<&'buf mut [u8]> { 51 | let count = ::std::cmp::min(buf.len(), self.len()); 52 | let (to_copy, remaining) = self.split_at(count); 53 | *self = remaining; 54 | 55 | // Taken from stdlib: 56 | // "First check if the amount of bytes we want to read is small: 57 | // `copy_from_slice` will generally expand to a call to `memcpy`, and 58 | // for a single byte the overhead is significant." 59 | if count == 1 { 60 | Ok(slice::from_mut(buf.get_out(0).unwrap().write(to_copy[0]))) 61 | } else { 62 | Ok(buf.get_out(..count).unwrap().copy_from_slice(to_copy)) 63 | } 64 | } 65 | } 66 | 67 | macro_rules! impl_ReadIntoUninit_for_impl_BufRead {( 68 | $( 69 | for [$($generics:tt)*] 70 | $T:ty 71 | $(where { 72 | $($wc:tt)* 73 | })? ; 74 | )* 75 | ) => ( 76 | $( 77 | // # Safety: 78 | // 79 | // - delegates to `<&'_ [u8] as ReadIntoUninit>::read_into_uninit` 80 | // 81 | // - `read_into_uninit_exact` is not overriden 82 | unsafe 83 | impl<$($generics)*> ReadIntoUninit 84 | for $T 85 | $(where 86 | $($wc)* 87 | )? 88 | { 89 | #[inline] 90 | fn read_into_uninit<'buf> ( 91 | self: &'_ mut Self, 92 | buf: Out<'buf, [u8]>, 93 | ) -> io::Result<&'buf mut [u8]> 94 | { 95 | let buf = { 96 | let mut read_buf: &[u8] = io::BufRead::fill_buf(self)?; 97 | read_buf.read_into_uninit(buf)? 98 | }; 99 | io::BufRead::consume(self, buf.len()); 100 | Ok(buf) 101 | } 102 | 103 | } 104 | )* 105 | )} 106 | 107 | impl_ReadIntoUninit_for_impl_BufRead! { 108 | for [R : io::Read] 109 | io::BufReader 110 | ; 111 | for [T : AsRef<[u8]>] 112 | io::Cursor 113 | ; 114 | for [] 115 | io::Empty 116 | ; 117 | for [] 118 | io::StdinLock<'_> 119 | ; 120 | for [T : io::BufRead] 121 | io::Take 122 | ; 123 | } 124 | 125 | // # Safety: 126 | // 127 | // - basic delegation 128 | // 129 | // - `read_into_uninit_exact` is not overriden 130 | unsafe impl ReadIntoUninit for Box { 131 | #[inline] 132 | fn read_into_uninit<'buf>( 133 | self: &'_ mut Self, 134 | buf: Out<'buf, [u8]>, 135 | ) -> io::Result<&'buf mut [u8]> { 136 | (**self).read_into_uninit(buf) 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/read/mod.rs: -------------------------------------------------------------------------------- 1 | //! Read into uninitialized bytes logic. 2 | 3 | use_prelude!(); 4 | 5 | use ::std::io::Read; 6 | 7 | /// Trait for a [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html)able 8 | /// type that can output the bytes read into 9 | /// [uninitialised memory][`MaybeUninit`]. 10 | /// 11 | /// # Safety (to implement) / Guarantees (for users of `impl ReadIntoUninit` types) 12 | /// 13 | /// The trait is `unsafe` (to implement) because it **needs to guarantee** to 14 | /// users of generic `R : ReadIntoUninit` code (that may use `unsafe` code 15 | /// relying on it!) that: 16 | /// 17 | /// - `if let Ok(init_buf) = self.read_into_uninit(buf)`, then it must be 18 | /// sound to: 19 | /// 20 | /// ```rust 21 | /// # macro_rules! ignore {($($t:tt)*) => ()} ignore! { 22 | /// unsafe { 23 | /// buf.get_out_unchecked(.. init_buf.len()).assume_init() 24 | /// } 25 | /// # } 26 | /// ``` 27 | /// 28 | /// - `if self.read_into_uninit_exact(buf).is_ok()`, then it must be 29 | /// sound to: `buf.assume_init()`. 30 | /// 31 | /// # Counterexample 32 | /// 33 | /// ```rust,no_run 34 | /// #![feature(specialization)] 35 | /// use ::uninit::{prelude::*, 36 | /// read::{auto_impl, ReadIntoUninit}, 37 | /// }; 38 | /// 39 | /// pub 40 | /// struct Evil; 41 | /// 42 | /// auto_impl! { #[derived_from(ReadIntoUninit)] impl Read for Evil } 43 | /// unsafe // unsound! 44 | /// impl ReadIntoUninit for Evil { 45 | /// fn read_into_uninit<'buf> ( 46 | /// self: &'_ mut Self, 47 | /// buf: Out<'buf, [u8]>, 48 | /// ) -> ::std::io::Result<&'buf mut [u8]> 49 | /// { 50 | /// Ok(Box::leak(vec![0; buf.len()].into_boxed_slice())) 51 | /// } 52 | /// } 53 | /// ``` 54 | /// 55 | /// Indeed, with such an impl, the following function could cause UB, when 56 | /// instanced with `R = Evil`: 57 | /// 58 | /// ```rust 59 | /// use ::uninit::{prelude::*, read::ReadIntoUninit}; 60 | /// 61 | /// fn read_byte (reader: &'_ mut R) 62 | /// -> ::std::io::Result 63 | /// where 64 | /// R : ReadIntoUninit, 65 | /// { 66 | /// let mut byte = MaybeUninit::uninit(); 67 | /// reader.read_into_uninit_exact(::std::slice::from_mut(&mut byte).as_out())?; 68 | /// Ok(unsafe { 69 | /// // Safety: Guaranteed by `ReadIntoUninit` contract 70 | /// byte.assume_init() 71 | /// }) 72 | /// } 73 | /// ``` 74 | pub unsafe trait ReadIntoUninit: Read 75 | // Safety: `.read_into_uninit_exact()` delegates to `.read_into_uninit()`. 76 | { 77 | /// Single attempt to read bytes from `Self` into `buf`. 78 | /// 79 | /// On success, it returns the bytes having been read. 80 | /// 81 | /// # Guarantees (that `unsafe` code may rely on) 82 | /// 83 | /// - `if let Ok(init_buf) = self.read_into_uninit(buf)`, then it is 84 | /// sound to: 85 | /// 86 | /// ```rust 87 | /// # macro_rules! ignore {($($t:tt)*) => ()} ignore! { 88 | /// unsafe { 89 | /// buf.get_out_unchecked(.. init_buf.len()).assume_init() 90 | /// } 91 | /// # } 92 | /// ``` 93 | /// 94 | /// This is not guaranteed to read `buf.len()` bytes, see the docs of 95 | /// [`.read()`][`Read::read`] for more information. 96 | fn read_into_uninit<'buf>( 97 | self: &'_ mut Self, 98 | buf: Out<'buf, [u8]>, 99 | ) -> io::Result<&'buf mut [u8]>; 100 | 101 | /// Attempts to _fill_ `buf` through multiple `.read()` calls if necessary. 102 | /// 103 | /// On success, it returns the bytes having been read. 104 | /// 105 | /// # Guarantees (that `unsafe` code may rely on) 106 | /// 107 | /// - `if self.read_into_uninit_exact(buf).is_ok()`, then it is 108 | /// sound to: `buf.assume_init()`. 109 | /// 110 | /// See the docs of [`.read_exact()`][`Read::read_exact`] for more 111 | /// information. 112 | fn read_into_uninit_exact<'buf>( 113 | self: &'_ mut Self, 114 | mut buf: Out<'buf, [u8]>, 115 | ) -> io::Result<&'buf mut [u8]> { 116 | { 117 | let mut buf = buf.reborrow(); 118 | while buf.is_empty().not() { 119 | match self.read_into_uninit(buf.r()).map(|it| it.len()) { 120 | Ok(0) => { 121 | return Err(io::Error::new( 122 | io::ErrorKind::UnexpectedEof, 123 | "failed to fill whole buffer", 124 | )); 125 | } 126 | Ok(n) => { 127 | // buf = &mut buf[n ..]; 128 | buf = buf.get_out(n..).unwrap(); 129 | } 130 | Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} 131 | Err(e) => { 132 | return Err(e); 133 | } 134 | } 135 | } 136 | } 137 | Ok(unsafe { 138 | // # Safety 139 | // 140 | // - this is the "concatenation" of all the "buf[.. n]" 141 | // initialisation witnesses. 142 | buf.assume_init() 143 | }) 144 | } 145 | 146 | /// Chains / concats two `ReadIntoUninit` readers into one. 147 | #[cfg(feature = "chain")] 148 | #[cfg_attr(feature = "nightly", doc(cfg(feature = "chain")))] 149 | fn chain(self: Self, next: R) -> chain::Chain 150 | where 151 | Self: Sized, 152 | { 153 | chain::Chain { 154 | first: self, 155 | second: next, 156 | first_done: false, 157 | } 158 | } 159 | } 160 | 161 | /// Helper macro to alleviate the code duplication from implementing both 162 | /// `Read` and `ReadIntoUninit`. 163 | /// 164 | /// Once some type `T` implements `ReadIntoUninit`, you can derive `Read` by 165 | /// doing: 166 | /// 167 | /// ```rust 168 | /// # macro_rules! ignore {($($t:tt)*) => ()} ignore! { 169 | /// ::uninit::read::auto_impl! { 170 | /// #[derived_from(ReadIntoUninit)] 171 | /// impl Read for X 172 | /// } 173 | /// // and if X is generic, over, for instance, `Generics` 174 | /// ::uninit::read::auto_impl! { 175 | /// #[derived_from(ReadIntoUninit)] 176 | /// impl[Generics] Read for X 177 | /// } 178 | /// # } 179 | /// ``` 180 | #[doc(hidden)] 181 | #[macro_export] 182 | macro_rules! _private_auto_impl {( 183 | #[derived_from(ReadIntoUninit)] 184 | impl $( [$($generics:tt)*] )? Read for $T:ty 185 | $( 186 | where 187 | $($where_clause:tt)* 188 | )? 189 | ) => ( 190 | impl$(<$($generics)*>)? $crate::std::io::Read for $T 191 | where 192 | $( $($where_clause)* )? 193 | { 194 | #[inline] 195 | fn read (self: &'_ mut Self, buf: &'_ mut [u8]) 196 | -> $crate::std::io::Result 197 | { 198 | ::read_into_uninit( 199 | self, 200 | buf.as_out(), 201 | ).map(|x| x.len()) 202 | } 203 | 204 | #[inline] 205 | fn read_exact (self: &'_ mut Self, buf: &'_ mut [u8]) 206 | -> $crate::std::io::Result<()> 207 | { 208 | ::read_into_uninit_exact( 209 | self, 210 | buf.as_out(), 211 | ).map(drop) 212 | } 213 | } 214 | )} 215 | #[doc(inline)] 216 | pub use _private_auto_impl as auto_impl; 217 | 218 | pub use crate::extension_traits::VecExtendFromReader; 219 | 220 | mod impls; 221 | 222 | #[cfg(feature = "chain")] 223 | #[cfg_attr(feature = "nightly", doc(cfg(feature = "chain")))] 224 | pub mod chain { 225 | #![allow(missing_docs)] 226 | use super::*; 227 | 228 | #[cfg_attr(feature = "nightly", doc(cfg(feature = "chain")))] 229 | #[derive(Debug)] 230 | pub struct Chain 231 | where 232 | R1: ReadIntoUninit, 233 | R2: ReadIntoUninit, 234 | { 235 | pub(super) first: R1, 236 | 237 | pub(super) second: R2, 238 | 239 | pub(super) first_done: bool, 240 | } 241 | 242 | impl Chain 243 | where 244 | R1: ReadIntoUninit, 245 | R2: ReadIntoUninit, 246 | { 247 | pub fn into_inner(self: Self) -> (R1, R2) { 248 | let Self { first, second, .. } = self; 249 | (first, second) 250 | } 251 | 252 | pub fn get_ref(self: &'_ Self) -> (&'_ R1, &'_ R2) { 253 | let Self { first, second, .. } = self; 254 | (first, second) 255 | } 256 | } 257 | 258 | unsafe impl ReadIntoUninit for Chain 259 | where 260 | R1: ReadIntoUninit, 261 | R2: ReadIntoUninit, 262 | { 263 | fn read_into_uninit<'buf>( 264 | self: &'_ mut Self, 265 | mut buf: Out<'buf, [u8]>, 266 | ) -> io::Result<&'buf mut [u8]> { 267 | let len = buf.len(); 268 | if len == 0 { 269 | return Ok(buf.copy_from_slice(&[])); 270 | } 271 | if self.first_done.not() { 272 | let buf_ = self.first.read_into_uninit(buf.r())?; 273 | if buf_.is_empty() { 274 | self.first_done = true; 275 | } else { 276 | return unsafe { 277 | // Safety: `buf_` has been a witness of the 278 | // initialization of these bytes. 279 | let len = buf_.len(); 280 | let buf = buf.get_out(..len).unwrap(); 281 | Ok(buf.assume_init()) 282 | }; 283 | } 284 | } 285 | self.second.read_into_uninit(buf) 286 | } 287 | } 288 | 289 | super::auto_impl! { 290 | #[derived_from(ReadIntoUninit)] 291 | impl[R1, R2] Read for Chain 292 | where 293 | R1 : ReadIntoUninit, 294 | R2 : ReadIntoUninit, 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /src/utils/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! pub_in_crate {( 2 | $( 3 | $(#[$meta:meta])* 4 | use $($first:ident)? $(:: $extra:ident)* :: { 5 | $($tree:tt)* 6 | }; 7 | )* 8 | ) => ( 9 | $( 10 | $(#[$meta])* 11 | pub(in crate) 12 | use $($first)? $(:: $extra)* :: { 13 | $($tree)* 14 | }; 15 | )* 16 | )} 17 | 18 | macro_rules! use_prelude { 19 | () => { 20 | #[allow(unused_imports)] 21 | pub(crate) use crate::utils::prelude::*; 22 | }; 23 | } 24 | 25 | macro_rules! cfg_std {( 26 | $($item:item)* 27 | ) => ( 28 | $( 29 | #[cfg(feature = "std")] 30 | #[cfg_attr(feature = "nightly", 31 | doc(cfg(feature = "std")), 32 | )] 33 | $item 34 | )* 35 | )} 36 | 37 | macro_rules! cfg_alloc {( 38 | $($item:item)* 39 | ) => ( 40 | $( 41 | #[cfg(feature = "alloc")] 42 | #[cfg_attr(feature = "nightly", 43 | doc(cfg(any(feature = "alloc", feature = "std"))), 44 | )] 45 | $item 46 | )* 47 | )} 48 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | mod macros; 3 | 4 | pub(crate) mod prelude; 5 | -------------------------------------------------------------------------------- /src/utils/prelude.rs: -------------------------------------------------------------------------------- 1 | //! Internal crate-global `use` imports. 2 | 3 | #![allow(unused_imports)] 4 | 5 | pub_in_crate! { 6 | use ::core::{ 7 | convert::{ 8 | TryFrom, 9 | TryInto, 10 | }, 11 | hint, 12 | mem::{self, 13 | MaybeUninit, 14 | }, 15 | ptr, 16 | ops::{ 17 | Not, 18 | }, 19 | slice, 20 | }; 21 | #[cfg(feature = "alloc")] 22 | use ::alloc::{ 23 | alloc, 24 | boxed::Box, 25 | string::String, 26 | vec::Vec, 27 | }; 28 | #[cfg(feature = "std")] 29 | use ::std::{ 30 | io, 31 | }; 32 | use crate::{ 33 | prelude::*, 34 | }; 35 | #[cfg(feature = "std")] 36 | use crate::{ 37 | extension_traits::{ 38 | VecExtendFromReader, 39 | }, 40 | read::{ 41 | ReadIntoUninit, 42 | }, 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /tests/docs.rs: -------------------------------------------------------------------------------- 1 | #![cfg(miri)] 2 | #![allow(unused)] 3 | #![deny(unused_must_use)] 4 | 5 | macro_rules! mk_tests {( 6 | $( 7 | $name:ident : $body:block 8 | ),* $(,)? 9 | ) => ( 10 | $( 11 | #[test] 12 | fn $name () 13 | $body 14 | )* 15 | )} 16 | 17 | mk_tests! { 18 | readme_0: { 19 | use ::core::mem::MaybeUninit; 20 | let mut x = MaybeUninit::::uninit(); 21 | x = MaybeUninit::new(42); 22 | assert_eq!(42, unsafe { x.assume_init() }); 23 | }, 24 | 25 | readme_1: { 26 | use ::core::mem::MaybeUninit; 27 | let mut x = MaybeUninit::::uninit(); 28 | 29 | unsafe { 30 | x.as_mut_ptr().write(42); 31 | assert_eq!(x.assume_init(), 42); 32 | } 33 | }, 34 | 35 | readme_2: { 36 | use ::core::mem::MaybeUninit; 37 | use ::uninit::prelude::*; 38 | 39 | let mut x = MaybeUninit::uninit(); 40 | let at_init_x: &i32 = x.as_out().write(42); 41 | assert_eq!(at_init_x, &42); 42 | }, 43 | 44 | uninit_array: { 45 | use ::uninit::{prelude::*, read::ReadIntoUninit}; 46 | 47 | let mut reader = &b"Hello, World!"[..]; 48 | let mut backing_array = uninit_array![u8; 4]; // : [MaybeUninit; 4] 49 | let buf = backing_array.as_out(); 50 | assert_eq!( 51 | reader.read_into_uninit_exact(buf).unwrap(), 52 | b"Hell", 53 | ); 54 | }, 55 | 56 | vec_extend_from_reader: { 57 | use ::uninit::read::VecExtendFromReader; 58 | 59 | let mut reader = &b"World!"[..]; 60 | let mut vec = b"Greetings, ".to_vec(); 61 | vec.extend_from_reader_exact(6, &mut reader).unwrap(); 62 | assert_eq!( 63 | vec, 64 | b"Greetings, World!", 65 | ); 66 | }, 67 | } 68 | 69 | mod extension_traits { 70 | mk_tests! { 71 | as_out: { 72 | use ::uninit::prelude::*; 73 | 74 | let mut x = 0; 75 | x.as_out().write(42); 76 | 77 | let mut y = ::core::mem::MaybeUninit::uninit(); 78 | y.as_out().write(42); 79 | let y = unsafe { y.assume_init() }; 80 | 81 | assert_eq!(x, y); 82 | }, 83 | 84 | box_uninit: { 85 | use ::uninit::prelude::*; 86 | 87 | let ft: Box = Box::uninit().init(42); 88 | assert_eq!(*ft, 42); 89 | }, 90 | 91 | manually_drop_mut: { 92 | use ::uninit::prelude::*; 93 | use ::core::cell::Cell; 94 | 95 | let mut cell = Cell::new(0); 96 | cell.manually_drop_mut().as_out().write(Cell::new(42)); // OK 97 | assert_eq!(cell.get(), 42); 98 | }, 99 | 100 | vec_split_at_extra_cap: { 101 | use ::uninit::prelude::*; 102 | 103 | fn make_palindrome (v: &'_ mut Vec) 104 | { 105 | let len = v.len(); 106 | v.reserve(len); 107 | let (xs, extra) = v.split_at_extra_cap(); 108 | for (&x, at_dst) in xs.iter().rev().zip(extra) { 109 | at_dst.write(x); 110 | } 111 | unsafe { 112 | // Safety: the first `len` elements of `extra` have been initialized. 113 | v.set_len(2 * len); 114 | } 115 | } 116 | 117 | let mut v = vec![1, 2, 3]; 118 | make_palindrome(&mut v); 119 | assert_eq!(v, [1, 2, 3, 3, 2, 1]); 120 | }, 121 | 122 | vec_reserve_uninit: { 123 | use ::uninit::prelude::*; 124 | 125 | let mut vec = b"Hello, ".to_vec(); 126 | const WORLD: &[u8] = b"World!"; 127 | 128 | let mut extra: Out<'_, [u8]> = vec.reserve_uninit(WORLD.len()); 129 | extra.r().copy_from_slice(WORLD); 130 | 131 | // `.reserve_uninit()` guarantees the following properties: 132 | assert_eq!(extra.len(), WORLD.len()); 133 | let extra_start: *mut u8 = extra.r().as_mut_ptr().cast(); 134 | let uninit_start: *mut u8 = vec.as_mut_ptr().wrapping_add(vec.len()); 135 | assert_eq!(extra_start, uninit_start); 136 | 137 | unsafe { 138 | // # Safety 139 | // 140 | // - `.copy_from_slice()` contract guarantees initialization 141 | // of `extra`, which, in turn, from `reserve_uninit`'s contract, 142 | // leads to the `vec` extra capacity having been initialized. 143 | vec.set_len(vec.len() + WORLD.len()); 144 | } 145 | assert_eq!( 146 | vec, 147 | b"Hello, World!", 148 | ); 149 | }, 150 | } 151 | } 152 | 153 | mod out_refs { 154 | mk_tests! { 155 | get_out: { 156 | use ::uninit::prelude::*; 157 | 158 | let src: &[u8] = b"Hello, World!"; 159 | // Stack-allocate an uninitialized buffer. 160 | let mut buf = uninit_array![u8; 256]; 161 | // copy `src` into this stack allocated buffer, effectively initializing it. 162 | let buf: &mut [u8] = 163 | // buf[.. src.len()].as_out() 164 | buf.as_out().get_out(.. src.len()).unwrap() 165 | .copy_from_slice(src) 166 | ; 167 | assert_eq!(buf, b"Hello, World!"); 168 | buf[7 ..].copy_from_slice(b"Earth!"); 169 | assert_eq!(buf, b"Hello, Earth!"); 170 | }, 171 | 172 | copy_from_slice: { 173 | use ::uninit::prelude::*; 174 | 175 | let mut array = uninit_array![_; 13]; 176 | assert_eq!( 177 | array.as_out().copy_from_slice(b"Hello, World!"), 178 | b"Hello, World!", 179 | ); 180 | // we can thus soundly `assume_init` our array: 181 | let array = unsafe { 182 | ::core::mem::transmute::< 183 | [MaybeUninit; 13], 184 | [ u8 ; 13], 185 | >(array) 186 | }; 187 | assert_eq!( 188 | array, 189 | *b"Hello, World!", 190 | ); 191 | }, 192 | } 193 | } 194 | --------------------------------------------------------------------------------