Support calling Rust methods from C++

These methods can be declared in the bridge by naming the first
argument self and making it a reference to the containing class, e.g.,
  fn get(self: &R) -> usize;
  fn set(self: &mut R, n: usize);
This syntax requires Rust 1.43.
diff --git a/gen/write.rs b/gen/write.rs
index 41b5b37..7e1caac 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,7 @@
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{Api, ExternFn, Receiver, Signature, Struct, Type, Types, Var};
+use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 
 pub(super) fn gen(
@@ -45,9 +45,25 @@
     }
 
     for api in apis {
-        if let Api::Struct(strct) = api {
-            out.next_section();
-            write_struct(out, strct);
+        match api {
+            Api::Struct(strct) => {
+                out.next_section();
+                write_struct(out, strct);
+            }
+            Api::RustType(ety) => {
+                let methods = apis.iter().filter_map(|api| match api {
+                    Api::RustFunction(efn) => match &efn.sig.receiver {
+                        Some(rcvr) if rcvr.ident == ety.ident => Some(efn),
+                        _ => None,
+                    },
+                    _ => None,
+                }).collect::<Vec<_>>();
+                if !methods.is_empty() {
+                    out.next_section();
+                    write_struct_with_methods(out, ety, methods);
+                }
+            }
+            _ => {}
         }
     }
 
@@ -300,6 +316,21 @@
     writeln!(out, "using {} = {};", ident, ident);
 }
 
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: Vec<&ExternFn>) {
+    for line in ety.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "struct {} final {{", ety.ident);
+    for method in &methods {
+        write!(out, "  ");
+        let sig = &method.sig;
+        let local_name = method.ident.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, None, false);
+        writeln!(out, ";");
+    }
+    writeln!(out, "}};");
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
@@ -326,7 +357,11 @@
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    write!(out, "{}cxxbridge02${}${}(", out.namespace, receiver_type, efn.ident);
     if let Some(base) = &efn.receiver {
         write!(out, "{} *__receiver$", base.ident);
     }
@@ -471,7 +506,11 @@
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let link_name = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let link_name = format!("{}cxxbridge02${}${}", out.namespace, receiver_type, efn.ident);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
 }
@@ -490,6 +529,10 @@
     }
     write!(out, "{}(", link_name);
     let mut needs_comma = false;
+    if let Some(base) = &sig.receiver {
+        write!(out, "{} &__receiver$", base.ident);
+        needs_comma = true;
+    }
     for arg in &sig.args {
         if needs_comma {
             write!(out, ", ");
@@ -519,20 +562,26 @@
         writeln!(out, "//{}", line);
     }
     let local_name = efn.ident.to_string();
-    let invoke = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let invoke = format!("{}cxxbridge02${}${}", out.namespace, receiver_type, efn.ident);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
 }
 
-fn write_rust_function_shim_impl(
+fn write_rust_function_shim_decl(
     out: &mut OutFile,
     local_name: &str,
     sig: &Signature,
-    types: &Types,
-    invoke: &str,
+    receiver: Option<&Receiver>,
     indirect_call: bool,
 ) {
     write_return_type(out, &sig.ret);
+    if let Some(base) = receiver {
+        write!(out, "{}::", base.ident);
+    }
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
@@ -551,6 +600,21 @@
     if !sig.throws {
         write!(out, " noexcept");
     }
+}
+
+fn write_rust_function_shim_impl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    types: &Types,
+    invoke: &str,
+    indirect_call: bool,
+) {
+    if out.header && sig.receiver.is_some() {
+        // We've already defined this inside the struct.
+        return;
+    }
+    write_rust_function_shim_decl(out, local_name, sig, sig.receiver.as_ref(), indirect_call);
     if out.header {
         writeln!(out, ";");
     } else {
@@ -589,8 +653,11 @@
             write!(out, "::rust::Str::Repr error$ = ");
         }
         write!(out, "{}(", invoke);
+        if let Some(_) = &sig.receiver {
+            write!(out, "*this");
+        }
         for (i, arg) in sig.args.iter().enumerate() {
-            if i > 0 {
+            if i > 0 || sig.receiver.is_some() {
                 write!(out, ", ");
             }
             match &arg.ty {