blob: cf8771fb0f287b80781ee50ffd4305435e8782f3 [file]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! This module defines the RustOnceClosure type, which logically equivalent to
//! base::OnceClosure. Later it might contain equivalents for other base
//! callback types.
//!
//! Note that the types in this file are logically equivalent to the C++ types,
//! but they are not FFI compatible. To make a base::OnceClosure from a
//! RustOnceClosure, call base::BindOnce with the closure and the `run`
//! method.
chromium::import! {
"//base:scoped_refptr";
}
#[cxx::bridge(namespace = "base")]
pub mod ffi {
// Allow C++ to use RustOnceClosure types
extern "Rust" {
#[derive(ExternType)]
type RustOnceClosure;
#[Self = "RustOnceClosure"]
fn run(boxed: Box<RustOnceClosure>);
}
}
// TODO(crbug.com/493253831): In theory we don't need a box here, we could just
// have this struct be an unsized type since we're going to have to box it
// anyway to call run(). But the cxx bridge complains if we do that, so see if
// we can figure out how to make it work in reality.
pub struct RustOnceClosure(Box<dyn FnOnce()>);
impl RustOnceClosure {
/// Execute the contained closure.
///
/// Logically, this should take `self` by value, but we want to expose it
/// in the cxx bridge and that doesn't allow opaque rust types to be taken
/// by value. So we put it in a Box instead.
#[allow(clippy::boxed_local)]
pub fn run(boxed: Box<Self>) {
boxed.0();
}
}
impl<T: FnOnce() + 'static> From<T> for RustOnceClosure {
fn from(f: T) -> Self {
Self(Box::new(f))
}
}