pub struct DocumentFile { /* private fields */ }Expand description
Implementations§
Source§impl DocumentFile
impl DocumentFile
Sourcepub fn open(
path: impl AsRef<Path>,
format_override: Option<Format>,
) -> DocumentResult<DocumentFile>
pub fn open( path: impl AsRef<Path>, format_override: Option<Format>, ) -> DocumentResult<DocumentFile>
Open and parse path.
format_override takes precedence; otherwise the format is detected
from the file extension via Format::detect. Reading is always
allowed — this does not run the mutation guard.
Sourcepub fn open_capped(
path: impl AsRef<Path>,
format_override: Option<Format>,
max_bytes: u64,
) -> DocumentResult<DocumentFile>
pub fn open_capped( path: impl AsRef<Path>, format_override: Option<Format>, max_bytes: u64, ) -> DocumentResult<DocumentFile>
Open and parse path like DocumentFile::open, but reject any
non-regular file and limit the actual read to max_bytes + 1.
Use this over open when reading untrusted or
secret-bearing config, where an unbounded read of an arbitrary path is
a denial-of-service risk. The file is opened exactly once; both metadata
and contents come from that same handle, so replacing or growing the
path cannot bypass the cap.
On unix, Cargo feature libc also opens with O_NONBLOCK, so a special
file such as a FIFO cannot block before metadata rejects it. Without
that feature, the single-handle and byte-cap guarantees still hold, but
opening a special file can block before its type is inspected.
Sourcepub fn open_capped_with_policy(
path: impl AsRef<Path>,
format_override: Option<Format>,
max_bytes: u64,
symlink_policy: SymlinkPolicy,
) -> DocumentResult<DocumentFile>
pub fn open_capped_with_policy( path: impl AsRef<Path>, format_override: Option<Format>, max_bytes: u64, symlink_policy: SymlinkPolicy, ) -> DocumentResult<DocumentFile>
open_capped with an explicit symbolic-link
policy.
SymlinkPolicy::NoFollow requires Cargo feature libc on unix and is
unsupported on other platforms.
Sourcepub fn create_atomic(
path: impl AsRef<Path>,
document: Document,
options: CreateOptions,
) -> DocumentResult<DocumentFile>
pub fn create_atomic( path: impl AsRef<Path>, document: Document, options: CreateOptions, ) -> DocumentResult<DocumentFile>
Safely create and commit a new file-backed document.
Safely create and commit a new file-backed document.
The document must already have passed a supported parser through
Document::parse. Its source is parsed once more before any write,
then written to a private same-directory temporary file, fsynced, and
atomically installed. The default CreateOptions never replaces an
existing path; replacement must be explicitly requested.
The document’s format must match what the path resolves to, so a commit
cannot produce a file open would then reject.
Sourcepub fn ensure_mutable(&self, operation: &str) -> DocumentResult<()>
pub fn ensure_mutable(&self, operation: &str) -> DocumentResult<()>
Preflight-check that this document format is writable and this file is safe to mutate — not a symlink, and on unix not hardlinked — without performing any write.
save runs this same guard before it writes, so
calling it directly is only useful to front-run a separate side effect
with the same guarantee — e.g. a CLI reading a secret from stdin for a
set should refuse an unsafe target before consuming that input.
Source§impl DocumentFile
impl DocumentFile
Sourcepub fn edit<F>(&mut self, edit: F) -> DocumentResult<()>
pub fn edit<F>(&mut self, edit: F) -> DocumentResult<()>
Run edit against the in-memory Document, then commit once with
save. The single-call form of stage-then-save:
closure and pre-install failures reach neither this handle nor disk,
while a successful commit updates both. As with save, a
parent-directory fsync error after installation is commit-uncertain and
callers should reopen the path.
Sourcepub fn edit_and_validate<T>(
&mut self,
edit: impl FnOnce(&mut Document) -> DocumentResult<()>,
) -> DocumentResult<T>where
T: DeserializeOwned,
pub fn edit_and_validate<T>(
&mut self,
edit: impl FnOnce(&mut Document) -> DocumentResult<()>,
) -> DocumentResult<T>where
T: DeserializeOwned,
Transactionally edit, deserialize, and validate the complete document before committing it.
The closure works on a clone. Editing, typed decoding, and every pre-install write failure leave both this handle and the file in their original state. No partial file is observable. If the final parent directory fsync fails after the rename, a complete new file may already be installed even though durability could not be confirmed; reopen the file after that error. On success the decoded model is returned so callers need not deserialize a second time.
Sourcepub fn save(&self) -> DocumentResult<()>
pub fn save(&self) -> DocumentResult<()>
Persist the document — every edit staged since open
— to its path in a single atomic write.
The mutation verbs (set/unset/add/remove) stage their
source-preserving edit in memory and do not touch disk; this is the
one commit point. That lets a caller apply several edits and inspect the
result via value (e.g. deserialize-and-validate)
before any bytes are written, and makes a multi-edit change atomic —
all edits land together or none do.
Methods from Deref<Target = Document>§
Sourcepub fn source(&self) -> &str
pub fn source(&self) -> &str
Borrow the current source text — the original bytes with every
source-preserving edit applied. This is what DocumentFile::save
writes.
Sourcepub fn addressing(&self) -> Addressing<'static>
pub fn addressing(&self) -> Addressing<'static>
How a non-numeric path segment resolves against an array in this
document: whatever its format declares (see Format::array_rule),
with no caller-declared keyed lists.
Use addressing_keyed to add those.
Sourcepub fn addressing_keyed<'a>(
&self,
keyed_lists: &'a [KeyedList<'a>],
) -> Addressing<'a>
pub fn addressing_keyed<'a>( &self, keyed_lists: &'a [KeyedList<'a>], ) -> Addressing<'a>
addressing plus the caller’s keyed lists,
which take precedence over the format rule for the arrays they name.
Sourcepub fn value_at(&self, path: &str) -> DocumentResult<Value>
pub fn value_at(&self, path: &str) -> DocumentResult<Value>
Resolve a dotted path against the parsed document and return the value
at that address.
A non-empty ASCII-decimal segment against an array is an index;
anything else goes through the format’s own rule, so a Markdown document answers
h2.look while a JSON one refuses deps.foo. See
addressing.
Sourcepub fn value_at_typed(
&self,
path: &str,
expected: ValueType,
) -> DocumentResult<Value>
pub fn value_at_typed( &self, path: &str, expected: ValueType, ) -> DocumentResult<Value>
value_at that also asserts the value at path
satisfies expected, returning a DocumentError::TypeMismatch
otherwise.
Sourcepub fn decode<T: DeserializeOwned>(&self) -> DocumentResult<T>
pub fn decode<T: DeserializeOwned>(&self) -> DocumentResult<T>
Deserialize the complete document into a typed serde model.
This is the convenience form of
crate::document::from_value(self.value(), "").
Type errors are returned as content-redactable DocumentError values.
Sourcepub fn set_typed(
&mut self,
key: &str,
raw: Option<&str>,
value_type: ValueType,
) -> DocumentResult<()>
pub fn set_typed( &mut self, key: &str, raw: Option<&str>, value_type: ValueType, ) -> DocumentResult<()>
Sourcepub fn encode(&self) -> DocumentResult<String>
pub fn encode(&self) -> DocumentResult<String>
Re-render the current value in its format via Format::save.
This is a fresh, non-source-preserving render: comments and original
formatting are not retained. Use source after
source-preserving edits to keep the original formatting.
Sourcepub fn set(&mut self, key: &str, value: Value) -> DocumentResult<()>
pub fn set(&mut self, key: &str, value: Value) -> DocumentResult<()>
Set key to the typed value, preserving the rest of the source
document. The edit is staged in memory — call
save to persist it.
Backend capability mirrors crate::document::set_path where the
source editor allows it: the JSON backend replaces an existing value
(scalar or collection) and creates missing intermediate parent objects;
YAML replaces collection blocks while preserving bytes outside the
replaced block; TOML updates arrays, inline tables, and ordinary tables
in place. Arrays of tables are refused because this editor has no
explicit element-identity policy. Backends return
DocumentError::UnsupportedOperation when an edit cannot be expressed
source-preservingly.
Sourcepub fn set_addressed(
&mut self,
key: &str,
value: Value,
addressing: Addressing<'_>,
) -> DocumentResult<()>
pub fn set_addressed( &mut self, key: &str, value: Value, addressing: Addressing<'_>, ) -> DocumentResult<()>
set with the caller’s own addressing, so a path that
names an array element by its content — identities.me.email — can be
written and not merely read.
The address is canonicalized to indices first (see
crate::document::resolve_path); everything below this point, the
source-preserving backends included, sees only identities.0.email.
Sourcepub fn add(
&mut self,
key: &str,
slug: &str,
slug_field: &str,
fields: &[(String, Value)],
) -> DocumentResult<()>
pub fn add( &mut self, key: &str, slug: &str, slug_field: &str, fields: &[(String, Value)], ) -> DocumentResult<()>
Add a new element to the keyed list at key, identified by
slug/slug_field, with the given fields. Preserves the rest of
the source document. An empty key targets the document root when the
root is itself the keyed array.
Only JSON and YAML backends implement a source-preserving
keyed-collection editor today; other formats return
DocumentError::UnsupportedOperation.
Sourcepub fn remove(
&mut self,
key: &str,
slug: &str,
slug_field: &str,
) -> DocumentResult<()>
pub fn remove( &mut self, key: &str, slug: &str, slug_field: &str, ) -> DocumentResult<()>
Remove the element identified by slug/slug_field from the keyed
list at key. Preserves the rest of the source document. An empty
key targets the document root when the root is itself the keyed array.
Only JSON and YAML backends implement a source-preserving
keyed-collection editor today; other formats return
DocumentError::UnsupportedOperation.
Sourcepub fn unset(&mut self, key: &str) -> DocumentResult<bool>
pub fn unset(&mut self, key: &str) -> DocumentResult<bool>
Remove the entry at key entirely, preserving the rest of the source
document. The edit is staged in memory — call
DocumentFile::save to persist it.
Idempotent, like HashSet::remove:
returns Ok(false) when there was nothing at key to remove (nothing
is staged), and Ok(true) when it was removed.
“Nothing there” does not depend on how deep the path is. A missing leaf
and a missing ancestor are the same fact — a.b.c is absent whether
a.b exists or not — so both answer Ok(false). Only a path that is
malformed stays an error: bad syntax, an index into a non-array, or a
segment that tries to traverse through a scalar. Those describe a caller
asking something incoherent, not a document that already lacks the key.
A read-only format is the one case that errors before the idempotent answer: “nothing to remove” would report success for a document this verb can never edit.
A content-addressed segment that matches no element is also an error
(DocumentError::SlugNotFound), not Ok(false). It is not the same
fact as an absent key: the caller named an element and the document has
none by that name, which is how a mistyped slug looks, and answering
“removed nothing, all good” would swallow it.
Sourcepub fn unset_addressed(
&mut self,
key: &str,
addressing: Addressing<'_>,
) -> DocumentResult<bool>
pub fn unset_addressed( &mut self, key: &str, addressing: Addressing<'_>, ) -> DocumentResult<bool>
unset with the caller’s own addressing, so an
element named by its content can be removed and not merely read. See
set_addressed for why the address is
canonicalized before anything below sees it.
Trait Implementations§
Source§impl Clone for DocumentFile
impl Clone for DocumentFile
Source§fn clone(&self) -> DocumentFile
fn clone(&self) -> DocumentFile
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more