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/examples/subclass/src/billy.rs b/examples/subclass/src/billy.rs
new file mode 100644
index 0000000..5defe1b
--- /dev/null
+++ b/examples/subclass/src/billy.rs
@@ -0,0 +1,20 @@
+// Copyright 2021 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.
+
+pub(crate) static SHAKESPEARE_QUOTES: [&str; 10] = [
+ "All that glitters is not gold",
+ "Hell is empty and all the devils are here.",
+ "Good night, good night! parting is such sweet sorrow, That I shall say good night till it be morrow.",
+ "These violent delights have violent ends...",
+ "Something is rotten in the state of Denmark.",
+ "Love all, trust a few, do wrong to none.",
+ "The lady doth protest too much, methinks.",
+ "Brevity is the soul of wit.",
+ "Uneasy lies the head that wears a crown.",
+ "Now is the winter of our discontent.",
+];
diff --git a/examples/subclass/src/main.rs b/examples/subclass/src/main.rs
new file mode 100644
index 0000000..2841598
--- /dev/null
+++ b/examples/subclass/src/main.rs
@@ -0,0 +1,145 @@
+// Copyright 2021 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.
+
+// This example shows some Rust subclasses of C++ classes.
+
+mod billy;
+mod uwu;
+
+use autocxx::prelude::*;
+use autocxx::subclass::prelude::*;
+use cxx::CxxString;
+use std::cell::RefCell;
+use std::rc::Rc;
+
+include_cpp! {
+ #include "messages.h"
+ safety!(unsafe) // unsafety policy; see docs
+}
+
+// Here's the definition of MessageDisplayer from src/messages.h:
+// ```cpp
+// class MessageDisplayer {
+// public:
+// virtual void display_message(const std::string& message) const = 0;
+// virtual ~MessageDisplayer() {};
+// };
+// ```
+// The following lines define a subclass of MessageDisplayer.
+// See the main function at the bottom for how this subclass
+// is instantiated.
+
+#[is_subclass(superclass("MessageDisplayer"))]
+#[derive(Default)]
+pub struct UwuDisplayer {}
+
+impl ffi::MessageDisplayer_methods for UwuDisplayer {
+ fn display_message(&self, msg: &CxxString) {
+ let uwu = uwu::uwu(msg.to_str().unwrap());
+ println!("{}", uwu);
+ }
+}
+
+// And here's a different pure virtual class.
+// Here's its definition from src/messages.h:
+// ```cpp
+// class MessageProducer {
+// public:
+// virtual std::string get_message() const = 0;
+// virtual ~MessageProducer() {};
+// };
+// ```
+// This one is notable only in that the interface of the C++ class
+// involves std::string, yet in Rust the subclass uses
+// std::unique_ptr<std::string> (for all the normal reasons in autocxx -
+// for now, at least, we can't hold non-trivial C++ objects on the Rust stack.)
+// All the boxing and unboxing is done automatically by autocxx layers.
+
+#[is_subclass(superclass("MessageProducer"))]
+#[derive(Default)]
+pub struct QuoteProducer;
+
+// Here we've chosen to have an explicit constructor instead rather than deriving
+// from CppSubclassDefault. It's functionally the same.
+impl QuoteProducer {
+ fn new() -> Rc<RefCell<Self>> {
+ Self::new_rust_owned(Self::default())
+ }
+}
+
+impl ffi::MessageProducer_methods for QuoteProducer {
+ fn get_message(&self) -> cxx::UniquePtr<CxxString> {
+ use ffi::ToCppString;
+ billy::SHAKESPEARE_QUOTES[fastrand::usize(0..billy::SHAKESPEARE_QUOTES.len())].into_cpp()
+ }
+}
+
+// Here's another subclass of the same 'displayer' class.
+// This one is more complex in two ways.
+//
+// First, we actually want to store some data here in our subclass.
+// That means we can't just allocate ourselves with Default::default().
+// And that means we need to be aware of the cpp_peer field which is
+// added by the #[subclass] macro.
+//
+// Second, we're going to simulate the observer/listener type pattern
+// in C++ where a const* is used to send messages around a codebase yet
+// recipients need to react by mutating themselves or otherwise actively
+// doing stuff. In C++ you'd probably need a const_cast. Here we use
+// interior mutability.
+
+#[is_subclass(superclass("MessageDisplayer"))]
+pub struct BoxDisplayer {
+ message_count: RefCell<usize>,
+}
+
+impl BoxDisplayer {
+ fn new() -> Rc<RefCell<Self>> {
+ Self::new_rust_owned(Self {
+ // As we're allocating this class ourselves instead of using [`Default`]
+ // we need to initialize the `cpp_peer` member ourselves. This member is
+ // inserted by the `#[is_subclass]` annotation. autocxx will
+ // later use this to store a pointer back to the C++ peer.
+ cpp_peer: Default::default(),
+ message_count: RefCell::new(1usize),
+ })
+ }
+}
+
+impl ffi::MessageDisplayer_methods for BoxDisplayer {
+ fn display_message(&self, msg: &CxxString) {
+ let msg = textwrap::fill(msg.to_str().unwrap(), 70);
+ let horz_line = std::iter::repeat("#").take(74).collect::<String>();
+ println!("{}", horz_line);
+ let msgmsg = format!("Message {}", self.message_count.borrow());
+ self.message_count.replace_with(|old| *old + 1usize);
+ println!("# {:^70} #", msgmsg);
+ println!("{}", horz_line);
+ for l in msg.lines() {
+ println!("# {:^70} #", l);
+ }
+ println!("{}", horz_line);
+ }
+}
+
+fn main() {
+ ffi::register_cpp_thingies();
+ // Construct a Rust-owned UwuDisplayer. We can also construct
+ // a C++-owned or self-owned subclass - see docs for `CppSubclass`.
+ let uwu = UwuDisplayer::default_rust_owned();
+ // The next line casts the &UwuDisplayerCpp to a &MessageDisplayer.
+ ffi::register_displayer(uwu.as_ref().borrow().as_ref());
+ // Constructs in just the same way as the first one, but using
+ // our explicit constructor.
+ let boxd = BoxDisplayer::new();
+ ffi::register_displayer(boxd.as_ref().borrow().as_ref());
+ let shakespeare = QuoteProducer::new();
+ ffi::register_producer(shakespeare.as_ref().borrow().as_ref());
+ ffi::run_demo();
+ ffi::run_demo();
+}
diff --git a/examples/subclass/src/messages.cc b/examples/subclass/src/messages.cc
new file mode 100644
index 0000000..4d24aab
--- /dev/null
+++ b/examples/subclass/src/messages.cc
@@ -0,0 +1,70 @@
+// Copyright 2021 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.
+
+// This example shows Rust subclasses of C++ classes.
+// See messages.h and main.rs for most of the interesting code.
+
+#include "messages.h"
+#include <ctime>
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <functional>
+
+class CppExampleProducer : public MessageProducer {
+public:
+ CppExampleProducer() {}
+ std::string get_message() const {
+ std::time_t result = std::time(nullptr);
+ std::ostringstream st;
+ st << std::asctime(std::localtime(&result))
+ << result << " seconds since the Epoch";
+ return st.str();
+ }
+};
+
+class CppExampleDisplayer : public MessageDisplayer {
+public:
+ CppExampleDisplayer() {}
+ void display_message(const std::string& msg) const {
+ std::cout << "Message: " << msg << std::endl;
+ }
+};
+
+std::vector<std::reference_wrapper<const MessageProducer>> producers;
+std::vector<std::reference_wrapper<const MessageDisplayer>> displayers;
+CppExampleProducer cpp_producer;
+CppExampleDisplayer cpp_displayer;
+
+
+// Maybe we should use a language which tracks lifetimes
+// better than this. If only such a language existed.
+void register_displayer(const MessageDisplayer& displayer) {
+ displayers.push_back(displayer);
+}
+
+void register_producer(const MessageProducer& producer) {
+ producers.push_back(producer);
+}
+
+void register_cpp_thingies() {
+ register_producer(cpp_producer);
+ register_displayer(cpp_displayer);
+}
+
+void run_demo() {
+ for (auto& producer: producers) {
+ auto msg = producer.get().get_message();
+ for (auto& displayer: displayers) {
+ displayer.get().display_message(msg);
+ std::cout << std::endl;
+ }
+ std::cout << std::endl;
+ }
+}
+
diff --git a/examples/subclass/src/messages.h b/examples/subclass/src/messages.h
new file mode 100644
index 0000000..02ff248
--- /dev/null
+++ b/examples/subclass/src/messages.h
@@ -0,0 +1,33 @@
+// Copyright 2021 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.
+
+// This example shows Rust subclasses of C++ classes.
+// Here are the C++ classes which we're subclassing.
+
+#pragma once
+
+#include <string>
+#include <memory>
+
+class MessageProducer {
+public:
+ virtual std::string get_message() const = 0;
+ virtual ~MessageProducer() {};
+};
+
+class MessageDisplayer {
+public:
+ virtual void display_message(const std::string& message) const = 0;
+ virtual ~MessageDisplayer() {};
+};
+
+void register_cpp_thingies();
+void register_producer(const MessageProducer& producer);
+void register_displayer(const MessageDisplayer& displayer);
+
+void run_demo();
diff --git a/examples/subclass/src/uwu.rs b/examples/subclass/src/uwu.rs
new file mode 100644
index 0000000..ce02510
--- /dev/null
+++ b/examples/subclass/src/uwu.rs
@@ -0,0 +1,17 @@
+// Copyright 2021 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.
+
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub(crate) fn uwu(msg: &str) -> String {
+ uwuifier::uwuify_str_sse(msg)
+}
+
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+pub(crate) fn uwu(_msg: &str) -> String {
+ "uwuification is unavailable for this pwatform :(".to_string()
+}