use core::cell::{Ref, RefCell}; use core::ptr::drop_in_place; #[cfg(test)] mod simple { use super::*; #[derive(incrstruct::IncrStruct)] struct AStruct<'a> { #[borrows(b)] pub c: &'a i32, #[borrows(head1, head2)] pub b: Ref<'a, i32>, pub head1: RefCell, pub head2: i64, #[header] hdr: incrstruct::Header, } impl<'a> AStructInit<'a> for AStruct<'a> { fn init_field_c(b: &'a Ref<'a, i32>) -> &'a i32 { b } fn init_field_b(_head2: &'a i64, head1: &'a RefCell) -> Ref<'a, i32> { head1.borrow() } } #[test] fn new_uninit_works() { let mut a = unsafe { AStruct::new_uninit(4711, RefCell::new(42)) }; let aref = AStruct::ensure_init(&mut a); assert_eq!(*aref.head1.borrow(), 42); assert_eq!(*aref.b, 42); assert_eq!(*aref.c, 42); unsafe { drop_in_place(aref) }; } #[test] fn drop_uninit_in_place_works() { let a = unsafe { AStruct::new_uninit(4711, RefCell::new(42)) }; assert_eq!(*(unsafe { &*a.as_ptr() }).head1.borrow(), 42); unsafe { AStruct::drop_uninit(a) }; } #[test] fn new_box_works() { let a = AStruct::new_box(4711, RefCell::new(42)); assert_eq!(*a.head1.borrow(), 42); assert_eq!(*a.b, 42); assert_eq!(*a.c, 42); } #[test] fn new_rc_works() { let a = AStruct::new_rc(4711, RefCell::new(42)); assert_eq!(*a.head1.borrow(), 42); assert_eq!(*a.b, 42); assert_eq!(*a.c, 42); } #[test] fn force_init_works() { let a = AStruct::new_box(4711, RefCell::new(42)); let mut b = *a; AStruct::force_init(&mut b); assert_eq!(*b.head1.borrow(), 42); assert_eq!(*b.b, 42); assert_eq!(*b.c, 42); } } #[cfg(test)] mod init_err { use super::*; #[derive(Debug, Eq, PartialEq)] enum Error { Failed, } #[derive(Debug, incrstruct::IncrStruct)] #[init_err(Error)] struct AStruct<'a> { #[borrows(b, head2)] pub c: &'a i32, #[borrows(head1)] pub b: Ref<'a, i32>, pub head1: RefCell, pub head2: i64, #[header] hdr: incrstruct::Header, } const HEAD2_FAIL: i64 = 18; impl<'a> AStructInit<'a> for AStruct<'a> { fn init_field_c(head2: &'a i64, b: &'a Ref<'a, i32>) -> Result<&'a i32, Error> { if *head2 == HEAD2_FAIL { Err(Error::Failed) } else { Ok(b) } } fn init_field_b(head1: &'a RefCell) -> Result, Error> { Ok(head1.borrow()) } } #[test] fn new_uninit_works() { let mut a = unsafe { AStruct::new_uninit(4711, RefCell::new(42)) }; let aref = AStruct::ensure_init(&mut a).unwrap(); assert_eq!(*aref.head1.borrow(), 42); assert_eq!(*aref.b, 42); assert_eq!(*aref.c, 42); unsafe { drop_in_place(aref) }; } #[test] fn drop_uninit_in_place_works() { let a = unsafe { AStruct::new_uninit(4711, RefCell::new(42)) }; assert_eq!(*(unsafe { &*a.as_ptr() }).head1.borrow(), 42); unsafe { AStruct::drop_uninit(a) }; } #[test] fn new_box_works() { let a = AStruct::new_box(4711, RefCell::new(42)).unwrap(); assert_eq!(*a.head1.borrow(), 42); assert_eq!(*a.b, 42); assert_eq!(*a.c, 42); } #[test] fn new_rc_works() { let a = AStruct::new_rc(4711, RefCell::new(42)).unwrap(); assert_eq!(*a.head1.borrow(), 42); assert_eq!(*a.b, 42); assert_eq!(*a.c, 42); } #[test] fn force_init_works() { let a = AStruct::new_box(4711, RefCell::new(42)).unwrap(); let mut b = *a; AStruct::force_init(&mut b).unwrap(); assert_eq!(*b.head1.borrow(), 42); assert_eq!(*b.b, 42); assert_eq!(*b.c, 42); } #[test] fn new_box_fails_gracefully() { assert_eq!( AStruct::new_box(HEAD2_FAIL, RefCell::new(42)).unwrap_err(), Error::Failed ); } #[test] fn second_force_init_fails_gracefully() { let a = AStruct::new_box(4711, RefCell::new(42)).unwrap(); let mut b = *a; AStruct::force_init(&mut b).unwrap(); b.head2 = HEAD2_FAIL; assert_eq!(AStruct::force_init(&mut b).unwrap_err(), Error::Failed); } }