How to handle Self referencing struct?

// this struct is from thrid party can't modify it
struct DataView<'a> {
    data: &'a [u8]
}

struct Builder<'a> {
    data: Vec<u8>,
    views: Vec<DataView<'a>>
}

struct Product;

impl<'a> Builder<'a> {
    pub fn new() -> Self {
        Self {
            data: vec![],
            views: vec![]
        }
    }
    pub fn add_sample_view(&'a mut self) -> &mut Self{
        let dummy_data = vec![0_u8,1,2]; //can be anything will be 
        //dynamically generated
        self.data = dummy_data;
        self.views.push(DataView{
            data: &self.data
        });
        self
    }
    pub fn build(&mut self) -> Product {
        Product
    }
}
fn main() {
    let mut b = Builder::new();
    b.add_sample_view()
    .build();
}

The code does not complie. I know whats the issue, i am hoping a way to fix it without modifying the builder pattern

You'll have to split it into two local variables so that one can reference the other.

// this struct is from thrid party can't modify it
struct DataView<'a> {
    data: &'a [u8]
}

struct Builder<'a> {
    data: Vec<u8>,
    views: Vec<DataView<'a>>
}

struct Product;

impl<'a> Builder<'a> {
    pub fn new() -> Self {
        Self {
            data: vec![],
            views: vec![]
        }
    }
    fn set_data(&mut self) -> &mut Self {
        let dummy_data = vec![0_u8,1,2]; //can be anything will be 
        //dynamically generated
        self.data = dummy_data;
        self
    }
    pub fn add_sample_view(&'a mut self) -> &mut Self{
        self.set_data();
        self.views.push(DataView{
            data: &self.data
        });
        self
    }
    pub fn build(&mut self) -> Product {
        Product
    }
}
fn main() {
    let mut b = Builder::new();
    b.add_sample_view()
    .build();
}

Still same issue

You misunderstand. The vector and the borrow cannot be owned by the same thing. The main function will need two separate variables - one for holding the vector and one for holding the view.

Oh, ok. But, I have a situation where I need this behaviour. I want the data to be associated with the Builder and get cleaned up when the builder instance goes out of scope. In my real case, the data should be generated from builder and it has no knowledge of outer scope. Thanks

You might want to check out the similar discussion over here:

But generally, the Rust language just doesn't really support this kind of stuff.

2 Likes

The underlying problem is that Rust structures can be relocated in memory, usually when the structure grows or shrinks in size. Self-referential addresses contained within such a structure become dangling pointers when such relocation occurs. However, indices are unaffected by relocation because the layout of the structure remains unchanged no matter where the structure is relocated in memory.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.