- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的目标是实现一个 Codec
,它将提供的 EasyBuf
排到消息边界并将其解码为仅引用内容的结构,以防止不必要的复制。查看 EasyBuf
的实现,目前似乎不可能,但也许我遗漏了一些东西。
这是我正在玩的代码,这样做实际上需要 tokio-cassandra :
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<()>;
}
Codec::In
中缺少生命周期,我认为目前无法完成此操作 - 我们必须将其声明为 'static
,这就是问题所在借用检查员。EasyBuf
本身(Codec::In = EasyBuf
)来实现,并在后面的步骤中进行解码,例如在类似链接的 future 如 this example (usize, *const u8)
,后来在用户请求时变成一个 &str
。最佳答案
tokio-core 的最新版本不包含 codec
模块,它已被移动到 tokio-io .移动时,它也从 bytes crate 中的 EasyBuf
切换到 BytesMut
.通过该更改,您的缓冲区将以 BytesMut
的形式出现,它是为 0-copy 缓冲区消耗而构建的。您可以使用 split_to()
使用缓冲区,这将返回您拆分位置之前的数据的 BytesMut
,并将缓冲区的开头推进到该指针。这是我一直在使用的服务器的 tokio 端口的示例,rustygear :
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)) }))
}
}
}
}
关于rust - 如何在 tokio_core::io::Codec::decode(...) 中实现零拷贝?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42164981/
编辑备注 由于 Rust(版本:1.42)仍然没有稳定的 ABI ,推荐使用extern (目前相当于extern "C"(将来可能会改变))否则,可能需要重新编译库。 This article解释如
词法分析器/解析器文件位于 here非常大,我不确定它是否适合只检索 Rust 函数列表。也许我自己编写/使用另一个库是更好的选择? 最终目标是创建一种执行管理器。为了上下文化,它将能够读取包装在函数
我试图在 Rust 中展平 Enum 的向量,但我遇到了一些问题: enum Foo { A(i32), B(i32, i32), } fn main() { let vf =
我正在 64 位模式下运行的 Raspberry Pi 3 上使用 Rust 进行裸机编程。我已经实现了一个自旋锁,如下所示: use core::{sync::atomic::{AtomicBool
我无法理解以下示例是如何从 this code 中提炼出来的, 编译: trait A: B {} trait B {} impl B for T where T: A {} struct Foo;
在我写了一些代码和阅读了一些文章之后,我对 Rust 中的移动语义有点困惑,我认为值移动后,它应该被释放,内存应该是无效的。所以我尝试写一些代码来作证。 第一个例子 #[derive(Debug)]
https://doc.rust-lang.org/reference/types/closure.html#capture-modes struct SetVec { set: HashSe
考虑 const-generic 数据结构的经典示例:方矩阵。 struct Matrix { inner: [[T; N]; N] } 我想返回一个结构体,其 const 参数是动态定义的:
以下代码无法编译,因为 x在移动之后使用(因为 x 具有类型 &mut u8 ,它没有实现 Copy 特性) fn main() { let mut a: u8 = 1; let x:
我在玩 Rust,发现了下面的例子: fn main() { let mut x = [3, 4, 5].to_vec(); x; println!("{:?}", x); }
假设一个 Rust 2018 宏定义了一个 async里面的功能。它将使用的语法与 Rust 2015 不兼容。因此,如果您使用 2015 版编译您的 crate,那么宏中的扩展代码不会与它冲突吗?
假设我有一些 Foo 的自定义集合s: struct Bar {} struct Foo { bar: Bar } struct SubList { contents: Vec, }
代码如下: fn inner(x:&'a i32, _y:&'b i32) -> &'b i32 { x } fn main() { let a = 1; { let b
在lifetime_things的定义中,'b的生命周期比'a长,但实际上当我调用这个函数时,x1比y1长,但是这样可以编译成功: //here you could see 'b:'a means
我正在尝试检索 FLTK-RS Widget 周围的 Arc Mutex 包装器的内部值: pub struct ArcWidget(Arc>); impl ArcWidget{ pub
如下代码所示,我想封装一个定时函数,返回一个闭包的结果和执行时间。 use tap::prelude::Pipe; use std::time::{Instant, Duration}; pub fn
我想实现自己的通用容器,这是我正在使用的特征的片段: pub trait MyVec where Self: Default + Clone + IntoIterator, Self:
所需代码: 注释掉的块可以编译并工作,但是我想从嵌套的匹配样式转变为更简洁的函数链 async fn ws_req_resp(msg: String, conn: PgConn) -> Result>
我正在尝试编写一些代码,该代码将生成具有随机值的随机结构。对于结构,我具有以下特征和帮助程序宏: use rand::{thread_rng, Rng}; use std::fmt; pub trai
我有一个带有函数成员的结构: struct Foo { fun: Box, } type FooI = Foo; 这不起作用: error[E0106]: missing lifetime s
我是一名优秀的程序员,十分优秀!