pub mod clone_on_extract;
pub mod into_clone_on_extract;
pub use clone_on_extract::CloneOnExtract;
pub use into_clone_on_extract::AsCloneOnExtract;
pub use into_clone_on_extract::IntoCloneOnExtract;
pub use into_clone_on_extract::IntoDerefCloneOnExtract;
#[cfg(test)]
mod tests {
use std::{borrow::Borrow, ops::*};
use self::{
clone_on_extract::CloneOnExtract,
into_clone_on_extract::{AsCloneOnExtract, IntoCloneOnExtract, IntoDerefCloneOnExtract},
};
use super::*;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct A {
pub a: i32,
}
impl Add<&A> for A {
type Output = i32;
fn add(self, rhs: &Self) -> Self::Output {
self.a + rhs.a
}
}
impl Add for CloneOnExtract<'_, A, A> {
type Output = i32;
fn add(self, rhs: Self) -> Self::Output {
self.extract() + rhs.borrow()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct B {
pub b: i32,
}
impl Add<B> for &B {
type Output = i32;
fn add(self, rhs: B) -> Self::Output {
self.b + rhs.b
}
}
impl Add for CloneOnExtract<'_, B, B> {
type Output = i32;
fn add(self, rhs: Self) -> Self::Output {
self.borrow() + rhs.extract()
}
}
pub fn add_then_double<T: Add<T, Output = i32>>(lhs: T, rhs: T) -> i32 {
(lhs + rhs) * 2
}
#[test]
pub fn test() {
let a1 = A { a: 1 }.coe();
let a2 = A { a: 2 }.as_coe();
let _a_works = add_then_double(a1, a2);
let b1 = B { b: 1 }.coe();
let b2 = B { b: 2 }.as_coe();
let _b_works = add_then_double(b1, b2);
}
#[test]
pub fn test_constructors() {
let coe = CloneOnExtract::from_owned("balls".to_string());
let _borrow = coe.deref();
let _owned = coe.into_owned();
let coe = CloneOnExtract::from_deref_owned("balls".to_string());
let _borrow = coe.deref();
let _owned = coe.into_owned();
let coe = CloneOnExtract::from_ref("balls");
let _borrow = coe.deref();
let _owned = coe.into_owned();
}
#[test]
pub fn test_converters() {
let coe = "balls".to_string().coe();
let _borrow = coe.deref();
let _owned = coe.into_owned();
let coe = "balls".to_string().coe_deref();
let _borrow = coe.deref();
let _owned = coe.into_owned();
let coe = "balls".as_coe();
let _borrow = coe.deref();
let _owned = coe.into_owned();
}
}
mod doc_tests {
#[allow(unused)]
use crate::{AsCloneOnExtract, IntoCloneOnExtract};
use super::CloneOnExtract;
pub trait AddTogether<T> {
fn add_together(self, other: T) -> i32;
}
impl AddTogether<u8> for u8 {
fn add_together(self, other: u8) -> i32 {
(self + other) as i32
}
}
impl AddTogether<&i32> for i32 {
fn add_together(self, other: &i32) -> i32 {
self + other
}
}
impl AddTogether<CloneOnExtract<'_, u8, u8>> for CloneOnExtract<'_, u8, u8> {
fn add_together(self, other: CloneOnExtract<u8, u8>) -> i32 {
self.extract().add_together(other.extract())
}
}
impl AddTogether<CloneOnExtract<'_, i32, i32>> for CloneOnExtract<'_, i32, i32> {
fn add_together(self, other: CloneOnExtract<i32, i32>) -> i32 {
self.extract().add_together(other.as_ref())
}
}
#[allow(unused)]
pub fn add_together_and_double<T: Clone>(lhs: CloneOnExtract<T, T>, rhs: CloneOnExtract<T, T>) -> i32
where
for<'a, 'b> CloneOnExtract<'a, T, T>: AddTogether<CloneOnExtract<'b, T, T>>,
{
lhs.as_borrowed().add_together(rhs.as_borrowed()) + lhs.as_borrowed().add_together(rhs)
}
#[test]
fn test() {
assert_eq!(add_together_and_double(1u8.coe(), 2u8.coe()), 6);
assert_eq!(add_together_and_double(1i32.coe(), 2i32.coe()), 6);
}
}