Import async-stream-impl v0.3.0 am: 4d90486f87 am: c3955df4a0 am: 20101450eb am: fde7dd2afd

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/async-stream-impl/+/1594011

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ife97b5b3530d3a64e7dc7888cc9881a47d4b5b2e
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 <[email protected]>"]
+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 <[email protected]>"]
+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()
+}