loaned 0.1.2

Safely move values with live inner borrows.
Documentation
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "alloc")]
use alloc::{boxed::Box, vec::Vec};

use core::{
  marker::PhantomData,
  mem::{self, ManuallyDrop, MaybeUninit},
  ops::{Deref, DerefMut},
  ptr,
};

mod convert;
mod loanable;
mod loaned;
mod loaned_mut;
mod place;
mod raw_loaned;
mod take;

pub use loanable::*;
pub use loaned::*;
pub use loaned_mut::*;
pub use place::*;
use raw_loaned::*;
pub use take::*;

#[cfg(all(test, feature = "std"))]
mod test {
  use super::*;
  use std::sync::atomic::{AtomicU32, Ordering};

  #[test]
  fn loaned_mut() {
    let (r, b) = LoanedMut::loan(Box::new(0));
    *r = 1;
    let mut x = Box::new(0);
    b.place(&mut x);
    *r = 2;
    assert_eq!(*x, 2);
  }

  #[test]
  fn loaned_atomic() {
    let (r, b) = Loaned::loan(Box::new(AtomicU32::new(0)));
    r.fetch_add(1, Ordering::Relaxed);
    b.borrow().fetch_add(2, Ordering::Relaxed);
    assert_eq!(b.load(Ordering::Relaxed), 3);
    let mut x = Box::new(AtomicU32::new(0));
    b.place(&mut x);
    r.fetch_add(4, Ordering::Relaxed);
    *x.as_mut().get_mut() += 5;
    assert_eq!(*x.as_mut().get_mut(), 12);
  }

  #[test]
  fn place_option() {
    let (r, b) = LoanedMut::loan(Box::new(123));
    *r = 1;
    let mut x = None;
    b.place(&mut x);
    *r = 2;
    assert_eq!(x, Some(Box::new(2)));
  }

  #[test]
  fn take() {
    let (r, b) = LoanedMut::loan(Box::new(123));
    *r = 1;
    *r = 2;
    assert_eq!(take!(b), Box::new(2));
  }

  #[test]
  fn take_merge() {
    let (r1, b1) = LoanedMut::loan(Box::new(123));
    let (r2, b2) = LoanedMut::loan(Box::new(123));
    *r1 = 1;
    let a = LoanedMut::<(Box<i32>, Box<i32>)>::merge(Default::default(), |x, m| {
      m.place(b1, &mut x.0);
      m.place(b2, &mut x.1);
    });
    *r2 = 2;
    assert_eq!(take!(a), (Box::new(1), Box::new(2)));
  }

  #[test]
  fn into_box() {
    let (r, b) = LoanedMut::loan(Box::new(123));
    *r = 1;
    let x = LoanedMut::<Box<Box<_>>>::from(Box::new(b));
    *r = 2;
    assert_eq!(take!(x), Box::new(Box::new(2)));
  }

  #[test]
  fn into_vec() {
    let (r1, b1) = LoanedMut::loan(Box::new(123));
    let (r2, b2) = LoanedMut::loan(Box::new(123));
    let (r3, b3) = LoanedMut::loan(Box::new(123));
    let mut x = Vec::new();
    x.push(b1);
    *r1 = 1;
    *r2 = 2;
    x.push(b2);
    x.push(b3);
    let x: LoanedMut<Vec<Box<_>>> = x.into();
    *r3 = 3;
    assert_eq!(take!(x), vec![Box::new(1), Box::new(2), Box::new(3)]);
  }

  #[test]
  fn into_tuple() {
    let (r, b) = LoanedMut::loan(Box::new(0));
    let xy = LoanedMut::<(_, _)>::from((b, LoanedMut::new(Box::new(456))));
    *r = 123;
    assert_eq!(take!(xy), (Box::new(123), Box::new(456)));
  }
}