Skip to main content

zyris_fs/
lib.rs

1//! The reference `file_io` implementation for
2//! [Zyris](https://github.com/attacca-cc/zyris-protocol): local files, over `tokio::fs`.
3//!
4//! [`zyris_caps::FileIo`] is the contract — stat, list, read, a streaming read, write, edit,
5//! remove and mkdir — and says nothing about where the bytes live. This crate is one answer to it,
6//! [`LocalFileIo`], backed by the filesystem of the machine the node runs on. A node that wants
7//! different storage behind the same tools implements the trait itself and never depends on this.
8//!
9//! ```no_run
10//! use zyris::{Node, NodeKind};
11//! use zyris_caps::FileIoServer;
12//! use zyris_fs::LocalFileIo;
13//!
14//! # fn serve() -> zyris::Result<Node> {
15//! let node = Node::builder()
16//!     .name("fs-node")
17//!     .kind(NodeKind::Service)
18//!     // Relative paths from a caller join this directory.
19//!     .capability(FileIoServer(LocalFileIo::rooted(".")))
20//!     .build()?;
21//! # Ok(node)
22//! # }
23//! ```
24//!
25//! # The root is a default, not a jail
26//!
27//! [`LocalFileIo::rooted`] takes the directory a caller's relative paths join. It is not a
28//! boundary: a path with a leading `/` addresses the host filesystem directly and `..` pops out of
29//! the root, exactly as [`zyris_caps::resolve_under`] describes. That is deliberate — an agent
30//! working in a checkout still has to read `/etc/hostname` or a sibling directory sometimes, and a
31//! limit that some callers need is not the same as one every caller gets.
32//!
33//! A node that does need a boundary puts one in front of this type, where it can also see the
34//! program's own policy. Enforcing it is not this crate's job, and pretending otherwise would be
35//! worse than saying so.
36//!
37//! # Reads are bounded, and say when they are
38//!
39//! [`FileIo::read`](zyris_caps::FileIo::read) is unary, so its whole result has to fit in one
40//! response; it returns at most 128 KiB and sets `truncated` when the file continues past what it
41//! returned. Feeding the next `offset` back in walks the rest, and
42//! [`FileIo::read_stream`](zyris_caps::FileIo::read_stream) has no such ceiling for a caller that
43//! declared a stream.
44
45mod file_io;
46pub use file_io::LocalFileIo;