Directory
Owns incremental native directory enumeration with explicit errors. TryOpen requires an absolute native path. ReadEntry allocates an owned filename; prior entries survive later advances and owner cleanup. Ordering/snapshot stability is target-defined. Read/close/move require external serialization; mutable task loans retain ownership until completion. Close consumes authority even on failure. Destruction closes synchronously without reporting errors. Consuming cursors transfer this resource, rather than opening a hidden second enumeration or retaining a raw borrowed libc entry. The example below selects the Linux filesystem adapter; other stream providers do not require filesystem support. It performs no filesystem mutation.
Module std.fs
import std.fs;Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.
Directory
pub final class DirectoryOwns incremental native directory enumeration with explicit errors. TryOpen requires an absolute native path. ReadEntry allocates an owned filename; prior entries survive later advances and owner cleanup. Ordering/snapshot stability is target-defined. Read/close/move require external serialization; mutable task loans retain ownership until completion. Close consumes authority even on failure. Destruction closes synchronously without reporting errors. Consuming cursors transfer this resource, rather than opening a hidden second enumeration or retaining a raw borrowed libc entry. The example below selects the Linux filesystem adapter; other stream providers do not require filesystem support. It performs no filesystem mutation.
Example
module example.directory_ownership;
from std.fs import Directory, DirectoryIterator, DirectoryEntry, Path;
from std.iteration import Take;
from std.prelude import Result;
from std.io import IoError;
fn Main() -> i32 {
var Root = {
// Scoped writable carriers end immediately after explicit payload transfer.
var RootCreation = Path.TryCreate("/");
switch RootCreation {
case .Ok { Value = Value: mut Path& } => break move(Value);
case .Err => return 1;
}
};
var Opened = {
var OpenedCreation = Directory.TryOpen(Root.View);
switch OpenedCreation {
case .Ok { Value = Value: mut Directory& } => break move(Value);
case .Err => return 2;
}
};
var Moved = move(Opened);
if !Opened.IsClosed || Moved.IsClosed { return 3; }
var First = {
// Retain the Result's writable payload until its explicit ownership transfer.
var EntryCreation = Moved.ReadEntry();
switch EntryCreation {
case .Ok { Value = Value: mut DirectoryEntry?& } => break move(Value);
case .Err => return 4;
}
};
if Moved.Close() is .Err { Error = _ } { return 5; }
if !Moved.IsClosed || Moved.Close() is .Err { Error = _ } { return 6; }
// A copied native name remains owned after its enumeration is closed.
switch First {
case .Some { Value = Entry: readonly DirectoryEntry& } => { if Entry.Name.IsEmpty { return 7; } switch Entry.Kind { case .Some { Value = _ } => {} case .None => {} } }
case .None => {}
}
switch Moved.ReadEntry() {
case .Err { Error = PatternPayload5054 } => {
switch PatternPayload5054 {
case .Failure { Reason = PatternPayload5055 } if (PatternPayload5055 is .Closed) => {}
default => return 8;
}
}
default => return 8;
}
var Another = {
var AnotherCreation = Directory.TryOpen(Root.View);
switch AnotherCreation {
case .Ok { Value = Value: mut Directory& } => break move(Value);
case .Err => return 9;
}
};
var Cursor = Another.CreateConsumingIterator();
if !Another.IsClosed { return 10; }
// Limit native reads without claiming an enumeration order or fixed size.
var Prefix = Take<Result<DirectoryEntry, IoError>>(move(Cursor), 1);
switch Prefix.Next() {
case .Some { Value = PatternPayload5056 } => {
switch PatternPayload5056 {
case .Ok { Value = Entry: readonly DirectoryEntry& } => { if Entry.Name.IsEmpty { return 11; } }
case .Err { Error = _ } => return 12;
}
}
case .None => {}
}
if Prefix.Next() is .Some { Value = _ } { return 13; }
var Empty = DirectoryIterator();
var EmptyMoved = move(Empty);
if Empty.Next() is .Some { Value = _ } { return 14; }
if EmptyMoved.Next() is .Some { Value = _ } { return 15; }
var Name = {
var NameCreation = Path.TryCreate("owned-component");
switch NameCreation {
case .Ok { Value = Value: mut Path& } => break move(Value);
case .Err => return 16;
}
};
var Entry = DirectoryEntry(move(Name), none);
if !Name.IsEmpty || Entry.Name.IsEmpty || Entry.Kind is .Some { Value = _ } { return 17; }
var Relative = {
var RelativeCreation = Path.TryCreate("relative-directory");
switch RelativeCreation {
case .Ok { Value = Value: mut Path& } => break move(Value);
case .Err => return 18;
}
};
switch Directory.TryOpen(Relative.View) {
case .Err { Error = PatternPayload5057 } => {
switch PatternPayload5057 {
case .Failure { Reason = PatternPayload5058 } if (PatternPayload5058 is .InvalidInput) => {}
default => return 19;
}
}
default => return 19;
}
return 0;
}Directory.init
pub init()Creates a closed allocation-free owner.
Directory.init
pub init(Source: readonly Self&) = delete;Rejects duplicated close authority. Source: Existing owner.
Directory.init
pub init(Source: mut Self&&)Transfers resource without advancing. Source: Owner left closed.
Directory.operator
pub fn operator =(Source: readonly Self&) -> void = delete;Rejects duplicated resource ownership. Source: Existing owner. Return: No runtime result; this assignment is deleted and cannot be invoked.
Directory.operator
pub fn operator =(Source: mut Self&&) -> void = delete;Requires explicit close before replacing resources. Source: Existing owner. Return: No runtime result; this assignment is deleted and cannot be invoked.
Directory.IsClosed
pub IsClosed: bool;Observes closed/moved state without I/O.
Directory.TryOpen
pub static fn TryOpen(mut Path: PathView, Links: LinkPolicy) -> Result<Self, IoError>Opens incremental native enumeration for an absolute path. Path: Borrowed native units used only until return. Links: Final-component policy; NoFollow rejects a directory symlink. Intermediate components resolve normally; this is not a sandbox.
Return: Sole owner or portable path/storage/native failure. Warning: May allocate/block.
Example
module example.link_policy;
from std.process import ProgramInputs;
from std.fs import Path;
from std.fs import File, Directory, PathView;
from std.io import IoError;
from std.prelude import Result;
// Caller owns fixture paths: a two-byte regular file selected through FileLink,
// and a directory selected through DirectoryLink. Each is a final symbolic link.
// Observations retain no path/handle loan after return; no mutation is intended.
fn InspectLinks(FileLink: PathView, DirectoryLink: PathView) -> Result<void, IoError> {
let Link = switch File.ReadMetadataAt(FileLink, .NoFollow) { case .Ok { Value = Value } => Value; case .Err { Error = Error } => return .Err { Error = Error }; };
let Target = switch File.ReadMetadataAt(FileLink, .Follow) { case .Ok { Value = Value } => Value; case .Err { Error = Error } => return .Err { Error = Error }; };
if Link.Kind != .SymbolicLink || Target.Kind != .Regular { return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; }
// Keep an unexpected success writable until its explicit close.
var FileOpenAttempt = File.TryOpen(FileLink, .CreateOrTruncate, .NoFollow);
switch FileOpenAttempt {
case .Err { Error = PatternPayload5018 } => {
switch PatternPayload5018 {
case .Failure { Reason = PatternPayload5019 } if (PatternPayload5019 is .LinkResolutionFailure) => {}
default => { let Error = PatternPayload5018; return .Err { Error = Error }; }
}
}
case .Ok { Value = Value: mut File& } => { var Unexpected = move(Value); switch Unexpected.Close() { case .Ok => {} case .Err { Error = Error } => return .Err { Error = Error }; } return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; }
}
let Preserved = switch File.ReadMetadataAt(FileLink) { case .Ok { Value = Value } => Value; case .Err { Error = Error } => return .Err { Error = Error }; };
let Length = switch Preserved.ByteLength { case .Some { Value = Value } => Value; case .None => return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; };
if Length != 2 { return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; }
var OpenedDirectory = {
// Scoped writable carriers end immediately after explicit payload transfer.
var OpenedDirectoryCreation = Directory.TryOpen(DirectoryLink, .Follow);
switch OpenedDirectoryCreation {
case .Ok { Value = Value: mut Directory& } => break move(Value);
case .Err { Error = Error } => return .Err { Error = Error };
}
};
switch OpenedDirectory.Close() { case .Ok => {} case .Err { Error = Error } => return .Err { Error = Error }; }
// Linux O_DIRECTORY|O_NOFOLLOW may report ENOTDIR instead of ELOOP.
var DirectoryOpenAttempt = Directory.TryOpen(DirectoryLink, .NoFollow);
switch DirectoryOpenAttempt {
case .Err { Error = PatternPayload5020 } => {
switch PatternPayload5020 {
case .Failure { Reason = PatternPayload5021 } if (PatternPayload5021 is .LinkResolutionFailure) => {}
case .Failure { Reason = PatternPayload5022 } if (PatternPayload5022 is .NotFound) => {}
default => { let Error = PatternPayload5020; return .Err { Error = Error }; }
}
}
case .Ok { Value = Value: mut Directory& } => { var Unexpected = move(Value); switch Unexpected.Close() { case .Ok => {} case .Err { Error = Error } => return .Err { Error = Error }; } return .Err { Error = .Failure { Reason = .NativeFailure, Transferred = 0 } }; }
}
return .Ok;
}
// Supply absolute paths to exclusively owned, disposable fixtures as arguments.
fn Main(Inputs: ProgramInputs) -> i32 {
if Inputs.Arguments().Length != 3 { return 20; }
let FilePathText = switch Inputs.Arguments()[1].TryViewUtf8() { case .Some { Value = Text } => break Text; case .None => return 21; };
var FilePath = {
var Creation = Path.TryCreate(FilePathText);
switch Creation { case .Ok { Value = Created: mut Path& } => break move(Created); case .Err => return 22; }
};
let DirectoryPathText = switch Inputs.Arguments()[2].TryViewUtf8() { case .Some { Value = Text } => break Text; case .None => return 21; };
var DirectoryPath = {
var Creation = Path.TryCreate(DirectoryPathText);
switch Creation { case .Ok { Value = Created: mut Path& } => break move(Created); case .Err => return 22; }
};
switch InspectLinks(FilePath.View, DirectoryPath.View) { case .Ok => return 0; case .Err => return 23; }
}Directory.TryOpen
pub static fn TryOpen(mut Path: PathView) -> Result<Self, IoError>Supplies the omitted arguments to TryOpen. Note: Defaults: Links = .Follow. Path: Same input, ownership and lifetime contract as the full operation. Return: The full synchronous operation's owned success value or typed failure.
Directory.ReadEntry
pub fn ReadEntry() -> Result<DirectoryEntry?, IoError>Reads one owned entry, sticky EOF or explicit retryable failure. Return: Optional owned entry, none at EOF, or portable failure. Warning: May allocate/block; previous entries remain valid.
Directory.Close
pub fn Close() -> Result<void, IoError>Consumes close authority on every result, idempotently for closed owners. Return: Portable native close outcome. Warning: May block.
Directory.CreateConsumingIterator
pub fn CreateConsumingIterator() -> DirectoryIteratorTransfers enumeration into a cursor yielding owned result items. Return: Noncopy cursor; this owner becomes closed. First error ends that cursor.
Directory.CreateConsumingAsyncIterator
pub fn CreateConsumingAsyncIterator() -> AsyncDirectoryIteratorTransfers enumeration into a fallible async cursor without scheduling work. Return: Noncopy async cursor; this owner becomes closed.
Directory.TryOpenAsync
pub static async fn TryOpenAsync(mut Path: PathView, mut Token: CancellationToken, Links: LinkPolicy) -> Task<Result<Self, IoError>>Native calls run on bounded workers; pre-cancelled steps leave traversal available for retry. Destruction still performs synchronous cleanup.
Opens enumeration inside the bounded blocking worker callback. Path: Borrowed absolute native units retained through completion. Token: Cooperative cancellation observation. Links: Final-component policy; NoFollow rejects a directory symlink. Intermediate components resolve normally; this is not a sandbox.
Return: Task yielding sole owner or portable admission/native failure. Warning: Native I/O runs on a worker; cancellation cannot undo started open.
Example
module example.async_directory_ownership;
from std.fs import Directory, DirectoryEntry, AsyncDirectoryIterator, Path;
from std.task import Task, CancellationSource;
async fn Main() -> Task<i32> {
var Root = {
// Scoped writable carriers end immediately after explicit payload transfer.
var RootCreation = Path.TryCreate("/");
switch RootCreation {
case .Ok { Value = Value: mut Path& } => break move(Value);
case .Err => return 1;
}
};
var Cancel = {
var CancellationCreation = CancellationSource.TryCreate();
switch CancellationCreation {
case .Ok { Value = Value: mut CancellationSource& } => break move(Value);
case .Err => return 2;
}
};
Cancel.RequestCancellation();
switch await Directory.TryOpenAsync(Root.View, Cancel.Token) {
case .Err { Error = PatternPayload5059 } => {
switch PatternPayload5059 {
case .Failure { Reason = PatternPayload5060 } if (PatternPayload5060 is .Cancelled) => {}
default => return 2;
}
}
default => return 2;
}
var Opened = {
var OpenedCreation = await Directory.TryOpenAsync(Root.View);
switch OpenedCreation {
case .Ok { Value = Value: mut Directory& } => break move(Value);
case .Err => return 3;
}
};
switch await Opened.CloseAsync(Cancel.Token) {
case .Err { Error = PatternPayload5061 } => {
switch PatternPayload5061 {
case .Failure { Reason = PatternPayload5062 } if (PatternPayload5062 is .Cancelled) => {}
default => return 4;
}
}
default => return 4;
}
if Opened.IsClosed { return 5; }
var Cursor = Opened.CreateConsumingAsyncIterator();
if !Opened.IsClosed { return 6; }
// The transferred owner is already closed. Exercise the omitted-token
// entry without consuming an entry from Cursor's live enumeration.
switch await Opened.ReadEntryAsync() {
case .Err { Error = ClosedError } => {
switch ClosedError {
case .Failure { Reason = Reason, Transferred = Count } => {
if Count != 0 { return 17; }
switch Reason {
case .Closed => {}
default => return 17;
}
}
default => return 17;
}
}
default => return 17;
}
switch await Cursor.NextAsync(Cancel.Token) {
case .Err { Error = PatternPayload5063 } => {
switch PatternPayload5063 {
case .Failure { Reason = PatternPayload5064 } if (PatternPayload5064 is .Cancelled) => {}
default => return 7;
}
}
default => return 7;
}
// A rejected step does not latch exhaustion or consume a native entry.
switch await Cursor.NextAsync() {
case .Ok { Value = PatternPayload5065 } => {
switch PatternPayload5065 {
case .Some { Value = Entry: readonly DirectoryEntry& } => { if Entry.Name.IsEmpty { return 8; } }
case .None => {}
}
}
case .Err => return 9;
}
var Moved = move(Cursor);
switch await Cursor.NextAsync() {
case .Ok { Value = PatternPayload5066 } => { switch PatternPayload5066 { case .None => {} default => return 10; } }
default => return 10;
}
var Empty = AsyncDirectoryIterator();
var EmptyMoved = move(Empty);
switch await Empty.NextAsync() {
case .Ok { Value = PatternPayload5067 } => { switch PatternPayload5067 { case .None => {} default => return 11; } }
default => return 11;
}
switch await EmptyMoved.NextAsync() {
case .Ok { Value = PatternPayload5068 } => { switch PatternPayload5068 { case .None => {} default => return 12; } }
default => return 12;
}
var ToClose = {
var ToCloseCreation = await Directory.TryOpenAsync(Root.View);
switch ToCloseCreation {
case .Ok { Value = Value: mut Directory& } => break move(Value);
case .Err => return 13;
}
};
if await ToClose.CloseAsync() is .Err { Error = _ } { return 14; }
if !ToClose.IsClosed { return 15; }
if await ToClose.CloseAsync() is .Err { Error = _ } { return 16; }
return 0;
}Directory.TryOpenAsync
pub static fn TryOpenAsync(mut Path: PathView) -> Task<Result<Self, IoError>>Supplies the omitted arguments to TryOpenAsync. Note: Defaults: Token = CancellationToken(), Links = .Follow. Path: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.
Directory.TryOpenAsync
pub static fn TryOpenAsync(mut Path: PathView, mut Token: CancellationToken) -> Task<Result<Self, IoError>>Supplies the omitted arguments to TryOpenAsync. Note: Defaults: Links = .Follow. Path: Same input, ownership and lifetime contract as the full operation. Token: Same input, ownership and lifetime contract as the full operation. Return: Exact full-operation result; no additional async frame is created.
Directory.ReadEntryAsync
pub async fn ReadEntryAsync(mut Token: CancellationToken) -> Task<Result<DirectoryEntry?, IoError>>Reads one owned entry through bounded worker admission. Token: Cancellation observation checked before callback invocation. Return: Task yielding optional entry/EOF or portable failure. Warning: Receiver cannot move/close while pending; native calls may block a worker.
Directory.ReadEntryAsync
pub fn ReadEntryAsync() -> Task<Result<DirectoryEntry?, IoError>>Supplies the omitted arguments to ReadEntryAsync. Note: Defaults: Token = CancellationToken(). Return: Exact full-operation result; no additional async frame is created.
Directory.CloseAsync
pub async fn CloseAsync(mut Token: CancellationToken) -> Task<Result<void, IoError>>Closes inside a worker, retaining authority if admission fails. Token: Cancellation observation; cannot undo committed native close. Return: Task yielding close outcome or portable admission failure. Warning: Receiver cannot move/read while pending.
Directory.CloseAsync
pub fn CloseAsync() -> Task<Result<void, IoError>>Supplies the omitted arguments to CloseAsync. Note: Defaults: Token = CancellationToken(). Return: Exact full-operation result; no additional async frame is created.