Skip to main content

iris_source/
lib.rs

1//! Range oriented data sources for iris.
2//!
3//! A decoder declares the byte ranges it needs and the host serves them. That inversion is what lets
4//! the same decoder run against a local file, a page cache, and an object store.
5//!
6//! What exists so far is [`Window`], the sliding file view the host maps ranges through. The
7//! `RangeSource` trait it will sit behind, and the object store implementation of it, belong to a
8//! later milestone. See `docs/ROADMAP.md`.
9//!
10//! # Unsafe code
11//!
12//! This is the one crate in the workspace that has any. Reserving address space and mapping a file
13//! into part of it is not expressible without it, and the alternative to writing it here is writing
14//! it in the crate that runs the sandbox, which is the last place it should be. Every other crate
15//! carries `#![forbid(unsafe_code)]` and keeps it.
16//!
17//! All of it is in [`window`] and its platform modules, every block carries a comment saying why it
18//! is sound, and the stress test in `tests/window.rs` runs thousands of remap cycles on all four
19//! supported platforms on every change.
20
21#[cfg(any(unix, windows))]
22mod sys;
23
24#[cfg(any(unix, windows))]
25pub mod window;
26
27#[cfg(any(unix, windows))]
28pub use window::{DEFAULT_SPAN, Window, WindowError};
29
30/// Asks the operating system whether an address range can be read, without reading it.
31///
32/// This exists for the tests that hold an address across a window slide, where the property being
33/// checked is that the address stopped being readable and the obvious way to check it ends the
34/// process. It is behind a feature because it is a question about a mapping rather than about a data
35/// source, and nothing that uses this crate for its actual purpose should need to ask it.
36#[cfg(all(feature = "probe", any(unix, windows)))]
37pub mod probe {
38    /// Whether the first and last byte of `len` bytes at `ptr` can be read.
39    ///
40    /// False means a read would fault. True means it would not, which is not the same as saying the
41    /// bytes are the ones the caller expects.
42    ///
43    /// On Unix this hands the address to `write` and looks for `EFAULT`, because there is no
44    /// portable way to ask what a mapping looks like. On Windows it asks `VirtualQuery` directly.
45    /// Neither one dereferences the address.
46    #[must_use]
47    pub fn readable(ptr: *const u8, len: usize) -> bool {
48        crate::sys::readable(ptr, len)
49    }
50
51    /// How many operating system handles this process holds, or `None` where that cannot be found
52    /// out.
53    ///
54    /// The number on its own means nothing. The difference between two of them, taken the same way
55    /// on either side of a loop, is what a handle leak looks like. `None` means the platform did not
56    /// answer, and a caller should skip the check rather than treat it as zero.
57    ///
58    /// Descriptors on Unix, handles on Windows. Those are not the same kind of object and the counts
59    /// are not comparable across platforms, which does not matter, because the only comparison worth
60    /// making is against another count from the same process.
61    #[must_use]
62    pub fn handles() -> Option<u32> {
63        crate::sys::handles()
64    }
65}
66
67/// The version of this crate, as reported by build metadata.
68pub const VERSION: &str = env!("CARGO_PKG_VERSION");