1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
//! A type-safe, heterogeneous collection with zero-cost add and borrow. //! //! `BorrowBag` allows the storage of any value, and returns a `Handle` which can be used to borrow //! the value back later. As the `BorrowBag` is add-only, `Handle` values remain valid for the //! lifetime of the `BorrowBag`. #![deny(missing_docs)] #![deny(private_in_public)] mod append; mod handle; mod lookup; use append::Append; pub use lookup::Lookup; pub use handle::Handle; /// Creates a new, empty `BorrowBag`. pub fn new_borrow_bag() -> BorrowBag<()> { BorrowBag { v: () } } /// `BorrowBag` allows the storage of any value using `add(T)`, and returns a `Handle` which can be /// used to borrow the value back later. As the `BorrowBag` is add-only, `Handle` values remain /// valid for the lifetime of the `BorrowBag`. /// /// After being added, the `Handle` can be passed to `borrow(Handle)`, which will return a /// reference to the value. /// /// ```rust /// use borrow_bag::new_borrow_bag; /// /// #[derive(PartialEq, Debug)] /// struct X; /// /// #[derive(PartialEq, Debug)] /// struct Y; /// /// #[derive(PartialEq, Debug)] /// struct Z; /// /// let bag = new_borrow_bag(); /// let (bag, x_handle) = bag.add(X); /// let (bag, y_handle) = bag.add(Y); /// let (bag, z_handle) = bag.add(Z); /// /// let x: &X = bag.borrow(x_handle); /// assert_eq!(x, &X); /// let y: &Y = bag.borrow(y_handle); /// assert_eq!(y, &Y); /// let z: &Z = bag.borrow(z_handle); /// assert_eq!(z, &Z); /// /// // Can borrow multiple times using the same handle /// let x: &X = bag.borrow(x_handle); /// assert_eq!(x, &X); /// ``` pub struct BorrowBag<V> { v: V, } impl<V> BorrowBag<V> { /// Adds a value to the bag, and returns a tuple containing: /// /// 1. The new bag containing the added element; and /// 2. A `Handle` which can be used to retrieve the added element. /// /// The trait bound is used to constrain and define the `BorrowBag` implementation, but is not /// intended to provide any restrictions on the value being added. /// /// ```rust /// # use borrow_bag::new_borrow_bag; /// # /// let bag = new_borrow_bag(); /// // Consumes the empty `bag`, and produces a new `bag` containing the value. The `handle` /// // can be used to borrow the value back later. /// let (bag, handle) = bag.add(15u8); /// ``` pub fn add<T>(self, t: T) -> (BorrowBag<V::Output>, Handle<T, V::Navigator>) where V: Append<T> { let (v, handle) = Append::append(self.v, t); (BorrowBag { v }, handle) } /// Borrows a value previously added to the bag. /// /// ```rust /// # use borrow_bag::new_borrow_bag; /// # /// # let bag = new_borrow_bag(); /// # let (bag, handle) = bag.add(15u8); /// # /// let i: &u8 = bag.borrow(handle); /// assert_eq!(*i, 15); /// ``` pub fn borrow<T, N>(&self, handle: Handle<T, N>) -> &T where V: Lookup<T, N> { drop(handle); // Otherwise it's unused. Lookup::<T, N>::get_from(&self.v) } }