Ouroboros: one struct has accessors, another doesn't

Trying to use ouroboros in my code, I met this issue: the second struct hasn't accessor for feature_iterator field.

I can't see why, because other things are equal.

Full source code, and expanded code.

What am I doing wrong?

// this has accessors for all fields
#[self_referencing]
pub struct FgbDriver {
	fp: File,
	#[borrows(mut fp)]
	#[covariant]
	features_selected: FgbReader<'this, File, FeaturesSelectedSeek>,
}

// this has no accessors for feature_iterator
#[self_referencing]
pub struct GpkgDriver {
	pub feature_iterator: OwnedFeatureIterator,
	#[borrows(mut feature_iterator)]
	#[covariant]
	current_feature: Option<GdalFeature<'this>>,
}

Adding/removing pub before feature_iterator makes no difference.

FgbDriver won’t have an accessor for fp either.

1 Like

Here’s (the mockup of) a possible solution

use std::error::Error;

use ouroboros::self_referencing;

struct OwnedFeatureIterator;

impl<'a> Iterator for &'a mut OwnedFeatureIterator
where
    Self: 'a,
{
    type Item = Feature<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        todo!()
    }
}

struct Feature<'a>(&'a ());

#[self_referencing]
pub struct GpkgDriver {
    feature_iterator: OwnedFeatureIterator,
    #[borrows(mut feature_iterator)]
    #[covariant]
    inner: GpkgDriverInner<'this>,
}
struct GpkgDriverInner<'a> {
    feature_iterator_ref: &'a mut OwnedFeatureIterator,
    current_feature: Option<Feature<'a>>,
}

impl<'a> GpkgDriver {
    fn forward(&mut self) -> Result<bool, Box<dyn Error>> {
        self.with_inner_mut(|inner| {
            if let Some(f) = inner.feature_iterator_ref.next() {
                inner.current_feature.replace(f);
                Ok(true)
            } else {
                Ok(false)
            }
        })
    }
}
1 Like

Alternative approach, might be nicer looking:

use std::error::Error;

use ouroboros::self_referencing;

struct OwnedFeatureIterator;

impl<'a> Iterator for &'a mut OwnedFeatureIterator
where
    Self: 'a,
{
    type Item = Feature<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        todo!()
    }
}

struct Feature<'a>(&'a ());

#[self_referencing]
pub struct GpkgDriver {
    feature_iterator: OwnedFeatureIterator,
    #[borrows(mut feature_iterator)]
    feature_iterator_ref: &'this mut OwnedFeatureIterator,
    #[borrows()] // needs to borrow nothing initially: set to `None` on construction, populate later
    #[covariant]
    current_feature: Option<Feature<'this>>,
}

impl<'a> GpkgDriver {
    fn forward(&mut self) -> Result<bool, Box<dyn Error>> {
        self.with_mut(|mut this| {
            if let Some(f) = this.feature_iterator_ref.next() {
                this.current_feature.replace(f);
                Ok(true)
            } else {
                Ok(false)
            }
        })
    }
}
1 Like

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.