Layer 0 Spec — Crate air-sys-types
Technical specification — Version 0.1 (partial, to be completed)
⚠️ Document status
This spec covers the fundamental types of the
air-sys-typescrate, identified throughout the specifications of the syscall families. The types are grouped by their family of origin. The estimated total is roughly ~187 public types in the complete crate.This document lists the types and their signatures. A complete spec would detail, for each type, its methods, invariants, conversions, and tests. Work to resume: produce the exhaustive spec type by type, in parallel with the actual implementation.
Crate overview
The air-sys-types crate is the absolute foundation of the Air stack: every other module depends on it. It exposes:
- The fundamental newtypes:
Errno,Pid,Tid, etc. - The RAII wrappers for kernel resources:
OwnedFd,BorrowedFd,Mapping, etc. - The bitflags for kernel flags:
OpenFlags,CloneFlags, etc. - The typed enums for kernel semantics:
Signal,Capability, etc. - The data structures mirroring the kernel:
StatxResult,SignalFdInfo, etc.
Crate principles.
-
No allocation by default. The fundamental types (Errno, Pid, etc.) are newtypes over primitive types, without allocation.
-
#[repr(transparent)]or#[repr(C)]as needed. Types that must have a kernel-compatible layout use#[repr(C)]. Simple newtypes use#[repr(transparent)]. -
Explicit conversions. Conversions between types (for example,
Pid::as_raw() -> i32) are explicit via named methods, not via implicitFrom/Into. -
Validation at construction. Types that have invariants (for example,
Pid, which isNonZeroI32) validate at construction and exposetry_newmethods that returnOptionorResult. -
Extensive documentation. Each type has a docstring that explains its role, its invariants, and its relationship with the kernel.
Fundamental types (universal)
Errno
#![allow(unused)]
fn main() {
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Errno(NonZeroI32);
impl Errno {
// ~140 constants corresponding to the standard errno codes
pub const EPERM: Self;
pub const ENOENT: Self;
pub const ESRCH: Self;
pub const EINTR: Self;
pub const EIO: Self;
// ... etc.
pub const fn as_raw(self) -> i32;
pub const fn name(self) -> &'static str;
pub const fn description(self) -> &'static str;
}
impl core::fmt::Display for Errno { /* ... */ }
impl core::error::Error for Errno {}
}
See ADR-019 for the context.
File descriptors
#![allow(unused)]
fn main() {
pub struct OwnedFd { /* ... */ }
pub struct BorrowedFd<'fd> { /* ... */ }
pub type RawFd = i32;
impl OwnedFd {
pub fn as_fd(&self) -> BorrowedFd<'_>;
pub fn into_raw_fd(self) -> RawFd;
pub unsafe fn from_raw_fd(fd: RawFd) -> Self;
}
impl<'fd> BorrowedFd<'fd> {
pub fn as_raw_fd(&self) -> RawFd;
pub unsafe fn borrow_raw(fd: RawFd) -> Self;
}
impl Drop for OwnedFd {
fn drop(&mut self) { /* calls close(fd), ignores error */ }
}
}
Discipline: every FD managed by Air goes through OwnedFd/BorrowedFd. No bare RawFd except in the raw APIs.
DirFd
#![allow(unused)]
fn main() {
pub enum DirFd<'fd> {
Cwd,
Fd(BorrowedFd<'fd>),
}
}
Basis for the *at operations (see ADR-021 convention 1).
Types of the process family
#![allow(unused)]
fn main() {
pub struct Pid(NonZeroI32);
pub struct Tid(NonZeroI32);
pub struct PidFd { /* internal OwnedFd */ }
pub struct PidFdReceiver { /* ... */ }
pub struct TidReceiver { /* ... */ }
pub enum WaitTarget<'fd> {
AnyChild,
Pid(Pid),
ProcessGroup(Pid),
AnyProcessGroup,
PidFd(BorrowedFd<'fd>),
}
pub struct WaitOptions(i32); // bitflags
pub struct WaitStatus {
pub pid: Pid,
pub uid: u32,
pub event: WaitEvent,
}
pub enum WaitEvent {
Exited { code: i32 },
Killed { signal: Signal, core_dumped: bool },
Stopped { signal: Signal },
Continued,
Trapped { signal: Signal },
}
pub struct CloneFlags(u64); // bitflags
pub struct CloneArgs { /* ... */ }
pub enum CloneResult { /* ... */ }
pub struct Signal(NonZeroI32);
pub struct SignalMask { /* ... */ }
pub enum Capability { /* enum of the Linux capabilities */ }
pub struct CapabilityMask(u64);
pub struct CapabilitySet { /* ... */ }
pub enum CapabilityTarget { /* ... */ }
pub enum Resource { /* enum of the Linux limits */ }
pub struct Rlimit { /* ... */ }
pub enum RlimitValue { Finite(u64), Infinity }
pub enum DumpableMode { /* ... */ }
pub struct ExecveatFlags(i32); // bitflags
pub struct PidFdOpenFlags(u32); // bitflags
}
~20 types for this family.
Types of the fs family
#![allow(unused)]
fn main() {
pub struct OpenFlags(u64); // bitflags
pub type Mode = u32;
pub struct OpenHow { /* ... */ }
pub struct ResolveFlags(u64); // bitflags
pub struct StatxResult { /* ... */ }
pub struct StatxMask(u32); // bitflags
pub struct StatxFlags(u32); // bitflags
pub struct StatxTimestamp { /* ... */ }
pub struct AccessMode(u32); // bitflags
pub struct AccessFlags(i32); // bitflags
pub struct RenameFlags(u32); // bitflags
pub struct FallocateMode(i32); // bitflags
pub enum SeekWhence { Set, Current, End, Data, Hole }
pub struct DirEntry { /* ... */ } // name: Vec<u8> (octets) — ADR-048
pub enum DirEntryType { /* ... */ }
pub struct DirEntryIter<'buf> { /* ... */ }
pub enum UtimeValue { Now, Omit, Time(StatxTimestamp) }
pub struct FdFlags(i32); // bitflags
pub struct StatusFlags(i32); // bitflags
pub struct FileLock { /* ... */ }
pub struct Seals(u32); // bitflags
pub struct FileHandle { /* ... */ }
pub struct NameToHandleFlags(i32); // bitflags
pub struct IoSlice<'data> { /* ... */ }
pub struct IoSliceMut<'data> { /* ... */ }
}
~25 types for this family.
Types of the mem family
#![allow(unused)]
fn main() {
pub struct Mapping {
addr: NonNull<u8>,
length: usize,
}
pub struct MappingPointer { /* ... */ }
pub struct ProtectionFlags(i32); // bitflags
pub struct MapFlags(i32); // bitflags
pub struct MremapFlags(i32); // bitflags
pub enum MadviseAdvice { /* ~25 variants */ }
pub struct MlockFlags(u32); // bitflags
pub struct MlockallFlags(i32); // bitflags
pub struct MemfdFlags(u32); // bitflags
pub struct MsyncFlags(i32); // bitflags
pub struct RemoteIoSlice { /* ... */ }
}
~10 types for this family.
Types of the io_uring module
Type placement (ADR-022 / ADR-028). This document specifies the
air-sys-typescrate. Forio_uring, only the pure-data types (with no behavior, no FD/mmap, no lifetime tied to a ring) live here; the stateful / coupled types (ring, builders, tokens, completions,#[repr(C)]mirrors, RAII guards) live inair-sys-syscall::io_uringby encapsulation. The rule is decided Temps by Temps, as the implementation progresses.Note (naming, ADR-029). Explicit facade names, without abbreviation. The old abbreviated names (
IoUringOp,RawSqe,RawCqe,RawOp,FdPool,RegisteredBuffer,ProvidedBuffers) are replaced; the kernel mirrors keep their short inherited names.
#![allow(unused)]
fn main() {
// PLACEMENT (ADR-022/028). Only `SetupFlags`, `CompletionFlags` and
// `IoUringOpcode` live in `air-sys-types` (pure types, delivered in Temps 1).
// ALL the other types below live in `air-sys-syscall::io_uring`
// (stateful / coupled — encapsulation); listed here for reference, specified in
// the `io-uring-*.md` specs. The later Temps will place their types according to
// the same rule (pure here, coupled in air-sys-syscall).
pub struct IoUring { /* ... */ }
pub struct IoUringBuilder { /* ... */ }
pub struct IoUringParams { /* ... */ }
pub struct IoUringCapabilities { /* ... */ }
pub struct SetupFlags(u32); // bitflags
pub struct Completion { /* ... */ }
pub struct CompletionFlags(u32); // bitflags
pub struct CompletionIter<'ring> { /* ... */ }
pub struct SubmitOptions { /* ... */ }
pub struct SubmissionToken(/* opaque: slot index + generation */);
pub struct MultishotToken(/* opaque */);
pub enum IoUringOpcode { /* enum of the operations */ }
pub enum CancelTarget { /* token / fd / op / any */ }
// Fixed resources (Temps 3a)
pub struct FixedFdTable { /* ... */ }
pub struct FixedSlot<'t> { /* ... */ }
pub enum FixedSlotTarget { /* Index(u32) | Alloc */ }
pub struct RegisteredBuffers { /* ... */ }
pub struct RegisteredBufferSlice<'b> { /* ... */ }
pub struct Personality(/* id */);
pub struct WorkQueueWorkerLimits { /* ... */ }
pub struct NapiConfig { /* ... */ }
pub enum ClockSource { /* Monotonic | Boottime | Realtime */ }
// Ring-mapped provided buffers (Temps 3b)
pub struct ProvidedBufferRing { /* ... */ }
pub struct ProvidedBuffer<'r> { /* RAII guard */ }
pub struct ProvidedBufferRingOptions { /* ... */ }
pub struct ProvidedBufferRingStatus { /* ... */ }
// Linked / multishot / zero-copy network
pub struct LinkedChainBuilder<'ring> { /* ... */ }
pub struct ChainTokens { /* ... */ }
pub struct ZeroCopyFlags(u32); // bitflags
// Multi-thread (Temps 3e)
pub struct LockedIoUring { /* ... */ }
pub struct RingPool { /* ... */ }
pub struct RingHandle { /* ... */ }
pub struct SqpollIoUring { /* ... */ }
// Confinement (Temps 3f)
pub struct RestrictionSet { /* ... */ }
pub enum Restriction { /* ... */ }
pub enum RegisterOp { /* ... */ }
pub struct SqeFlagSet { /* ... */ }
// Raw access level 1 (Temps 4) — verbose type, fields = kernel names
#[repr(C)]
pub struct RawSubmissionQueueEntry { /* 64 bytes; fields user_data, res… */ }
#[repr(C)]
pub struct RawCompletionQueueEntry { /* 16 or 32 bytes */ }
pub struct RawOpcode(pub u8);
pub const RAW_USER_DATA_TAG: u64 = 1 << 63;
pub struct TimeoutFlags(u32); // bitflags
pub struct PollEvents(u32); // bitflags
pub enum EpollOp { /* ... */ }
pub struct EpollEvent { /* ... */ }
}
In air-sys-types: 3 types (Temps 1 — SetupFlags, CompletionFlags,
IoUringOpcode). The others live in air-sys-syscall::io_uring or are not
yet implemented.
Types of the signal family
#![allow(unused)]
fn main() {
pub struct SignalFdInfo { /* ... */ }
pub struct SignalFdFlags(i32); // bitflags
pub struct SignalQueueInfo { /* ... */ }
pub enum SignalValue { Integer(i32), Pointer(u64) }
// synchronous_handler submodule
pub enum FatalSignal { Segv, Bus, Fpe, Ill }
pub struct SignalInfo { /* ... */ }
pub struct PreviousHandler { /* opaque */ }
}
~6 types for this family.
Types of the time family
#![allow(unused)]
fn main() {
pub enum Clock {
Realtime, Monotonic, ProcessCpuTime, ThreadCpuTime,
MonotonicRaw, RealtimeCoarse, MonotonicCoarse,
Boottime, RealtimeAlarm, BoottimeAlarm, Tai,
}
pub struct Instant {
clock: Clock,
seconds: i64,
nanoseconds: u32,
}
pub struct Timespec { /* internal */ }
pub struct TimerFd { /* internal OwnedFd */ }
pub struct TimerFdSpecification {
pub initial: Duration,
pub interval: Duration,
}
pub struct TimerFdFlags(i32); // bitflags
pub struct TimerSetFlags(i32); // bitflags
pub enum SleepDeadline {
Relative(Duration),
AbsoluteInstant(Instant),
}
pub enum SleepError {
Interrupted { remaining: Duration },
Other(Errno),
}
}
~9 types for this family.
Types of the net family
#![allow(unused)]
fn main() {
pub enum SocketDomain { /* ... */ }
pub enum SocketType { /* ... */ }
pub enum SocketAddr {
Unix(UnixSocketAddr),
Inet(InetSocketAddr),
Inet6(Inet6SocketAddr),
// ...
}
pub struct UnixSocketAddr { /* ... */ }
pub struct InetSocketAddr { /* ... */ }
pub struct Inet6SocketAddr { /* ... */ }
pub struct MessageFlags(i32); // bitflags
pub struct AcceptFlags(i32); // bitflags
pub struct AcceptResult { /* ... */ }
pub struct SendMessageRequest { /* ... */ }
pub struct ReceiveMessageRequest { /* ... */ }
pub struct SendMessageResult { /* ... */ }
pub struct ReceiveMessageResult { /* ... */ }
pub enum ShutdownMode { Read, Write, Both }
pub enum AncillarySent { /* ... */ }
pub enum AncillaryReceived { /* ... */ }
pub enum SocketOptionLevel { /* ... */ }
pub enum LingerOption { Disabled, Enabled(Duration) }
pub struct UnixCredentials { /* ... */ }
}
~20 types for this family.
Types of the ipc family
#![allow(unused)]
fn main() {
pub struct EventFd { /* internal OwnedFd */ }
pub struct EventFdFlags(i32); // bitflags
pub struct PipeFlags(i32); // bitflags
pub struct SpliceFlags(u32); // bitflags
}
~4 types for this family.
Types of the security family
#![allow(unused)]
fn main() {
pub struct SeccompFilter { /* ... */ }
pub struct SeccompRule { /* ... */ }
pub enum SeccompAction { /* ... */ }
pub enum SeccompMode { /* ... */ }
pub struct SeccompFilterFlags(u32); // bitflags
pub struct SyscallNumber(i32);
pub struct SyscallArgumentCondition { /* ... */ }
pub enum ConditionOp { /* ... */ }
pub struct LandlockRuleset { /* ... */ }
pub struct LandlockAccessFs(u64); // bitflags
}
~10 types for this family.
Types of the system family
#![allow(unused)]
fn main() {
pub struct UtsName {
pub sysname: CString,
pub nodename: CString,
pub release: CString,
pub version: CString,
pub machine: CString,
pub domainname: CString,
}
pub struct SystemInfo { /* ... */ }
pub struct GetrandomFlags(u32); // bitflags
}
3 types for this family.
Global summary
| Family | Approximate number of types |
|---|---|
| Fundamental | 5 (Errno, OwnedFd, BorrowedFd, RawFd, DirFd) |
process | 20 |
fs | 25 |
mem | 10 |
io_uring (in air-sys-types) | 3 (Temps 1) |
signal | 6 |
time | 9 |
net | 20 |
ipc | 4 |
security | 10 |
system | 3 |
Estimated total: ~140-160 public types.
The final spec would perhaps have a few more types depending on the needs that emerge during implementation. The initial estimate of ~187 types remains reasonable.
Work to resume
TODO: produce an exhaustive spec of
air-sys-types:For each type, document:
- Internal representation (
#[repr(...)]).- Constructors (
new,try_new, etc.) and invariants.- Main methods (
as_raw,from_raw, conversions).- Trait implementations (
Debug,Display,Error,Clone,Copy, etc.).- Tests to plan for (constructions, invariants, conversions).
- Relationship with the equivalent kernel types.
This exhaustive spec is probably to be produced in parallel with the actual implementation of the crate, rather than ahead of it, because adjustments will emerge naturally.
Document license: MPL 2.0
Status: Partial spec of the air-sys-types crate. To be completed in parallel with the implementation.