Squashed 'third_party/autocxx/' content from commit 629e8fa53

git-subtree-dir: third_party/autocxx
git-subtree-split: 629e8fa531a633164c0b52e2a3cab536d4cd0849
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I62a03b0049f49adf029e0204639cdb5468dde1a1
diff --git a/engine/src/conversion/codegen_rs/unqualify.rs b/engine/src/conversion/codegen_rs/unqualify.rs
new file mode 100644
index 0000000..6f245c2
--- /dev/null
+++ b/engine/src/conversion/codegen_rs/unqualify.rs
@@ -0,0 +1,94 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use syn::{
+    parse_quote, punctuated::Punctuated, FnArg, GenericArgument, PathArguments, PathSegment,
+    ReturnType, Token, Type, TypePath,
+};
+
+/// Mod to handle stripping paths off the front of types.
+
+fn unqualify_type_path(typ: TypePath) -> TypePath {
+    // If we've still got more than one
+    // path segment then this is referring to a type within
+    // C++ namespaces. Strip them off for now, until cxx supports
+    // nested mods within a cxx::bridge.
+    // This is 'safe' because earlier code will already have
+    // failed with 'DuplicateType' if we had several types called
+    // the same thing.
+    let last_seg = typ.path.segments.into_iter().last().unwrap();
+    let ident = &last_seg.ident;
+    let args = match last_seg.arguments {
+        PathArguments::AngleBracketed(mut ab) => {
+            ab.args = unqualify_punctuated(ab.args);
+            PathArguments::AngleBracketed(ab)
+        }
+        _ => last_seg.arguments.clone(),
+    };
+    let last_seg: PathSegment = parse_quote!( #ident #args );
+    parse_quote!(
+        #last_seg
+    )
+}
+
+fn unqualify_punctuated<P>(pun: Punctuated<GenericArgument, P>) -> Punctuated<GenericArgument, P>
+where
+    P: Default,
+{
+    let mut new_pun = Punctuated::new();
+    for arg in pun.into_iter() {
+        new_pun.push(match arg {
+            GenericArgument::Type(t) => GenericArgument::Type(unqualify_type(t)),
+            _ => arg,
+        });
+    }
+    new_pun
+}
+
+fn unqualify_type(typ: Type) -> Type {
+    match typ {
+        Type::Path(typ) => Type::Path(unqualify_type_path(typ)),
+        Type::Reference(mut typeref) => {
+            typeref.elem = unqualify_boxed_type(typeref.elem);
+            Type::Reference(typeref)
+        }
+        Type::Ptr(mut typeptr) => {
+            typeptr.elem = unqualify_boxed_type(typeptr.elem);
+            Type::Ptr(typeptr)
+        }
+        _ => typ,
+    }
+}
+
+fn unqualify_boxed_type(typ: Box<Type>) -> Box<Type> {
+    Box::new(unqualify_type(*typ))
+}
+
+pub(crate) fn unqualify_ret_type(ret_type: ReturnType) -> ReturnType {
+    match ret_type {
+        ReturnType::Type(tok, boxed_type) => {
+            ReturnType::Type(tok, unqualify_boxed_type(boxed_type))
+        }
+        _ => ret_type,
+    }
+}
+
+pub(crate) fn unqualify_params(
+    params: Punctuated<FnArg, Token![,]>,
+) -> Punctuated<FnArg, Token![,]> {
+    params
+        .into_iter()
+        .map(|p| match p {
+            FnArg::Typed(mut pt) => {
+                pt.ty = unqualify_boxed_type(pt.ty);
+                FnArg::Typed(pt)
+            }
+            _ => p,
+        })
+        .collect()
+}