// Copyright 2021 Ian Jackson and contributors // SPDX-License-Identifier: GPL-3.0-or-later // There is NO WARRANTY. use super::*; use crate::*; #[derive(Debug,PartialBorrow)] #[partial_borrow(Debug)] struct AB { a: usize, b: String, } impl Default for AB { fn default() -> Self { Self { a: 42, b: "hello".into() } } } impl AB { fn bump(&mut self) { self.a += 1; self.b.push('|'); println!("-----\n{:?}", self); } fn use_const(&self) { println!("{:?}", self); } } #[ext] impl partial!(AB mut a, !*) { fn use_mut_a(&mut self) { *self.a += 10; } } #[ext] impl partial!(AB const a, !*) { fn use_const_a(&self) { println!("{}", &*self.a); } } #[ext] impl partial!(AB mut b, !*) { fn use_mut_b(&mut self) { self.b.push('U'); } } #[ext] impl partial!(AB const b, !*) { fn use_const_b(&self) { println!("{}", &*self.b); } } macro_rules! test_downgrade { { $tfn:ident, $downgrade:path, $downgrade_mut:path } => { #[test] fn $tfn() { println!("downgrade {}", stringify!($tfn)); let mut ab = AB::default(); // &mut Mut let a: &mut partial!(AB mut a) = $downgrade_mut(&mut ab); *a.a += 1; a.as_mut().use_mut_a(); println!("{:?}", a); let a: &partial!(AB) = $downgrade(&ab); let a_ab = &**a; println!("{:?}", a_ab); a.use_const(); a_ab.use_const(); ab.bump(); // &mut Const let a: &mut partial!(AB const a, !*) = $downgrade_mut(&mut ab); println!("{}", &*a.a); a.use_const_a(); println!("{:?}", a); // &Mut, &Const let a0: &partial!(AB mut a, !*) = $downgrade(&ab); let a1: &partial!(AB const a, !*) = $downgrade(&ab); println!("{} {}", &*a0.a, &*a1.a); a0.as_ref().use_const_a(); a1.use_const_a(); println!("{:?} {:?}", a0, a1); ab.bump(); } }} test_downgrade!{ downgrade, Downgrade::downgrade, Downgrade::downgrade_mut } test_downgrade!{ asref, AsRef::as_ref, AsMut::as_mut } macro_rules! test_split { { $tfn:ident, $split:path, $split_mut:path } => { #[test] fn $tfn() { println!("split {}", stringify!($tfn)); let mut ab = AB::default(); // &mut Mut let (a,b): (&mut partial!(AB mut a, !*), &mut partial!(AB mut b, !*)) = $split_mut(&mut ab); *a.a += 1; *b.b += "+"; a.use_mut_a(); b.use_mut_b(); println!("{:?} {:?}", a, b); ab.bump(); // &mut Const let (a,b): (&mut partial!(AB const a, !*), &mut partial!(AB const a, mut *)) = $split_mut(&mut ab); println!("{}", &*a.a); *b.b += "#"; a.use_const_a(); b.as_mut().use_mut_b(); println!("{:?} {:?}", a, b); // &mut Const Const let (a,b): (&mut partial!(AB), &mut partial!(AB)) = $split_mut(&mut ab); println!("{} {}", &*a.a, &*b.b); a.as_ref().use_const_a(); b.as_ref().use_const_b(); let a_ab = &**a; let b_ab = &**b; println!("{:?} {:?} {:?} {:?}", a, b, a_ab, b_ab); a.use_const(); b.use_const(); a_ab.use_const(); b_ab.use_const(); ab.bump(); // &Mut let (a,b): (&partial!(AB mut a, !*), &partial!(AB mut b, !*)) = $split(&ab); println!("{} {}", &*a.a, &*b.b); a.as_ref().use_const_a(); b.as_ref().use_const_b(); println!("{:?} {:?}", a, b); ab.bump(); // &Const let (a,b): (&partial!(AB const a, !*), &partial!(AB const a, mut *)) = $split(&ab); println!("{} {}", &*a.a, &*b.b); a.use_const_a(); b.as_ref().use_const_b(); println!("{:?} {:?}", a, b); ab.bump(); } }} test_split!{ split_off, SplitOff::split_off, SplitOff::split_off_mut } test_split!{ split_into, SplitInto::split_into, SplitInto::split_into_mut } test_split!{ split_into_into, Into::into, Into::into } test_split!{ split_from_from, From::from, From::from }