chore: Fix feature flags and build docs (#311)
Signed-off-by: Lucio Franco <[email protected]>
This commit is contained in:
+5
-5
@@ -23,7 +23,7 @@ categories = ["web-programming", "network-programming", "asynchronous"]
|
||||
keywords = ["rpc", "grpc", "async", "futures", "protobuf"]
|
||||
|
||||
[features]
|
||||
default = ["transport", "codegen", "data-prost"]
|
||||
default = ["transport", "codegen", "prost"]
|
||||
codegen = ["async-trait"]
|
||||
transport = [
|
||||
"hyper",
|
||||
@@ -35,7 +35,7 @@ transport = [
|
||||
]
|
||||
tls = ["transport", "tokio-rustls"]
|
||||
tls-roots = ["tls", "rustls-native-certs"]
|
||||
data-prost = ["prost", "prost-derive"]
|
||||
prost = ["prost1", "prost-derive"]
|
||||
|
||||
# [[bench]]
|
||||
# name = "bench_main"
|
||||
@@ -57,15 +57,15 @@ http-body = "0.3"
|
||||
pin-project = "0.4"
|
||||
|
||||
# prost
|
||||
prost = { version = "0.6", optional = true }
|
||||
prost1 = { package = "prost", version = "0.6", optional = true }
|
||||
prost-derive = { version = "0.6", optional = true }
|
||||
|
||||
# codegen
|
||||
async-trait = { version = "0.1.13", optional = true }
|
||||
|
||||
# transport
|
||||
hyper = { version = "0.13", features = ["stream"], optional = true }
|
||||
tokio = { version = "0.2", features = ["tcp"], optional = true }
|
||||
hyper = { version = "0.13.4", features = ["stream"], optional = true }
|
||||
tokio = { version = "0.2.13", features = ["tcp"], optional = true }
|
||||
tower = { version = "0.3", optional = true}
|
||||
tower-make = { version = "0.3", features = ["connect"] }
|
||||
tower-balance = { version = "0.3", optional = true }
|
||||
|
||||
@@ -6,18 +6,15 @@
|
||||
mod buffer;
|
||||
mod decode;
|
||||
mod encode;
|
||||
#[cfg(feature = "data-prost")]
|
||||
#[cfg(feature = "prost")]
|
||||
mod prost;
|
||||
|
||||
#[cfg(all(test, feature = "data-prost"))]
|
||||
mod prost_tests;
|
||||
|
||||
use std::io;
|
||||
|
||||
pub use self::decode::Streaming;
|
||||
pub(crate) use self::encode::{encode_client, encode_server};
|
||||
#[cfg(feature = "data-prost")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "data-prost")))]
|
||||
#[cfg(feature = "prost")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "prost")))]
|
||||
pub use self::prost::ProstCodec;
|
||||
use crate::Status;
|
||||
pub use buffer::{DecodeBuf, EncodeBuf};
|
||||
|
||||
+156
-2
@@ -1,7 +1,7 @@
|
||||
use super::{Codec, DecodeBuf, Decoder, Encoder};
|
||||
use crate::codec::EncodeBuf;
|
||||
use crate::{Code, Status};
|
||||
use prost::Message;
|
||||
use prost1::Message;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// A [`Codec`] that implements `application/grpc+proto` via the prost library..
|
||||
@@ -69,8 +69,162 @@ impl<U: Message + Default> Decoder for ProstDecoder<U> {
|
||||
}
|
||||
}
|
||||
|
||||
fn from_decode_error(error: prost::DecodeError) -> crate::Status {
|
||||
fn from_decode_error(error: prost1::DecodeError) -> crate::Status {
|
||||
// Map Protobuf parse errors to an INTERNAL status code, as per
|
||||
// https://github.com/grpc/grpc/blob/master/doc/statuscodes.md
|
||||
Status::new(Code::Internal, error.to_string())
|
||||
}
|
||||
|
||||
#[cfg(tests)]
|
||||
mod tests {
|
||||
use super::{encode_server, Decoder, Encoder, Streaming};
|
||||
use crate::codec::buffer::DecodeBuf;
|
||||
use crate::codec::EncodeBuf;
|
||||
use crate::Status;
|
||||
use bytes::{Buf, BufMut, BytesMut};
|
||||
use http_body::Body;
|
||||
|
||||
const LEN: usize = 10000;
|
||||
|
||||
#[tokio::test]
|
||||
async fn decode() {
|
||||
let decoder = MockDecoder::default();
|
||||
|
||||
let msg = vec![0u8; LEN];
|
||||
|
||||
let mut buf = BytesMut::new();
|
||||
|
||||
buf.reserve(msg.len() + 5);
|
||||
buf.put_u8(0);
|
||||
buf.put_u32(msg.len() as u32);
|
||||
|
||||
buf.put(&msg[..]);
|
||||
|
||||
let body = body::MockBody::new(&buf[..], 10005, 0);
|
||||
|
||||
let mut stream = Streaming::new_request(decoder, body);
|
||||
|
||||
let mut i = 0usize;
|
||||
while let Some(output_msg) = stream.message().await.unwrap() {
|
||||
assert_eq!(output_msg.len(), msg.len());
|
||||
i += 1;
|
||||
}
|
||||
assert_eq!(i, 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn encode() {
|
||||
let encoder = MockEncoder::default();
|
||||
|
||||
let msg = Vec::from(&[0u8; 1024][..]);
|
||||
|
||||
let messages = std::iter::repeat(Ok::<_, Status>(msg)).take(10000);
|
||||
let source = futures_util::stream::iter(messages);
|
||||
|
||||
let body = encode_server(encoder, source);
|
||||
|
||||
futures_util::pin_mut!(body);
|
||||
|
||||
while let Some(r) = body.data().await {
|
||||
r.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct MockEncoder;
|
||||
|
||||
impl Encoder for MockEncoder {
|
||||
type Item = Vec<u8>;
|
||||
type Error = Status;
|
||||
|
||||
fn encode(&mut self, item: Self::Item, buf: &mut EncodeBuf<'_>) -> Result<(), Self::Error> {
|
||||
buf.put(&item[..]);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct MockDecoder;
|
||||
|
||||
impl Decoder for MockDecoder {
|
||||
type Item = Vec<u8>;
|
||||
type Error = Status;
|
||||
|
||||
fn decode(&mut self, buf: &mut DecodeBuf<'_>) -> Result<Option<Self::Item>, Self::Error> {
|
||||
let out = Vec::from(buf.bytes());
|
||||
buf.advance(LEN);
|
||||
Ok(Some(out))
|
||||
}
|
||||
}
|
||||
|
||||
mod body {
|
||||
use crate::Status;
|
||||
use bytes::Bytes;
|
||||
use http_body::Body;
|
||||
use std::{
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct MockBody {
|
||||
data: Bytes,
|
||||
|
||||
// the size of the partial message to send
|
||||
partial_len: usize,
|
||||
|
||||
// the number of times we've sent
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl MockBody {
|
||||
pub(super) fn new(b: &[u8], partial_len: usize, count: usize) -> Self {
|
||||
MockBody {
|
||||
data: Bytes::copy_from_slice(&b[..]),
|
||||
partial_len,
|
||||
count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Body for MockBody {
|
||||
type Data = Bytes;
|
||||
type Error = Status;
|
||||
|
||||
fn poll_data(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||
// every other call to poll_data returns data
|
||||
let should_send = self.count % 2 == 0;
|
||||
let data_len = self.data.len();
|
||||
let partial_len = self.partial_len;
|
||||
let count = self.count;
|
||||
if data_len > 0 {
|
||||
let result = if should_send {
|
||||
let response =
|
||||
self.data
|
||||
.split_to(if count == 0 { partial_len } else { data_len });
|
||||
Poll::Ready(Some(Ok(response)))
|
||||
} else {
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
};
|
||||
// make some fake progress
|
||||
self.count += 1;
|
||||
result
|
||||
} else {
|
||||
Poll::Ready(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_trailers(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
|
||||
drop(cx);
|
||||
Poll::Ready(Ok(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
use super::{encode_server, Decoder, Encoder, Streaming};
|
||||
use crate::codec::buffer::DecodeBuf;
|
||||
use crate::codec::EncodeBuf;
|
||||
use crate::Status;
|
||||
use bytes::{Buf, BufMut, BytesMut};
|
||||
use http_body::Body;
|
||||
|
||||
const LEN: usize = 10000;
|
||||
|
||||
#[tokio::test]
|
||||
async fn decode() {
|
||||
let decoder = MockDecoder::default();
|
||||
|
||||
let msg = vec![0u8; LEN];
|
||||
|
||||
let mut buf = BytesMut::new();
|
||||
|
||||
buf.reserve(msg.len() + 5);
|
||||
buf.put_u8(0);
|
||||
buf.put_u32(msg.len() as u32);
|
||||
|
||||
buf.put(&msg[..]);
|
||||
|
||||
let body = body::MockBody::new(&buf[..], 10005, 0);
|
||||
|
||||
let mut stream = Streaming::new_request(decoder, body);
|
||||
|
||||
let mut i = 0usize;
|
||||
while let Some(output_msg) = stream.message().await.unwrap() {
|
||||
assert_eq!(output_msg.len(), msg.len());
|
||||
i += 1;
|
||||
}
|
||||
assert_eq!(i, 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn encode() {
|
||||
let encoder = MockEncoder::default();
|
||||
|
||||
let msg = Vec::from(&[0u8; 1024][..]);
|
||||
|
||||
let messages = std::iter::repeat(Ok::<_, Status>(msg)).take(10000);
|
||||
let source = futures_util::stream::iter(messages);
|
||||
|
||||
let body = encode_server(encoder, source);
|
||||
|
||||
futures_util::pin_mut!(body);
|
||||
|
||||
while let Some(r) = body.data().await {
|
||||
r.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct MockEncoder;
|
||||
|
||||
impl Encoder for MockEncoder {
|
||||
type Item = Vec<u8>;
|
||||
type Error = Status;
|
||||
|
||||
fn encode(&mut self, item: Self::Item, buf: &mut EncodeBuf<'_>) -> Result<(), Self::Error> {
|
||||
buf.put(&item[..]);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct MockDecoder;
|
||||
|
||||
impl Decoder for MockDecoder {
|
||||
type Item = Vec<u8>;
|
||||
type Error = Status;
|
||||
|
||||
fn decode(&mut self, buf: &mut DecodeBuf<'_>) -> Result<Option<Self::Item>, Self::Error> {
|
||||
let out = Vec::from(buf.bytes());
|
||||
buf.advance(LEN);
|
||||
Ok(Some(out))
|
||||
}
|
||||
}
|
||||
|
||||
mod body {
|
||||
use crate::Status;
|
||||
use bytes::Bytes;
|
||||
use http_body::Body;
|
||||
use std::{
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct MockBody {
|
||||
data: Bytes,
|
||||
|
||||
// the size of the partial message to send
|
||||
partial_len: usize,
|
||||
|
||||
// the number of times we've sent
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl MockBody {
|
||||
pub(super) fn new(b: &[u8], partial_len: usize, count: usize) -> Self {
|
||||
MockBody {
|
||||
data: Bytes::copy_from_slice(&b[..]),
|
||||
partial_len,
|
||||
count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Body for MockBody {
|
||||
type Data = Bytes;
|
||||
type Error = Status;
|
||||
|
||||
fn poll_data(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
|
||||
// every other call to poll_data returns data
|
||||
let should_send = self.count % 2 == 0;
|
||||
let data_len = self.data.len();
|
||||
let partial_len = self.partial_len;
|
||||
let count = self.count;
|
||||
if data_len > 0 {
|
||||
let result = if should_send {
|
||||
let response =
|
||||
self.data
|
||||
.split_to(if count == 0 { partial_len } else { data_len });
|
||||
Poll::Ready(Some(Ok(response)))
|
||||
} else {
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
};
|
||||
// make some fake progress
|
||||
self.count += 1;
|
||||
result
|
||||
} else {
|
||||
Poll::Ready(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_trailers(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
|
||||
drop(cx);
|
||||
Poll::Ready(Ok(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user