Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 如何在tokio_core::io::Codec::decode(…)中实现零拷贝?_Rust_Rust Tokio - Fatal编程技术网

Rust 如何在tokio_core::io::Codec::decode(…)中实现零拷贝?

Rust 如何在tokio_core::io::Codec::decode(…)中实现零拷贝?,rust,rust-tokio,Rust,Rust Tokio,我的目标是实现一个Codec,它将提供的EasyBuf抽取到消息边界,并将其解码为仅引用内容的结构,以防止不必要的复制。 查看EasyBuf的实现,目前似乎不可能实现,但可能我遗漏了一些东西 以下是我使用的代码,这样做实际上是为了: struct V>, } 结构C; C语言的impl编解码器{ 输入=R{ buf:&'a mut Vec, 结束:&'a mut usize, } 简单易用{ pub fn new()->EasyBuf{ EasyBuf::具有_容量(8*1024) } 酒吧fn

我的目标是实现一个
Codec
,它将提供的
EasyBuf
抽取到消息边界,并将其解码为仅引用内容的结构,以防止不必要的复制。 查看
EasyBuf
的实现,目前似乎不可能实现,但可能我遗漏了一些东西

以下是我使用的代码,这样做实际上是为了:

struct V>,
}
结构C;
C语言的impl编解码器{
输入=R{
buf:&'a mut Vec,
结束:&'a mut usize,
}
简单易用{
pub fn new()->EasyBuf{
EasyBuf::具有_容量(8*1024)
}
酒吧fn,容量(上限:usize)->EasyBuf{
轻松的{
buf:Arc::新建(Vec::带容量(cap)),
起点:0,
完:0,,
}
}
fn set_start(&mut self,start:usize)->&mut EasyBuf{
断言!(启动EasyBuf){
让mut other=EasyBuf{buf:self.buf.clone(),..*self};
设idx=self.start+at;
其他。设置启动(idx);
自整定端(idx);
归还他人;
}
pub fn drain_to(&mut self,at:usize)->EasyBuf{
让mut other=EasyBuf{buf:self.buf.clone(),..*self};
设idx=self.start+at;
其他。设置_端(idx);
自启动(idx);
归还他人;
}
pub fn get_mut(&mut self)->EasyBufMut{
if Arc::get_mut(&mut self.buf.)。是_some(){
让buf=Arc::get_mut(&mut self.buf).unwrap();
buf.排水管(…自启动);
self.start=0;
返回EasyBufMut{
buf:buf,
结束:&mut self.end,
};
}
设mut v=Vec::with_capacity(self.buf.capacity());
v、 从_切片(self.as_ref())扩展_;
self.start=0;
self.buf=弧::新(v);
易如反掌{
buf:Arc::get_mut(&mut self.buf).unwrap(),
结束:&mut self.end,
}
}
}
EasyBuf的impl AsRef{
fn作为参考(&self)->和[u8]{
&self.buf[self.start..self.end]
}
}
恳求{
类型目标=Vec;
fn deref(&self)->&Vec{
自我介绍
}
}
恳求{
fn deref_mut(&mut self)->&mut Vec{
自我介绍
}
}
来自EasyBuf的impl{
fn from(vec:vec)->EasyBuf{
让end=vec.len();
轻松的{
buf:Arc::新建(vec),
起点:0,
完:完,,
}
}
}
恳求{
fn下降(&mut自我){
*self.end=self.buf.len();
}
}
///通过缓冲器对帧进行编码和解码。
///
///此特性在构造“Framed”的实例时使用。它提供
///两种类型:`In`,用于解码输入帧;`Out`,用于输出帧
///它还提供了实际执行
///编码和解码,与相应的缓冲区类型一起工作。
///
///trait本身是在一个可以跟踪解码状态的类型上实现的
///或编码,这对于流式解析器特别有用
///不过,在某些情况下,这种类型只是一个单元结构(例如,`struct
///HttpCodec`)。
发布特性编解码器{
///解码帧的类型。
输入;
///要编码的帧的类型。
打字;
///尝试从提供的字节缓冲区解码帧。
///
///每当字节准备好进行解析时,“Framed”就会调用此方法。
///提供的字节缓冲区是到目前为止已读取的,并且
///'Decode'的实例可以确定整个帧是否在
///缓冲区,并准备返回。
///
///如果整个帧可用,则此实例将删除这些帧
///从提供的缓冲区返回字节,并将其作为解码
///请注意,从提供的缓冲区中删除字节并不总是
///必须复制字节,因此这应该是一个高效的操作
///大多数情况下。
///
///如果字节看起来有效,但帧尚未完全可用,则
///返回'Ok(None)'。这向'Framed'实例指示
///在再次调用此方法之前,它需要读取更多字节。
///
///最后,如果缓冲区中的字节格式不正确,则会出现错误
///返回,说明原因。这会通知'Framed',流现在已被设置
///腐败,应该终止。
fn解码(&mut self,buf:&mut EasyBuf)->io::Result;
///没有更多字节时可调用的默认方法
///可从底层I/O读取。
///
///此方法默认调用'decode',如果
///返回`Ok(None)`通常不需要实现
///除非帧协议在流末尾附近不同。
fn decode_eof(&mut self,buf:&mut EasyBuf)->io::Result{
匹配尝试!(自我解码(buf)){
一些(帧)=>正常(帧),
None=>Err(io::Error::new(io::ErrorKind::Other,“流上剩余的字节”),
}
}
///将帧编码到提供的缓冲区中。
///
///此方法将“msg”编码到“buf”提供的字节缓冲区中。
///提供的'buf'是'Framed'实例的内部缓冲区,并且
///在可能的情况下会写出来。
fn encode(&mut self,msg:self::Out,buf:&mut Vec)->io::Result;
}

思想
  • 由于
    Codec::in
    中缺少生存期,我认为目前无法实现这一点-我们必须声明它是静态的,这是借阅检查器的问题
  • 它可以通过返回
    EasyBuf
    本身(
    Codec::In=EasyBuf
    )来实现,并在稍后的步骤中进行解码,例如在类似于中的未来链接中进行解码
  • 它也可以通过将索引解析到EasyBuf中,并通过使用reference生成实际的数据类型来实现
    struct V<'a> {
        s: &'a [u8],
    }
    
    struct R<'a> {
        b: EasyBuf,
        v: Option<V<'a>>,
    }
    
    
    struct C;
    
    impl Codec for C {
        type In = R<'static>;
        type Out = String;
    
        fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<Self::In>> {
            let mut r = R {
                b: buf.clone(),
                v: None,
            };
            r.v = Some(V { s: r.b.as_slice() });
            Ok(Some(r))
        }
        fn encode(&mut self, msg: Self::Out, buf: &mut Vec<u8>) -> io::Result<()> {
            Ok(())
        }
    }
    
    
    fn main() {
        let b = EasyBuf::new();
        let mut r = R { b: b, v: None };
        r.v = Some(V { s: r.b.as_slice() });
    }
    
    
    use std::fmt;
    use std::io;
    use std::ops::{Deref, DerefMut};
    use std::sync::Arc;
    
    
    
    #[derive(Clone)]
    pub struct EasyBuf {
        buf: Arc<Vec<u8>>,
        start: usize,
        end: usize,
    }
    
    pub struct EasyBufMut<'a> {
        buf: &'a mut Vec<u8>,
        end: &'a mut usize,
    }
    
    impl EasyBuf {
        pub fn new() -> EasyBuf {
            EasyBuf::with_capacity(8 * 1024)
        }
    
        pub fn with_capacity(cap: usize) -> EasyBuf {
            EasyBuf {
                buf: Arc::new(Vec::with_capacity(cap)),
                start: 0,
                end: 0,
            }
        }
    
        fn set_start(&mut self, start: usize) -> &mut EasyBuf {
            assert!(start <= self.buf.as_ref().len());
            assert!(start <= self.end);
            self.start = start;
            self
        }
    
        fn set_end(&mut self, end: usize) -> &mut EasyBuf {
            assert!(end <= self.buf.len());
            assert!(self.start <= end);
            self.end = end;
            self
        }
    
        pub fn len(&self) -> usize {
            self.end - self.start
        }
    
        pub fn as_slice(&self) -> &[u8] {
            self.as_ref()
        }
    
        pub fn split_off(&mut self, at: usize) -> EasyBuf {
            let mut other = EasyBuf { buf: self.buf.clone(), ..*self };
            let idx = self.start + at;
            other.set_start(idx);
            self.set_end(idx);
            return other;
        }
    
        pub fn drain_to(&mut self, at: usize) -> EasyBuf {
            let mut other = EasyBuf { buf: self.buf.clone(), ..*self };
            let idx = self.start + at;
            other.set_end(idx);
            self.set_start(idx);
            return other;
        }
    
        pub fn get_mut(&mut self) -> EasyBufMut {
            if Arc::get_mut(&mut self.buf).is_some() {
                let buf = Arc::get_mut(&mut self.buf).unwrap();
                buf.drain(..self.start);
                self.start = 0;
                return EasyBufMut {
                    buf: buf,
                    end: &mut self.end,
                };
            }
    
            let mut v = Vec::with_capacity(self.buf.capacity());
            v.extend_from_slice(self.as_ref());
            self.start = 0;
            self.buf = Arc::new(v);
            EasyBufMut {
                buf: Arc::get_mut(&mut self.buf).unwrap(),
                end: &mut self.end,
            }
        }
    }
    
    impl AsRef<[u8]> for EasyBuf {
        fn as_ref(&self) -> &[u8] {
            &self.buf[self.start..self.end]
        }
    }
    
    impl<'a> Deref for EasyBufMut<'a> {
        type Target = Vec<u8>;
    
        fn deref(&self) -> &Vec<u8> {
            self.buf
        }
    }
    
    impl<'a> DerefMut for EasyBufMut<'a> {
        fn deref_mut(&mut self) -> &mut Vec<u8> {
            self.buf
        }
    }
    
    impl From<Vec<u8>> for EasyBuf {
        fn from(vec: Vec<u8>) -> EasyBuf {
            let end = vec.len();
            EasyBuf {
                buf: Arc::new(vec),
                start: 0,
                end: end,
            }
        }
    }
    
    impl<'a> Drop for EasyBufMut<'a> {
        fn drop(&mut self) {
            *self.end = self.buf.len();
        }
    }
    
    /// Encoding and decoding of frames via buffers.
    ///
    /// This trait is used when constructing an instance of `Framed`. It provides
    /// two types: `In`, for decoded input frames, and `Out`, for outgoing frames
    /// that need to be encoded. It also provides methods to actually perform the
    /// encoding and decoding, which work with corresponding buffer types.
    ///
    /// The trait itself is implemented on a type that can track state for decoding
    /// or encoding, which is particularly useful for streaming parsers. In many
    /// cases, though, this type will simply be a unit struct (e.g. `struct
    /// HttpCodec`).
    pub trait Codec {
        /// The type of decoded frames.
        type In;
    
        /// The type of frames to be encoded.
        type Out;
    
        /// Attempts to decode a frame from the provided buffer of bytes.
        ///
        /// This method is called by `Framed` whenever bytes are ready to be parsed.
        /// The provided buffer of bytes is what's been read so far, and this
        /// instance of `Decode` can determine whether an entire frame is in the
        /// buffer and is ready to be returned.
        ///
        /// If an entire frame is available, then this instance will remove those
        /// bytes from the buffer provided and return them as a decoded
        /// frame. Note that removing bytes from the provided buffer doesn't always
        /// necessarily copy the bytes, so this should be an efficient operation in
        /// most circumstances.
        ///
        /// If the bytes look valid, but a frame isn't fully available yet, then
        /// `Ok(None)` is returned. This indicates to the `Framed` instance that
        /// it needs to read some more bytes before calling this method again.
        ///
        /// Finally, if the bytes in the buffer are malformed then an error is
        /// returned indicating why. This informs `Framed` that the stream is now
        /// corrupt and should be terminated.
        fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<Self::In>>;
    
        /// A default method available to be called when there are no more bytes
        /// available to be read from the underlying I/O.
        ///
        /// This method defaults to calling `decode` and returns an error if
        /// `Ok(None)` is returned. Typically this doesn't need to be implemented
        /// unless the framing protocol differs near the end of the stream.
        fn decode_eof(&mut self, buf: &mut EasyBuf) -> io::Result<Self::In> {
            match try!(self.decode(buf)) {
                Some(frame) => Ok(frame),
                None => Err(io::Error::new(io::ErrorKind::Other, "bytes remaining on stream")),
            }
        }
    
        /// Encodes a frame into the buffer provided.
        ///
        /// This method will encode `msg` into the byte buffer provided by `buf`.
        /// The `buf` provided is an internal buffer of the `Framed` instance and
        /// will be written out when possible.
        fn encode(&mut self, msg: Self::Out, buf: &mut Vec<u8>) -> io::Result<()>;
    }
    
    pub struct PacketCodec {
        pub data_todo: Option<usize>,
    }
    
    type PacketItem = Frame<PacketHeader, BytesMut, io::Error>;
    impl PacketHeader {
        pub fn admin_decode(buf: &mut BytesMut) -> Result<Option<PacketItem>, io::Error> {
            let newline = buf[..].iter().position(|b| *b == b'\n');
            if let Some(n) = newline {
                let line = buf.split_to(n);
                buf.split_to(1); // drop the newline itself
                let data_str = match str::from_utf8(&line[..]) {
                    Ok(s) => s,
                    Err(_) => return Err(io::Error::new(io::ErrorKind::Other, "invalid string")),
                };
                info!("admin command data: {:?}", data_str);
                let command = match data_str.trim() {
                    "version" => ADMIN_VERSION,
                    "status" => ADMIN_STATUS,
                    _ => ADMIN_UNKNOWN,
                };
                return Ok(Some(Frame::Message {
                    message: PacketHeader {
                        magic: PacketMagic::TEXT,
                        ptype: command,
                        psize: 0,
                    },
                    body: false,
                }));
            }
            Ok(None) // Wait for more data
        }
    
        pub fn decode(buf: &mut BytesMut) -> Result<Option<PacketItem>, io::Error> {
            debug!("Decoding {:?}", buf);
            // Peek at first 4
            // Is this a req/res
            if buf.len() < 4 {
                return Ok(None);
            }
            let mut magic_buf: [u8; 4] = [0; 4];
            magic_buf.clone_from_slice(&buf[0..4]);
            let magic = match magic_buf {
                REQ => PacketMagic::REQ,
                RES => PacketMagic::RES,
                // TEXT/ADMIN protocol
                _ => PacketMagic::TEXT,
            };
            debug!("Magic is {:?}", magic);
            if magic == PacketMagic::TEXT {
                debug!("admin protocol detected");
                return PacketHeader::admin_decode(buf);
            }
            if buf.len() < 12 {
                return Ok(None);
            }
            buf.split_to(4);
            // Now get the type
            let ptype = buf.split_to(4).into_buf().get_u32::<BigEndian>();
            debug!("We got a {}", &PTYPES[ptype as usize].name);
            // Now the length
            let psize = buf.split_to(4).into_buf().get_u32::<BigEndian>();
            debug!("Data section is {} bytes", psize);
            Ok(Some(Frame::Message {
                message: PacketHeader {
                    magic: magic,
                    ptype: ptype,
                    psize: psize,
                },
                body: true, // TODO: false for 0 psize?
            }))
        }
    }
    
    impl Decoder for PacketCodec {
        type Item = Frame<PacketHeader, BytesMut, io::Error>;
        type Error = io::Error;
    
        fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
            match self.data_todo {
                None => {
                    match PacketHeader::decode(buf)? {
                        Some(Frame::Message { message, body }) => {
                            self.data_todo = Some(message.psize as usize);
                            Ok(Some(Frame::Message {
                                message: message,
                                body: body,
                            }))
                        }
                        Some(_) => panic!("Expecting Frame::Message, got something else"),
                        None => Ok(None),
                    }
                }
                Some(0) => {
                    self.data_todo = None;
                    Ok(Some(Frame::Body { chunk: None }))
                }
                Some(data_todo) => {
                    let chunk_size = min(buf.len(), data_todo);
                    self.data_todo = Some(data_todo - chunk_size);
                    Ok(Some(Frame::Body { chunk: Some(buf.split_to(chunk_size)) }))
                }
            }
        }
    }