blob: 00f681c892e74e61e511d79668593f112e283510 [file] [log] [blame]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//! This crate is used as a test input for `cc_bindings_from_rs` and the
//! generated C++ bindings are then tested via `drop_test.cc`.
pub mod counters {
use std::sync::atomic::{AtomicUsize, Ordering};
static CLONE_COUNTER: AtomicUsize = AtomicUsize::new(0);
static CLONE_FROM_COUNTER: AtomicUsize = AtomicUsize::new(0);
static DEFAULT_COUNTER: AtomicUsize = AtomicUsize::new(0);
static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
pub fn reset_counts() {
CLONE_COUNTER.store(0, Ordering::Relaxed);
CLONE_FROM_COUNTER.store(0, Ordering::Relaxed);
DEFAULT_COUNTER.store(0, Ordering::Relaxed);
DROP_COUNTER.store(0, Ordering::Relaxed);
}
pub fn get_clone_count() -> usize {
CLONE_COUNTER.load(Ordering::Relaxed)
}
pub fn get_clone_from_count() -> usize {
CLONE_FROM_COUNTER.load(Ordering::Relaxed)
}
pub fn get_default_count() -> usize {
DEFAULT_COUNTER.load(Ordering::Relaxed)
}
pub fn get_drop_count() -> usize {
DROP_COUNTER.load(Ordering::Relaxed)
}
pub fn increment_clone_count() {
CLONE_COUNTER.fetch_add(1, Ordering::Relaxed);
}
pub fn increment_clone_from_count() {
CLONE_FROM_COUNTER.fetch_add(1, Ordering::Relaxed);
}
pub fn increment_default_count() {
DEFAULT_COUNTER.fetch_add(1, Ordering::Relaxed);
}
pub fn increment_drop_count() {
DROP_COUNTER.fetch_add(1, Ordering::Relaxed);
}
}
/// Test for `Drop` support when:
/// * `Drop` is provided by `impl` (rather than requiring "drop glue" for
/// fields).
/// * The type implements the `Default` trait.
/// * The type cannot be copied via `Clone` (although this aspect is not
/// load-bearing in this test.)
pub mod drop_impl_with_default {
pub struct DropImplWithDefault {
pub field: i32,
}
impl Default for DropImplWithDefault {
fn default() -> Self {
super::counters::increment_default_count();
Self { field: 0 }
}
}
impl Drop for DropImplWithDefault {
fn drop(&mut self) {
super::counters::increment_drop_count();
}
}
impl DropImplWithDefault {
pub fn get_int(&self) -> i32 {
self.field
}
pub fn set_int(&mut self, i: i32) {
self.field = i;
}
}
}
/// Test for `Drop` support when:
/// * There is no `Drop` `impl`, but the type under test requires "drop glue"
/// for its fields (i.e. the field implements `Drop`, but the type containing
/// the field doesn't).
/// * The type implements the `Default` trait.
/// * The type cannot be copied via `Clone` (although this aspect is not
/// load-bearing in this test.)
pub mod drop_glue_with_default {
use super::drop_impl_with_default::DropImplWithDefault;
#[derive(Default)]
pub struct DropGlueWithDefault {
pub field: DropImplWithDefault,
}
impl DropGlueWithDefault {
pub fn get_int(&self) -> i32 {
self.field.get_int()
}
pub fn set_int(&mut self, i: i32) {
self.field.set_int(i)
}
}
}
/// Test for `Drop` support when:
/// * `Drop` is provided by `impl` (rather than requiring "drop glue" for
/// fields).
/// * The type does *not* implement the `Default` trait.
/// * The type can be copied via `Clone`
pub mod drop_impl_with_clone {
pub struct DropImplWithClone {
pub field: i32,
}
impl Clone for DropImplWithClone {
fn clone(&self) -> Self {
super::counters::increment_clone_count();
Self { field: self.field }
}
/// We implement `clone_from` to avoid depending on the implementation
/// details of the default implementation (which for example ends up
/// dropping a temporary value).
fn clone_from(&mut self, source: &Self) {
super::counters::increment_clone_from_count();
self.field = source.field
}
}
impl Drop for DropImplWithClone {
fn drop(&mut self) {
super::counters::increment_drop_count();
}
}
impl DropImplWithClone {
pub fn create_from_int(i: i32) -> Self {
Self { field: i }
}
pub fn get_int(&self) -> i32 {
self.field
}
pub fn set_int(&mut self, i: i32) {
self.field = i;
}
}
}
/// Test for `Drop` support when:
/// * `Drop` is provided by `impl` (rather than requiring "drop glue" for
/// fields).
/// * The type does *not* implement the `Default` trait.
/// * The type cannot be copied via `Clone`
pub mod drop_impl_with_nothing_else {
pub struct DropImplWithNothingElse {
pub field: i32,
}
impl Drop for DropImplWithNothingElse {
fn drop(&mut self) {
super::counters::increment_drop_count();
}
}
impl DropImplWithNothingElse {
pub fn get_int(&self) -> i32 {
self.field
}
}
/// FFI bindings for `DropImplWithNothingElse` have no constructors (the
/// move constructor is explicitly `=delete`d, because the Rust
/// type doesn't provide any APIs that could
/// leave the moved-away object in a well-formed, safe-to-destruct
/// state). This also means that its currently not possible to return
/// `DropImplWithNothingElse` by value from Rust (e.g. from factory
/// methods), because `ReturnValueSlot` uses `std::move` internally.
///
/// To work around the constraints above, we construct the value on Rust
/// side, and expose it to C++ in a "wrapped" form. This means that tests
/// don't need to construct or move `DropImplWithNothingElse` on C++
/// side.
pub struct WrappedDropImplWithNothingElse {
pub field: DropImplWithNothingElse,
}
impl Default for WrappedDropImplWithNothingElse {
fn default() -> Self {
Self { field: DropImplWithNothingElse { field: 123 } }
}
}
}