path
The path module provides utilities for working with filesystem paths.
Note that Hare expects paths to be valid UTF-8 strings. If you require the use of non-UTF-8 paths (ideally for only as long as it takes to delete or rename those files), see the low-level functions available from rt::.
Use of the buffer type is recommended for efficient and consistent manipulation of filesystem paths. The path will always be normalized, which is to say that it will not include any of the following:
- Redundant ".." components
- Redundant path separators
- Any "." components, except in the case of "."
Assuming that SEP is '/', "/usr//bin/../bin/./hare/" becomes "/usr/bin/hare" and "../../foo/bar" is unchanged.
Different fs::fs implementations may have different rules for normalizing paths. For use-cases in which this is relevant, fs::resolve should be used instead.
The buffer object includes an array of length MAX, which can be somewhat large; on Linux it's 4095 bytes. You can allocate this on the stack in most cases, but you may prefer to allocate it elsewhere depending on your needs. Functions in this module return too_long if the buffer's capacity would be exceeded.
// Stack allocated
let buf = path::init()!;
// Statically allocated
static let buf = path::buffer { ... };
path::set(&buf)!;
// Heap allocated
let buf = alloc(path::init()!);
defer free(buf);
Index
Types
type buffer = struct {
buf: [MAX]u8,
end: size,
};
type iterator = struct {
cur: []u8,
reverse: bool,
};
Errors
type cant_extend = !void;
type error = !(cant_extend | too_long | not_prefix);
type not_prefix = !void;
type too_long = !void;
Constants
def MAX: size = 4095;
def SEP: u8 = '/';
Functions
fn abs(path: (*buffer | str)) bool;
fn basename(path: const str) const str;
fn dirname(path: const str) const str;
fn init(items: str...) (buffer | error);
fn isroot(path: (*buffer | str)) bool;
fn iter(buf: *buffer) iterator;
fn iterrem(it: *iterator) str;
fn local(path: str) str;
fn nextiter(it: *iterator) (str | done);
fn parent(buf: *const buffer) (str | error);
fn peek(buf: *const buffer) (str | void);
fn peek_ext(buf: *buffer) (str | void);
fn peek_exts(buf: *buffer) (str | void);
fn peekiter(it: *iterator) (str | void);
fn pop(buf: *buffer) (str | void);
fn pop_ext(buf: *buffer) (str | void);
fn pop_exts(buf: *buffer) (str | void);
fn popprefix(buf: *buffer, prefix: str) (str | error);
fn prepend(buf: *buffer, prefix: str...) (str | error);
fn push(buf: *buffer, items: str...) (str | error);
fn push_ext(buf: *buffer, exts: str...) (str | error);
fn riter(buf: *buffer) iterator;
fn set(buf: *buffer, items: str...) (str | error);
fn strerror(e: error) str;
fn string(buf: *buffer) str;
fn trimprefix(buf: *buffer, prefix: str) (str | error);
Types
type buffer
Show undocumented member
type buffer = struct {
buf: [MAX]u8,
end: size,
};
type iterator
Show undocumented member
type iterator = struct {
cur: []u8,
reverse: bool,
};
Errors
type cant_extend
type cant_extend = !void;
Returned when adding an extension if the path is root, or the final path segment consists entirely of dots.
type error
type error = !(cant_extend | too_long | not_prefix);
Represents an error during a path manipulation
type not_prefix
type not_prefix = !void;
Returned when trimprefix receives a prefix that is not present.
type too_long
type too_long = !void;
Returned when a path buffer would have overflowed.
Constants
def MAX
def MAX: size = 4095;
Maximum length of a file path for this platform.
def SEP
def SEP: u8 = '/';
Platform-specific path separator byte.
Functions
fn abs
fn abs(path: (*buffer | str)) bool;
Check if a path is an absolute path.
fn basename
fn basename(path: const str) const str;
A POSIX-compliant implementation of basename. See the POSIX specification for more information. Note that this function does *not* normalize the input. The return value is either borrowed from the input or statically allocated; use strings::dup to extend its lifetime.
fn dirname
fn dirname(path: const str) const str;
A POSIX-compliant implementation of dirname. See the POSIX specification for more information. Note that this function does *not* normalize the input. The return value is either borrowed from the input or statically allocated; use strings::dup to extend its lifetime.
fn init
fn init(items: str...) (buffer | error);
Initializes a new path buffer.
fn isroot
fn isroot(path: (*buffer | str)) bool;
Check if a path is the root directory.
fn iter
fn iter(buf: *buffer) iterator;
Returns an iterator which yields each component of a path, moving down through child dirs. If the path is absolute, the first component will be the root. The iterator can be copied to save its state.
fn iterrem
fn iterrem(it: *iterator) str;
Gets the remaining path from an iterator, without advancing the iterator.
fn local
fn local(path: str) str;
Replaces all instances of '/' in a string with SEP. The result is statically-allocated.
fn nextiter
fn nextiter(it: *iterator) (str | done);
Returns the next path component from an iterator, or done if none remain. Advances the iterator.
fn parent
fn parent(buf: *const buffer) (str | error);
Returns the parent directory for a given path, without modifying the buffer. If the path is the root directory, the root directory is returned. The value is either borrowed from the input or statically allocated; use strings::dup to extend its lifetime or modify it.
fn peek
fn peek(buf: *const buffer) (str | void);
Examine the final path segment in a buffer. Returns void if the path is empty or is the root dir.
fn peek_ext
fn peek_ext(buf: *buffer) (str | void);
Examine the final extension in a path. The result will not include the leading '.'. The result is borrowed from the buffer. Leading dots will be ignored when looking for extensions, such that ".ssh" isn't considered to have any extensions.
fn peek_exts
fn peek_exts(buf: *buffer) (str | void);
Examine all the extensions in a path. The result will not include the leading '.', but will include separating dots. Leading dots will be ignored when looking for extensions, such that ".ssh" isn't considered to have any extensions. The result is borrowed from the buffer.
fn peekiter
fn peekiter(it: *iterator) (str | void);
Returns the next path component from an iterator, or void if none remain. Does not advance the iterator.
fn pop
fn pop(buf: *buffer) (str | void);
Remove and return the final path segment in a buffer. Returns void if the path is empty or is the root dir.
fn pop_ext
fn pop_ext(buf: *buffer) (str | void);
Remove and return the final extension in a path. The result will not include the leading '.'. The result is borrowed from the buffer. Leading dots will be ignored when looking for extensions, such that ".ssh" isn't considered to have any extensions.
fn pop_exts
fn pop_exts(buf: *buffer) (str | void);
Remove and return all the extensions in a path. The result will not include the leading '.', but will include separating dots. Leading dots will be ignored when looking for extensions, such that ".ssh" isn't considered to have any extensions. The result is borrowed from the buffer.
fn popprefix
fn popprefix(buf: *buffer, prefix: str) (str | error);
Equivalent to trimprefix, but modifies the buffer in the process.
fn prepend
fn prepend(buf: *buffer, prefix: str...) (str | error);
Add a prefix to a buffer. The buffer will be modified, and it will remain normalized, so any ".." components in the original buffer may be collapsed.
fn push
fn push(buf: *buffer, items: str...) (str | error);
Appends path elements onto the end of a path buffer. Returns the new string value of the path.
fn push_ext
fn push_ext(buf: *buffer, exts: str...) (str | error);
Add extensions onto the end of the final path segment. The separating '.' will be inserted for you. If the final path segment consists entirely of dots or the path is root, this function will return cant_extend.
fn riter
fn riter(buf: *buffer) iterator;
Returns an iterator which yields each component of a path, moving up through parent dirs. If the path is absolute, the last component will be the root. The iterator can be copied to save its state.
fn set
fn set(buf: *buffer, items: str...) (str | error);
Sets the value of a path buffer to a list of components, overwriting any previous value. Returns the new string value of the path.
fn strerror
fn strerror(e: error) str;
Convert an error into a descriptive string.
fn string
fn string(buf: *buffer) str;
Returns the current path stored in this buffer. The return value is borrowed from the buffer. Use strings::dup to extend the lifetime of the string.
fn trimprefix
fn trimprefix(buf: *buffer, prefix: str) (str | error);
Returns a buffer without a prefix. The prefix is normalized before processing, and this function will return too_long if the prefix is longer than MAX. If the prefix is not present, returns not_prefix. The resulting path will always be relative.
This function does not modify the buffer. See popprefix.