Skip to main content

loonfs_api/
options.rs

1//! Per-operation option shapes shared by the runtime and client surfaces.
2//!
3//! `loonfs` (embedded runtime) and `loonfs-client` (HTTP client) expose the
4//! same semantic filesystem operations, so the options that parameterize them
5//! are defined once here and re-exported by both under their existing names.
6//! Keeping one definition is what stops the two surfaces from drifting a
7//! field apart.
8//!
9//! There is one type per operation, even where two of them currently hold the
10//! same fields: options follow the operation they parameterize, so a guard
11//! added to one is not silently offered on the others.
12//!
13//! These are plain in-process argument structs, not wire shapes: nothing here
14//! serializes. The request bodies that do cross the wire live in
15//! [`crate::v0`], and each surface resolves these options into one. A read's
16//! options reach the wire as query parameters the surface builds from them.
17
18use crate::{
19    ActorRef, AttributeKey, AttributeRevisionNo, AttributeValue, CommitId, DeleteDirectoryBehavior,
20    DestinationBehavior, InodeId, RevisionNo,
21};
22use std::collections::BTreeMap;
23
24/// Commit settings shared by every filesystem mutation.
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct CommitOptions {
27    /// Actor responsible for the commit, as supplied by the application.
28    pub actor: ActorRef,
29    /// Optional idempotency key. LoonFS generates one when this is `None`.
30    pub commit_id: Option<CommitId>,
31    /// Optional commit message. Changing it changes the commit identity.
32    pub message: Option<String>,
33}
34
35impl CommitOptions {
36    /// Creates settings with no commit ID or message.
37    pub fn new(actor: ActorRef) -> Self {
38        Self {
39            actor,
40            commit_id: None,
41            message: None,
42        }
43    }
44}
45
46/// Options for stating one path.
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct StatPathOptions {
49    /// Project the inode's attribute map and its revision onto the answer.
50    ///
51    /// Defaults to on. A stat answers for one path, and an attribute map is
52    /// capped at 64 KiB, so the cost of including it is bounded by the
53    /// request.
54    pub include_attributes: bool,
55}
56
57impl Default for StatPathOptions {
58    fn default() -> Self {
59        Self {
60            include_attributes: true,
61        }
62    }
63}
64
65/// Options for listing a directory.
66#[derive(Debug, Clone, PartialEq, Eq, Default)]
67pub struct ListPathEntriesOptions {
68    /// Project each entry's attribute map and its revision onto the answer.
69    ///
70    /// Defaults to off, and that default is what bounds a listing: a page
71    /// holds up to 1,000 entries and each attribute map may be 64 KiB, so an
72    /// always-on projection would put a 64 MiB response behind a request that
73    /// declares no byte budget anywhere. A caller that wants attributes for a
74    /// whole directory asks for them, and pages accordingly.
75    pub include_attributes: bool,
76}
77
78/// Options for writing and removing an inode's attributes.
79#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct UpdateAttributesOptions {
81    /// Attributes to write. Each key replaces whatever the inode holds under
82    /// it; keys the inode holds and this map does not name are left alone.
83    pub set: BTreeMap<AttributeKey, AttributeValue>,
84    /// Keys to remove.
85    pub remove: Vec<AttributeKey>,
86    /// Actor, commit ID, and message.
87    pub commit: CommitOptions,
88    /// When set, the update applies only while the path still resolves to
89    /// this inode, so a raced rebinding fails instead of writing attributes
90    /// onto the wrong inode.
91    pub expected_inode_id: Option<InodeId>,
92    /// When set, the update applies only while the inode's attribute revision
93    /// is still this one. Every update carries its own revision guard either
94    /// way, so a concurrent update never merges silently.
95    pub expected_attributes_revision_no: Option<AttributeRevisionNo>,
96}
97
98impl UpdateAttributesOptions {
99    /// Creates an empty attribute update for this actor.
100    pub fn new(actor: ActorRef) -> Self {
101        Self {
102            set: BTreeMap::new(),
103            remove: Vec::new(),
104            commit: CommitOptions::new(actor),
105            expected_inode_id: None,
106            expected_attributes_revision_no: None,
107        }
108    }
109}
110
111/// Options for writing a file path.
112#[derive(Debug, Clone, PartialEq, Eq)]
113pub struct PutFileOptions {
114    /// Create-only or replace-existing behavior.
115    pub behavior: DestinationBehavior,
116    /// Actor, commit ID, and message.
117    pub commit: CommitOptions,
118    /// Replace only while the file's current revision is still this one.
119    /// Requires `Replace` behavior; a raced write fails instead of stacking a
120    /// revision on state the caller never saw.
121    pub expected_revision_no: Option<RevisionNo>,
122}
123
124impl PutFileOptions {
125    /// Creates options that refuse to replace an existing file.
126    pub fn new(actor: ActorRef) -> Self {
127        Self {
128            behavior: DestinationBehavior::NoReplace,
129            commit: CommitOptions::new(actor),
130            expected_revision_no: None,
131        }
132    }
133}
134
135/// Options for creating a directory.
136#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct CreateDirectoryOptions {
138    /// Actor, commit ID, and message.
139    pub commit: CommitOptions,
140    /// Also create missing ancestor directories, like `put_file` does.
141    pub parents: bool,
142}
143
144impl CreateDirectoryOptions {
145    /// Creates options that do not create missing parent directories.
146    pub fn new(actor: ActorRef) -> Self {
147        Self {
148            commit: CommitOptions::new(actor),
149            parents: false,
150        }
151    }
152}
153
154/// Options for deleting a path.
155#[derive(Debug, Clone, PartialEq, Eq)]
156pub struct DeleteOptions {
157    /// Directory delete behavior.
158    pub behavior: DeleteDirectoryBehavior,
159    /// Actor, commit ID, and message.
160    pub commit: CommitOptions,
161    /// When set, the delete applies only while the path still resolves to
162    /// this inode, so a raced rebinding fails instead of deleting the wrong
163    /// inode.
164    pub expected_inode_id: Option<InodeId>,
165}
166
167impl DeleteOptions {
168    /// Creates options for a non-recursive delete.
169    pub fn new(actor: ActorRef) -> Self {
170        Self {
171            behavior: DeleteDirectoryBehavior::NonRecursive,
172            commit: CommitOptions::new(actor),
173            expected_inode_id: None,
174        }
175    }
176}
177
178/// Options for moving a path.
179#[derive(Debug, Clone, PartialEq, Eq)]
180pub struct MoveOptions {
181    /// Create-only or replace-existing behavior for the destination.
182    pub behavior: DestinationBehavior,
183    /// Actor, commit ID, and message.
184    pub commit: CommitOptions,
185}
186
187impl MoveOptions {
188    /// Creates options that refuse to replace the destination.
189    pub fn new(actor: ActorRef) -> Self {
190        Self {
191            behavior: DestinationBehavior::NoReplace,
192            commit: CommitOptions::new(actor),
193        }
194    }
195}
196
197/// Options for copying a file path.
198#[derive(Debug, Clone, PartialEq, Eq)]
199pub struct CopyOptions {
200    /// Create-only or replace-existing behavior for the destination.
201    pub behavior: DestinationBehavior,
202    /// Actor, commit ID, and message.
203    pub commit: CommitOptions,
204}
205
206impl CopyOptions {
207    /// Creates options that refuse to replace the destination.
208    pub fn new(actor: ActorRef) -> Self {
209        Self {
210            behavior: DestinationBehavior::NoReplace,
211            commit: CommitOptions::new(actor),
212        }
213    }
214}
215
216/// Options for restoring a file revision by path.
217#[derive(Debug, Clone, PartialEq, Eq)]
218pub struct RestoreRevisionOptions {
219    /// Actor, commit ID, and message.
220    pub commit: CommitOptions,
221}
222
223impl RestoreRevisionOptions {
224    /// Creates restore options for this actor.
225    pub fn new(actor: ActorRef) -> Self {
226        Self {
227            commit: CommitOptions::new(actor),
228        }
229    }
230}
231
232/// Options for recovering a deleted file or subtree.
233#[derive(Debug, Clone, PartialEq, Eq)]
234pub struct UndeleteOptions {
235    /// Actor, commit ID, and message.
236    pub commit: CommitOptions,
237}
238
239impl UndeleteOptions {
240    /// Creates undelete options for this actor.
241    pub fn new(actor: ActorRef) -> Self {
242        Self {
243            commit: CommitOptions::new(actor),
244        }
245    }
246}