summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Vander Stoep <jeffv@google.com>2021-02-18 12:05:23 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-02-18 12:05:23 +0000
commitfde7dd2afdb998cac79e73c4bf429e31b47f306c (patch)
tree52b990e50d273f5e4e561e5a98403aaa8bd14688
parente140a6a6538d47f87b3b3538c56f4ca6dba2536b (diff)
parent20101450eb364c3bd72837b62537ce06b7e67c87 (diff)
downloadasync-stream-impl-fde7dd2afdb998cac79e73c4bf429e31b47f306c.tar.gz
Import async-stream-impl v0.3.0 am: 4d90486f87 am: c3955df4a0 am: 20101450eb
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/async-stream-impl/+/1594011 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I3a86e0d5874fd042c6f48732eb8b219b1bd476dc
-rw-r--r--Android.bp19
-rw-r--r--Cargo.toml43
-rw-r--r--Cargo.toml.orig24
-rw-r--r--LICENSE51
-rw-r--r--METADATA19
-rw-r--r--MODULE_LICENSE_MIT0
-rw-r--r--OWNERS1
-rw-r--r--TEST_MAPPING17
-rw-r--r--patches/lib.diff9
-rw-r--r--src/lib.rs271
10 files changed, 454 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..82b7860
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,19 @@
+// This file is generated by cargo2android.py --run --dependencies --device.
+
+rust_proc_macro {
+ name: "libasync_stream_impl",
+ crate_name: "async_stream_impl",
+ srcs: ["src/lib.rs"],
+ edition: "2018",
+ rustlibs: [
+ "libproc_macro2",
+ "libquote",
+ "libsyn",
+ ],
+}
+
+// dependent_library ["feature_list"]
+// proc-macro2-1.0.24 "default,proc-macro"
+// quote-1.0.8 "default,proc-macro"
+// syn-1.0.60 "clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,quote,visit-mut"
+// unicode-xid-0.2.1 "default"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..df59eae
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,43 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "async-stream-impl"
+version = "0.3.0"
+authors = ["Carl Lerche <me@carllerche.com>"]
+description = "proc macros for async-stream crate"
+homepage = "https://github.com/tokio-rs/async-stream"
+documentation = "https://docs.rs/async-stream-impl/0.3.0/async-stream-impl"
+license = "MIT"
+repository = "https://github.com/tokio-rs/async-stream"
+
+[lib]
+proc-macro = true
+[dependencies.proc-macro2]
+version = "1"
+
+[dependencies.quote]
+version = "1"
+
+[dependencies.syn]
+version = "1"
+features = ["extra-traits", "full", "visit-mut"]
+[dev-dependencies.futures-core]
+version = "0.3"
+
+[dev-dependencies.futures-util]
+version = "0.3"
+
+[dev-dependencies.tokio]
+version = "0.2"
+features = ["full"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..dd6d9d9
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,24 @@
+[package]
+name = "async-stream-impl"
+version = "0.3.0"
+edition = "2018"
+license = "MIT"
+authors = ["Carl Lerche <me@carllerche.com>"]
+description = "proc macros for async-stream crate"
+documentation = "https://docs.rs/async-stream-impl/0.3.0/async-stream-impl"
+homepage = "https://github.com/tokio-rs/async-stream"
+repository = "https://github.com/tokio-rs/async-stream"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1"
+syn = { version = "1", features = ["extra-traits", "full", "visit-mut"]}
+quote = "1"
+
+[dev-dependencies]
+# async-stream = { version = "0.3.0", path = "../async-stream" }
+futures-core = "0.3"
+futures-util = "0.3"
+tokio = { version = "0.2", features = ["full"] }
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8cbd7d6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,51 @@
+Copyright (c) 2019 Carl Lerche
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+Copyright (c) 2018 David Tolnay
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..8e2e26d
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "async-stream-impl"
+description: "proc macros for async-stream crate"
+third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://crates.io/crates/async-stream-impl"
+ }
+ url {
+ type: ARCHIVE
+ value: "https://static.crates.io/crates/async-stream-impl/async-stream-impl-0.3.0.crate"
+ }
+ version: "0.3.0"
+ license_type: NOTICE
+ last_upgrade_date {
+ year: 2021
+ month: 2
+ day: 8
+ }
+}
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_MIT
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..46fc303
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1 @@
+include platform/prebuilts/rust:/OWNERS
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..8fccfe0
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,17 @@
+// Generated by update_crate_tests.py for tests that depend on this crate.
+{
+ "presubmit": [
+ {
+ "name": "tokio-test_device_test_tests_block_on"
+ },
+ {
+ "name": "tokio-test_device_test_tests_io"
+ },
+ {
+ "name": "tokio-test_device_test_src_lib"
+ },
+ {
+ "name": "tokio-test_device_test_tests_macros"
+ }
+ ]
+}
diff --git a/patches/lib.diff b/patches/lib.diff
new file mode 100644
index 0000000..9f60ea6
--- /dev/null
+++ b/patches/lib.diff
@@ -0,0 +1,9 @@
+diff --git a/src/lib.rs b/src/lib.rs
+index 3d4d185..9081ecf 100644
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -1,3 +1,4 @@
++extern crate proc_macro;
+ use proc_macro::TokenStream;
+ use proc_macro2::{Delimiter, Group, TokenStream as TokenStream2, TokenTree};
+ use quote::quote;
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..9081ecf
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,271 @@
+extern crate proc_macro;
+use proc_macro::TokenStream;
+use proc_macro2::{Delimiter, Group, TokenStream as TokenStream2, TokenTree};
+use quote::quote;
+use syn::visit_mut::VisitMut;
+
+struct Scrub {
+ is_xforming: bool,
+ is_try: bool,
+ unit: Box<syn::Expr>,
+ num_yield: u32,
+}
+
+fn parse_input(input: TokenStream) -> syn::Result<Vec<syn::Stmt>> {
+ let input = replace_for_await(input.into());
+ // syn does not provide a way to parse `Vec<Stmt>` directly from `TokenStream`,
+ // so wrap input in a brace and then parse it as a block.
+ let input = TokenStream2::from(TokenTree::Group(Group::new(Delimiter::Brace, input)));
+ let syn::Block { stmts, .. } = syn::parse2(input)?;
+
+ Ok(stmts)
+}
+
+impl VisitMut for Scrub {
+ fn visit_expr_mut(&mut self, i: &mut syn::Expr) {
+ if !self.is_xforming {
+ syn::visit_mut::visit_expr_mut(self, i);
+ return;
+ }
+
+ match i {
+ syn::Expr::Yield(yield_expr) => {
+ self.num_yield += 1;
+
+ let value_expr = if let Some(ref e) = yield_expr.expr {
+ e
+ } else {
+ &self.unit
+ };
+
+ // let ident = &self.yielder;
+
+ *i = if self.is_try {
+ syn::parse_quote! { __yield_tx.send(Ok(#value_expr)).await }
+ } else {
+ syn::parse_quote! { __yield_tx.send(#value_expr).await }
+ };
+ }
+ syn::Expr::Try(try_expr) => {
+ syn::visit_mut::visit_expr_try_mut(self, try_expr);
+ // let ident = &self.yielder;
+ let e = &try_expr.expr;
+
+ *i = syn::parse_quote! {
+ match #e {
+ Ok(v) => v,
+ Err(e) => {
+ __yield_tx.send(Err(e.into())).await;
+ return;
+ }
+ }
+ };
+ }
+ syn::Expr::Closure(_) | syn::Expr::Async(_) => {
+ let prev = self.is_xforming;
+ self.is_xforming = false;
+ syn::visit_mut::visit_expr_mut(self, i);
+ self.is_xforming = prev;
+ }
+ syn::Expr::ForLoop(expr) => {
+ syn::visit_mut::visit_expr_for_loop_mut(self, expr);
+ // TODO: Should we allow other attributes?
+ if expr.attrs.len() != 1 || !expr.attrs[0].path.is_ident("await") {
+ return;
+ }
+ let syn::ExprForLoop {
+ attrs,
+ label,
+ pat,
+ expr,
+ body,
+ ..
+ } = expr;
+
+ let attr = attrs.pop().unwrap();
+ if let Err(e) = syn::parse2::<syn::parse::Nothing>(attr.tokens) {
+ *i = syn::parse2(e.to_compile_error()).unwrap();
+ return;
+ }
+
+ *i = syn::parse_quote! {{
+ let mut __pinned = #expr;
+ let mut __pinned = unsafe {
+ ::core::pin::Pin::new_unchecked(&mut __pinned)
+ };
+ #label
+ loop {
+ let #pat = match ::async_stream::reexport::next(&mut __pinned).await {
+ ::core::option::Option::Some(e) => e,
+ ::core::option::Option::None => break,
+ };
+ #body
+ }
+ }}
+ }
+ _ => syn::visit_mut::visit_expr_mut(self, i),
+ }
+ }
+
+ fn visit_item_mut(&mut self, i: &mut syn::Item) {
+ let prev = self.is_xforming;
+ self.is_xforming = false;
+ syn::visit_mut::visit_item_mut(self, i);
+ self.is_xforming = prev;
+ }
+}
+
+/// Asynchronous stream
+///
+/// See [crate](index.html) documentation for more details.
+///
+/// # Examples
+///
+/// ```rust
+/// use async_stream::stream;
+///
+/// use futures_util::pin_mut;
+/// use futures_util::stream::StreamExt;
+///
+/// #[tokio::main]
+/// async fn main() {
+/// let s = stream! {
+/// for i in 0..3 {
+/// yield i;
+/// }
+/// };
+///
+/// pin_mut!(s); // needed for iteration
+///
+/// while let Some(value) = s.next().await {
+/// println!("got {}", value);
+/// }
+/// }
+/// ```
+#[proc_macro]
+pub fn stream(input: TokenStream) -> TokenStream {
+ let mut stmts = match parse_input(input) {
+ Ok(x) => x,
+ Err(e) => return e.to_compile_error().into(),
+ };
+
+ let mut scrub = Scrub {
+ is_xforming: true,
+ is_try: false,
+ unit: syn::parse_quote!(()),
+ num_yield: 0,
+ };
+
+ for mut stmt in &mut stmts[..] {
+ scrub.visit_stmt_mut(&mut stmt);
+ }
+
+ let dummy_yield = if scrub.num_yield == 0 {
+ Some(quote!(if false {
+ __yield_tx.send(()).await;
+ }))
+ } else {
+ None
+ };
+
+ quote!({
+ let (mut __yield_tx, __yield_rx) = ::async_stream::yielder::pair();
+ ::async_stream::AsyncStream::new(__yield_rx, async move {
+ #dummy_yield
+ #(#stmts)*
+ })
+ })
+ .into()
+}
+
+/// Asynchronous fallible stream
+///
+/// See [crate](index.html) documentation for more details.
+///
+/// # Examples
+///
+/// ```rust
+/// use tokio::net::{TcpListener, TcpStream};
+///
+/// use async_stream::try_stream;
+/// use futures_core::stream::Stream;
+///
+/// use std::io;
+/// use std::net::SocketAddr;
+///
+/// fn bind_and_accept(addr: SocketAddr)
+/// -> impl Stream<Item = io::Result<TcpStream>>
+/// {
+/// try_stream! {
+/// let mut listener = TcpListener::bind(addr).await?;
+///
+/// loop {
+/// let (stream, addr) = listener.accept().await?;
+/// println!("received on {:?}", addr);
+/// yield stream;
+/// }
+/// }
+/// }
+/// ```
+#[proc_macro]
+pub fn try_stream(input: TokenStream) -> TokenStream {
+ let mut stmts = match parse_input(input) {
+ Ok(x) => x,
+ Err(e) => return e.to_compile_error().into(),
+ };
+
+ let mut scrub = Scrub {
+ is_xforming: true,
+ is_try: true,
+ unit: syn::parse_quote!(()),
+ num_yield: 0,
+ };
+
+ for mut stmt in &mut stmts[..] {
+ scrub.visit_stmt_mut(&mut stmt);
+ }
+
+ let dummy_yield = if scrub.num_yield == 0 {
+ Some(quote!(if false {
+ __yield_tx.send(()).await;
+ }))
+ } else {
+ None
+ };
+
+ quote!({
+ let (mut __yield_tx, __yield_rx) = ::async_stream::yielder::pair();
+ ::async_stream::AsyncStream::new(__yield_rx, async move {
+ #dummy_yield
+ #(#stmts)*
+ })
+ })
+ .into()
+}
+
+fn replace_for_await(input: TokenStream2) -> TokenStream2 {
+ let mut input = input.into_iter().peekable();
+ let mut tokens = Vec::new();
+
+ while let Some(token) = input.next() {
+ match token {
+ TokenTree::Ident(ident) => {
+ match input.peek() {
+ Some(TokenTree::Ident(next)) if ident == "for" && next == "await" => {
+ tokens.extend(quote!(#[#next]));
+ let _ = input.next();
+ }
+ _ => {}
+ }
+ tokens.push(ident.into());
+ }
+ TokenTree::Group(group) => {
+ let stream = replace_for_await(group.stream());
+ tokens.push(Group::new(group.delimiter(), stream).into());
+ }
+ _ => tokens.push(token),
+ }
+ }
+
+ tokens.into_iter().collect()
+}