// Copyright 2021 Ian Jackson and contributors // SPDX-License-Identifier: GPL-3.0-or-later // There is NO WARRANTY. // This is a skeleton demonstrating a simple open-coded version // of the generated code. use memoffset::offset_of; use std::fmt::{self, Debug}; use std::ops::{Deref, DerefMut}; struct AB { a: usize, b: String, } #[repr(C)] #[derive(Debug)] struct PartA { a: ZstA } #[repr(C)] struct ZstA; #[repr(C)] #[derive(Debug)] struct PartB { b: ZstB } #[repr(C)] struct ZstB; impl Debug for ZstA where String: Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&**self, f) } } impl Deref for ZstA { type Target = usize; fn deref(&self) -> &usize { let p: *const ZstA = self; let p: *const AB = p as usize as _; // use exposed provenance AB at p let offset = offset_of!(AB, a); let p: *const u8 = p as _; let p = unsafe { p.add(offset) }; let p: *const usize = p as _; let p: &usize = unsafe { p.as_ref().unwrap() }; p } } impl DerefMut for ZstA { fn deref_mut(&mut self) -> &mut usize { let p: *mut ZstA = self; let p: *mut AB = p as usize as _; // use exposed provenance AB at p let offset = offset_of!(AB, a); let p: *mut u8 = p as _; let p = unsafe { p.add(offset) }; let p: *mut usize = p as _; let p: &mut usize = unsafe { p.as_mut().unwrap() }; p } } impl Debug for ZstB where String: Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&**self, f) } } impl Deref for ZstB { type Target = String; fn deref(&self) -> &String { let p: *const ZstB = self; let p: *const AB = p as usize as _; // use exposed provenance AB at p let offset = offset_of!(AB, b); let p: *const u8 = p as _; let p = unsafe { p.add(offset) }; let p: *const String = p as usize as _; let p: &String = unsafe { p.as_ref().unwrap() }; p } } impl DerefMut for ZstB { fn deref_mut(&mut self) -> &mut String { let p: *mut ZstB = self; let p: *mut AB = p as usize as _; // use exposed provenance AB at p let offset = offset_of!(AB, b); let p: *mut u8 = p as _; let p = unsafe { p.add(offset) }; let p: *mut String = p as usize as _; let p: &mut String = unsafe { p.as_mut().unwrap() }; p } } fn split(ab: &AB) -> (&PartA, &PartB) { let ab: *const AB = ab; let a: *const PartA = ab as usize as _; // expose provenance AB at p let a: & PartA = unsafe { a.as_ref().unwrap() }; let b: *const PartB = ab as usize as _; let b: & PartB = unsafe { b.as_ref().unwrap() }; (a,b) } fn split_mut(ab: &mut AB) -> (&mut PartA, &mut PartB) { let ab: *mut AB = ab; let a: *mut PartA = ab as usize as _; let a: &mut PartA = unsafe { a.as_mut().unwrap() }; let b: *mut PartB = ab as usize as _; let b: &mut PartB = unsafe { b.as_mut().unwrap() }; (a,b) } impl AsRef for AB { fn as_ref(&self) -> &PartB { split(self).1 } } impl AsMut for AB { fn as_mut(&mut self) -> &mut PartB { split_mut(self).1 } } fn using_a(p: &mut PartA) { eprintln!("b={:?}", p); *p.a += 1; eprintln!("b={:?}", p); } fn using_av(p: &mut usize) { eprintln!("b={:?}", p); *p += 2; eprintln!("b={:?}", p); } fn using_b(p: &mut PartB) { let f = &mut p.b; eprintln!("b={:?}", f); f.push('y'); eprintln!("b={:?}", f); p.b.push('z'); eprintln!("b={:?}", p); } fn using_bv(p: &mut String) { eprintln!("b={:?}", p); p.push('b'); eprintln!("b={:?}", p); } impl PartB { fn b_method(&mut self) { eprintln!("b={:?}", self); self.b.push('b'); eprintln!("b={:?}", self); } } pub fn check() { let mut ab = AB { a: 42, b: format!("x") }; let (a,b) = split_mut(&mut ab); using_a(a); using_b(b); using_av(&mut a.a); using_bv(&mut b.b); using_a(a); using_b(b); using_a(a); using_b(b); ab.as_mut().b_method(); let ab = &mut ab; using_b(ab.as_mut()); }