Skip to main content

darkbio_wire/transport/
io.rs

1// wire-rs: encrypted protocol between Ark and host
2// Copyright 2026 Dark Bio AG. All rights reserved.
3//
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7//! Standard byte I/O with separate read and write deadlines. Transport chooses
8//! an absolute deadline. The adapter limits how long its I/O can block and keeps
9//! the stream reusable after a timeout.
10
11use std::io;
12use std::time::Instant;
13
14/// A standard byte reader whose blocking operations honor an absolute deadline.
15///
16/// An idle read returns `TimedOut` when its deadline expires, without consuming
17/// bytes. Transport retries early timeouts and interruptions within the same
18/// deadline. Reads that consume bytes must report them through the standard
19/// [`io::Read`] contract. Timeouts leave the adapter open and reusable.
20///
21/// The actual I/O must honor the deadline. Checking the clock before a call that
22/// can block indefinitely is insufficient. With no deadline, reads wait for data
23/// or shutdown. The stream's shutdown operation must release blocked reads.
24pub trait Read: io::Read {
25    /// Installs the deadline for subsequent reads until replaced; `None` clears
26    /// it. Returns promptly, transfers no bytes and leaves the write deadline
27    /// unchanged.
28    /// Reads attempted after expiration must not wait. Adapters may return
29    /// immediately available bytes, EOF or an empty read, or report `TimedOut`.
30    /// Transport enforces its own deadline before calling the adapter. If this
31    /// setter fails, transport returns the error without attempting a read.
32    fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()>;
33}
34
35impl<T: Read + ?Sized> Read for &mut T {
36    fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
37        (**self).set_read_deadline(deadline)
38    }
39}
40
41impl<T: Read + ?Sized> Read for Box<T> {
42    fn set_read_deadline(&mut self, deadline: Option<Instant>) -> io::Result<()> {
43        (**self).set_read_deadline(deadline)
44    }
45}
46
47/// A standard byte writer whose writes and flushes honor an absolute deadline.
48///
49/// The installed deadline covers partial writes and flush. Progress does not
50/// restart it. Expiration returns `TimedOut` and leaves the adapter open and
51/// reusable. Each write reports accepted bytes through the standard [`io::Write`]
52/// contract. A frame can therefore fail after earlier writes accepted a prefix.
53/// Successful output does not guarantee that the peer received or processed it.
54///
55/// Pending transfers must remain ordered before subsequent output or be cancelled
56/// before that output begins. An abandoned operation must never append bytes out
57/// of order after a later call starts writing. The adapter must bound actual I/O.
58pub trait Write: io::Write {
59    /// Installs the deadline for subsequent writes and flushes until replaced.
60    /// Returns promptly, transfers no bytes and leaves the read deadline unchanged.
61    /// Operations attempted after expiration return `TimedOut`. If this setter
62    /// fails, transport returns the error without attempting a write or flush.
63    fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()>;
64}
65
66impl<T: Write + ?Sized> Write for &mut T {
67    fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
68        (**self).set_write_deadline(deadline)
69    }
70}
71
72impl<T: Write + ?Sized> Write for Box<T> {
73    fn set_write_deadline(&mut self, deadline: Instant) -> io::Result<()> {
74        (**self).set_write_deadline(deadline)
75    }
76}
77
78/// Refuses work whose absolute I/O deadline has already elapsed.
79pub(super) fn check_deadline(deadline: Instant) -> io::Result<()> {
80    if Instant::now() >= deadline {
81        Err(io::Error::new(
82            io::ErrorKind::TimedOut,
83            "I/O deadline expired",
84        ))
85    } else {
86        Ok(())
87    }
88}