blob: 6e058c4e23e35302f28c316e0a0d51bd8ae0e569 [file]
// Copyright 2026 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
use core::pin::Pin;
use page_source_bindings as bindings;
use pin_init::pin_data;
use zr::{Opaque, pin_init_ffi, unsafe_pinned_drop_ffi};
/// Wrapper around tracking multiple different page requests that might need waiting. Only one
/// individual request is allowed to be considered 'active' at a time as the one that next needs
/// waiting on. Tracking whether a request is active is, depending on the request type, partially
/// automatic and partially requiring additional input from the user.
/// The PageRequest and LazyPageRequest access methods do not currently have a way to enforce that
/// those specific types of requests are made with the returned objects, however this could change
/// and callers are expected to use the correct method.
/// TODO(adanis): Implement an enforcement strategy.
#[pin_data(PinnedDrop)]
pub struct MultiPageRequest {
/// The optional inner `PageRequest` can appear in intrusive containers, so this object must be
/// pinned.
#[pin]
opaque: Opaque<bindings::MultiPageRequest>,
}
unsafe_pinned_drop_ffi!(MultiPageRequest, bindings::cpp_multi_page_request_destroy);
impl MultiPageRequest {
/// Returns an in-place initializer for stack-pinning a `MultiPageRequest`.
pub fn new() -> impl pin_init::PinInit<Self> {
/// # Safety
/// `ptr` must point to uninitialized `MultiPageRequest` storage.
unsafe fn init_shim(ptr: *mut core::ffi::c_void) {
let req_ptr: *mut bindings::MultiPageRequest = ptr.cast();
// SAFETY: `ptr` is guaranteed by `pin_init_ffi!` to point to valid `MultiPageRequest`
// storage.
unsafe { bindings::cpp_multi_page_request_construct(req_ptr) }
}
pin_init_ffi!(init_shim)
}
/// Cancel all requests and have no active request.
pub fn cancel_requests(self: Pin<&mut Self>) {
// SAFETY: Calling C++ CancelRequests on the pinned instance does not move it.
unsafe { bindings::cpp_multi_page_request_cancel_requests(self.as_raw()) }
}
/// Returns a raw pointer to the underlying C++ `MultiPageRequest`.
///
/// Callers must not use the returned raw pointer to move the object in memory.
pub fn as_raw(self: Pin<&mut Self>) -> *mut bindings::MultiPageRequest {
// SAFETY: Obtaining a raw pointer to `opaque` does not move the pinned object.
unsafe { self.get_unchecked_mut().opaque.get() }
}
}