├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src ├── ext.rs └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | target 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "supercow" 3 | version = "0.1.0" 4 | authors = ["Jason Lingle"] 5 | license = "MIT/Apache-2.0" 6 | readme = "README.md" 7 | repository = "https://github.com/altsysrq/supercow" 8 | homepage = "https://github.com/altsysrq/supercow" 9 | documentation = "https://altsysrq.github.io/rustdoc/supercow/index.html" 10 | keywords = ["ref", "borrow", "generic", "cow"] 11 | 12 | description = """ 13 | A generic way to accept general reference-like values without proliferating 14 | generics. 15 | """ 16 | 17 | [dependencies] 18 | -------------------------------------------------------------------------------- /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 [yyyy] [name of copyright owner] 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-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Jason Lingle 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Supercow 2 | 3 | [![Latest Version](https://img.shields.io/crates/v/supercow.svg)](https://crates.io/crates/supercow) 4 | 5 | `Supercow` is a versatile and low-overhead generalised reference, allowing to 6 | transparently work with owned or borrowed values, as well as shared-ownership 7 | types like `Arc`. 8 | 9 | More information can be found in the 10 | [documentation](https://altsysrq.github.io/rustdoc/supercow/index.html). 11 | 12 | ## Status 13 | 14 | Experimental. This crate is fairly well internally tested, but has not yet seen 15 | much serious use. 16 | 17 | ## Contribution 18 | 19 | Unless you explicitly state otherwise, any contribution intentionally submitted 20 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall 21 | be dual licensed as above, without any additional terms or conditions. 22 | -------------------------------------------------------------------------------- /src/ext.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jason Lingle 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! Miscellaneous things used to integrate other code with Supercow, but which 10 | //! are not of interest to most client developers. 11 | 12 | use std::borrow::Borrow; 13 | use std::ffi::{CStr, OsStr}; 14 | use std::marker::PhantomData; 15 | use std::mem; 16 | use std::path::Path; 17 | use std::ptr; 18 | use std::rc::Rc; 19 | use std::sync::Arc; 20 | 21 | /// Marker trait indicating a `Deref`-like which always returns the same 22 | /// reference. 23 | /// 24 | /// This is not intended for general use outside Supercow. Notably, mundane 25 | /// references satisfy this trait's requirements, but deliberately do not 26 | /// implement it. It is also not a subtrait of `Deref` due to some additional 27 | /// special logic around boxes. 28 | /// 29 | /// ## Unsafety 30 | /// 31 | /// Behaviour is undefined if the implementation does not always return the 32 | /// same reference from `const_deref()` for any particular implementing value 33 | /// (including if that value is moved or cloned). 34 | pub unsafe trait ConstDeref { 35 | /// The type this value dereferences to. 36 | type Target : ?Sized; 37 | /// Returns the (constant) value that this value dereferences to. 38 | fn const_deref(&self) -> &Self::Target; 39 | } 40 | 41 | unsafe impl ConstDeref for Rc { 42 | type Target = T; 43 | fn const_deref(&self) -> &T { self } 44 | } 45 | 46 | unsafe impl ConstDeref for Arc { 47 | type Target = T; 48 | fn const_deref(&self) -> &T { self } 49 | } 50 | 51 | unsafe impl ConstDeref for Box { 52 | type Target = T::Target; 53 | fn const_deref(&self) -> &T::Target { 54 | (**self).const_deref() 55 | } 56 | } 57 | 58 | 59 | /// Trait for `ConstDeref` implementations which can be constructed in a 60 | /// two-step process. 61 | /// 62 | /// This is used by `Supercow` to safely promote owned values to shared values. 63 | /// A two-step process is necessary because the implementation must atomically 64 | /// transfer ownership of the value and so must set everything up first in case 65 | /// setup panics. 66 | /// 67 | /// Essentially, such shared references actually hold an `Option` which 68 | /// defaults to `None`, and panic if dereferenced before the value is set. 69 | pub trait TwoStepShared { 70 | /// Returns a new, empty instance of `Self`. 71 | fn new_two_step() -> Self; 72 | /// Returns the internal `Option` backing this value. 73 | /// 74 | /// ## Unsafety 75 | /// 76 | /// This call may assume that `self` was produced by a call to 77 | /// `new_two_step` on the same implementation. (This is to allow 78 | /// downcasting without requiring `Any` which in turn requires `'static`.) 79 | /// 80 | /// The address of the value inside `Some` may not be altered by the 81 | /// implementation. 82 | unsafe fn deref_holder(&mut self) -> &mut Option; 83 | } 84 | 85 | macro_rules! twostepwrapper { ($outer:ident, $inner:ident) => { 86 | /// Wrapper providing a `TwoStepShared` implementation. 87 | pub struct $outer($inner>, PhantomData); 88 | impl Clone for $outer { 89 | fn clone(&self) -> Self { 90 | $outer(self.0.clone(), PhantomData) 91 | } 92 | } 93 | 94 | impl TwoStepShared for $outer 95 | where T : SafeBorrow { 96 | fn new_two_step() -> Self { 97 | $outer($inner::new(None), PhantomData) 98 | } 99 | unsafe fn deref_holder(&mut self) -> &mut Option { 100 | // Safety: No operation here is actually unsafe. 101 | $inner::get_mut(&mut self.0) 102 | .expect("Two-step wrapper already cloned") 103 | } 104 | } 105 | } } 106 | twostepwrapper!(TwoStepRc, Rc); 107 | twostepwrapper!(TwoStepArc, Arc); 108 | 109 | /// The maximum displacement (relative to the start of the object) that a 110 | /// reference pointing into `self` from an instance of `SafeBorrow` may have. 111 | /// 112 | /// This value is deliberately conservative to account for other memory layout 113 | /// factors. 114 | pub const MAX_INTERNAL_BORROW_DISPLACEMENT: usize = 2048; 115 | 116 | /// Extension of `Borrow` used to allow `Supercow::to_mut()` to work safely. 117 | /// 118 | /// ## Unsafety 119 | /// 120 | /// Behaviour is undefined if the `borrow()` implementation may return a 121 | /// reference into `self` which is more than `MAX_INTERNAL_BORROW_DISPLACEMENT` 122 | /// bytes beyond the base of `self`. 123 | pub unsafe trait SafeBorrow: Borrow { 124 | /// Given `ptr`, which was obtained from a prior call to `Self::borrow()`, 125 | /// return a value with the same nominal lifetime which is guaranteed to 126 | /// survive mutations to `Self`. 127 | /// 128 | /// Types which implement `Borrow` by pure, constant pointer arithmetic on 129 | /// `self` can simply return `ptr` unmodified. Other types typically need 130 | /// to provide some static reference, such as the empty string for `&str`. 131 | /// 132 | /// ## Unsafety 133 | /// 134 | /// Behaviour is undefined if this call returns `ptr`, but a mutation to 135 | /// `Self` could invalidate the reference. 136 | fn borrow_replacement<'a>(ptr: &'a T) -> &'a T; 137 | } 138 | unsafe impl SafeBorrow for T { 139 | fn borrow_replacement(ptr: &T) -> &T { ptr } 140 | } 141 | unsafe impl SafeBorrow<[B]> for T where T : Borrow<[B]> { 142 | fn borrow_replacement(_: &[B]) -> &[B] { 143 | &[] 144 | } 145 | } 146 | unsafe impl SafeBorrow for T where T : Borrow { 147 | fn borrow_replacement(_: &str) -> &str { "" } 148 | } 149 | unsafe impl SafeBorrow for T 150 | where T : Borrow { 151 | fn borrow_replacement(_: &CStr) -> &CStr { 152 | Default::default() 153 | } 154 | } 155 | unsafe impl SafeBorrow for T 156 | where T : Borrow { 157 | fn borrow_replacement(_: &OsStr) -> &OsStr { 158 | OsStr::new("") 159 | } 160 | } 161 | unsafe impl SafeBorrow for T 162 | where T : Borrow { 163 | fn borrow_replacement(_: &Path) -> &Path { 164 | Path::new("") 165 | } 166 | } 167 | 168 | /// Marker trait identifying a pointer type which begins with an absolute 169 | /// address and contains no other address-dependent information. 170 | /// 171 | /// `Supercow` expects to be able to read the first machine-pointer-sized value 172 | /// of such a pointer and perform address arithmetic upon it. 173 | /// 174 | /// There is no utility of applying this trait to anything other than a const 175 | /// pointer. 176 | /// 177 | /// ## Unsafety 178 | /// 179 | /// Behaviour is undefined if a marked type does not begin with a real pointer 180 | /// to a value (with the usual exception of ZSTs, where the pointer does not 181 | /// need to point to anything in particular) or if other parts of the type 182 | /// contain address-dependent information. 183 | /// 184 | /// Behaviour is undefined if the pointer has any `Drop` implementation, 185 | /// should a future Rust version make such things possible. 186 | pub unsafe trait PointerFirstRef : Copy { } 187 | 188 | unsafe impl PointerFirstRef for *const T { } 189 | unsafe impl PointerFirstRef for *const [T] { } 190 | unsafe impl PointerFirstRef for *const str { } 191 | unsafe impl PointerFirstRef for *const ::std::ffi::CStr { } 192 | unsafe impl PointerFirstRef for *const ::std::ffi::OsStr { } 193 | unsafe impl PointerFirstRef for *const ::std::path::Path { } 194 | 195 | /// Like `std::convert::From`, but without the blanket implementations that 196 | /// cause problems for `supercow_features!`. 197 | /// 198 | /// ## Unsafety 199 | /// 200 | /// The conversion may not invalidate the address returned by 201 | /// `T::const_deref()` if `T` is `ConstDeref`. 202 | pub unsafe trait SharedFrom { 203 | /// Converts the given `T` to `Self`. 204 | fn shared_from(t: T) -> Self; 205 | } 206 | unsafe impl SharedFrom> for Rc { 207 | fn shared_from(t: Rc) -> Rc { t } 208 | } 209 | unsafe impl SharedFrom> for Arc { 210 | fn shared_from(t: Arc) -> Arc { t } 211 | } 212 | 213 | /// Describes how an `OWNED` or `SHARED` value is stored in a `Supercow`. 214 | /// 215 | /// All notes for `*_b` functions are the same as the corresponding `*_a` 216 | /// functions. 217 | /// 218 | /// ## Unsafety 219 | /// 220 | /// `Supercow` relies strongly on the contracts of the functions in this trait 221 | /// being implemented correctly. 222 | /// 223 | /// No function may mutate the `A` or `B` values. 224 | pub unsafe trait OwnedStorage : Default { 225 | /// Allocates the given owned value. 226 | /// 227 | /// `self` is a `Default`-initialised instance. 228 | /// 229 | /// Returns a pointer with 2-byte alignment. 230 | /// 231 | /// ## Unsafety 232 | /// 233 | /// Behaviour is undefined if this call returns a pointer with incorrect 234 | /// alignment. 235 | /// 236 | /// Behaviour is undefined if the returned value is an address inside 237 | /// `self` offset by more than `MAX_INTERNAL_BORROW_DISPLACEMENT/2` (note 238 | /// division by two). 239 | /// 240 | /// Behaviour is undefined if this returns a null pointer. (But the 241 | /// returned pointer does not need to actually point at anything.) 242 | fn allocate_a(&mut self, value: A) -> *mut (); 243 | /// See `allocate_a`. 244 | fn allocate_b(&mut self, value: B) -> *mut (); 245 | /// Extracts the immutable reference from the saved pointer and storage. 246 | /// 247 | /// ## Unsafety 248 | /// 249 | /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it 250 | /// returned from `allocate_a`, and that `self` was initialised by a call 251 | /// to `allocate_a`. 252 | unsafe fn get_ptr_a<'a>(&'a self, ptr: *mut ()) -> &'a A; 253 | /// See `get_ptr_a`. 254 | unsafe fn get_ptr_b<'a>(&'a self, ptr: *mut ()) -> &'a B; 255 | /// Extracts the mutable reference from the saved pointer and storage. 256 | /// 257 | /// ## Unsafety 258 | /// 259 | /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it 260 | /// returned from `allocate_a` and that `self` was initialised by a call to 261 | /// `allocate_a`. 262 | unsafe fn get_mut_a<'a>(&'a mut self, ptr: *mut ()) -> &'a mut A; 263 | /// See `get_mut_a`. 264 | unsafe fn get_mut_b<'a>(&'a mut self, ptr: *mut ()) -> &'a mut B; 265 | /// Releases any allocations that would not be released by `Stored` 266 | /// being dropped. 267 | /// 268 | /// ## Unsafety 269 | /// 270 | /// This call may assume that `ptr` is exactly a (2-byte-aligned) value it 271 | /// returned from `allocate_a`. 272 | /// 273 | /// Once this function is called, the given `ptr` is considered invalid and 274 | /// any further use is undefined. 275 | /// 276 | /// This call must not panic (assuming the input contract is satisfied). 277 | unsafe fn deallocate_a(&mut self, ptr: *mut ()); 278 | /// See `deallocate_b`. 279 | unsafe fn deallocate_b(&mut self, ptr: *mut ()); 280 | /// Like `deallocate_a()`, but also return the owned value. 281 | unsafe fn deallocate_into_a(&mut self, ptr: *mut ()) -> A; 282 | /// See `deallocate_into_a`. 283 | unsafe fn deallocate_into_b(&mut self, ptr: *mut ()) -> B; 284 | 285 | /// Returns whether this storage implementation ever causes the owned 286 | /// object to be stored internally to the `Supercow`. 287 | /// 288 | /// ## Unsafety 289 | /// 290 | /// Behaviour is undefined if this returns `false` but the owned value is 291 | /// stored within the `Supercow`. 292 | fn is_internal_storage() -> bool; 293 | } 294 | 295 | /// Causes the `OWNED` or `SHARED` value of a `Supercow` to be stored inline. 296 | /// 297 | /// This makes allocation of owned `Supercow`s much faster, at the expense of 298 | /// making the `Supercow` itself much bigger (since it now must contain the 299 | /// whole object). 300 | #[derive(Clone, Copy, Debug)] 301 | pub struct InlineStorage(InlineStorageImpl); 302 | 303 | #[derive(Clone, Copy, Debug)] 304 | enum InlineStorageImpl { 305 | None, 306 | A(A), 307 | B(B), 308 | } 309 | 310 | impl Default for InlineStorage { 311 | fn default() -> Self { 312 | InlineStorage(InlineStorageImpl::None) 313 | } 314 | } 315 | 316 | unsafe impl OwnedStorage for InlineStorage { 317 | #[inline] 318 | fn allocate_a(&mut self, value: A) -> *mut () { 319 | self.0 = InlineStorageImpl::A(value); 320 | 2usize as *mut () 321 | } 322 | 323 | #[inline] 324 | fn allocate_b(&mut self, value: B) -> *mut () { 325 | self.0 = InlineStorageImpl::B(value); 326 | 2usize as *mut () 327 | } 328 | 329 | #[inline] 330 | unsafe fn get_ptr_a<'a>(&'a self, _: *mut ()) -> &'a A { 331 | match self.0 { 332 | InlineStorageImpl::A(ref r) => r, 333 | _ => unreachable!(), 334 | } 335 | } 336 | 337 | #[inline] 338 | unsafe fn get_ptr_b<'a>(&'a self, _: *mut ()) -> &'a B { 339 | match self.0 { 340 | InlineStorageImpl::B(ref r) => r, 341 | _ => unreachable!(), 342 | } 343 | } 344 | 345 | #[inline] 346 | unsafe fn get_mut_a<'a>(&'a mut self, _: *mut ()) -> &'a mut A { 347 | match self.0 { 348 | InlineStorageImpl::A(ref mut r) => r, 349 | _ => unreachable!(), 350 | } 351 | } 352 | 353 | #[inline] 354 | unsafe fn get_mut_b<'a>(&'a mut self, _: *mut ()) -> &'a mut B { 355 | match self.0 { 356 | InlineStorageImpl::B(ref mut r) => r, 357 | _ => unreachable!(), 358 | } 359 | } 360 | 361 | #[inline] 362 | unsafe fn deallocate_a(&mut self, _: *mut ()) { } 363 | 364 | #[inline] 365 | unsafe fn deallocate_b(&mut self, _: *mut ()) { } 366 | 367 | #[inline] 368 | unsafe fn deallocate_into_a(&mut self, _: *mut ()) -> A { 369 | match mem::replace(&mut self.0, InlineStorageImpl::None) { 370 | InlineStorageImpl::A(v) => v, 371 | _ => unreachable!(), 372 | } 373 | } 374 | 375 | #[inline] 376 | unsafe fn deallocate_into_b(&mut self, _: *mut ()) -> B { 377 | match mem::replace(&mut self.0, InlineStorageImpl::None) { 378 | InlineStorageImpl::B(v) => v, 379 | _ => unreachable!(), 380 | } 381 | } 382 | 383 | #[inline] 384 | fn is_internal_storage() -> bool { true } 385 | } 386 | 387 | /// Used to give arbitrary values at least pointer alignment without making 388 | /// them otherwise bigger. 389 | /// 390 | /// This likely isn't strictly necessary, since any allocator has an inherent 391 | /// alignment anyway, but it doesn't hurt to be explicit. 392 | type Aligned = ([*const();0], T); 393 | 394 | /// Causes the `OWNED` or `SHARED` value of a `Supercow` to be stored in a 395 | /// `Box`. 396 | /// 397 | /// This makes allocation of owned `Supercow`s more expensive, but incurs zero 398 | /// space overhead within the `Supercow`. It also results in a faster `Deref` 399 | /// implementation. 400 | #[derive(Debug, Clone, Copy, Default)] 401 | pub struct BoxedStorage; 402 | unsafe impl OwnedStorage for BoxedStorage { 403 | #[inline] 404 | fn allocate_a(&mut self, value: A) -> *mut () { 405 | if mem::size_of::() > 0 { 406 | let boxed: Box> = Box::new(([], value)); 407 | let address = Box::into_raw(boxed); 408 | unsafe { &mut (*address).1 as *mut A as *mut () } 409 | } else { 410 | // Handle ZSTs specially, since `Box` "allocates" them at address 411 | // 1. 412 | 2 as *mut () 413 | } 414 | } 415 | 416 | #[inline] 417 | fn allocate_b(&mut self, value: B) -> *mut () { 418 | if mem::size_of::() > 0 { 419 | let boxed: Box> = Box::new(([], value)); 420 | let address = Box::into_raw(boxed); 421 | unsafe { &mut (*address).1 as *mut B as *mut () } 422 | } else { 423 | // Handle ZSTs specially, since `Box` "allocates" them at address 424 | // 1. 425 | 2 as *mut () 426 | } 427 | } 428 | 429 | #[inline] 430 | unsafe fn get_ptr_a<'a>(&'a self, ptr: *mut ()) -> &'a A { 431 | &(*(ptr as *const Aligned)).1 432 | } 433 | 434 | #[inline] 435 | unsafe fn get_ptr_b<'a>(&'a self, ptr: *mut ()) -> &'a B { 436 | &(*(ptr as *const Aligned)).1 437 | } 438 | 439 | #[inline] 440 | unsafe fn get_mut_a<'a>(&'a mut self, ptr: *mut ()) -> &'a mut A { 441 | &mut(*(ptr as *mut Aligned)).1 442 | } 443 | 444 | #[inline] 445 | unsafe fn get_mut_b<'a>(&'a mut self, ptr: *mut ()) -> &'a mut B { 446 | &mut(*(ptr as *mut Aligned)).1 447 | } 448 | 449 | #[inline] 450 | unsafe fn deallocate_a(&mut self, ptr: *mut ()) { 451 | if mem::size_of::() > 0 { 452 | drop(Box::from_raw(ptr as *mut Aligned)) 453 | } 454 | } 455 | 456 | #[inline] 457 | unsafe fn deallocate_b(&mut self, ptr: *mut ()) { 458 | if mem::size_of::() > 0 { 459 | drop(Box::from_raw(ptr as *mut B)) 460 | } 461 | } 462 | 463 | #[inline] 464 | unsafe fn deallocate_into_a(&mut self, ptr: *mut ()) -> A { 465 | if mem::size_of::() > 0 { 466 | let t = *Box::from_raw(ptr as *mut Aligned); 467 | t.1 468 | } else { 469 | ptr::read(ptr as *mut A) 470 | } 471 | } 472 | 473 | #[inline] 474 | unsafe fn deallocate_into_b(&mut self, ptr: *mut ()) -> B { 475 | if mem::size_of::() > 0 { 476 | let t = *Box::from_raw(ptr as *mut Aligned); 477 | t.1 478 | } else { 479 | ptr::read(ptr as *mut B) 480 | } 481 | } 482 | 483 | #[inline] 484 | fn is_internal_storage() -> bool { false } 485 | } 486 | 487 | /// Optionally stores a pointer to a value. 488 | /// 489 | /// It is doubtful that there are any types besides `()` and `*mut T` which 490 | /// could implement this usefully. 491 | pub unsafe trait PtrWrite : Copy { 492 | /// Returns an instance of `Self` with no particular value. 493 | fn new() -> Self; 494 | 495 | /// Writes the given pointer into `self`. 496 | /// 497 | /// ## Unsafety 498 | /// 499 | /// The implementation must not inspect the given pointer. This call must 500 | /// not panic. 501 | fn store_ptr(&mut self, t: *const T); 502 | } 503 | 504 | unsafe impl PtrWrite for () { 505 | #[inline(always)] 506 | fn new() -> Self { () } 507 | 508 | #[inline(always)] 509 | fn store_ptr(&mut self, _: *const T) { } 510 | } 511 | 512 | unsafe impl PtrWrite for *const T { 513 | #[inline(always)] 514 | fn new() -> Self { 515 | unsafe { mem::uninitialized() } 516 | } 517 | 518 | #[inline(always)] 519 | fn store_ptr(&mut self, t: *const T) { 520 | *self = t; 521 | } 522 | } 523 | 524 | /// Read trait corresponding to `PtrWrite`. 525 | pub unsafe trait PtrRead : PtrWrite { 526 | /// Returns the pointer most recently stored via `store_ptr()`. 527 | /// 528 | /// ## Unsafety 529 | /// 530 | /// Behaviour is undefined if the returned value is not *exactly* equal to 531 | /// the value passed in to the last call to `store_ptr()`. This call must 532 | /// not panic. 533 | fn get_ptr(&self) -> *const T; 534 | } 535 | 536 | unsafe impl PtrRead for *const T { 537 | #[inline(always)] 538 | fn get_ptr(&self) -> *const T { 539 | *self 540 | } 541 | } 542 | 543 | // This is completely unsafe for anything outside of `Ref` to use. It exists so 544 | // that `Ref` doesn't need to have all the generics needed to refer to its 545 | // parent directly, instead allowing anyone to just say `Ref>`. 546 | // 547 | // It does need to be public though since it's mentioned in type constraints 548 | // and so forth. 549 | #[allow(missing_docs)] 550 | #[doc(hidden)] 551 | pub trait RefParent { 552 | type Owned : ?Sized; 553 | 554 | /// Notifies `self` that a `Ref` has been dropped. 555 | /// 556 | /// ## Unsafety 557 | /// 558 | /// Behaviour is undefined if `self` is not in owned mode. 559 | /// 560 | /// Behaviour is undefined if a mutable reference to the owned value in 561 | /// `self` is still live. 562 | unsafe fn supercow_ref_drop(&mut self); 563 | } 564 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Jason Lingle 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #![deny(missing_docs)] 10 | 11 | //! `Supercow` is `Cow` on steroids. 12 | //! 13 | //! `Supercow` provides a mechanism for making APIs that accept or return very 14 | //! general references while maintaining very low overhead for usages not 15 | //! involving heavy-weight references (e.g, `Arc`). Though nominally similar to 16 | //! `Cow` in structure (and being named after it), `Supercow` does not require 17 | //! the containee to be `Clone` or `ToOwned` unless operations inherently 18 | //! depending on either are invoked. 19 | //! 20 | //! `Supercow` allows you to 21 | //! 22 | //! - Return values with ownership semantics decided at run-time; 23 | //! 24 | //! - Write APIs that allow client code to manage its resources however it 25 | //! wants; 26 | //! 27 | //! - Perform efficient copy-on-write and data sharing; 28 | //! 29 | //! - Avoid cloning until absolutely necessary, even if the point at which it 30 | //! becomes necessary is determined dynamically. 31 | //! 32 | //! # Quick Start 33 | //! 34 | //! ## Simple Types 35 | //! 36 | //! In many cases, you can think of a `Supercow` as having only one lifetime 37 | //! parameter and one type parameter, corresponding to the lifetime and type of 38 | //! an immutable reference, i.e., `Supercow<'a, Type>` ⇒ `&'a Type`. 39 | //! 40 | //! ``` 41 | //! extern crate supercow; 42 | //! 43 | //! use std::sync::Arc; 44 | //! use supercow::Supercow; 45 | //! 46 | //! // This takes a `Supercow`, so it can accept owned, borrowed, or shared 47 | //! // values with the same API. The calls to it are annotated below. 48 | //! // 49 | //! // Normally a function like this would elide the lifetime and/or use an 50 | //! // `Into` conversion, but here it is written out for clarity. 51 | //! fn assert_is_forty_two<'a>(s: Supercow<'a, u32>) { 52 | //! // `Supercow` can be dereferenced just like a normal reference. 53 | //! assert_eq!(42, *s); 54 | //! } 55 | //! 56 | //! # fn main() { 57 | //! // Declare some data we want to reference. 58 | //! let forty_two = 42u32; 59 | //! // Make a Supercow referencing the above. 60 | //! let mut a = Supercow::borrowed(&forty_two); 61 | //! // It dereferences to the value of `forty_two`. 62 | //! assert_is_forty_two(a.clone()); // borrowed 63 | //! // And we can see that it actually still *points* to forty_two as well. 64 | //! assert_eq!(&forty_two as *const u32, &*a as *const u32); 65 | //! 66 | //! // Clone `a` so that `b` also points to `forty_two`. 67 | //! let mut b = a.clone(); 68 | //! assert_is_forty_two(b.clone()); // borrowed 69 | //! assert_eq!(&forty_two as *const u32, &*b as *const u32); 70 | //! 71 | //! // `to_mut()` can be used to mutate `a` and `b` independently, taking 72 | //! // ownership as needed. 73 | //! *a.to_mut() += 2; 74 | //! // Our immutable variable hasn't been changed... 75 | //! assert_eq!(42, forty_two); 76 | //! // ...but `a` now stores the new value... 77 | //! assert_eq!(44, *a); 78 | //! // ...and `b` still points to the unmodified variable. 79 | //! assert_eq!(42, *b); 80 | //! assert_eq!(&forty_two as *const u32, &*b as *const u32); 81 | //! 82 | //! // And now we modify `b` as well, which as before affects nothing else. 83 | //! *b.to_mut() = 56; 84 | //! assert_eq!(44, *a); 85 | //! assert_eq!(56, *b); 86 | //! assert_eq!(42, forty_two); 87 | //! 88 | //! // We can call `assert_is_forty_two` with an owned value as well. 89 | //! assert_is_forty_two(Supercow::owned(42)); // owned 90 | //! 91 | //! // We can also use `Arc` transparently. 92 | //! let mut c = Supercow::shared(Arc::new(42)); 93 | //! assert_is_forty_two(c.clone()); // shared 94 | //! *c.to_mut() += 1; 95 | //! assert_eq!(43, *c); 96 | //! # } 97 | //! ``` 98 | //! 99 | //! ## Owned/Borrowed Types 100 | //! 101 | //! `Supercow` can have different owned and borrowed types, for example 102 | //! `String` and `str`. In this case, the two are separate type parameters, 103 | //! with the owned one written first. (Both need to be listed explicitly since 104 | //! `Supercow` does not require the contained value to be `ToOwned`.) 105 | //! 106 | //! ``` 107 | //! extern crate supercow; 108 | //! 109 | //! use std::sync::Arc; 110 | //! use supercow::Supercow; 111 | //! 112 | //! # fn main() { 113 | //! let hello: Supercow = Supercow::borrowed("hello"); 114 | //! let mut hello_world = hello.clone(); 115 | //! hello_world.to_mut().push_str(" world"); 116 | //! 117 | //! assert_eq!(hello, "hello"); 118 | //! assert_eq!(hello_world, "hello world"); 119 | //! # } 120 | //! ``` 121 | //! 122 | //! ## Accepting `Supercow` in an API 123 | //! 124 | //! If you want to make an API taking `Supercow` values, the recommended 125 | //! approach is to accept anything that is `Into>`, which 126 | //! allows bare owned types and references to owned values to be accepted as 127 | //! well. 128 | //! 129 | //! ``` 130 | //! use std::sync::Arc; 131 | //! use supercow::Supercow; 132 | //! 133 | //! fn some_api_function<'a, T : Into>> 134 | //! (t: T) -> Supercow<'a,u32> 135 | //! { 136 | //! let mut x = t.into(); 137 | //! *x.to_mut() *= 2; 138 | //! x 139 | //! } 140 | //! 141 | //! fn main() { 142 | //! assert_eq!(42, *some_api_function(21)); 143 | //! let twenty_one = 21; 144 | //! assert_eq!(42, *some_api_function(&twenty_one)); 145 | //! assert_eq!(42, *some_api_function(Arc::new(21))); 146 | //! } 147 | //! ``` 148 | //! 149 | //! ## Choosing the right variant 150 | //! 151 | //! `Supercow` is extremely flexible as to how it internally stores and manages 152 | //! data. There are four variants provided by default: `Supercow`, 153 | //! `NonSyncSupercow`, `InlineSupercow`, and `InlineNonSyncSupercow`. Here is a 154 | //! quick reference on the trade-offs: 155 | //! 156 | //! | Variant | Send+Sync? | `Rc`? | Size | Init | Deref | 157 | //! |-------------------|---------------|-------|-------|-------|------------| 158 | //! | (Default) | Yes | No | Small | Slow | Very Fast | 159 | //! | `NonSync` | No | Yes | Small | Slow | Very Fast | 160 | //! | `Inline` | Yes | No | Big | Fast | Fast | 161 | //! | `InlineNonSync` | No | Yes | Big | Fast | Fast | 162 | //! 163 | //! "Init" above specifically refers to initialisation with an owned value or 164 | //! shared reference. Supercows constructed with mundane references always 165 | //! construct extremely quickly. 166 | //! 167 | //! The only difference between the `NonSync` variant and the default is that 168 | //! the default is to require the shared pointer type (e.g., `Arc`) to be 169 | //! `Send` and `Sync` (which thus prohibits using `Rc`), whereas `NonSync` does 170 | //! not and so allows `Rc`. Note that a side-effect of the default `Send + 171 | //! Sync` requirement is that the type of `BORROWED` also needs to be `Send` 172 | //! and `Sync` when using `Arc` as the shared reference type; if it is not 173 | //! `Send` and `Sync`, use `NonSyncSupercow` instead. 174 | //! 175 | //! By default, `Supercow` boxes any owned value or shared reference. This 176 | //! makes the `Deref` implementation faster since it does not need to account 177 | //! for internal pointers, but more importantly, means that the `Supercow` does 178 | //! not need to reserve space for the owned and shared values, so the default 179 | //! `Supercow` is only one pointer wider than a bare reference. 180 | //! 181 | //! The obvious problem with boxing values is that it makes construction of the 182 | //! `Supercow` slower, as one must pay for an allocation. If you want to avoid 183 | //! the allocation, you can use the `Inline` variants instead, which store the 184 | //! values inline inside the `Supercow`. (Note that if you are looking to 185 | //! eliminate allocation entirely, you will also need to tinker with the 186 | //! `SHARED` type, which by default has its own `Box` as well.) Note that this 187 | //! of course makes the `Supercow` much bigger; be particularly careful if you 188 | //! create a hierarchy of things containing `InlineSupercow`s referencing each 189 | //! other, as each would effectively have space for the entire tree above it 190 | //! inline. 191 | //! 192 | //! The default to box values was chosen on the grounds that it is generally 193 | //! easier to use, less likely to cause confusing problems, and in many cases 194 | //! the allocation doesn't affect performance: 195 | //! 196 | //! - In either choice, creating a `Supercow` with a borrowed reference incurs 197 | //! no allocation. The boxed option will actually be slightly faster since it 198 | //! does not need to initialise as much memory and results in better locality 199 | //! due to being smaller. 200 | //! 201 | //! - The value contained usually is reasonably expensive to construct anyway, 202 | //! or else there would be less incentive to pass it around as a reference when 203 | //! possible. In these cases, the extra allocation likely is a minor impact on 204 | //! performance. 205 | //! 206 | //! - Overuse of boxed values results in a "uniform slowness" that can be 207 | //! identified reasonably easily, and results in a linear performance 208 | //! degradation relative to overuse. Overuse of `InlineSupercow`s at best 209 | //! results in linear memory bloat, but if `InlineSupercow`s reference 210 | //! structures containing other `InlineSupercow`s, the result can even be 211 | //! exponential bloat to the structures. At best, this is a harder problem to 212 | //! track down; at worst, it can result in entirely non-obvious stack 213 | //! overflows. 214 | //! 215 | //! # Use Cases 216 | //! 217 | //! ## More flexible Copy-on-Write 218 | //! 219 | //! `std::borrow::Cow` only supports two modes of ownership: You either fully 220 | //! own the value, or only borrow it. `Rc` and `Arc` have the `make_mut()` 221 | //! method, which allows either total ownership or shared ownership. `Supercow` 222 | //! supports all three: owned, shared, and borrowed. 223 | //! 224 | //! ## More flexible Copy-if-Needed 225 | //! 226 | //! A major use of `Cow` in `std` is found on functions like 227 | //! `OsStr::to_string_lossy()`, which returns a borrowed view into itself if 228 | //! possible, or an owned string if it needed to change something. If the 229 | //! caller does not intend to do its own writing, this is more a "copy if 230 | //! needed" structure, and the fact that it requires the contained value to be 231 | //! `ToOwned` limits it to things that can be cloned. 232 | //! 233 | //! `Supercow` only requires `ToOwned` if the caller actually intends to invoke 234 | //! functionality which requires cloning a borrowed value, so it can fit this 235 | //! use-case even for non-cloneable types. 236 | //! 237 | //! ## Working around awkward lifetimes 238 | //! 239 | //! This is the original case for which `Supercow` was designed. 240 | //! 241 | //! Say you have an API with a sort of hierarchical structure of heavyweight 242 | //! resources, for example handles to a local database and tables within it. A 243 | //! natural representation may be to make the table handle hold a reference to 244 | //! the database handle. 245 | //! 246 | //! ```no_run 247 | //! struct Database; 248 | //! impl Database { 249 | //! fn new() -> Self { 250 | //! // Computation... 251 | //! Database 252 | //! } 253 | //! fn close(self) -> bool { 254 | //! // E.g., it returns an error on failure or something 255 | //! true 256 | //! } 257 | //! } 258 | //! impl Drop for Database { 259 | //! fn drop(&mut self) { 260 | //! println!("Dropping database"); 261 | //! } 262 | //! } 263 | //! struct Table<'a>(&'a Database); 264 | //! impl<'a> Table<'a> { 265 | //! fn new(db: &'a Database) -> Self { 266 | //! // Computation... 267 | //! Table(db) 268 | //! } 269 | //! } 270 | //! impl<'a> Drop for Table<'a> { 271 | //! fn drop(&mut self) { 272 | //! println!("Dropping table"); 273 | //! // Notify `self.db` about this 274 | //! } 275 | //! } 276 | //! ``` 277 | //! 278 | //! We can use this quite easily: 279 | //! 280 | //! ``` 281 | //! # struct Database; 282 | //! # impl Database { 283 | //! # fn new() -> Self { 284 | //! # // Computation... 285 | //! # Database 286 | //! # } 287 | //! # fn close(self) -> bool { 288 | //! # // E.g., it returns an error on failure or something 289 | //! # true 290 | //! # } 291 | //! # } 292 | //! # impl Drop for Database { 293 | //! # fn drop(&mut self) { 294 | //! # println!("Dropping database"); 295 | //! # } 296 | //! # } 297 | //! # struct Table<'a>(&'a Database); 298 | //! # impl<'a> Table<'a> { 299 | //! # fn new(db: &'a Database) -> Self { 300 | //! # // Computation... 301 | //! # Table(db) 302 | //! # } 303 | //! # } 304 | //! # impl<'a> Drop for Table<'a> { 305 | //! # fn drop(&mut self) { 306 | //! # println!("Dropping table"); 307 | //! # // Notify `self.db` about this 308 | //! # } 309 | //! # } 310 | //! 311 | //! # #[allow(unused_variables)] 312 | //! fn main() { 313 | //! let db = Database::new(); 314 | //! { 315 | //! let table1 = Table::new(&db); 316 | //! let table2 = Table::new(&db); 317 | //! do_stuff(&table1); 318 | //! // Etc 319 | //! } 320 | //! assert!(db.close()); 321 | //! } 322 | //! 323 | //! # #[allow(unused_variables)] 324 | //! fn do_stuff(table: &Table) { 325 | //! // Stuff 326 | //! } 327 | //! ``` 328 | //! 329 | //! That is, until we want to hold the database and the tables in a struct. 330 | //! 331 | //! ```ignore 332 | //! struct Resources { 333 | //! db: Database, 334 | //! table: Table<'uhhh>, // Uh, what is the lifetime here? 335 | //! } 336 | //! ``` 337 | //! 338 | //! There are several options here: 339 | //! 340 | //! - Change the API to use `Arc`s or similar. This works, but adds overhead 341 | //! for clients that don't need it, and additionally removes from everybody the 342 | //! ability to statically know whether `db.close()` can be called. 343 | //! 344 | //! - Force clients to resort to unsafety, such as 345 | //! [`OwningHandle`](http://kimundi.github.io/owning-ref-rs/owning_ref/struct.OwningHandle.html). 346 | //! This sacrifices no performance and allows the stack-based client usage to 347 | //! be able to call `db.close()` easily, but makes things much more difficult 348 | //! for other clients. 349 | //! 350 | //! - Take a `Borrow` type parameter. This works and is zero-overhead, but 351 | //! results in a proliferation of generics throughout the API and client code, 352 | //! and becomes especially problematic when the hierarchy is multiple such 353 | //! levels deep. 354 | //! 355 | //! - Use `Supercow` to get the best of both worlds. 356 | //! 357 | //! We can adapt and use the API like so: 358 | //! 359 | //! ``` 360 | //! use std::sync::Arc; 361 | //! 362 | //! use supercow::Supercow; 363 | //! 364 | //! struct Database; 365 | //! impl Database { 366 | //! fn new() -> Self { 367 | //! // Computation... 368 | //! Database 369 | //! } 370 | //! fn close(self) -> bool { 371 | //! // E.g., it returns an error on failure or something 372 | //! true 373 | //! } 374 | //! } 375 | //! impl Drop for Database { 376 | //! fn drop(&mut self) { 377 | //! println!("Dropping database"); 378 | //! } 379 | //! } 380 | //! struct Table<'a>(Supercow<'a, Database>); 381 | //! impl<'a> Table<'a> { 382 | //! fn new>>(db: T) -> Self { 383 | //! // Computation... 384 | //! Table(db.into()) 385 | //! } 386 | //! } 387 | //! impl<'a> Drop for Table<'a> { 388 | //! fn drop(&mut self) { 389 | //! println!("Dropping table"); 390 | //! // Notify `self.db` about this 391 | //! } 392 | //! } 393 | //! 394 | //! // The original stack-based code, unmodified 395 | //! 396 | //! # #[allow(unused_variables)] 397 | //! fn on_stack() { 398 | //! let db = Database::new(); 399 | //! { 400 | //! let table1 = Table::new(&db); 401 | //! let table2 = Table::new(&db); 402 | //! do_stuff(&table1); 403 | //! // Etc 404 | //! } 405 | //! assert!(db.close()); 406 | //! } 407 | //! 408 | //! // If we only wanted one Table and didn't care about ever getting the 409 | //! // Database back, we don't even need a reference. 410 | //! fn by_value() { 411 | //! let db = Database::new(); 412 | //! let table = Table::new(db); 413 | //! do_stuff(&table); 414 | //! } 415 | //! 416 | //! // And we can declare our holds-everything struct by using `Arc`s to deal 417 | //! // with ownership. 418 | //! struct Resources { 419 | //! db: Arc, 420 | //! table: Table<'static>, 421 | //! } 422 | //! impl Resources { 423 | //! fn new() -> Self { 424 | //! let db = Arc::new(Database::new()); 425 | //! let table = Table::new(db.clone()); 426 | //! Resources { db: db, table: table } 427 | //! } 428 | //! 429 | //! fn close(self) -> bool { 430 | //! drop(self.table); 431 | //! Arc::try_unwrap(self.db).ok().unwrap().close() 432 | //! } 433 | //! } 434 | //! 435 | //! fn with_struct() { 436 | //! let res = Resources::new(); 437 | //! do_stuff(&res.table); 438 | //! assert!(res.close()); 439 | //! } 440 | //! 441 | //! # #[allow(unused_variables)] 442 | //! fn do_stuff(table: &Table) { 443 | //! // Stuff 444 | //! } 445 | //! 446 | //! ``` 447 | //! 448 | //! # Conversions 449 | //! 450 | //! To facilitate client API designs, `Supercow` converts (via `From`/`Into`) 451 | //! from a number of things. Unfortunately, due to trait coherence rules, this 452 | //! does not yet apply in all cases where one might hope. The currently 453 | //! available conversions are: 454 | //! 455 | //! - The `OWNED` type into an owned `Supercow`. This applies without 456 | //! restriction. 457 | //! 458 | //! - A reference to the `OWNED` type. References to a different `BORROWED` 459 | //! type are currently not convertible; `Supercow::borrowed()` will be needed 460 | //! to construct the `Supercow` explicitly. 461 | //! 462 | //! - `Rc` and `Arc` for `Supercow`s where `OWNED` and `BORROWED` 463 | //! are the exact same type, and where the `Rc` or `Arc` can be converted into 464 | //! `SHARED` via `supercow::ext::SharedFrom`. If `OWNED` and `BORROWED` are 465 | //! different types, `Supercow::shared()` will be needed to construct the 466 | //! `Supercow` explicitly. 467 | //! 468 | //! # Advanced 469 | //! 470 | //! ## Variance 471 | //! 472 | //! `Supercow` is covariant on its lifetime and all its type parameters, except 473 | //! for `SHARED` which is invariant. The default `SHARED` type for both 474 | //! `Supercow` and `NonSyncSupercow` uses the `'static` lifetime, so simple 475 | //! `Supercow`s are in general covariant. 476 | //! 477 | //! ``` 478 | //! use std::rc::Rc; 479 | //! 480 | //! use supercow::Supercow; 481 | //! 482 | //! fn assert_covariance<'a, 'b: 'a>( 483 | //! imm: Supercow<'b, u32>, 484 | //! bor: &'b Supercow<'b, u32>) 485 | //! { 486 | //! let _imm_a: Supercow<'a, u32> = imm; 487 | //! let _bor_aa: &'a Supercow<'a, u32> = bor; 488 | //! let _bor_ab: &'a Supercow<'b, u32> = bor; 489 | //! // Invalid, since the external `&'b` reference is declared to live longer 490 | //! // than the internal `&'a` reference. 491 | //! // let _bor_ba: &'b Supercow<'a, u32> = bor; 492 | //! } 493 | //! 494 | //! # fn main() { } 495 | //! ``` 496 | //! 497 | //! ## `Sync` and `Send` 498 | //! 499 | //! A `Supercow` is `Sync` and `Send` iff the types it contains, including the 500 | //! shared reference type, are. 501 | //! 502 | //! ``` 503 | //! use supercow::Supercow; 504 | //! 505 | //! fn assert_sync_and_send(_: T) { } 506 | //! fn main() { 507 | //! let s: Supercow = Supercow::owned(42); 508 | //! assert_sync_and_send(s); 509 | //! } 510 | //! ``` 511 | //! 512 | //! ## Shared Reference Type 513 | //! 514 | //! The third type parameter type to `Supercow` specifies the shared reference 515 | //! type. 516 | //! 517 | //! The default is `Box>`, which is a boxed trait 518 | //! object describing the features a shared reference type must have while 519 | //! allowing any such reference to be used without needing a generic type 520 | //! argument. 521 | //! 522 | //! An alternate feature set can be found in `NonSyncFeatures`, which is also 523 | //! usable through the `NonSyncSupercow` typedef (which also makes it 524 | //! `'static`). You can create custom feature traits in this style with 525 | //! `supercow_features!`. 526 | //! 527 | //! It is perfectly legal to use a non-`'static` shared reference type. In 528 | //! fact, the original design for `Supercow<'a>` used `DefaultFeatures<'a>`. 529 | //! However, a non-`'static` lifetime makes the system harder to use, and if 530 | //! entangled with `'a` on `Supercow`, makes the structure lifetime-invariant, 531 | //! which makes it much harder to treat as a reference. 532 | //! 533 | //! Boxing the shared reference and putting it behind a trait object both add 534 | //! overhead, of course. If you wish, you can use a real reference type in the 535 | //! third parameter as long as you are OK with losing the flexibility the 536 | //! boxing would provide. For example, 537 | //! 538 | //! ``` 539 | //! use std::rc::Rc; 540 | //! 541 | //! use supercow::Supercow; 542 | //! 543 | //! # fn main() { 544 | //! let x: Supercow> = Supercow::shared(Rc::new(42u32)); 545 | //! println!("{}", *x); 546 | //! # } 547 | //! ``` 548 | //! 549 | //! Note that you may need to provide an identity `supercow::ext::SharedFrom` 550 | //! implementation if you have a custom reference type. 551 | //! 552 | //! ## Storage Type 553 | //! 554 | //! When in owned or shared mode, a `Supercow` needs someplace to store the 555 | //! `OWNED` or `SHARED` value itself. This can be customised with the fourth 556 | //! type parameter (`STORAGE`), and the `OwnedStorage` trait. Two strategies 557 | //! are provided by this crate: 558 | //! 559 | //! - `BoxedStorage` puts everything behind `Box`es. This has the advantage 560 | //! that the `Supercow` structure is only one pointer wider than a basic 561 | //! reference, and results in a faster `Deref`. The obvious drawback is that 562 | //! you pay for allocations on construction. This is the default with 563 | //! `Supercow` and `NonSyncSupercow`. 564 | //! 565 | //! - `InlineStorage` uses an `enum` to store the values inline in the 566 | //! `Supercow`, thus incurring no allocation, but making the `Supercow` itself 567 | //! bigger. This is easily available via the `InlineSupercow` and 568 | //! `InlineNonSyncSupercow` types. 569 | //! 570 | //! If you find some need, you can define custom storage types, though note 571 | //! that the trait is quite unsafe and somewhat subtle. 572 | //! 573 | //! ## `PTR` type 574 | //! 575 | //! The `PTR` type is used to consolidate the implementations of `Supercow` and 576 | //! `Phantomcow`; there is likely little, if any, use for ever using anything 577 | //! other than `*const BORROWED` or `()` here. 578 | //! 579 | //! # Performance Considerations 580 | //! 581 | //! ## Construction Cost 582 | //! 583 | //! Since it inherently moves certain decisions about ownership from 584 | //! compile-time to run-time, `Supercow` is obviously not as fast as using an 585 | //! owned value directly or a reference directly. 586 | //! 587 | //! Constructing any kind of `Supercow` with a normal reference is very fast, 588 | //! only requiring a bit of internal memory initialisation besides setting the 589 | //! reference itself. 590 | //! 591 | //! The default `Supercow` type boxes the owned type and double-boxes the shared 592 | //! type. This obviously dominates construction cost in those cases. 593 | //! 594 | //! `InlineSupercow` eliminates one box layer. This means that constructing an 595 | //! owned instance is simply a move of the owned structure plus the common 596 | //! reference initialisation. Shared values still by default require one boxing 597 | //! level as well as virtual dispatch on certain operations; as described 598 | //! above, this property too can be dealt with by using a custom `SHARED` type. 599 | //! 600 | //! ## Destruction Cost 601 | //! 602 | //! Destroying a `Supercow` is roughly the same proportional cost of creating 603 | //! it. 604 | //! 605 | //! ## `Deref` Cost 606 | //! 607 | //! For the default `Supercow` type, the `Deref` is exactly equivalent to 608 | //! dereferencing an `&&BORROWED`. 609 | //! 610 | //! For `InlineSupercow`, the implementation is a bit slower, comparable to 611 | //! `std::borrow::Cow` but with fewer memory accesses.. 612 | //! 613 | //! In all cases, the `Deref` implementation is not dependent on the ownership 614 | //! mode of the `Supercow`, and so is not affected by the shared reference 615 | //! type, most importantly, making no virtual function calls even under the 616 | //! default boxed shared reference type. However, the way it works could 617 | //! prevent LLVM optimisations from applying in particular circumstances. 618 | //! 619 | //! For those wanting specifics, the function 620 | //! 621 | //! ```ignore 622 | //! // Substitute Cow with InlineSupercow for the other case. 623 | //! // This takes references so that the destructor code is not intermingled. 624 | //! fn add_two(a: &Cow, b: &Cow) -> u32 { 625 | //! **a + **b 626 | //! } 627 | //! ``` 628 | //! 629 | //! results in the following on AMD64 with Rust 1.13.0: 630 | //! 631 | //! ```text 632 | //! Cow Supercow 633 | //! cmp DWORD PTR [rdi],0x1 mov rcx,QWORD PTR [rdi] 634 | //! lea rcx,[rdi+0x4] xor eax,eax 635 | //! cmovne rcx,QWORD PTR [rdi+0x8] cmp rcx,0x800 636 | //! cmp DWORD PTR [rsi],0x1 cmovae rdi,rax 637 | //! lea rax,[rsi+0x4] mov rdx,QWORD PTR [rsi] 638 | //! cmovne rax,QWORD PTR [rsi+0x8] cmp rdx,0x800 639 | //! mov eax,DWORD PTR [rax] cmovb rax,rsi 640 | //! add eax,DWORD PTR [rcx] mov eax,DWORD PTR [rax+rdx] 641 | //! ret add eax,DWORD PTR [rdi+rcx] 642 | //! ret 643 | //! ``` 644 | //! 645 | //! The same code on ARM v7l and Rust 1.12.1: 646 | //! 647 | //! ```text 648 | //! Cow Supercow 649 | //! push {fp, lr} ldr r2, [r0] 650 | //! mov r2, r0 ldr r3, [r1] 651 | //! ldr r3, [r2, #4]! cmp r2, #2048 652 | //! ldr ip, [r0] addcc r2, r2, r0 653 | //! mov r0, r1 cmp r3, #2048 654 | //! ldr lr, [r0, #4]! addcc r3, r3, r1 655 | //! ldr r1, [r1] ldr r0, [r2] 656 | //! cmp ip, #1 ldr r1, [r3] 657 | //! moveq r3, r2 add r0, r1, r0 658 | //! cmp r1, #1 bx lr 659 | //! ldr r2, [r3] 660 | //! moveq lr, r0 661 | //! ldr r0, [lr] 662 | //! add r0, r0, r2 663 | //! pop {fp, pc} 664 | //! ``` 665 | //! 666 | //! If the default `Supercow` is used above instead of `InlineSupercow`, the 667 | //! function actually compiles to the same thing as one taking two `&u32` 668 | //! arguments. (This is partially due to optimisations eliminating one level of 669 | //! indirection; if the optimiser did not do as much, it would be equivalent to 670 | //! taking two `&&u32` arguments.) 671 | //! 672 | //! ## `to_mut` Cost 673 | //! 674 | //! Obtaining a `Ref` is substantially more expensive than `Deref`, as it must 675 | //! inspect the ownership mode of the `Supercow` and possibly move it into the 676 | //! owned mode. This will include a virtual call to the boxed shared reference 677 | //! if in shared mode when using the default `Supercow` shared reference type. 678 | //! 679 | //! There is also cost in releasing the mutable reference, though 680 | //! insubstantial in comparison. 681 | //! 682 | //! ## Memory Usage 683 | //! 684 | //! The default `Supercow` is only one pointer wider than a mundane reference 685 | //! on Rust 1.13.0 and later. Earlier Rust versions have an extra word due to 686 | //! the drop flag. 687 | //! 688 | //! ``` 689 | //! use std::mem::size_of; 690 | //! 691 | //! use supercow::Supercow; 692 | //! 693 | //! // Determine the size of the drop flag including alignment padding. 694 | //! // On Rust 0.13.0+, `dflag` will be zero. 695 | //! struct DropFlag(*const ()); 696 | //! impl Drop for DropFlag { fn drop(&mut self) { } } 697 | //! let dflag = size_of::() - size_of::<*const ()>(); 698 | //! 699 | //! assert_eq!(size_of::<&'static u32>() + size_of::<*const ()>() + dflag, 700 | //! size_of::>()); 701 | //! 702 | //! assert_eq!(size_of::<&'static str>() + size_of::<*const ()>() + dflag, 703 | //! size_of::>()); 704 | //! ``` 705 | //! 706 | //! Of course, you also pay for heap space in this case when using owned or 707 | //! shared `Supercow`s. 708 | //! 709 | //! `InlineSupercow` can be quite large in comparison to a normal reference. 710 | //! You need to be particularly careful that structures you reference don't 711 | //! themselves contain `InlineSupercow`s or you can end up with 712 | //! quadratically-sized or even exponentially-sized structures. 713 | //! 714 | //! ``` 715 | //! use std::mem; 716 | //! 717 | //! use supercow::InlineSupercow; 718 | //! 719 | //! // Define our structures 720 | //! struct Big([u8;1024]); 721 | //! struct A<'a>(InlineSupercow<'a, Big>); 722 | //! struct B<'a>(InlineSupercow<'a, A<'a>>); 723 | //! struct C<'a>(InlineSupercow<'a, B<'a>>); 724 | //! 725 | //! // Now say an API consumer, etc, decides to use references 726 | //! let big = Big([0u8;1024]); 727 | //! let a = A((&big).into()); 728 | //! let b = B((&a).into()); 729 | //! let c = C((&b).into()); 730 | //! 731 | //! // Well, we've now allocated space for four `Big`s on the stack, despite 732 | //! // only really needing one. 733 | //! assert!(mem::size_of_val(&big) + mem::size_of_val(&a) + 734 | //! mem::size_of_val(&b) + mem::size_of_val(&c) > 735 | //! 4 * mem::size_of::()); 736 | //! ``` 737 | //! 738 | //! # Other Notes 739 | //! 740 | //! Using `Supercow` will not give your application `apt-get`-style Super Cow 741 | //! Powers. 742 | 743 | pub mod ext; 744 | 745 | use std::borrow::Borrow; 746 | use std::cmp; 747 | use std::convert::AsRef; 748 | use std::fmt; 749 | use std::hash::{Hash, Hasher}; 750 | use std::marker::PhantomData; 751 | use std::mem; 752 | use std::ops::{Deref, DerefMut}; 753 | use std::ptr; 754 | use std::rc::Rc; 755 | use std::sync::Arc; 756 | 757 | use self::ext::*; 758 | 759 | /// Defines a "feature set" for a custom `Supercow` type. 760 | /// 761 | /// ## Syntax 762 | /// 763 | /// ``` 764 | /// #[macro_use] extern crate supercow; 765 | /// 766 | /// # pub trait SomeTrait { } 767 | /// # pub trait AnotherTrait { } 768 | /// 769 | /// supercow_features!( 770 | /// /// Some documentation, etc, if desired. 771 | /// pub trait FeatureName: SomeTrait, AnotherTrait); 772 | /// supercow_features!( 773 | /// pub trait FeatureName2: SomeTrait, Clone, AnotherTrait); 774 | /// 775 | /// # fn main() { } 776 | /// ``` 777 | /// 778 | /// ## Semantics 779 | /// 780 | /// A public trait named `FeatureName` is defined which extends all the listed 781 | /// traits, minus special cases below. 782 | /// 783 | /// If `Clone` is listed, the trait gains a `clone_boxed()` method and 784 | /// `Box` is `Clone`. 785 | /// 786 | /// If `TwoStepShared(SomeType)` is listed, the boxed type will implement 787 | /// `TwoStepShared` for all `OWNED`/`BORROWED` pairs where 788 | /// `SomeType` implements the feature a whole and 789 | /// `OWNED: SafeBorrow`. 790 | /// 791 | /// All types which implement all the listed traits (including special cases) 792 | /// implement `FeatureName`. 793 | 794 | // Historical note: Originally, the shared type was required to implement 795 | // `ConstDeref`, and so the shared type was `Box<$feature>`. 796 | // This mostly worked, but it confused lifetime inference in a number of 797 | // cases, particularly surrounding variance. Because of that, we instead have 798 | // stricter requirements on a number of traits (including making `SharedFrom` 799 | // unsafe) so that we can pull the pointer out of the non-boxed shared 800 | // reference and hold onto it thereon out, thus obviating the need for `SHARED` 801 | // to carry that part of the type information. 802 | #[macro_export] 803 | macro_rules! supercow_features { 804 | // Since we have special cases (and sometimes syntax) for the trait list, 805 | // handling the trait list is a bit difficult. Basically, we need to 806 | // massage it into a form where we can properly match everything at once. 807 | // 808 | // What we basically do here is match the head token tree one at a time, 809 | // and move it into one of several bracketed lists that come before the 810 | // unparsed list. This allows us to match the special cases. 811 | // 812 | // The bracketed lists are: 813 | // 814 | // - Clone. Either empty or `[Clone clone_boxed]`. There needs to be 815 | // useful tokens to match here so that we can "iterate" over them to 816 | // conditionally generate related code. 817 | // 818 | // - Two-step. Contains just the bare inner type. We "iterate" over the 819 | // type to conditionally generate the related code. 820 | // 821 | // - Everything else. A comma-separated list of identifiers. 822 | ($(#[$meta:meta])* pub trait $feature_name:ident: $($stuff:tt)*) => { 823 | supercow_features!(@_ACCUM $(#[$meta])* pub trait $feature_name: 824 | [] [] [] $($stuff)*); 825 | }; 826 | 827 | // Special case for Clone 828 | (@_ACCUM $(#[$meta:meta])* pub trait $feature_name:ident: 829 | $clone:tt $twostep:tt [$($others:tt),*] Clone $($more:tt)*) => { 830 | supercow_features!(@_ACCUM $(#[$meta])* pub trait $feature_name: 831 | [Clone clone_boxed] $twostep [$($others)*] 832 | $($more)*); 833 | }; 834 | 835 | // Special case for Two-Step 836 | (@_ACCUM $(#[$meta:meta])* pub trait $feature_name:ident: 837 | $clone:tt $twostep:tt [$($others:tt),*] 838 | TwoStepShared($($inner:tt)*) 839 | $($more:tt)*) => { 840 | supercow_features!(@_ACCUM $(#[$meta])* pub trait $feature_name: 841 | $clone [$($inner)*] [$($others)*] 842 | $($more)*); 843 | }; 844 | 845 | // Since we match token-trees instead of identifiers or similar, we get 846 | // comma as a bare token. Simply throw it away. 847 | // 848 | // This does mean people can invoke the macro without the commata, though 849 | // we don't officially support it. It would be possible to adjust the macro 850 | // to reject invocations missing commas, but there the error would not be 851 | // particularly clear, so for now just be tolerant. 852 | (@_ACCUM $(#[$meta:meta])* pub trait $feature_name:ident: 853 | $clone:tt $twostep:tt [$($others:tt),*], $($more:tt)*) => { 854 | supercow_features!(@_ACCUM $(#[$meta])* pub trait $feature_name: 855 | $clone $twostep [$($others)*] $($more)*); 856 | }; 857 | 858 | // General case for non-special traits. 859 | (@_ACCUM $(#[$meta:meta])* pub trait $feature_name:ident: 860 | $clone:tt $twostep:tt [$($others:ident),*] $other:ident $($more:tt)*) => { 861 | supercow_features!(@_ACCUM $(#[$meta])* pub trait $feature_name: 862 | $clone $twostep [$($others, )* $other] 863 | $($more)*); 864 | }; 865 | 866 | // Once there's no unexamined items left, we can actually fall through to 867 | // defining stuff. 868 | (@_ACCUM $(#[$meta:meta])* pub trait $feature_name:ident: 869 | $clone:tt $twostep:tt [$($others:ident),*]) => { 870 | supercow_features!(@_DEFINE $(#[$meta])* pub trait $feature_name: 871 | $clone $twostep [$($others),*]); 872 | }; 873 | 874 | (@_DEFINE $(#[$meta:meta])* 875 | pub trait $feature_name:ident: 876 | [$($clone:ident $clone_boxed:ident)*] 877 | [$($twostep_inner:ident)*] 878 | [$($req:ident),*]) => { 879 | $(#[$meta])* 880 | pub trait $feature_name<'a>: $($req +)* 'a { 881 | // NB "Iterate" over the clone section to conditionally generate 882 | // this code. 883 | $( 884 | /// Clone this value, and then immediately put it into a `Box` 885 | /// behind a trait object of this trait. 886 | fn $clone_boxed(&self) -> Box<$feature_name<'a> + 'a>; 887 | )* 888 | 889 | /// Returns the address of `self`. 890 | /// 891 | /// This is used to disassemble trait objects of this trait without 892 | /// resorting to transmuting or the unstable `TraitObject` type. 893 | fn self_address_mut(&mut self) -> *mut (); 894 | } 895 | impl<'a, T : 'a + $($req +)* $($clone +)* Sized> 896 | $feature_name<'a> for T { 897 | $( 898 | fn $clone_boxed(&self) -> Box<$feature_name<'a> + 'a> { 899 | let cloned: T = self.clone(); 900 | Box::new(cloned) 901 | } 902 | )* 903 | 904 | fn self_address_mut(&mut self) -> *mut () { 905 | self as *mut Self as *mut () 906 | } 907 | } 908 | // This implementation is safe -- all we do is move `T`, so if `T` is 909 | // `ConstDeref`, its returned address will not be affected. 910 | unsafe impl<'a, T : $feature_name<'a>> $crate::ext::SharedFrom 911 | for Box<$feature_name<'a> + 'a> { 912 | fn shared_from(t: T) -> Self { 913 | Box::new(t) 914 | } 915 | } 916 | $( 917 | impl<'a> $clone for Box<$feature_name<'a> + 'a> { 918 | fn clone(&self) -> Self { 919 | $feature_name::clone_boxed(&**self) 920 | } 921 | } 922 | )* 923 | $( 924 | impl<'a, S : 'a + ?Sized, T : 'a> $crate::ext::TwoStepShared 925 | for Box<$feature_name<'a> + 'a> 926 | where T : $crate::ext::SafeBorrow, 927 | $twostep_inner : $feature_name<'a> { 928 | fn new_two_step() -> Self { 929 | Box::new( 930 | <$twostep_inner as $crate::ext::TwoStepShared>:: 931 | new_two_step()) 932 | } 933 | 934 | unsafe fn deref_holder(&mut self) -> &mut Option { 935 | <$twostep_inner as $crate::ext::TwoStepShared>:: 936 | deref_holder( 937 | // Unsafe downcast from $feature_name to the declared 938 | // two-step type. This is safe since the contract of 939 | // `deref_holder()` guarantees that this value was 940 | // constructed by `new_two_step()`. 941 | &mut* ($feature_name::self_address_mut(&mut **self) 942 | as *mut $twostep_inner)) 943 | } 944 | } 945 | )* 946 | }; 947 | } 948 | 949 | supercow_features!( 950 | /// The default shared reference type for `Supercow`. 951 | /// 952 | /// This requires the shared reference type to be `Clone`, `Send`, and 953 | /// `Sync`, which thus disqualifies using `Rc`. This was chosen as the 954 | /// default since the inability to use `Rc` is generally a less subtle 955 | /// issue than the `Supercow` not being `Send` or `Sync`. 956 | /// 957 | /// See also `NonSyncFeatures`. 958 | pub trait DefaultFeatures: Clone, TwoStepShared(TwoStepArc), Send, Sync); 959 | supercow_features!( 960 | /// The shared reference type for `NonSyncSupercow`. 961 | /// 962 | /// Unlike `DefaultFeatures`, this only requires the shared reference type 963 | /// to be `Clone`, thus permitting `Rc`. 964 | pub trait NonSyncFeatures: Clone, TwoStepShared(TwoStepRc)); 965 | 966 | /// `Supercow` with the default `SHARED` changed to `NonSyncFeatures`, enabling 967 | /// the use of `Rc` as a shared reference type as well as making it possible to 968 | /// use non-`Send` or non-`Sync` `BORROWED` types easily. 969 | /// 970 | /// Note that the `SHARED` type must have `'static` lifetime, since this is 971 | /// generally more convenient and makes the `Supercow` as a whole covariant. 972 | /// 973 | /// ## Example 974 | /// 975 | /// ``` 976 | /// use supercow::{NonSyncSupercow, Supercow}; 977 | /// 978 | /// # fn main() { 979 | /// let x: NonSyncSupercow = Supercow::owned(42u32); 980 | /// println!("{}", *x); 981 | /// # } 982 | /// ``` 983 | pub type NonSyncSupercow<'a, OWNED, BORROWED = OWNED> = 984 | Supercow<'a, OWNED, BORROWED, 985 | Box + 'static>, 986 | BoxedStorage>; 987 | 988 | /// `Supercow` with the default `STORAGE` changed to `InlineStorage`. 989 | /// 990 | /// This reduces the number of allocations needed to construct an owned or 991 | /// shared `Supercow` (down to zero for owned, but note that the default 992 | /// `SHARED` still has its own `Box`) at the cost of bloating the `Supercow` 993 | /// itself, as it now needs to be able to fit a whole `OWNED` instance. 994 | pub type InlineSupercow<'a, OWNED, BORROWED = OWNED, 995 | SHARED = Box + 'static>> = 996 | Supercow<'a, OWNED, BORROWED, SHARED, InlineStorage>; 997 | 998 | /// `NonSyncSupercow` with the `STORAGE` changed to `InlineStorage`. 999 | /// 1000 | /// This combines both properties of `NonSyncSupercow` and `InlineSupercow`. 1001 | pub type InlineNonSyncSupercow<'a, OWNED, BORROWED = OWNED> = 1002 | Supercow<'a, OWNED, BORROWED, 1003 | Box + 'static>, 1004 | InlineStorage + 'static>>>; 1005 | 1006 | /// The actual generic reference type. 1007 | /// 1008 | /// See the module documentation for most of the details. 1009 | /// 1010 | /// Most of the generics requirements you don't need to pay too much attention 1011 | /// to if you aren't making custom `SHARED` or `STORAGE` types, etc. In 1012 | /// general: 1013 | /// 1014 | /// - `OWNED` may be constrained to be `Clone` and/or `BORROWED` as `ToOwned` 1015 | /// if cloning an inner value is needed. 1016 | /// 1017 | /// - External traits are defined against `BORROWED`. 1018 | /// 1019 | /// - `PTR : PtrRead` means the operation is not available on 1020 | /// `Phantomcow`. 1021 | pub struct Supercow<'a, OWNED, BORROWED : ?Sized = OWNED, 1022 | SHARED = Box + 'static>, 1023 | STORAGE = BoxedStorage, PTR = *const BORROWED> 1024 | where BORROWED : 'a, 1025 | *const BORROWED : PointerFirstRef, 1026 | STORAGE : OwnedStorage, 1027 | PTR : PtrWrite { 1028 | // This stores the precalculated `Deref` target, and is the only thing the 1029 | // `Deref` implementation needs to inspect. 1030 | // 1031 | // Note that there are three cases with this pointer: 1032 | // 1033 | // - A pointer to an external value. In this case, we know that the pointer 1034 | // will not be invalidated by movement or for the lifetime of `'a` and 1035 | // simply store the reference here as an absolute address. 1036 | // 1037 | // - A pointer to a ZST at an "external" location, often address 1. We 1038 | // don't need to handle this in any particular manner as long as we don't 1039 | // accidentally make a null reference during deref(), since the only thing 1040 | // safe rust can do with a ZST reference is inspect its address, and if we 1041 | // do "move" it around, there's nothing unsafe from this fact being leaked. 1042 | // 1043 | // - A pointer into this `Supercow`. In this case, the absolute address 1044 | // will change whenever this `Supercow` is relocated. To handle this, we 1045 | // instead store the offset from `&self` here, and adjust it at `Deref` 1046 | // time. We differentiate between the two cases by inspecting the absolute 1047 | // value of the address: If it is less than 1048 | // `MAX_INTERNAL_BORROW_DISPLACEMENT*2`, we assume it is an internal 1049 | // pointer, since no modern system ever has virtual memory mapped between 0 1050 | // and 4kB (and any code elsewhere involving this region is presumably too 1051 | // low-level to be using `Supercow`). 1052 | // 1053 | // One peculiarity is that this is declared as a typed pointer even though 1054 | // it does not necessarily point to anything (due to internal pointers). 1055 | // This is so that it works with DSTs, which have pointers larger than 1056 | // simple machine pointers. We assume the first pointer-sized value is the 1057 | // actual address (see `PointerFirstRef`). 1058 | // 1059 | // If `STORAGE` does not use internal pointers, we can skip all the 1060 | // arithmetic and return this value unmodified. 1061 | ptr: PTR, 1062 | // The current ownership mode of this `Supercow`. 1063 | // 1064 | // This has three states: 1065 | // 1066 | // - Null. The `Supercow` holds a `&'a BORROWED`. 1067 | // 1068 | // - Even alignment. The `Supercow` holds an `OWNED` accessible via 1069 | // `STORAGE` field a, and this value is what is passed into the `STORAGE` 1070 | // methods. 1071 | // 1072 | // - Odd alignment. The `Supercow` holds a `SHARED`, accessible via 1073 | // `STORAGE` field b, with a pointer value one less than this one. Note 1074 | // that since the default `SHARED` is a `Box`, we actually 1075 | // end up with two levels of boxing here for `BoxedStorage`. This is 1076 | // actually necessary so that the whole thing only takes one immediate 1077 | // pointer. 1078 | mode: *mut (), 1079 | storage: STORAGE, 1080 | 1081 | _owned: PhantomData, 1082 | _borrowed: PhantomData<&'a BORROWED>, 1083 | _shared: PhantomData, 1084 | } 1085 | 1086 | /// `Phantomcow<'a, Type>` is to `Supercow<'a, Type>` as 1087 | /// `PhantomData<&'a Type>` is to `&'a Type`. 1088 | /// 1089 | /// That is, `Phantomcow` effects a lifetime dependency on the borrowed value, 1090 | /// while still permitting the owned and shared modes of `Supercow`, and 1091 | /// keeping the underlying objects alive as necessary. 1092 | /// 1093 | /// There is not much one can do with a `Phantomcow`; it can be moved around, 1094 | /// and in some cases cloned. Its main use is in FFI wrappers, where `BORROWED` 1095 | /// maintains some external state or resource that will be destroyed when it 1096 | /// is, and which the owner of the `Phantomcow` depends on to function. 1097 | /// 1098 | /// The size of a `Phantomcow` is generally equal to the size of the 1099 | /// corresponding `Supercow` type minus the size of `&'a BORROWED`, though this 1100 | /// may not be exact depending on `STORAGE` alignment, etc. 1101 | pub type Phantomcow<'a, OWNED, BORROWED = OWNED, 1102 | SHARED = Box + 'static>, 1103 | STORAGE = BoxedStorage> = 1104 | Supercow<'a, OWNED, BORROWED, SHARED, STORAGE, ()>; 1105 | 1106 | /// The `Phantomcow` variant corresponding to `NonSyncSupercow`. 1107 | pub type NonSyncPhantomcow<'a, OWNED, BORROWED = OWNED> = 1108 | Phantomcow<'a, OWNED, BORROWED, Box + 'static>, 1109 | BoxedStorage>; 1110 | 1111 | /// The `Phantomcow` variant corresponding to `InlineStorage`. 1112 | pub type InlinePhantomcow<'a, OWNED, BORROWED = OWNED, 1113 | SHARED = Box + 'static>> = 1114 | Phantomcow<'a, OWNED, BORROWED, SHARED, InlineStorage>; 1115 | 1116 | /// The `Phantomcow` variant corresponding to `InlineNonSyncSupercow`. 1117 | pub type InlineNonSyncPhantomcow<'a, OWNED, BORROWED = OWNED> = 1118 | Phantomcow<'a, OWNED, BORROWED, Box + 'static>, 1119 | InlineStorage + 'static>>>; 1120 | 1121 | enum SupercowMode { 1122 | Owned(*mut ()), 1123 | Borrowed, 1124 | Shared(*mut ()), 1125 | } 1126 | 1127 | impl SupercowMode { 1128 | fn from_ptr(mode: *mut ()) -> Self { 1129 | if mode.is_null() { 1130 | Borrowed 1131 | } else if mode.is_2_aligned() { 1132 | Owned(mode) 1133 | } else { 1134 | Shared(mode.align2()) 1135 | } 1136 | } 1137 | } 1138 | 1139 | use self::SupercowMode::*; 1140 | 1141 | macro_rules! defimpl { 1142 | ($(@$us:tt)* [$($tparm:ident $(: ?$tparmsized:ident)*),*] ($($spec:tt)*) 1143 | where { $($wo:tt)* } $body:tt) => { 1144 | $($us)* impl<'a, $($tparm $(: ?$tparmsized)*,)* OWNED, 1145 | BORROWED : ?Sized, SHARED, STORAGE, PTR> 1146 | $($spec)* Supercow<'a, OWNED, BORROWED, SHARED, STORAGE, PTR> 1147 | where BORROWED : 'a, 1148 | *const BORROWED : PointerFirstRef, 1149 | STORAGE : OwnedStorage, 1150 | PTR : PtrWrite, 1151 | $($wo)* 1152 | $body 1153 | } 1154 | } 1155 | 1156 | defimpl! {[] (Drop for) where { } { 1157 | fn drop(&mut self) { 1158 | match self.mode() { 1159 | Owned(ptr) => unsafe { self.storage.deallocate_a(ptr) }, 1160 | Shared(ptr) => unsafe { self.storage.deallocate_b(ptr) }, 1161 | Borrowed => (), 1162 | } 1163 | } 1164 | } } 1165 | 1166 | defimpl! {@unsafe [] (Send for) where { 1167 | OWNED : Send, 1168 | &'a BORROWED : Send, 1169 | SHARED : Send, 1170 | STORAGE : Send, 1171 | } { } } 1172 | 1173 | defimpl! {@unsafe [] (Sync for) where { 1174 | OWNED : Sync, 1175 | &'a BORROWED : Sync, 1176 | SHARED : Sync, 1177 | STORAGE : Sync, 1178 | } { } } 1179 | 1180 | defimpl! {[] () where { } { 1181 | /// Creates a new `Supercow` which owns the given value. 1182 | /// 1183 | /// This can create a `Supercow` with a `'static` lifetime. 1184 | pub fn owned(inner: OWNED) -> Self 1185 | where OWNED : SafeBorrow { 1186 | // Safety: The invalid `ptr` does not escape; either the function sets 1187 | // it properly, or panics and the value is destroyed. 1188 | let mut this = unsafe { Self::empty() }; 1189 | this.mode = this.storage.allocate_a(inner); 1190 | // This line could panic, but the only thing that has not yet been 1191 | // initialised properly is `ptr`, which is immaterial since the 1192 | // `Supercow` will not escape this frame if this panics, and `Drop` 1193 | // does not care about `ptr`. 1194 | // 1195 | // Safety: We know that the value is in owned mode since we just 1196 | // constructed it. 1197 | unsafe { this.borrow_owned(); } 1198 | this 1199 | } 1200 | 1201 | /// Creates a new `Supercow` which borrows the given value. 1202 | pub fn borrowed + ?Sized>(inner: &'a T) -> Self { 1203 | // Safety: The invalid `ptr` value will be overwritten before this 1204 | // function returns, and the value is destroyed on panic. 1205 | let mut this = unsafe { Self::empty() }; 1206 | // No need to write to `mode`; `empty()` returns a borrowed-mode 1207 | // `Supercow`. 1208 | this.ptr.store_ptr(inner.borrow() as *const BORROWED); 1209 | this 1210 | } 1211 | 1212 | /// Creates a new `Supercow` using the given shared reference. 1213 | /// 1214 | /// The reference must be convertible to `SHARED` via `SharedFrom`. 1215 | pub fn shared(inner: T) -> Self 1216 | where T : ConstDeref, 1217 | SHARED : SharedFrom { 1218 | let mut ptr = PTR::new(); 1219 | ptr.store_ptr(inner.const_deref()); 1220 | Self::shared_nocvt(SHARED::shared_from(inner), ptr) 1221 | } 1222 | 1223 | fn shared_nocvt(shared: SHARED, ptr: PTR) -> Self { 1224 | // Safety: The invalid `ptr` value will be overwritten before this 1225 | // function returns, and the value is destroyed on panic. 1226 | let mut this = unsafe { Self::empty() }; 1227 | // If something panics below, `ptr` is may become a dangling pointer. 1228 | // That's fine, though, because the `Supercow` will not escape the 1229 | // frame and `Drop` does not inspect `ptr`. 1230 | this.ptr = ptr; 1231 | this.mode = this.storage.allocate_b(shared).unalign2() as *mut (); 1232 | this 1233 | } 1234 | 1235 | /// If `this` is non-owned, clone `this` and return it. 1236 | /// 1237 | /// Otherwise, return `None`. 1238 | /// 1239 | /// ## Example 1240 | /// 1241 | /// ``` 1242 | /// use supercow::Supercow; 1243 | /// 1244 | /// struct SomeNonCloneThing; 1245 | /// 1246 | /// let owned: Supercow = SomeNonCloneThing.into(); 1247 | /// assert!(Supercow::clone_non_owned(&owned).is_none()); 1248 | /// 1249 | /// let the_thing = SomeNonCloneThing; 1250 | /// let borrowed: Supercow = (&the_thing).into(); 1251 | /// let also_borrowed = Supercow::clone_non_owned(&borrowed).unwrap(); 1252 | /// ``` 1253 | pub fn clone_non_owned(this: &Self) -> Option 1254 | where SHARED : Clone { 1255 | match this.mode() { 1256 | Owned(_) => None, 1257 | 1258 | Borrowed => Some(Supercow { 1259 | ptr: this.ptr, 1260 | mode: this.mode, 1261 | storage: Default::default(), 1262 | _owned: PhantomData, 1263 | _borrowed: PhantomData, 1264 | _shared: PhantomData, 1265 | }), 1266 | 1267 | Shared(s) => Some(Self::shared_nocvt(unsafe { 1268 | // Safety: `mode` indicates we have storage b allocated. 1269 | this.storage.get_ptr_b(s) 1270 | }.clone(), this.ptr)), 1271 | } 1272 | } 1273 | 1274 | /// Logically clone `this` without needing to clone `OWNED`. 1275 | /// 1276 | /// If this `Supercow` is in owned mode, the owned value is first moved 1277 | /// into a new shared reference so that `OWNED` does not need to be cloned. 1278 | /// 1279 | /// ## Example 1280 | /// 1281 | /// ``` 1282 | /// use supercow::Supercow; 1283 | /// 1284 | /// struct NonCloneType(u32); 1285 | /// 1286 | /// let mut first: Supercow = 1287 | /// Supercow::owned(NonCloneType(42)); 1288 | /// let second = Supercow::share(&mut first); 1289 | /// 1290 | /// assert_eq!(42, (*first).0); 1291 | /// assert_eq!(42, (*second).0); 1292 | /// ``` 1293 | pub fn share(this: &mut Self) -> Self 1294 | where OWNED : SafeBorrow, 1295 | SHARED : Clone + TwoStepShared { 1296 | match this.mode() { 1297 | Owned(ptr) => { 1298 | let unboxed = SHARED::new_two_step(); 1299 | let mut new_storage: STORAGE = Default::default(); 1300 | let shared_ptr = new_storage.allocate_b(unboxed); 1301 | let internal_ptr: *const BORROWED = { 1302 | // `deref_holder` is technically allowed to panic. In 1303 | // practise it isn't expected to since any implementation 1304 | // would be trivial. If it *does*, we're still safe, but we 1305 | // may leak the storage allocated above. 1306 | let holder = unsafe { 1307 | // Safety: We just allocated new_storage b above. 1308 | new_storage.get_mut_b(shared_ptr) 1309 | .deref_holder() 1310 | }; 1311 | 1312 | // The natural way to determine `internal_ptr` below would 1313 | // be to first write into holder, then do 1314 | // internal_ptr = holder.as_ref().unwrap().borrow(); 1315 | // 1316 | // But this isn't safe since `borrow()` could panic and we 1317 | // have dangling pointers everywhere. 1318 | // 1319 | // But we can take advantage of three facts: 1320 | // 1321 | // - The memory returned by `borrow()` the last time we 1322 | // called it must remain valid during these operations 1323 | // since the owner is not being mutated. 1324 | // 1325 | // - Moving the owned value is just a `memcpy()`. This 1326 | // means anything outside of it remains valid and at the 1327 | // same address. 1328 | // 1329 | // - Anything _inside_ the owned value will be valid at the 1330 | // same relative position at whatever new address the value 1331 | // obtains below. 1332 | // 1333 | // So what we do instead is determine whether the borrowed 1334 | // value is internal or external and the calculate what the 1335 | // new borrowed address is by hand. 1336 | let owned_base = unsafe { 1337 | // Safety: `mode` indicates we are in owned mode and so 1338 | // have storage a allocated. 1339 | this.storage.get_ptr_a(ptr) 1340 | }.address(); 1341 | let owned_size = mem::size_of::(); 1342 | // Call borrow() again instead of using our own deref() 1343 | // since `Phantomcow` can't do the latter. 1344 | let borrowed_ptr = unsafe { 1345 | // Safety: `mode` indicates we are in owned mode and so 1346 | // have storage a allocated. 1347 | this.storage.get_ptr_a(ptr) 1348 | }.borrow() as *const BORROWED; 1349 | 1350 | // These steps need to be uninterrupted by safe function 1351 | // calls, as any panics would result in dangling pointers. 1352 | // 1353 | // Specifically: 1354 | // 1355 | // - `mode` is a dangling pointer until we both it and 1356 | // `storage` below. But we can't set storage until we've 1357 | // moved the value out of it. 1358 | // 1359 | // - `ptr` is a dangling pointer until we borrow the shared 1360 | // value below. Because of this, we can't eliminate the 1361 | // `mode` case by setting it to null, since we don't have 1362 | // anything `ptr` can legally point to. 1363 | *holder = Some(unsafe { 1364 | // Safety: `mode` indicates we are in owned mode and so 1365 | // have storage a allocated. 1366 | // 1367 | // See also comment above, as this operation causes 1368 | // `this.mode` and `this.ptr` to be invalid. 1369 | this.storage.deallocate_into_a(ptr) 1370 | }); 1371 | 1372 | if borrowed_ptr.within(owned_base, owned_size) { 1373 | // unwrap() won't panic since we just wrote `Some` 1374 | // above. 1375 | let new_base = holder.as_ref().unwrap().address(); 1376 | borrowed_ptr.rebase(owned_base, new_base) 1377 | } else { 1378 | borrowed_ptr 1379 | } 1380 | }; 1381 | this.storage = new_storage; 1382 | this.mode = shared_ptr.unalign2() as *mut (); 1383 | this.ptr.store_ptr(internal_ptr); 1384 | // End uninterrupted section 1385 | // `this.mode` now indicates shared mode, and `this.ptr` points 1386 | // into `this.storage` which has been replaced by 1387 | // `new_storage`. 1388 | 1389 | Self::shared_nocvt(unsafe { 1390 | // Safety: We just allocated new_storage b above and then 1391 | // moved it into this.storage. 1392 | this.storage.get_ptr_b(shared_ptr) 1393 | }.clone(), this.ptr) 1394 | }, 1395 | 1396 | Borrowed => Supercow { 1397 | ptr: this.ptr, 1398 | mode: this.mode, 1399 | storage: Default::default(), 1400 | _owned: PhantomData, 1401 | _borrowed: PhantomData, 1402 | _shared: PhantomData, 1403 | }, 1404 | 1405 | Shared(s) => Self::shared_nocvt(unsafe { 1406 | // Safety: `mode` indicates we have storage b allocated. 1407 | this.storage.get_ptr_b(s) 1408 | }.clone(), this.ptr), 1409 | } 1410 | } 1411 | 1412 | /// If `this` is borrowed, return the underlying reference with the 1413 | /// original lifetime. Otherwise, return `None`. 1414 | /// 1415 | /// The returned reference has a lifetime independent of `this`. 1416 | /// 1417 | /// This can be used to bridge between `Supercow` APIs and mundane 1418 | /// reference APIs without needing to restrict the lifetime to the 1419 | /// `Supercow`, but as a result is only available if the contained 1420 | /// reference is actually independent. 1421 | /// 1422 | /// ## Example 1423 | /// 1424 | /// ``` 1425 | /// use std::sync::Arc; 1426 | /// 1427 | /// use supercow::Supercow; 1428 | /// 1429 | /// let forty_two: u32 = 42; 1430 | /// 1431 | /// let borrowed: Supercow = (&forty_two).into(); 1432 | /// assert_eq!(Some(&forty_two), Supercow::extract_ref(&borrowed)); 1433 | /// 1434 | /// let owned: Supercow = forty_two.into(); 1435 | /// assert_eq!(None, Supercow::extract_ref(&owned)); 1436 | /// 1437 | /// let shared: Supercow = Arc::new(forty_two).into(); 1438 | /// assert_eq!(None, Supercow::extract_ref(&shared)); 1439 | /// ``` 1440 | pub fn extract_ref(this: &Self) -> Option<&'a BORROWED> 1441 | where PTR : PtrRead { 1442 | match this.mode() { 1443 | // Unsafe to turn the pointer (which we *know* to have lifetime 1444 | // at least 'a, *if* the mode is borrowed) into a reference. 1445 | Borrowed => Some(unsafe { &*this.ptr.get_ptr() }), 1446 | _ => None, 1447 | } 1448 | } 1449 | 1450 | /// Takes ownership of the underling value if needed, then returns it, 1451 | /// consuming `self`. 1452 | pub fn into_inner(mut this: Self) -> OWNED 1453 | where OWNED : Borrow, 1454 | BORROWED : ToOwned, 1455 | PTR : PtrRead { 1456 | match this.mode() { 1457 | Owned(ptr) => { 1458 | // Safety: `mode` indicates that storage a is allocated. 1459 | unsafe { this.storage.deallocate_into_a(ptr) } 1460 | }, 1461 | _ => (*this).to_owned(), 1462 | } 1463 | } 1464 | 1465 | /// Returns a (indirect) mutable reference to an underlying owned value. 1466 | /// 1467 | /// If this `Supercow` does not currently own the value, it takes 1468 | /// ownership. A `Ref` is then returned which allows accessing the mutable 1469 | /// owned value directly. 1470 | /// 1471 | /// ## Leak Safety 1472 | /// 1473 | /// If the returned `Ref` is released without its destructor being run, the 1474 | /// behaviour of the `Supercow` is unspecified (but does not result in 1475 | /// memory unsafety). 1476 | pub fn to_mut<'b>(&'b mut self) -> Ref<'b, Self> 1477 | where OWNED : SafeBorrow, 1478 | BORROWED : ToOwned, 1479 | PTR : PtrRead 1480 | { 1481 | // Become owned if not already. 1482 | match self.mode() { 1483 | Owned(_) => (), 1484 | _ => *self = Self::owned((*self).to_owned()), 1485 | } 1486 | 1487 | // Clear out `ptr` if it points somewhere unstable 1488 | let old_ptr = self.ptr.get_ptr(); 1489 | self.ptr.store_ptr(OWNED::borrow_replacement( 1490 | // Safety: We know old_ptr is a valid pointer for the lifetime of 1491 | // `self`; all we do here is turn it into a short-lived reference. 1492 | unsafe { &*old_ptr }) as *const BORROWED); 1493 | 1494 | Ref { 1495 | // Safety: We know that `self` is now in owned mode and so has 1496 | // storage a allocated. We also know that in owned mode, 1497 | // `self.mode` is the exact pointer value that storage returned. 1498 | r: unsafe { self.storage.get_mut_a(self.mode) } as *mut OWNED, 1499 | parent: self, 1500 | } 1501 | } 1502 | 1503 | /// If `this` is borrowed, clone the inner value so that the new `Supercow` 1504 | /// has a `'static` lifetime. 1505 | /// 1506 | /// If the inner value is owned or shared, this simply returns the input 1507 | /// unchanged. 1508 | /// 1509 | /// ## Example 1510 | /// 1511 | /// ``` 1512 | /// use supercow::Supercow; 1513 | /// 1514 | /// let s = { 1515 | /// let forty_two = 42u32; 1516 | /// let by_ref: Supercow = Supercow::borrowed(&forty_two); 1517 | /// // We can't return `by_ref` because it holds a reference to 1518 | /// // `forty_two`. However, we can change that lifetime parameter 1519 | /// // to `'static` and then move that out of the block. 1520 | /// let by_val: Supercow<'static, u32> = Supercow::unborrow(by_ref); 1521 | /// by_val 1522 | /// }; 1523 | /// assert_eq!(42, *s); 1524 | /// ``` 1525 | pub fn unborrow(mut this: Self) 1526 | -> Supercow<'static, OWNED, BORROWED, SHARED, STORAGE, PTR> 1527 | where OWNED : SafeBorrow, 1528 | BORROWED : ToOwned, 1529 | PTR : PtrRead { 1530 | // Call default() before the below in case it panics. 1531 | let new_storage = STORAGE::default(); 1532 | 1533 | match this.mode() { 1534 | Owned(_) | Shared(_) => Supercow { 1535 | ptr: this.ptr, 1536 | // mem::replace is critical for safety, otherwise we would 1537 | // double-free when `this` is dropped. 1538 | mode: mem::replace(&mut this.mode, ptr::null_mut()), 1539 | storage: mem::replace(&mut this.storage, new_storage), 1540 | _owned: PhantomData, 1541 | _borrowed: PhantomData, 1542 | _shared: PhantomData, 1543 | }, 1544 | 1545 | Borrowed => Supercow::owned((*this).to_owned()), 1546 | } 1547 | } 1548 | 1549 | /// Takes ownership of the underlying value, so that this `Supercow` has a 1550 | /// `'static` lifetime. 1551 | /// 1552 | /// This may also change the `SHARED` type parameter arbitrarily. 1553 | /// 1554 | /// ## Example 1555 | /// 1556 | /// ``` 1557 | /// use supercow::Supercow; 1558 | /// 1559 | /// let s = { 1560 | /// let forty_two = 42u32; 1561 | /// let by_ref: Supercow = Supercow::borrowed(&forty_two); 1562 | /// // We can't return `by_ref` because it holds a reference to 1563 | /// // `forty_two`. However, we can change that lifetime parameter 1564 | /// // to `'static` and then move that out of the block. 1565 | /// let by_val: Supercow<'static, u32> = 1566 | /// Supercow::take_ownership(by_ref); 1567 | /// by_val 1568 | /// }; 1569 | /// assert_eq!(42, *s); 1570 | /// ``` 1571 | pub fn take_ownership 1572 | (mut this: Self) -> Supercow<'static, OWNED, BORROWED, NS, STORAGE, PTR> 1573 | where OWNED : SafeBorrow, 1574 | BORROWED : ToOwned, 1575 | STORAGE : OwnedStorage, 1576 | PTR : PtrRead { 1577 | // Call default() before the below in case it panics 1578 | let new_storage = STORAGE::default(); 1579 | 1580 | match this.mode() { 1581 | // We can't just return `this` since we are changing the lifetime 1582 | // and possibly `STORAGE`. 1583 | Owned(_) => Supercow { 1584 | ptr: this.ptr, 1585 | // mem::replace is critical for safety, otherwise we would 1586 | // double-free when `this` is dropped. 1587 | mode: mem::replace(&mut this.mode, ptr::null_mut()), 1588 | storage: mem::replace(&mut this.storage, new_storage), 1589 | _owned: PhantomData, 1590 | _borrowed: PhantomData, 1591 | _shared: PhantomData, 1592 | }, 1593 | 1594 | _ => Supercow::owned((*this).to_owned()), 1595 | } 1596 | } 1597 | 1598 | /// Converts this `Supercow` into a `Phantomcow`. 1599 | pub fn phantom(mut this: Self) 1600 | -> Phantomcow<'a, OWNED, BORROWED, SHARED, STORAGE> { 1601 | // Call default() before the below in case it panics 1602 | let new_storage = STORAGE::default(); 1603 | 1604 | let ret = Supercow { 1605 | ptr: (), 1606 | // mem::replace is critical for safety, otherwise we would 1607 | // double-free when `this` is dropped. 1608 | mode: mem::replace(&mut this.mode, ptr::null_mut()), 1609 | storage: mem::replace(&mut this.storage, new_storage), 1610 | _owned: PhantomData, 1611 | _borrowed: PhantomData, 1612 | _shared: PhantomData, 1613 | }; 1614 | ret 1615 | } 1616 | 1617 | /// Sets `self.ptr` up for owned mode. 1618 | /// 1619 | /// `self.ptr` will either be written to a new valid value, or if this call 1620 | /// panics, will be left with whatever value it had before. 1621 | /// 1622 | /// ## Unsafety 1623 | /// 1624 | /// `self` must be in owned mode, and storage slot a allocated. 1625 | unsafe fn borrow_owned(&mut self) 1626 | where OWNED : SafeBorrow { 1627 | let mut borrowed_ptr = self.storage.get_ptr_a(self.mode).borrow() 1628 | as *const BORROWED; 1629 | 1630 | // We have a strong assumption that nothing ever gets allocated below 1631 | // MAX_INTERNAL_BORROW_DISPLACEMENT, so check that in debug mode. Note 1632 | // that ZSTs are frequently positioned in this range; as described in 1633 | // the `Deref` implementation, we consider it OK to relocate them and 1634 | // so ignore them. 1635 | debug_assert!( 1636 | 0 == mem::size_of_val(&* borrowed_ptr) || 1637 | borrowed_ptr.address() >= MAX_INTERNAL_BORROW_DISPLACEMENT, 1638 | "Supercow: Non-ZST allocated at {:p}, which is below the \ 1639 | minimum supported allocation address of {}", 1640 | borrowed_ptr, MAX_INTERNAL_BORROW_DISPLACEMENT); 1641 | 1642 | // Adjust the pointer if needed. We only need to consider this case 1643 | // when internal storage may be in use. 1644 | if STORAGE::is_internal_storage() { 1645 | let self_start = self.address(); 1646 | let self_size = mem::size_of::(); 1647 | 1648 | // If not an internal pointer, nothing to adjust. 1649 | if borrowed_ptr.within(self_start, self_size) { 1650 | // In debug mode, ensure that both `OWNED::borrow()` and 1651 | // `STORAGE` fulfilled their maximum offset contract. 1652 | // 1653 | // Note that the actual threshold is greater than the sum of 1654 | // the permitted offsets; here, we strictly check the maximum 1655 | // that the two together may produce. (Note <= and not <.) 1656 | debug_assert!(borrowed_ptr.address() - self_start <= 1657 | MAX_INTERNAL_BORROW_DISPLACEMENT * 3/2, 1658 | "Borrowed pointer displaced too far from \ 1659 | base address (supercow at {:x}, self at {:x}, \ 1660 | borrowed to {:x}", self_start, 1661 | (&self.storage).address(), 1662 | borrowed_ptr.address()); 1663 | 1664 | // Move the pointer from being based on `self` to being based 1665 | // on NULL. We identify this later in `Deref` by seeing that 1666 | // the nominal address is less than 1667 | // MAX_INTERNAL_BORROW_DISPLACEMENT. 1668 | borrowed_ptr = borrowed_ptr.rebase(self_start, 0); 1669 | } 1670 | } 1671 | 1672 | // Now that we've determined the new pointer value, write it back. Even 1673 | // if we weren't using the `PTR` abstraction, we would still want to 1674 | // delay this to ensure that this call is atomic. 1675 | self.ptr.store_ptr(borrowed_ptr); 1676 | } 1677 | 1678 | /// Create an "empty" `Supercow`. 1679 | /// 1680 | /// The value must not be exposed to the outside world as it has a null 1681 | /// `ptr`. However, it is safe to drop as-is as it is returned in reference 1682 | /// mode and has no uninitialised content as far as the compiler is 1683 | /// concerned. 1684 | unsafe fn empty() -> Self { 1685 | Supercow { 1686 | ptr: PTR::new(), 1687 | mode: ptr::null_mut(), 1688 | storage: Default::default(), 1689 | _owned: PhantomData, 1690 | _borrowed: PhantomData, 1691 | _shared: PhantomData, 1692 | } 1693 | } 1694 | 1695 | fn mode(&self) -> SupercowMode { 1696 | SupercowMode::from_ptr(self.mode) 1697 | } 1698 | } } 1699 | 1700 | defimpl! {[] (RefParent for) where { 1701 | OWNED : SafeBorrow 1702 | } { 1703 | type Owned = OWNED; 1704 | 1705 | unsafe fn supercow_ref_drop(&mut self) { 1706 | // Safety: Contract guarantees we are in owned mode and that there are 1707 | // no live borrows of the owned value remaining. 1708 | self.borrow_owned() 1709 | } 1710 | } } 1711 | 1712 | /// Provides mutable access to an owned value within a `Supercow`. 1713 | /// 1714 | /// This is similar to the `Ref` used with `RefCell`. 1715 | pub struct Ref<'a, P> 1716 | where P : RefParent + 'a { 1717 | // This is a pointer and not a reference as otherwise we would have two 1718 | // `&mut` references into the parent, which is illegal. 1719 | r: *mut P::Owned, 1720 | parent: &'a mut P, 1721 | } 1722 | 1723 | 1724 | impl<'a, P> Deref for Ref<'a, P> 1725 | where P : RefParent + 'a { 1726 | type Target = P::Owned; 1727 | 1728 | #[inline] 1729 | fn deref(&self) -> &P::Owned { 1730 | // Unsafety here and below: Just converting reference to pointer. 1731 | unsafe { &*self.r } 1732 | } 1733 | } 1734 | 1735 | impl<'a, P> DerefMut for Ref<'a, P> 1736 | where P : RefParent + 'a { 1737 | #[inline] 1738 | fn deref_mut(&mut self) -> &mut P::Owned { 1739 | unsafe { &mut*self.r } 1740 | } 1741 | } 1742 | 1743 | impl<'a, P> Drop for Ref<'a, P> 1744 | where P : RefParent + 'a { 1745 | #[inline] 1746 | fn drop(&mut self) { 1747 | // The value of `OWNED::borrow()` may have changed, so recompute 1748 | // everything instead of backing the old values up. 1749 | // 1750 | // Safety: The `Ref` could not have been constructed if the parent were 1751 | // not in owned mode. We know there are no reborrows of `r` since the 1752 | // borrow checker would have prevented that as it would also be a 1753 | // borrow of `self`. 1754 | unsafe { self.parent.supercow_ref_drop() } 1755 | } 1756 | } 1757 | 1758 | defimpl! {[] (Deref for) where { 1759 | PTR : PtrRead 1760 | } { 1761 | type Target = BORROWED; 1762 | #[inline] 1763 | fn deref(&self) -> &BORROWED { 1764 | let mut target_ref = self.ptr.get_ptr(); 1765 | unsafe { 1766 | // Safety: If `self` escaped to a location where other code could 1767 | // call `deref()`, we know that `ptr` has been set up 1768 | // appropriately. 1769 | 1770 | // If pointers may be stored internally to `self` and the nominal 1771 | // pointer is based on NULL (as positioned by `borrow_owned()`), 1772 | // move the pointer to be based on `self`. 1773 | if STORAGE::is_internal_storage() && 1774 | target_ref.within(0, MAX_INTERNAL_BORROW_DISPLACEMENT) 1775 | { 1776 | target_ref = target_ref.rebase(0, self.address()); 1777 | } 1778 | &*target_ref 1779 | } 1780 | } 1781 | } } 1782 | 1783 | defimpl! {[] (Borrow for) where { 1784 | PTR : PtrRead, 1785 | } { 1786 | fn borrow(&self) -> &BORROWED { 1787 | self.deref() 1788 | } 1789 | } } 1790 | 1791 | defimpl! {[] (AsRef for) where { 1792 | PTR : PtrRead, 1793 | } { 1794 | fn as_ref(&self) -> &BORROWED { 1795 | self.deref() 1796 | } 1797 | } } 1798 | 1799 | defimpl! {[] (Clone for) where { 1800 | OWNED : Clone + SafeBorrow, 1801 | SHARED : Clone, 1802 | } { 1803 | fn clone(&self) -> Self { 1804 | match self.mode() { 1805 | Owned(ptr) => Self::owned(unsafe { 1806 | // Safety: `mode` indicates storage `a` is allocated. 1807 | self.storage.get_ptr_a(ptr) 1808 | }.clone()), 1809 | 1810 | Borrowed => Supercow { 1811 | ptr: self.ptr, 1812 | mode: self.mode, 1813 | storage: Default::default(), 1814 | _owned: PhantomData, 1815 | _borrowed: PhantomData, 1816 | _shared: PhantomData, 1817 | }, 1818 | 1819 | Shared(s) => Self::shared_nocvt(unsafe { 1820 | // Safety: `mode` indicates storage `b` is allocated. 1821 | self.storage.get_ptr_b(s) 1822 | }.clone(), self.ptr), 1823 | } 1824 | } 1825 | } } 1826 | 1827 | defimpl! {[] (From for) where { 1828 | OWNED : SafeBorrow, 1829 | } { 1830 | fn from(inner: OWNED) -> Self { 1831 | Self::owned(inner) 1832 | } 1833 | } } 1834 | 1835 | // For now, we can't accept `&BORROWED` because it's theoretically possible for 1836 | // someone to make `::Owned = &BORROWED`, in which case 1837 | // the `OWNED` version above would apply. 1838 | // 1839 | // Maybe once specialisation lands in stable, we can make `From` do what we 1840 | // want everywhere. 1841 | defimpl! {[] (From<&'a OWNED> for) where { 1842 | // Does not need to be `SafeBorrow` since it's not embedded inside us. 1843 | OWNED : Borrow, 1844 | } { 1845 | fn from(inner: &'a OWNED) -> Self { 1846 | Self::borrowed(inner.borrow()) 1847 | } 1848 | } } 1849 | 1850 | // Similarly, we can't support arbitrary types here, and need to require 1851 | // `BORROWED == OWNED` for `Rc` and `Arc`. Ideally, we'd support anything that 1852 | // coerces into `SHARED`. Again, maybe one day after specialisation.. 1853 | impl<'a, OWNED, SHARED, STORAGE> From> 1854 | for Supercow<'a, OWNED, OWNED, SHARED, STORAGE> 1855 | where SHARED : SharedFrom>, 1856 | STORAGE : OwnedStorage, 1857 | OWNED : 'a, 1858 | *const OWNED : PointerFirstRef { 1859 | fn from(rc: Rc) -> Self { 1860 | Self::shared(rc) 1861 | } 1862 | } 1863 | impl<'a, OWNED, SHARED, STORAGE> From> 1864 | for Supercow<'a, OWNED, OWNED, SHARED, STORAGE> 1865 | where SHARED : SharedFrom>, 1866 | STORAGE : OwnedStorage, 1867 | OWNED : 'a, 1868 | *const OWNED : PointerFirstRef { 1869 | fn from(rc: Arc) -> Self { 1870 | Self::shared(rc) 1871 | } 1872 | } 1873 | 1874 | macro_rules! deleg_fmt { ($tr:ident) => { 1875 | defimpl! {[] (fmt::$tr for) where { 1876 | BORROWED : fmt::$tr, 1877 | PTR : PtrRead, 1878 | } { 1879 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1880 | (**self).fmt(f) 1881 | } 1882 | } } 1883 | } } 1884 | 1885 | deleg_fmt!(Binary); 1886 | deleg_fmt!(Display); 1887 | deleg_fmt!(LowerExp); 1888 | deleg_fmt!(LowerHex); 1889 | deleg_fmt!(Octal); 1890 | deleg_fmt!(Pointer); 1891 | deleg_fmt!(UpperExp); 1892 | deleg_fmt!(UpperHex); 1893 | 1894 | impl<'a, OWNED, BORROWED : ?Sized, SHARED, STORAGE> 1895 | fmt::Debug for Supercow<'a, OWNED, BORROWED, SHARED, STORAGE, ()> 1896 | where BORROWED : 'a, 1897 | *const BORROWED : PointerFirstRef, 1898 | STORAGE : OwnedStorage { 1899 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1900 | write!(f, "") 1901 | } 1902 | } 1903 | 1904 | impl<'a, OWNED, BORROWED : ?Sized, SHARED, STORAGE> 1905 | fmt::Debug for Supercow<'a, OWNED, BORROWED, SHARED, STORAGE, *const BORROWED> 1906 | where BORROWED : fmt::Debug + 'a, 1907 | *const BORROWED : PointerFirstRef, 1908 | STORAGE : OwnedStorage { 1909 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1910 | (**self).fmt(f) 1911 | } 1912 | } 1913 | 1914 | defimpl! {[T] (cmp::PartialEq for) where { 1915 | T : Borrow, 1916 | BORROWED : PartialEq, 1917 | PTR : PtrRead, 1918 | } { 1919 | fn eq(&self, other: &T) -> bool { 1920 | **self == *other.borrow() 1921 | } 1922 | 1923 | fn ne(&self, other: &T) -> bool { 1924 | **self != *other.borrow() 1925 | } 1926 | } } 1927 | 1928 | defimpl! {[] (cmp::Eq for) where { 1929 | BORROWED : Eq, 1930 | PTR : PtrRead, 1931 | } { } } 1932 | 1933 | defimpl! {[T] (cmp::PartialOrd for) where { 1934 | T : Borrow, 1935 | BORROWED : cmp::PartialOrd, 1936 | PTR : PtrRead, 1937 | } { 1938 | fn partial_cmp(&self, other: &T) -> Option { 1939 | (**self).partial_cmp(other.borrow()) 1940 | } 1941 | 1942 | fn lt(&self, other: &T) -> bool { 1943 | **self < *other.borrow() 1944 | } 1945 | 1946 | fn le(&self, other: &T) -> bool { 1947 | **self <= *other.borrow() 1948 | } 1949 | 1950 | fn gt(&self, other: &T) -> bool { 1951 | **self > *other.borrow() 1952 | } 1953 | 1954 | fn ge(&self, other: &T) -> bool { 1955 | **self >= *other.borrow() 1956 | } 1957 | } } 1958 | 1959 | defimpl! {[] (cmp::Ord for) where { 1960 | BORROWED : cmp::Ord, 1961 | PTR : PtrRead, 1962 | } { 1963 | fn cmp(&self, other: &Self) -> cmp::Ordering { 1964 | (**self).cmp(other) 1965 | } 1966 | } } 1967 | 1968 | defimpl! {[] (Hash for) where { 1969 | BORROWED : Hash, 1970 | PTR : PtrRead, 1971 | } { 1972 | fn hash(&self, h: &mut H) { 1973 | (**self).hash(h) 1974 | } 1975 | } } 1976 | 1977 | trait ReferenceExt { 1978 | fn address(&self) -> usize; 1979 | } 1980 | impl<'a, T : ?Sized + 'a> ReferenceExt for &'a T { 1981 | #[inline] 1982 | fn address(&self) -> usize { 1983 | (*self) as *const T as *const () as usize 1984 | } 1985 | } 1986 | impl<'a, T : ?Sized + 'a> ReferenceExt for &'a mut T { 1987 | #[inline] 1988 | fn address(&self) -> usize { 1989 | (*self) as *const T as *const () as usize 1990 | } 1991 | } 1992 | 1993 | unsafe trait PfrExt : Copy { 1994 | /// Returns the address of this pointer. 1995 | #[inline] 1996 | fn address(self) -> usize { 1997 | let saddr: &usize = unsafe { 1998 | // Safety, here and below: We know `Self` is a `PointerFirstRef` or 1999 | // similar. 2000 | mem::transmute(&self) 2001 | }; 2002 | *saddr 2003 | } 2004 | 2005 | /// Returns a pointer with the same extra data as `self`, but with the 2006 | /// given new `address`. 2007 | #[inline] 2008 | fn with_address(mut self, address: usize) -> Self { 2009 | let saddr: &mut usize = unsafe { 2010 | // Safety: These transmutes are visible to the borrow checker, so 2011 | // we aren't violating aliasing rules. 2012 | mem::transmute(&mut self) 2013 | }; 2014 | *saddr = address; 2015 | 2016 | let saddr: &mut Self = unsafe { 2017 | // Safety: Possibly a grey area, since we may be creating a 2018 | // non-native pointer out of thin air. 2019 | // 2020 | // Transmuting back to `&mut Self` makes the write dependency more 2021 | // explicit but is likely not strictly necessary. 2022 | mem::transmute(saddr) 2023 | }; 2024 | *saddr 2025 | } 2026 | 2027 | /// Returns whether this pointer is within the allocation starting at 2028 | /// `base` and with size `size` (bytes). 2029 | #[inline] 2030 | fn within(self, base: usize, size: usize) -> bool { 2031 | let a = self.address(); 2032 | a >= base && a < (base + size) 2033 | } 2034 | 2035 | /// Adjusts this pointer from being based at `old_base` to being based at 2036 | /// `new_base` (assuming this pointer is within the allocation starting at 2037 | /// `old_base`). 2038 | #[inline] 2039 | fn rebase(self, old_base: usize, new_base: usize) -> Self { 2040 | // Extra parentheses needed to avoid overflow. 2041 | self.with_address(new_base + (self.address() - old_base)) 2042 | } 2043 | 2044 | /// Returns whether this pointer has 2-byte alignment. 2045 | #[inline] 2046 | fn is_2_aligned(self) -> bool { 2047 | 0 == (self.address() & 1usize) 2048 | } 2049 | 2050 | /// Clears bit 0 of this pointer. 2051 | /// 2052 | /// NB This is used to restore the original pointer value from 2053 | /// `Supercow::mode` when indicating shared mode. 2054 | #[inline] 2055 | fn align2(self) -> Self { 2056 | self.with_address(self.address() & !1usize) 2057 | } 2058 | 2059 | /// Sets bit 0 of this pointer. 2060 | /// 2061 | /// NB This is used to set `Supercow::mode` to indicate shared mode (and 2062 | /// allocation in storage b). 2063 | #[inline] 2064 | fn unalign2(self) -> Self { 2065 | self.with_address(self.address() | 1usize) 2066 | } 2067 | } 2068 | unsafe impl PfrExt for T { } 2069 | unsafe impl PfrExt for *mut T { } 2070 | 2071 | #[cfg(test)] 2072 | mod misc_tests { 2073 | use std::borrow::Cow; 2074 | 2075 | use super::*; 2076 | 2077 | // This is where the asm in the Performance Notes section comes from. 2078 | #[inline(never)] 2079 | fn add_two_cow(a: &Cow, b: &Cow) -> u32 { 2080 | **a + **b 2081 | } 2082 | 2083 | #[inline(never)] 2084 | fn add_two_supercow(a: &InlineSupercow, 2085 | b: &InlineSupercow) -> u32 { 2086 | **a + **b 2087 | } 2088 | 2089 | #[test] 2090 | fn do_add_two() { 2091 | // Need to call `add_two_cow` twice to prevent LLVM from specialising 2092 | // it. 2093 | assert_eq!(42, add_two_cow(&Cow::Owned(40), &Cow::Owned(2))); 2094 | assert_eq!(44, add_two_cow(&Cow::Borrowed(&38), &Cow::Borrowed(&6))); 2095 | assert_eq!(42, add_two_supercow(&Supercow::owned(40), 2096 | &Supercow::owned(2))); 2097 | } 2098 | } 2099 | 2100 | macro_rules! tests { ($modname:ident, $stype:ident, $ptype:ident) => { 2101 | #[cfg(test)] 2102 | mod $modname { 2103 | use std::sync::Arc; 2104 | 2105 | use super::*; 2106 | 2107 | #[test] 2108 | fn ref_to_owned() { 2109 | let x = 42u32; 2110 | let a: $stype = Supercow::borrowed(&x); 2111 | assert_eq!(x, *a); 2112 | assert_eq!(&x as *const u32 as usize, 2113 | (&*a) as *const u32 as usize); 2114 | 2115 | let mut b = a.clone(); 2116 | assert_eq!(x, *b); 2117 | assert_eq!(&x as *const u32 as usize, 2118 | (&*b) as *const u32 as usize); 2119 | 2120 | *b.to_mut() = 56; 2121 | assert_eq!(42, *a); 2122 | assert_eq!(x, *a); 2123 | assert_eq!(&x as *const u32 as usize, 2124 | (&*a) as *const u32 as usize); 2125 | assert_eq!(56, *b); 2126 | } 2127 | 2128 | #[test] 2129 | fn supports_dst() { 2130 | let a: $stype = Supercow::borrowed("hello"); 2131 | let b: $stype = Supercow::owned("hello".to_owned()); 2132 | assert_eq!(a, b); 2133 | 2134 | let mut c = a.clone(); 2135 | c.to_mut().push_str(" world"); 2136 | assert_eq!(a, b); 2137 | assert_eq!(c, "hello world"); 2138 | } 2139 | 2140 | #[test] 2141 | fn default_accepts_arc() { 2142 | let x: $stype = Supercow::shared(Arc::new(42u32)); 2143 | assert_eq!(42, *x); 2144 | } 2145 | 2146 | #[test] 2147 | fn ref_safe_even_if_forgotten() { 2148 | let mut x: $stype = Supercow::owned("foo".to_owned()); 2149 | { 2150 | let mut m = x.to_mut(); 2151 | // Add a bunch of characters to invalidate the allocation 2152 | for _ in 0..65536 { 2153 | m.push('x'); 2154 | } 2155 | 2156 | // Prevent the dtor from running but allow us to release the borrow 2157 | ::std::mem::forget(m); 2158 | } 2159 | 2160 | // While the value has been corrupted, we have been left with a *safe* 2161 | // deref result nonetheless. 2162 | assert_eq!("", &*x); 2163 | // The actual String has not been lost so no memory has been leaked 2164 | assert_eq!(65539, x.to_mut().len()); 2165 | } 2166 | 2167 | #[test] 2168 | // `SipHasher` is deprecated, but its replacement `DefaultHasher` doesn't 2169 | // exist in Rust 1.12.1. 2170 | #[allow(deprecated)] 2171 | fn general_trait_delegs_work() { 2172 | use std::borrow::Borrow; 2173 | use std::convert::AsRef; 2174 | use std::cmp::*; 2175 | use std::hash::*; 2176 | 2177 | macro_rules! test_fmt { 2178 | ($fmt:expr, $x:expr) => { 2179 | assert_eq!(format!($fmt, 42u32), format!($fmt, $x)); 2180 | } 2181 | } 2182 | 2183 | let x: $stype = Supercow::owned(42u32); 2184 | test_fmt!("{}", x); 2185 | test_fmt!("{:?}", x); 2186 | test_fmt!("{:o}", x); 2187 | test_fmt!("{:x}", x); 2188 | test_fmt!("{:X}", x); 2189 | test_fmt!("{:b}", x); 2190 | 2191 | assert!(x == 42); 2192 | assert!(x != 43); 2193 | assert!(x < 43); 2194 | assert!(x <= 43); 2195 | assert!(x > 41); 2196 | assert!(x >= 41); 2197 | assert_eq!(42.partial_cmp(&43), x.partial_cmp(&43)); 2198 | assert_eq!(42.cmp(&43), x.cmp(&Supercow::owned(43))); 2199 | 2200 | let mut expected_hash = SipHasher::new(); 2201 | 42u32.hash(&mut expected_hash); 2202 | let mut actual_hash = SipHasher::new(); 2203 | x.hash(&mut actual_hash); 2204 | assert_eq!(expected_hash.finish(), actual_hash.finish()); 2205 | 2206 | assert_eq!(42u32, *x.borrow()); 2207 | assert_eq!(42u32, *x.as_ref()); 2208 | } 2209 | 2210 | #[test] 2211 | fn owned_mode_survives_moving() { 2212 | // Using a `HashMap` here because it means the optimiser can't reason 2213 | // about which one will eventually be chosen, and so one of the values 2214 | // is guaranteed to eventually be moved off the heap onto the stack. 2215 | #[inline(never)] 2216 | fn pick_one() -> $stype<'static, String> { 2217 | use std::collections::HashMap; 2218 | 2219 | let mut hm = HashMap::new(); 2220 | hm.insert("hello", Supercow::owned("hello".to_owned())); 2221 | hm.insert("world", Supercow::owned("world".to_owned())); 2222 | hm.into_iter().map(|(_, v)| v).next().unwrap() 2223 | } 2224 | 2225 | let s = pick_one(); 2226 | assert!("hello".to_owned() == *s || 2227 | "world".to_owned() == *s); 2228 | } 2229 | 2230 | #[test] 2231 | fn dst_string_str() { 2232 | let mut s: $stype<'static, String, str> = String::new().into(); 2233 | let mut expected = String::new(); 2234 | for i in 0..1024 { 2235 | assert_eq!(expected.as_str(), &*s); 2236 | expected.push_str(&format!("{}", i)); 2237 | s.to_mut().push_str(&format!("{}", i)); 2238 | assert_eq!(expected.as_str(), &*s); 2239 | } 2240 | } 2241 | 2242 | #[test] 2243 | fn dst_vec_u8s() { 2244 | let mut s: $stype<'static, Vec, [u8]> = Vec::new().into(); 2245 | let mut expected = Vec::::new(); 2246 | for i in 0..1024 { 2247 | assert_eq!(&expected[..], &*s); 2248 | expected.push((i & 0xFF) as u8); 2249 | s.to_mut().push((i & 0xFF) as u8); 2250 | assert_eq!(&expected[..], &*s); 2251 | } 2252 | } 2253 | 2254 | #[test] 2255 | fn dst_osstring_osstr() { 2256 | use std::ffi::{OsStr, OsString}; 2257 | 2258 | let mut s: $stype<'static, OsString, OsStr> = OsString::new().into(); 2259 | let mut expected = OsString::new(); 2260 | for i in 0..1024 { 2261 | assert_eq!(expected.as_os_str(), &*s); 2262 | expected.push(&format!("{}", i)); 2263 | s.to_mut().push(&format!("{}", i)); 2264 | assert_eq!(expected.as_os_str(), &*s); 2265 | } 2266 | } 2267 | 2268 | #[test] 2269 | fn dst_cstring_cstr() { 2270 | use std::ffi::{CStr, CString}; 2271 | use std::mem; 2272 | use std::ops::Deref; 2273 | 2274 | let mut s: $stype<'static, CString, CStr> = 2275 | CString::new("").unwrap().into(); 2276 | let mut expected = CString::new("").unwrap(); 2277 | for i in 0..1024 { 2278 | assert_eq!(expected.deref(), &*s); 2279 | { 2280 | let mut ve = expected.into_bytes_with_nul(); 2281 | ve.pop(); 2282 | ve.push(((i & 0xFF) | 1) as u8); 2283 | ve.push(0); 2284 | expected = unsafe { 2285 | CString::from_vec_unchecked(ve) 2286 | }; 2287 | } 2288 | { 2289 | let mut m = s.to_mut(); 2290 | let mut vs = mem::replace(&mut *m, CString::new("").unwrap()) 2291 | .into_bytes_with_nul(); 2292 | vs.pop(); 2293 | vs.push(((i & 0xFF) | 1) as u8); 2294 | vs.push(0); 2295 | *m = unsafe { 2296 | CString::from_vec_unchecked(vs) 2297 | }; 2298 | } 2299 | assert_eq!(expected.deref(), &*s); 2300 | } 2301 | } 2302 | 2303 | #[test] 2304 | fn dst_pathbuf_path() { 2305 | use std::path::{Path, PathBuf}; 2306 | 2307 | let mut s: $stype<'static, PathBuf, Path> = PathBuf::new().into(); 2308 | let mut expected = PathBuf::new(); 2309 | for i in 0..1024 { 2310 | assert_eq!(expected.as_path(), &*s); 2311 | expected.push(format!("{}", i)); 2312 | s.to_mut().push(format!("{}", i)); 2313 | assert_eq!(expected.as_path(), &*s); 2314 | } 2315 | } 2316 | 2317 | #[test] 2318 | fn unborrow_owned() { 2319 | let orig: Supercow = 2320 | Supercow::owned("hello world".to_owned()); 2321 | let unborrowed = Supercow::unborrow(orig); 2322 | assert_eq!(unborrowed, "hello world"); 2323 | } 2324 | 2325 | #[test] 2326 | fn unborrow_borrowed() { 2327 | let orig: Supercow = 2328 | Supercow::borrowed("hello world"); 2329 | let unborrowed = Supercow::unborrow(orig); 2330 | assert_eq!(unborrowed, "hello world"); 2331 | } 2332 | 2333 | #[test] 2334 | fn unborrow_shared() { 2335 | let orig: Supercow = 2336 | Supercow::shared(Arc::new("hello world".to_owned())); 2337 | let unborrowed = Supercow::unborrow(orig); 2338 | assert_eq!(unborrowed, "hello world".to_owned()); 2339 | } 2340 | 2341 | #[test] 2342 | fn take_ownership_owned() { 2343 | let orig: Supercow = 2344 | Supercow::owned("hello world".to_owned()); 2345 | let owned: Supercow = Supercow::take_ownership(orig); 2346 | assert_eq!(owned, "hello world"); 2347 | } 2348 | 2349 | #[test] 2350 | fn take_ownership_borrowed() { 2351 | let orig: Supercow = 2352 | Supercow::borrowed("hello world"); 2353 | let owned: Supercow = Supercow::take_ownership(orig); 2354 | assert_eq!(owned, "hello world"); 2355 | } 2356 | 2357 | #[test] 2358 | fn take_ownership_shared() { 2359 | let orig: Supercow = 2360 | Supercow::shared(Arc::new("hello world".to_owned())); 2361 | let owned: Supercow = Supercow::take_ownership(orig); 2362 | assert_eq!(owned, "hello world".to_owned()); 2363 | } 2364 | 2365 | struct MockNativeResource(*mut u32); 2366 | impl Drop for MockNativeResource { 2367 | fn drop(&mut self) { 2368 | unsafe { *self.0 = 0 }; 2369 | } 2370 | } 2371 | // Not truly safe, but we're not crossing threads here and we need 2372 | // something for the Sync tests either way. 2373 | unsafe impl Send for MockNativeResource { } 2374 | unsafe impl Sync for MockNativeResource { } 2375 | 2376 | struct MockDependentResource<'a> { 2377 | ptr: *mut u32, 2378 | _handle: $ptype<'a, MockNativeResource>, 2379 | } 2380 | 2381 | fn check_dependent_ok(mdr: MockDependentResource) { 2382 | assert_eq!(42, unsafe { *mdr.ptr }); 2383 | } 2384 | 2385 | #[test] 2386 | fn borrowed_phantomcow() { 2387 | let mut forty_two = 42u32; 2388 | 2389 | let native = MockNativeResource(&mut forty_two); 2390 | let sc: $stype = Supercow::borrowed(&native); 2391 | check_dependent_ok(MockDependentResource { 2392 | ptr: &mut forty_two, 2393 | _handle: Supercow::phantom(sc), 2394 | }); 2395 | } 2396 | 2397 | #[test] 2398 | fn owned_phantomcow() { 2399 | let mut forty_two = 42u32; 2400 | 2401 | let native = MockNativeResource(&mut forty_two); 2402 | let sc: $stype = Supercow::owned(native); 2403 | check_dependent_ok(MockDependentResource { 2404 | ptr: &mut forty_two, 2405 | _handle: Supercow::phantom(sc), 2406 | }); 2407 | } 2408 | 2409 | #[test] 2410 | fn shared_phantomcow() { 2411 | let mut forty_two = 42u32; 2412 | 2413 | let native = MockNativeResource(&mut forty_two); 2414 | let sc: $stype = 2415 | Supercow::shared(Arc::new(native)); 2416 | check_dependent_ok(MockDependentResource { 2417 | ptr: &mut forty_two, 2418 | _handle: Supercow::phantom(sc), 2419 | }); 2420 | } 2421 | 2422 | #[test] 2423 | fn clone_owned_phantomcow() { 2424 | let sc: $stype = Supercow::owned("hello world".to_owned()); 2425 | let p1 = Supercow::phantom(sc); 2426 | assert!(Supercow::clone_non_owned(&p1).is_none()); 2427 | let _p2 = p1.clone(); 2428 | } 2429 | 2430 | #[test] 2431 | fn clone_borrowed_phantomcow() { 2432 | let sc: $stype = Supercow::borrowed("hello world"); 2433 | let p1 = Supercow::phantom(sc); 2434 | assert!(Supercow::clone_non_owned(&p1).is_some()); 2435 | let _p2 = p1.clone(); 2436 | } 2437 | 2438 | #[test] 2439 | fn clone_shared_phantomcow() { 2440 | let sc: $stype = Supercow::shared( 2441 | Arc::new("hello world".to_owned())); 2442 | let p1 = Supercow::phantom(sc); 2443 | assert!(Supercow::clone_non_owned(&p1).is_some()); 2444 | let _p2 = p1.clone(); 2445 | } 2446 | 2447 | struct NotCloneable(u32); 2448 | impl Drop for NotCloneable { 2449 | fn drop(&mut self) { 2450 | self.0 = 0; 2451 | } 2452 | } 2453 | 2454 | #[test] 2455 | fn share_owned_supercow() { 2456 | let mut a: $stype = Supercow::owned(NotCloneable(42)); 2457 | let b = Supercow::share(&mut a); 2458 | 2459 | assert_eq!(42, (*a).0); 2460 | assert_eq!(42, (*b).0); 2461 | } 2462 | 2463 | #[test] 2464 | fn share_borrowed_supercow() { 2465 | let nc = NotCloneable(42); 2466 | let mut a: $stype = Supercow::borrowed(&nc); 2467 | let b = Supercow::share(&mut a); 2468 | 2469 | assert_eq!(42, (*a).0); 2470 | assert_eq!(42, (*b).0); 2471 | } 2472 | 2473 | #[test] 2474 | fn share_shared_supercow() { 2475 | let mut a: $stype = Supercow::shared( 2476 | Arc::new(NotCloneable(42))); 2477 | let b = Supercow::share(&mut a); 2478 | 2479 | assert_eq!(42, (*a).0); 2480 | assert_eq!(42, (*b).0); 2481 | } 2482 | 2483 | #[test] 2484 | fn share_owned_dst_supercow() { 2485 | let mut a: $stype = Supercow::owned("hello world".into()); 2486 | let b = Supercow::share(&mut a); 2487 | 2488 | assert_eq!("hello world", &*a); 2489 | assert_eq!("hello world", &*b); 2490 | } 2491 | 2492 | #[test] 2493 | fn share_owned_phantomcow() { 2494 | let sc: $stype = Supercow::owned(NotCloneable(42)); 2495 | let mut a: $ptype = Supercow::phantom(sc); 2496 | let _b = Supercow::share(&mut a); 2497 | } 2498 | 2499 | #[test] 2500 | fn share_borrowed_phantomcow() { 2501 | let nc = NotCloneable(42); 2502 | let sc: $stype = Supercow::borrowed(&nc); 2503 | let mut a: $ptype = Supercow::phantom(sc); 2504 | let _b = Supercow::share(&mut a); 2505 | } 2506 | 2507 | #[test] 2508 | fn share_shared_phantomcow() { 2509 | let sc: $stype = 2510 | Supercow::shared(Arc::new(NotCloneable(42))); 2511 | let mut a: $ptype = Supercow::phantom(sc); 2512 | let _b = Supercow::share(&mut a); 2513 | } 2514 | 2515 | #[test] 2516 | fn share_owned_dst_phantomcow() { 2517 | let sc: $stype = Supercow::owned("hello world".into()); 2518 | let mut a: $ptype = Supercow::phantom(sc); 2519 | let _b = Supercow::share(&mut a); 2520 | } 2521 | } } } 2522 | 2523 | tests!(inline_sync_tests, InlineSupercow, InlinePhantomcow); 2524 | tests!(inline_nonsync_tests, InlineNonSyncSupercow, InlineNonSyncPhantomcow); 2525 | tests!(boxed_sync_tests, Supercow, Phantomcow); 2526 | tests!(boxed_nonsync_tests, NonSyncSupercow, NonSyncPhantomcow); 2527 | --------------------------------------------------------------------------------