gpt4 book ai didi

rust - 如何正确使用特征对象,可变迭代可变特征对象容器,同时改变容器本身?

转载 作者:行者123 更新时间:2023-12-03 11:38:03 25 4
gpt4 key购买 nike

我正在尝试编写一个数据包解析器,基本上一个通过解析数据包中的每一层来构建一个数据包。然后数据包将这些“层”保存在一个向量中。
带有编译错误的 ~pseudo code~ 代码如下所示 -
还在下面添加了评论 - 对于每个步骤。我已经尝试过 RefCell ,但无法正常工作。本质上,挑战在代码末尾列出。
基本模式如下 - 获取 Layer 类型的对象(每个 Layer 类型都将返回一个 default 下一个对象,该对象基于当前层中的某个字段作为“盒装特征对象”。)
编辑:我添加的代码不仅仅是伪代码 - 还添加了以下编译错误。可能是一种弄清楚如何解决这些错误的方法可以解决问题。!


#[derive(Debug, Default)]
pub struct Packet<'a> {
data: Option<&'a [u8]>,
meta: PacketMetadata,
layers: Vec<Box<dyn Layer<'a>>>,
}

pub trait Layer<'a>: Debug {
fn from_u8<'b>(&mut self, bytes: &'b [u8]) -> Result<(Option<Box<dyn Layer>>, usize), Error>;
}

#[derive(Debug, Default)]
pub struct PacketMetadata {
timestamp: Timestamp,
inface: i8,
len: u16,
caplen: u16,
}

impl<'a> Packet<'a> {
fn from_u8(bytes: &'a [u8], _encap: EncapType) -> Result<Self, Error> {
let mut p = Packet::default();

let eth = ethernet::Ethernet::default();

let mut layer: RefCell<Box<dyn Layer>> = RefCell::new(Box::new(eth));
let mut res: (Option<Box<dyn Layer>>, usize);
let mut start = 0;
loop {
let mut decode_layer = layer.borrow_mut();

// process it
res = decode_layer.from_u8(&bytes[start..])?;

if res.0.is_none() {
break;
}

// if the layer exists, get it in a layer.
let boxed = layer.replace(res.0.unwrap());
start = res.1;

// append the layer to layers.
p.layers.push(boxed);
}
Ok(p)
}
}

编译错误
error[E0515]: cannot return value referencing local variable `decode_layer`
--> src/lib.rs:81:9
|
68 | res = decode_layer.from_u8(&bytes[start..])?;
| ------------ `decode_layer` is borrowed here
...
81 | Ok(p)
| ^^^^^ returns a value referencing data owned by the current function

error[E0515]: cannot return value referencing local variable `layer`
--> src/lib.rs:81:9
|
65 | let mut decode_layer = layer.borrow_mut();
| ----- `layer` is borrowed here
...
81 | Ok(p)
| ^^^^^ returns a value referencing data owned by the current function

error: aborting due to 2 previous errors; 3 warnings emitted

目前尚不清楚为什么会出现上述错误。我正在使用调用返回的值。 (上面显示的 3: 警告可以忽略,它们是未使用的警告。)
挑战——
  • p.layers.last_mutp.layers.push是同时可变的借用 - 不允许。我可以以某种方式把它放在一个 RefCell 后面,但是这还不清楚。
  • 此代码在模式上类似于 syn::token::Token s,但是一个基本的区别是,有一个 Enum被使用(TokenTree)。在上面的例子中,我不能使用 Enum因为要支持的协议(protocol)列表可能是无限的。
  • 我不能使用 Layer没有 Trait Objects 的特征由于 loop 构造。
  • 该模式可以被认为是 - 在更新容器本身的同时可变地迭代 Trait 对象的容器。
  • 也许我错过了一些非常基本的东西。
  • 最佳答案

    上述代码的问题是由于 Layer 上的生命周期注释。特征。如果删除了该生命周期注释,则上面的代码确实可以通过一些修改进行编译,如下所示 -

    // Layer Trait definition
    pub trait Layer: Debug {
    fn from_u8(&mut self, bytes: &[u8]) -> Result<(Option<Box<dyn Layer>>, usize), Error>;
    }


    impl<'a> Packet<'a> {
    fn from_u8(bytes: &'a [u8], _encap: EncapType) -> Result<Self, Error> {
    let mut p = Packet::default();

    let eth = ethernet::Ethernet::default();

    let layer: RefCell<Box<dyn Layer>> = RefCell::new(Box::new(eth));
    let mut res: (Option<Box<dyn Layer>>, usize);
    let mut start = 0;
    loop {
    {
    // Do a `borrow_mut` in it's own scope, that gets dropped at the end.
    let mut decode_layer = layer.borrow_mut();
    res = decode_layer.from_u8(&bytes[start..])?;
    }

    if res.0.is_none() {
    // This is just required to push something to the RefCell, that will get dropped anyways.
    let fake_boxed = Box::new(FakeLayer {});
    let boxed = layer.replace(fake_boxed);

    p.layers.push(boxed);
    break;
    }

    // if the layer exists, get it in a layer.
    let boxed = layer.replace(res.0.unwrap());
    start = res.1;

    // append the layer to layers.
    p.layers.push(boxed);
    }
    Ok(p)
    }
    }

    关于rust - 如何正确使用特征对象,可变迭代可变特征对象容器,同时改变容器本身?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66487432/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com