Unverified Commit 4c8e8266 authored by Josh Robson Chase's avatar Josh Robson Chase
Browse files

Merge branch 'master' into framed-embrio

parents 65290f25 81e0586d
[package]
name = "async-codec"
version = "0.4.0-alpha.2"
version = "0.4.0-alpha.4"
authors = ["Josh Robson Chase <josh@robsonchase.com>"]
edition = "2018"
license = "MIT/Apache-2.0"
......@@ -11,14 +11,14 @@ repository = "https://gitlab.com/jrobsonchase/async-codec"
readme = "README.md"
[dependencies]
futures-preview = { version = "0.3.0-alpha.17", default-features = false }
bytes = { version = "0.4.12", optional = true }
bytes = { version = "0.5.4", optional = true }
futures = { version = "0.3.4", default_features = false }
embrio-core = { git = "https://github.com/Nemo157/embrio-rs", optional = true }
[dev-dependencies]
runtime = "0.3.0-alpha.6"
async-std = { version = "1.5.0", features = ["attributes"] }
[features]
std = ["futures-preview/std", "bytes"]
std = ["futures/std", "bytes"]
embrio = ["embrio-core"]
default = ["std"]
max_width = 100
hard_tabs = false
tab_spaces = 4
newline_style = "Auto"
use_small_heuristics = "Default"
indent_style = "Block"
wrap_comments = false
format_code_in_doc_comments = true
comment_width = 80
normalize_comments = false
normalize_doc_attributes = false
license_template_path = ""
format_strings = false
format_macro_matchers = false
format_macro_bodies = true
empty_item_single_line = true
struct_lit_single_line = true
fn_single_line = false
where_single_line = false
imports_indent = "Block"
imports_layout = "Vertical"
merge_imports = true
reorder_imports = true
reorder_modules = true
reorder_impl_items = false
type_punctuation_density = "Wide"
space_before_colon = false
space_after_colon = true
spaces_around_ranges = false
binop_separator = "Front"
remove_nested_parens = true
combine_control_expr = true
overflow_delimited_expr = false
struct_field_align_threshold = 0
enum_discrim_align_threshold = 0
match_arm_blocks = true
force_multiline_blocks = false
fn_args_layout = "Tall"
brace_style = "SameLineWhere"
control_brace_style = "AlwaysSameLine"
trailing_semicolon = true
trailing_comma = "Vertical"
match_block_trailing_comma = false
blank_lines_upper_bound = 1
blank_lines_lower_bound = 0
edition = "2015"
version = "One"
inline_attribute_width = 0
merge_derives = true
use_try_shorthand = false
use_field_init_shorthand = false
force_explicit_abi = true
condense_wildcard_suffixes = false
color = "Auto"
required_version = "1.4.11"
unstable_features = false
disable_all_formatting = false
skip_children = false
hide_parse_errors = false
error_on_line_overflow = false
error_on_unformatted = false
report_todo = "Never"
report_fixme = "Never"
ignore = []
emit_mode = "Files"
make_backup = false
......@@ -289,7 +289,7 @@ That all your acts are queens.
r
}
#[runtime::test]
#[async_std::test]
async fn test_embrio_stream() {
let reader = assert_reader(SHAKESPEARE.as_bytes());
let mut framed = Framed::new(reader, LineCodec, vec![0u8; 1024]);
......@@ -300,7 +300,7 @@ That all your acts are queens.
}
assert_eq!(actual, expected);
}
#[runtime::test]
#[async_std::test]
async fn test_embrio_sink() {
let frames = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
let mut actual = vec![0u8; SHAKESPEARE.as_bytes().len()];
......
//! The `Framed` type for `futures::io::{AsyncRead, AsyncWrite}` streams
use std::error::Error;
use std::fmt::{self, Display};
use std::io;
use std::pin::Pin;
use bytes::{BufMut, BytesMut};
use futures::io::{AsyncRead, AsyncWrite};
use futures::prelude::*;
use futures::ready;
use futures::task::{Context, Poll};
use std::{
error::Error,
fmt::{
self,
Display,
},
io,
mem::MaybeUninit,
pin::Pin,
};
use bytes::{
Buf,
BufMut,
BytesMut,
};
use futures::{
io::{
AsyncRead,
AsyncWrite,
},
prelude::*,
ready,
task::{
Context,
Poll,
},
};
use super::*;
......@@ -23,7 +41,7 @@ pub struct Framed<S, C> {
write_buf: BytesMut,
}
impl<S: AsyncRead + AsyncWrite, C: Encode + Decode> Framed<S, C> {
impl<S, C: Encode + Decode> Framed<S, C> {
/// Create a new framed stream from a byte stream and a codec.
pub fn new(stream: S, codec: C) -> Self {
Framed {
......@@ -210,10 +228,7 @@ where
};
codec.reset();
loop {
// Safety: We zero the buffer without reading it to ensure that it's
// initialized. This is to protect the encoder from reading the
// buffer and triggering UB.
let b = unsafe { zero_buf(buffer.bytes_mut()) };
let b = zero_buf(buffer.bytes_mut());
match codec.encode(&item, b) {
EncodeResult::Ok(len) => {
// Safety: We made sure to zero the buffer above, so this is
......@@ -245,18 +260,21 @@ where
}
}
fn zero_buf(b: &mut [u8]) -> &mut [u8] {
fn zero_buf(b: &mut [MaybeUninit<u8>]) -> &mut [u8] {
for i in b.iter_mut() {
*i = 0x00
*i = MaybeUninit::new(0);
}
b
unsafe { std::mem::transmute(b) }
}
#[cfg(test)]
mod test {
use std::str::Utf8Error;
use futures::prelude::*;
use futures::{
io::Cursor,
prelude::*,
};
use super::*;
......@@ -316,9 +334,9 @@ Crowns what you are doing in the present deed,
That all your acts are queens.
"#;
#[runtime::test]
#[async_std::test]
async fn test_framed_stream() {
let reader = io::Cursor::new(Vec::from(SHAKESPEARE.as_bytes()));
let reader = Cursor::new(Vec::from(SHAKESPEARE.as_bytes()));
let mut framed = Framed::new(reader, LineCodec);
let expected = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
let mut actual = vec![];
......@@ -328,12 +346,12 @@ That all your acts are queens.
assert_eq!(actual, expected);
}
#[runtime::test]
#[async_std::test]
async fn test_framed_sink() {
let frames = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
let mut actual = vec![0u8; SHAKESPEARE.as_bytes().len()];
{
let writer = io::Cursor::new(&mut actual);
let writer = Cursor::new(&mut actual);
let mut framed = Framed::new(writer, LineCodec);
for frame in frames {
framed.send(frame).await.unwrap();
......
......@@ -60,10 +60,15 @@
//! ```rust
//! #![feature(async_await)]
//!
//! use std::io;
//! use std::str::Utf8Error;
//! use std::{
//! io,
//! str::Utf8Error,
//! };
//!
//! use futures::prelude::*;
//! use futures::{
//! io::Cursor,
//! prelude::*,
//! };
//!
//! use async_codec::*;
//!
......@@ -87,7 +92,7 @@
//! type Item = String;
//! type Error = Utf8Error;
//!
//! fn decode(&mut self, buf: &[u8]) -> (usize, DecodeResult<String, Utf8Error>) {
//! fn decode(&mut self, buf: &mut [u8]) -> (usize, DecodeResult<String, Utf8Error>) {
//! let newline = match buf.iter().position(|b| *b == b'\n') {
//! Some(idx) => idx,
//! None => return (0, DecodeResult::UnexpectedEnd),
......@@ -123,47 +128,41 @@
//! That all your acts are queens.
//! "#;
//!
//! let reader = io::Cursor::new(Vec::from(SHAKESPEARE.as_bytes()));
//! let mut framed = Framed::new(reader, LineCodec);
//! let expected = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
//! let mut actual = vec![];
//! futures::executor::block_on(async {
//! #[async_std::main]
//! async fn main() {
//! let reader = Cursor::new(Vec::from(SHAKESPEARE.as_bytes()));
//! let mut framed = Framed::new(reader, LineCodec);
//! let expected = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
//! let mut actual = vec![];
//! while let Some(frame) = framed.next().await.transpose().unwrap() {
//! actual.push(frame);
//! }
//! });
//! assert_eq!(actual, expected);
//! assert_eq!(actual, expected);
//!
//! let mut actual = vec![0u8; SHAKESPEARE.as_bytes().len()];
//! let expected = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
//! futures::executor::block_on(async {
//! let writer = io::Cursor::new(&mut actual);
//! let mut actual = vec![0u8; SHAKESPEARE.as_bytes().len()];
//! let expected = SHAKESPEARE.lines().map(String::from).collect::<Vec<_>>();
//! let writer = Cursor::new(&mut actual);
//! let mut framed = Framed::new(writer, LineCodec);
//! for frame in expected {
//! framed.send(frame).await.unwrap();
//! }
//! });
//! assert_eq!(std::str::from_utf8(&actual).unwrap(), SHAKESPEARE);
//! assert_eq!(std::str::from_utf8(&actual).unwrap(), SHAKESPEARE);
//! }
//! ```
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
#![cfg_attr(test, feature(async_await))]
#![warn(missing_docs)]
#[cfg(all(feature = "embrio", feature = "std"))]
pub mod framed_embrio;
#[cfg(all(feature = "embrio", not(feature = "std")))]
mod framed_embrio;
#[cfg(all(feature = "embrio", not(feature = "std")))]
pub use crate::framed_embrio::*;
#[cfg(all(feature = "embrio", feature = "std"))]
#[cfg(feature = "std")]
pub mod framed_std;
#[cfg(all(feature = "std", not(feature = "embrio")))]
mod framed_std;
#[cfg(all(feature = "std", not(feature = "embrio")))]
pub use crate::framed_std::*;
#[cfg(feature = "embrio")]
pub mod framed_embrio;
#[cfg(all(feature = "embrio", not(feature = "std")))]
pub use crate::framed_embrio::*;
/// The result of an `Encode::encode` call
pub enum EncodeResult<E> {
/// Item was successfully encoded and took `usize` bytes of the provided
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment