Struct that owns some data and a data reference
Constructing an object extracts the data that is needed for that object to live, but also creates another object that needs to maintain data references:
pub fn new() -> Obj {
let data = compute();
Obj {
original: data,
processed: AnotherObj {
reference: &data
}
}
}
Can this be expressed in terms of rust?
Here I would like to Obj
, AnotherObj
and data
have the same life span and, of course, experience the challenge new()
.
source to share
The raw design of structures based on your requirements might look like this:
struct AnotherObj<'a> { original: &'a Vec<i8>, // Let agree on Vec<i8> as your "data" type. } struct Obj<'a> { original: Vec<i8>, // <-------------------+ processed: AnotherObj<'a>, // should point here --+ }
However, it is very difficult to get a job (I personally could not) because you want 'a
to AnotherObj<'a>
was a time of life original
. However, you have to specify a lifetime Obj<'a>
, and you will need to indicate Obj<'tbc>
where 'tbc
is the lifetime of the item being created Obj
.
I suggest the following options:
1. Make AnotherObj truly original
Why not? Obj
will be owned AnotherObj
, so it can still be accessed original
as a nested child:
pub struct AnotherObj { original: Vec<i8>, } pub struct Obj { processed: AnotherObj, } pub fn new() -> Obj { let data = vec![1,2,3]; Obj { processed: AnotherObj { original: data, // ... } } } // access as obj.processed.original, you can even create a getter `fn original(&self)`
2. General construction of the pointer
Direct use of refcounted pointers:
use std::rc::Rc; pub struct AnotherObj { original: Rc<Vec<i8>>, } pub struct Obj { original: Rc<Vec<i8>>, processed: AnotherObj, } pub fn new() -> Obj { let data = Rc::new(vec![1,2,3]); Obj { original: data.clone(), processed: AnotherObj { original: data.clone(), } } }
3.With original pointers
Options 1 and 2 will bring you the peace of mind of the harmless gods of rust, so I don't recommend this third option. I am still posting it here for completeness. Note: it compiles, but I've never tested it at runtime, so it might bite. There's only safe code below, but you'll need to step into the scope unsafe
if you want to dereference a raw pointer.
use std::ptr; pub struct AnotherObj { original: *mut Vec<i8>, } pub struct Obj { original: Vec<i8>, processed: AnotherObj, } pub fn new() -> Obj { let data = vec![1,2,3]; let mut obj = Obj { original: data, processed: AnotherObj { original: ptr::null_mut(), } }; obj.processed.original = &mut obj.original as *mut Vec<i8>; obj }
source to share