std/path
Path, a root and a list of components, never a string, plus Root and PathError - the type behind Path.resolved.
Diese Seite gibt es noch nicht auf Deutsch, deshalb steht sie hier auf Englisch. Zur englischen Seite
Die generierte Referenz von std/path zeigt jede öffentliche Deklaration mit Signatur, Doc-Kommentar und Beispielen.
std/path is Path: a root and the components between its separators, and never a string. joined cannot be given
a root, parent cannot fall off the top, and .. is only ever resolved on purpose, by normalized() or
resolved(inside:). show() is the one text form, always with / regardless of platform. The package is pure value
arithmetic over text - it reads no disk and touches no file system, so whether a Path names a real file is a
question for std/fs.
Import#
use Path, Root, PathError from "std/path"use Path from "std/path"
const module = Path.from "std/path/src/lib.trb"
print "{module.name()} {module.parent()}"
print module.joined(Path.from("deeper"))Declarations#
Path#
type Path with Show, Equals, Hash, Compare {
fn root(): Root?
fn components(): List<String>
fn isAbsolute(): Bool
fn isRelative(): Bool
fn name(): String?
fn extension(): String?
fn nameWithoutExtension(): String?
fn parent(): Self?
fn joined(relative: Self): Self
fn withName(name: String): Self?
fn withExtension(extension: String): Self?
fn startsWith(prefix: Self): Bool
fn relativeTo(base: Self): Self?
fn normalized(): Self
fn resolved(inside: Self): Result<Self, PathError>
fn show(): String
fn compare(other: Self): Ordering
}
extend Path with From<String>A file path: where it starts, and the components between the separators. Path.from(text) builds one and never
fails - there is no text a file system is guaranteed to reject - and show() reads it back with / on every
platform. Path is Equals, Hash and Compare, and all three are lexical and case sensitive everywhere: two paths
that differ only in case are two different values, because whether they name the same file is a question for a file
system and not for this type.
Path is a capsule: both fields are private and neither has a default, so
Path.from is the one way to a value and root() and components() are the two reads. Its conversion pair is
String - Path has From<String> and String has From<Path>, which answers the same text as show() - so
Encode and Decode are derived through that pair and a path in a document is its text.
Every member that is defined for every path answers a value: isAbsolute, isRelative, joined, startsWith,
normalized, show, compare. name, nameWithoutExtension, extension, parent, withName, withExtension
and relativeTo answer an Option, because a root and the empty path have no name and no parent, and two paths on
different roots have nothing in common. resolved(inside:) is the one member that can be refused, and answers a
Result<Path, PathError>.
joined drops the root of its argument, so base.joined(other) always keeps base's root and starts with base's
components, for every other - base.joined(Path.from("/etc/passwd")) is base/etc/passwd and not /etc/passwd.
That does not cover ..: base.joined(Path.from("../../etc")) is text that escapes once it is normalized, which is
what resolved(inside:) guards against instead.
Root#
type Root with Show, Equals, Hash {
case Unix
case Drive(letter: Char)
case Share(server: String, share: String)
fn show(): String
}Where a path starts. A path without one is relative. Unix is / - the root of the file system, and on Windows the
root of the current drive. Drive is one drive with an absolute path on it, its letter always upper case. Share is
a UNC share, //server/share. Windows' drive-relative form (C:foo, "wherever the process last was on drive C") is
per-process state and not a value, so Path.from reads it as absolute on that drive instead of holding a fourth case
for it.
PathError#
type PathError with Show, Error {
case Outside(path: Path, base: Path)
case NoBase(base: Path)
fn show(): String
}What a path operation refuses. resolved(inside:) is the only member of Path that answers this: NoBase where the
base it was given has no root, so "inside" has nothing to be measured against, and Outside where the path, joined
under the base if it is relative or judged on its own if it is absolute, does not start with the base once both are
normalized.
Pitfalls#
- A POSIX file name that literally contains a backslash cannot be named as a
Pathat all. Both/and\separate on every platform, so that the same program behaves the same in every back end and on every platform, andPath.fromis the one way in. Reach such a file throughstd/fswith its text. - Comparison is lexical and case sensitive, on every platform, always.
Path.from("A") == Path.from("a")isfalseeverywhere, including on a case-insensitive mount - a case-insensitive==would make aMap<Path, _>answer differently on two platforms, and it would still be wrong, because case folding is a property of the mount and not of the operating system. resolved(inside:)is lexical: it reads no disk and follows no link. It says the text of a path does not leave a base, not that the file it opens is under that base. A symlink inside the base that points outside it defeats it; closing that gap needs the operating system asked while it opens, which belongs tostd/fs.
Related#
- std/fs - where a path meets the operating system, and where the capability to read or write one lives.
- The standard library - the other packages.