微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 Rust 中使用生命周期参数迭代结构列表?

如何解决如何在 Rust 中使用生命周期参数迭代结构列表?

Playground

我有以下生成代码(来自 flatbuffers 架构):

pub trait TFilterData {
    fn get_text(&self) -> &str;
}

pub struct Table<'a> {
    pub buf: &'a [u8],pub loc: usize,}

pub struct Data<'a> {
    pub _tab: Table<'a>,}

pub struct MatchResult<'a> {
    pub _tab: Table<'a>,}

pub struct FiltersByKeyword<'a> {
    pub _tab: Table<'a>,}

pub struct KeywordByFilter<'a> {
    pub _tab: Table<'a>,}

pub struct BlockingFilter<'a> {
    pub _tab: Table<'a>,}

impl TFilterData for BlockingFilter<'_> {
    fn get_text(&self) -> &str {
        todo!()
    }
}

impl<'a> MatchResult<'a> {
    pub fn blocking_filters(&self) -> Option<Vec<BlockingFilter<'a>>> {
        None
    }
}

impl<'a> FiltersByKeyword<'a> {
    pub fn filters(&self) -> Option<Vec<MatchResult<'a>>> {
        None
    }

    pub fn keyword(&self) -> String {
        "".to_owned()
    }
}

impl<'a> Data<'a> {
    pub fn keyword_by_filter_list(&self) -> Option<Vec<KeywordByFilter<'a>>> {
        None
    }

    pub fn filters_by_keyword_list(&self) -> Option<Vec<FiltersByKeyword<'a>>> {
        None
    }
}

我有自己的结构体:

pub type RcedFilterDataVec = Vec<Rc<dyn TFilterData>>;

pub struct FlatBuffersIndex<'a> {
    data: Data<'a>,filter_by_keyword: HashMap<String,RcedFilterDataVec>,// keyword -> list of `TFilterData`s
    keyword_by_filter: HashMap<String,String>,// Filter -> keyword
}

impl<'a> FlatBuffersIndex<'a> {
    pub fn new(buffer: &'a [u8]) -> Self {
        let data: Data<'a> = Data {
            _tab: Table {
                buf: buffer,loc: 0,},};

        let mut keyword_by_filter = HashMap::new();
        let mut filter_by_keyword = HashMap::new();
        if let Some(some_filters_by_keyword_list) = data.filters_by_keyword_list() {
            for key_value in some_filters_by_keyword_list {
                let mut filters = RcedFilterDataVec::new();

                // filters
                for each_match_result in key_value.filters().unwrap() {
                    // Todo: there is no sense in mixing of them as later matcher will have to separate them

                    // blocking
                    if let Some(some_blocking_filters) = each_match_result.blocking_filters() {
                        for each_blocking_filter in some_blocking_filters {
                            // actually we don't need BlockingFilter part more than RegExpFilter + FilterType
                            // let filter = each_blocking_filter.regexp_filter().clone();
                            let rc_filter = Rc::new(each_blocking_filter);
                            filters.push(rc_filter);
                            // Todo: add it!!! currently commented due to unclear lifetime issue
                        }
                    }

                    // ...
                }

                filter_by_keyword.insert(key_value.keyword().to_owned(),filters);
            }
        }

        FlatBuffersIndex {
            data,filter_by_keyword,keyword_by_filter,}
    }
}

尝试对其进行迭代时,我有以下错误输出

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> src/lib.rs:83:58
    |
83  |         if let Some(some_filters_by_keyword_list) = data.filters_by_keyword_list() {
    |                                                          ^^^^^^^^^^^^^^^^^^^^^^^
    |
note: first,the lifetime cannot outlive the lifetime `'a` as defined on the impl at 72:6...
   --> src/lib.rs:72:6
    |
72  | impl<'a> FlatBuffersIndex<'a> {
    |      ^^
note: ...so that the types are compatible
   --> src/lib.rs:83:58
    |
83  |         if let Some(some_filters_by_keyword_list) = data.filters_by_keyword_list() {
    |                                                          ^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected `&Data<'_>`
               found `&Data<'a>`
    = note: but,the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
   --> src/lib.rs:111:13
    |
111 |             filter_by_keyword,|             ^^^^^^^^^^^^^^^^^
    = note: expected `HashMap<_,Vec<Rc<(dyn TFilterData + 'static)>>>`
               found `HashMap<_,Vec<Rc<dyn TFilterData>>>`

为什么编译器不清楚它会存在于 'a 中,这在这里似乎没问题?我该如何解决

附注。这是生成代码的 flatbuffers IDL:

namespace com.eyeo.adblockplus.fb;

table AbpFilter {
  filter_text: string (required); // Strings are UTF-8,[ubyte] might be needed. How will we have `String` without convertions then?
  filter_type: ushort;
}

table CommentFilter {
  filter: AbpFilter (required);
}

table InvalidFilter {
  filter: AbpFilter (required);
  reason: string (required);
}

table ActiveFilter {
  filter: AbpFilter (required);
  sitekeys: [string];
  domain_separator: string (required);
  domain_source: string;
  domain_source_is_lower_case: bool;
}

table RegExpFilter {
  active_filter: ActiveFilter (required);
  third_party: bool;
  content_type: uint;
  pattern: string;
  rewrite: string;
}

// Probably we don't really need subclasses of RegExpFilter for matching
// as we have RegExpFilter + FilterType to be used by Matcher when matching
table BlockingFilter {
  regexp_filter: RegExpFilter (required);
  collapse: bool; // probably unneeded
  csp: string; // probably unneeded
}

table AllowingFilter {
  regexp_filter: RegExpFilter (required);
}

table MatchResult {
  blocking_filters: [BlockingFilter];
  allowing_filters: [AllowingFilter];
}

// non-abstract filters (leafs)
// vector of union's is not supported unfortunately,// thus we can't declare `filters: [FilterUnion]` in `struct` or `table`. Can we?
// union FilterUnion {
//   CommentFilter,//   InvalidFilter,// }

table KeywordByFilter {
  filter_text: string (required,key);
  keyword: string (required);
}

table FiltersByKeyword {
  keyword: string (key);
  filters: [MatchResult];
}

table Storage {
  invalid_filters: [InvalidFilter];
  comment_filters: [CommentFilter];
}

table Data {
  filters: [MatchResult];
  keyword_by_filter_list: [KeywordByFilter];
  filters_by_keyword_list: [FiltersByKeyword];
  storage: Storage;
}

root_type Data;

PPS。我发现它仅在迭代来自 flatbuffers 集合(each_match_result.blocking_filters()each_match_result.allowing_filters())的另一个向量并将其添加到放入 filters 的新过滤器向量 filter_by_keyword 中时发生:

if let Some(some_blocking_filters) = each_match_result.blocking_filters() {
                        for each_blocking_filter in some_blocking_filters {
                            // actually we don't need BlockingFilter part more than RegExpFilter + FilterType
                            filters.push(Rc::new(each_blocking_filter.regexp_filter()));
                        }
                    }

以下是其他集合的声明方式:

pub fn blocking_filters(&self) -> Option<flatbuffers::Vector<'a,flatbuffers::ForwardsUOffset<BlockingFilter<'a>>>> {
    self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<BlockingFilter<'a>>>>>(MatchResult::VT_BLOCKING_FILTERS,None)
  }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。