Skip to main content

AssociatedEndpoint

Struct AssociatedEndpoint 

Source
pub struct AssociatedEndpoint<'port> { /* private fields */ }
Expand description

An overlapped endpoint bound to exactly one CompletionPort.

The endpoint owns its handle and borrows the port it is associated with, so the port cannot be dropped while any endpoint still routes completions to it. It is intentionally not Clone.

Implementations§

Source§

impl AssociatedEndpoint<'_>

Source

pub unsafe fn ioctl<I: IoBuf, O: IoBufMut>( &self, code: u32, input: I, output: O, ) -> Result<Started<DeviceIoControlIo<I, O>, O>>

Submit an overlapped DeviceIoControl with control code code.

Returns Started::Pending with a DeviceIoControlIo token that recovers the output buffer and byte count from the operation’s completion, or – only on an endpoint in FILE_SKIP_COMPLETION_PORT_ON_SUCCESS mode, where a synchronous success queues no packet – Started::Completed with the output buffer already in hand.

input is the input buffer (empty for control codes that take none) and output is the buffer the device writes its result into. Both are owned buffers of the caller’s choosing, handed over for the operation’s life and returned when it completes: nothing is copied and nothing is allocated here.

§Errors

Returns io::ErrorKind::InvalidInput if either buffer is longer than u32::MAX bytes, which the control code’s byte counts cannot express, or any immediate failure from issuing the control operation.

§Safety

code’s input layout must be self-contained: the driver may read or write only the bytes inside input and the output buffer, never memory reached through a pointer embedded in input. Some control codes take an input structure that carries raw pointers to separate buffers – SCSI_PASS_THROUGH_DIRECT::DataBuffer is one – which this adapter neither owns nor keeps alive. Because the operation outlives this call, such a pointee could be freed while the driver is still using it. For such a code the caller must keep every referenced buffer alive until the operation completes; the adapter cannot, because it does not know the code’s layout. This is why the generic raw-code seam is unsafe even though a self-contained code (an FSCTL query, say) needs nothing more than owned buffers.

Source§

impl AssociatedEndpoint<'_>

Source

pub fn read<B: IoBufMut>( &self, buffer: B, offset: u64, ) -> Result<Started<FileIo<B>, B>>

Submit an overlapped read into buffer, starting at offset.

The buffer is any owned IoBufMut – a Vec<u8>, a Box<[u8]>, a PageBuffers, or a caller’s own pooled or aligned type – handed over for the operation’s life and returned when it completes. Nothing is copied and nothing is allocated here: a caller that wants a fresh Vec writes vec![0; n] at the call site, where the allocation is visible.

Returns Started::Pending with a FileIo token that recovers the buffer and byte count from the operation’s completion, or – only on an endpoint in FILE_SKIP_COMPLETION_PORT_ON_SUCCESS mode, where a synchronous success queues no packet – Started::Completed with the buffer already in hand.

§Errors

Returns io::ErrorKind::InvalidInput if the buffer is longer than u32::MAX, or any immediate failure from issuing the read.

Source

pub fn write<B: IoBuf>( &self, buffer: B, offset: u64, ) -> Result<Started<FileIo<B>, B>>

Submit an overlapped write of buffer, starting at offset.

The buffer is any owned IoBuf – including a shared Arc<[u8]> or a &'static [u8], neither of which can be a read destination – handed over for the operation’s life and returned when it completes. Nothing is copied.

Returns Started::Pending with a FileIo token, or Started::Completed with the buffer already in hand when the endpoint is in skip-on-success mode and the write completed synchronously.

§Errors

Returns io::ErrorKind::InvalidInput if the buffer is longer than u32::MAX, or any immediate failure from issuing the write.

Source§

impl AssociatedEndpoint<'_>

Source

pub fn read_scatter( &self, buffers: PageBuffers, offset: u64, ) -> Result<Started<ScatterGatherIo, PageBuffers>>

Submit an overlapped scatter-read into buffers, starting at offset.

Takes the caller’s pages rather than allocating fresh ones, so a pooled or reused PageBuffers costs nothing to submit. The endpoint must be opened with FILE_FLAG_NO_BUFFERING.

Returns Started::Pending with a ScatterGatherIo token, or Started::Completed with the PageBuffers already in hand when the endpoint is in skip-on-success mode and the read completed synchronously.

§Errors

Returns io::ErrorKind::InvalidInput if the pages total more than u32::MAX bytes, or any immediate failure from issuing the scatter-read.

Source

pub fn write_gather( &self, buffers: PageBuffers, offset: u64, ) -> Result<Started<ScatterGatherIo, PageBuffers>>

Submit an overlapped gather-write of buffers starting at offset.

Returns Started::Pending with a ScatterGatherIo token, or Started::Completed with the PageBuffers already in hand when the endpoint is in skip-on-success mode and the write completed synchronously. The endpoint must be opened with FILE_FLAG_NO_BUFFERING.

§Errors

Returns io::ErrorKind::InvalidInput if the buffers total more than u32::MAX bytes, or any immediate failure from issuing the gather-write.

Source§

impl<'port> AssociatedEndpoint<'port>

Source

pub fn handle(&self) -> BorrowedHandle<'_>

Borrow the underlying handle for issuing native operations.

Source

pub fn key(&self) -> usize

The completion key packets from this endpoint are tagged with.

Source

pub fn notification_modes(&self) -> NotificationModes

The completion-notification modes this endpoint carries, as declared before it was associated.

The adapters read this to classify a synchronous native success: with crate::NotificationModes::skip_completion_port_on_success set, no packet will arrive for one, so it is an Issued::Completed rather than an Issued::Pending.

Source

pub fn port(&self) -> &'port CompletionPort

The completion port this endpoint is associated with.

Source

pub fn outstanding(&self) -> usize

How many operations submitted on this endpoint have not yet had their completion packet dequeued.

Unlike CompletionPort::outstanding, this is scoped to this endpoint alone – what AssociatedEndpoint’s own blocking Drop waits on.

Source

pub unsafe fn submit<P, F>( &self, operation: Operation<P>, issue: F, ) -> Submitted<P>
where P: Send + 'static, F: FnOnce(BorrowedHandle<'_>, *mut OVERLAPPED) -> Result<Issued>,

Submit an owned operation on this endpoint.

issue performs the single native overlapped call using the endpoint’s handle and the operation’s stable OVERLAPPED pointer. It classifies the outcome as an Issued: Issued::Pending when a completion packet will be delivered, or Issued::Completed when the call finished synchronously and no packet will arrive – the state a handle in FILE_SKIP_COMPLETION_PORT_ON_SUCCESS mode reports on synchronous success. It returns Err for an immediate failure that yields no completion.

On the pending path the operation’s storage is transferred to the kernel and recovered later with Completion::claim. On the synchronous and failure paths the operation is returned intact through Submitted so its storage can be reused or inspected.

§Panics

Panics if this port already has a live operation registered at the new operation’s storage address. That cannot happen through ordinary use – operation owns freshly boxed storage – and indicates a defect in this crate’s own bookkeeping rather than in the calling code. See OperationRegistry::insert for the invariant involved.

§Safety

issue must start exactly one overlapped operation using the provided OVERLAPPED pointer and no other storage, and must classify the outcome correctly: Issued::Pending only when a completion packet will be delivered to this endpoint’s port, Issued::Completed only when the operation is already complete and no packet will arrive, and Err only when the submission failed and no completion will arrive.

issue must not unwind: a panic out of it can leave an operation registered with no completion coming, which makes rundown wait forever. A closure that might panic must catch it and return Err.

P: 'static because submitting leaks the operation’s storage, to be freed later through a thunk carrying no lifetime – see Operation::into_overlapped.

Source

pub fn cancel(&self, id: OperationId) -> Result<()>

Request cancellation of a single outstanding operation.

Cancellation is only a request: the operation still completes, typically with ERROR_OPERATION_ABORTED, and that completion remains the point at which its storage is reclaimed with Completion::claim.

The identity is checked against this port’s live operations first. An identity whose operation has already completed is rejected with io::ErrorKind::NotFound and no native call is made, even if another operation has since been given the same storage address – so retaining an identity too long can never cancel an unrelated operation.

§Errors

Returns io::ErrorKind::NotFound if id no longer names a live operation, or the error from CancelIoEx if the native request fails.

Source

pub fn cancel_all(&self) -> Result<()>

Request cancellation of every outstanding operation on this endpoint.

Trait Implementations§

Source§

impl<'port> Debug for AssociatedEndpoint<'port>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for AssociatedEndpoint<'_>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

§

impl<'port> Freeze for AssociatedEndpoint<'port>

§

impl<'port> RefUnwindSafe for AssociatedEndpoint<'port>

§

impl<'port> Send for AssociatedEndpoint<'port>

§

impl<'port> Sync for AssociatedEndpoint<'port>

§

impl<'port> Unpin for AssociatedEndpoint<'port>

§

impl<'port> UnsafeUnpin for AssociatedEndpoint<'port>

§

impl<'port> UnwindSafe for AssociatedEndpoint<'port>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.