Errors and platform types
Source: runtime/io/types.pep
FileHandle
[Target(!OS(Windows))] type FileHandle = int
The raw operating-system handle of an open file: a POSIX file descriptor.
File.Handle holds one. A valid descriptor is >= 0; a File that is
closed (or was never opened) holds -1. The standard streams are
descriptors 0, 1 and 2. On Windows this is a HANDLE instead.
See also
File
Note
- code that must build for every target should not rely on this being an
int
SocketHandle
[Target(!OS(Windows))] type SocketHandle = int
The raw operating-system handle of a socket: a POSIX file descriptor.
TcpListener, TcpStream and UdpSocket hold one. A valid descriptor
is >= 0; a closed socket holds -1. On Windows this is a SOCKET
instead.
See also
TcpStream
Note
- code that must build for every target should not rely on this being an
int
ErrorCode
[Target(!OS(Windows))] type ErrorCode = int
The raw platform error code carried by IoError.code: a POSIX errno
value such as ENOENT (2). On Windows this is a DWORD from
GetLastError() instead.
The numbers differ between platforms (and a few between Linux and
macOS), so portable code classifies an error with IoError.kind() or
its predicates (is_not_found(), …) rather than comparing codes.
See also
IoError
Mode
[Target(!OS(Windows))] type Mode = uint
File mode bits as reported in Metadata.Permissions: on POSIX the
mode_t permission bits mode & 07777 (the rwx bits for owner, group
and others plus setuid, setgid and sticky; the file-type bits are
removed). On Windows the same field holds FILE_ATTRIBUTE_* bits
instead.
See also
Metadata
FileHandle
[Target(OS(Windows))] type FileHandle = __ptr<void>
The raw operating-system handle of an open file: a Windows HANDLE.
File.Handle holds one. A File that is closed (or was never opened)
holds null; neither null nor INVALID_HANDLE_VALUE (-1) is a valid
handle. The standard streams are the handles from GetStdHandle. On
POSIX this is an int file descriptor instead.
See also
File
Note
- code that must build for every target should not rely on this being a
__ptr<void>
SocketHandle
[Target(OS(Windows))] type SocketHandle = ulong
The raw operating-system handle of a socket: a Winsock SOCKET, an
unsigned pointer-sized integer.
TcpListener, TcpStream and UdpSocket hold one. A closed socket
holds INVALID_SOCKET (all bits set). On POSIX this is an int file
descriptor instead.
See also
TcpStream
Note
- code that must build for every target should not rely on this being a
ulong
ErrorCode
[Target(OS(Windows))] type ErrorCode = uint
The raw platform error code carried by IoError.code: a Windows
DWORD error code from GetLastError(), such as ERROR_FILE_NOT_FOUND
(2). On POSIX this is an errno value instead.
The numbers differ between platforms, so portable code classifies an
error with IoError.kind() or its predicates (is_not_found(), …)
rather than comparing codes.
See also
IoError
Mode
[Target(OS(Windows))] type Mode = uint
File attribute bits as reported in Metadata.Permissions: on Windows the
whole FILE_ATTRIBUTE_* word of the file (FILE_ATTRIBUTE_READONLY is
1, FILE_ATTRIBUTE_DIRECTORY 16, FILE_ATTRIBUTE_REPARSE_POINT 1024,
…). On POSIX the same field holds mode_t permission bits instead.
See also
Metadata
Offset
type Offset = long
A byte position or distance within a file, as taken and returned by the
File.seek* methods: a signed 64-bit integer on every target (off_t on
POSIX, LARGE_INTEGER on Windows), so files larger than 4 GiB work
everywhere.
ErrorKind
enum ErrorKind
The portable kind of an IoError, as IoError.kind() returns it: the
platform’s error code sorted into the cases a program usually handles.
Each case except Other has a matching IoError predicate
(NotFound and is_not_found(), …), whose documentation lists the
codes it covers on each platform. A code that fits none of them, such as
the EIO of a short write or the EBADF of a closed File, is Other.
See also
IoError.kind
Example
import io;
var r = io.File.open(io.Path("settings.txt"));
if (r.is_err()) {
match (r.error().kind()) {
NotFound => { print("no settings file"); }
PermissionDenied => { print("settings file is not readable"); }
else => { print(r.error().message); }
}
}
Cases
NotFound
NotFound
The file, directory or host name does not exist (is_not_found()).
PermissionDenied
PermissionDenied
Access was denied (is_permission_denied()).
AlreadyExists
AlreadyExists
The target already exists (is_already_exists()).
NotADirectory
NotADirectory
A directory was expected but something else was found
(is_not_a_directory()).
IsADirectory
IsADirectory
A file was expected but a directory was found (is_is_a_directory()).
DirectoryNotEmpty
DirectoryNotEmpty
A directory to remove still has entries (is_directory_not_empty()).
InvalidInput
InvalidInput
An argument or the data was invalid (is_invalid_input()).
Interrupted
Interrupted
The operation was interrupted before it finished (is_interrupted()).
ConnectionRefused
ConnectionRefused
Nothing accepted the connection (is_connection_refused()).
ConnectionReset
ConnectionReset
The peer reset, aborted or closed the connection
(is_connection_reset()).
AddressInUse
AddressInUse
Another socket already uses the address (is_address_in_use()).
AddressNotAvailable
AddressNotAvailable
The address cannot be used on this machine
(is_address_not_available()).
TimedOut
TimedOut
The operation timed out (is_timed_out()).
Cancelled
Cancelled
Cancelling the task ended the operation (is_cancelled()).
Other
Other
Any other code, including 0 (no error).
IoError
struct IoError
An I/O failure: the raw platform error code plus a human-readable message.
kind() sorts the code into an ErrorKind, and a predicate per kind
(is_not_found(), is_permission_denied(), …) tests for one of them;
each knows the matching codes on the current platform. Test with those
rather than comparing code against numbers. Failures that Pepper detects
itself (invalid UTF-8, an empty path, a short write, a closed File)
use the platform’s own code for the kind they are (EINVAL /
ERROR_INVALID_PARAMETER for invalid input, ENOENT /
ERROR_FILE_NOT_FOUND for an empty path, …), so the kinds hold
for them too. A short write uses EIO / ERROR_WRITE_FAULT and a closed
File uses EBADF / ERROR_INVALID_HANDLE; those are ErrorKind.Other.
See also
IoResultErrorKind
Example
import io;
var r = io.File.open(io.Path("settings.txt"));
if (r.is_err()) {
if (r.error().is_not_found()) {
print("no settings file");
} else {
print(r.error().message);
}
}
Fields
code
ErrorCode code
The raw platform error code: an errno value on POSIX, a
GetLastError() code on Windows; 0 means no error.
message
String message
A human-readable description: the platform’s text for code
(strerror on POSIX, FormatMessageW on Windows, without its
trailing period and line break), or Pepper’s own text such as
"empty path" for errors it detects itself.
Constructor
IoError()
construct(code: ErrorCode = 0, message: String = "")
Creates an error from a platform code and a message.
The default, IoError(), has code 0 and an empty message; no
predicate holds for it.
Parameters
code— the raw platform error code (errnoon POSIX,GetLastError()on Windows)message— the human-readable description
Static methods
last
static last(): IoError
Captures the calling thread’s last platform error now: errno on
POSIX, GetLastError() on Windows, with the platform’s message for
it.
Call it immediately after the failing system call; any call in between (including one that allocates) may overwrite the code.
Returns
- an error holding the current
errno/GetLastError()code and its message
invalid_input
static invalid_input(message: String): IoError
Makes an error for data or an argument that is not valid, such as a
damaged file a library parses, with the platform’s code for invalid
input, so is_invalid_input() holds.
Parameters
message— what is wrong
Returns
- the error
Example
import io;
var error = io.IoError.invalid_input("data.bin: bad header");
assert(error.is_invalid_input(), "the kind");
Methods
kind
kind(): ErrorKind
Returns the portable kind of the error: code sorted by the codes the
current platform uses for each kind. Each predicate below is
kind() == ErrorKind.X for its kind.
Returns
- the kind of
code;ErrorKind.Otherfor a code that fits no kind, and for 0
Example
import io;
var r = io.File.open(io.Path("missing.txt"));
if (r.is_err() && r.error().kind() == io.ErrorKind.NotFound) {
print("no such file");
}
is_not_found
is_not_found(): bool
Returns whether the error means the file or directory does not exist.
Matches ENOENT on POSIX, and ERROR_FILE_NOT_FOUND or
ERROR_PATH_NOT_FOUND on Windows. An empty path fails with this kind
on POSIX (with the message "empty path"), and in File.open_with
on every platform.
resolve and TcpStream.connect_host fail with this kind too when a
host name has no address.
Returns
- true when a path, or a directory on the way to it, is missing, or a host name has no address
is_permission_denied
is_permission_denied(): bool
Returns whether the operation was refused for lack of permission.
Matches EACCES or EPERM on POSIX, and ERROR_ACCESS_DENIED on
Windows (which Windows also reports for, among others, deleting a
read-only file).
Returns
- true when access was denied
is_already_exists
is_already_exists(): bool
Returns whether the operation failed because its target already
exists, such as Directory.create on an existing path or opening with
create_new.
Matches EEXIST on POSIX, and ERROR_FILE_EXISTS or
ERROR_ALREADY_EXISTS on Windows.
Returns
- true when the target already exists
is_not_a_directory
is_not_a_directory(): bool
Returns whether a path that had to name a directory names something
else, such as Directory.open or Directory.remove on a file (or,
on POSIX, a file used as a directory in the middle of a path).
Matches ENOTDIR on POSIX, and ERROR_DIRECTORY (267, “the directory
name is invalid”) on Windows.
Returns
- true when a directory was expected
is_is_a_directory
is_is_a_directory(): bool
Returns whether an operation that needs a file was given a directory,
such as reading from a directory opened as a File.
Matches EISDIR on POSIX, and ERROR_DIRECTORY_NOT_SUPPORTED on
Windows (which File reads report for a directory handle).
Returns
- true when a directory was given where a file was expected
is_directory_not_empty
is_directory_not_empty(): bool
Returns whether a directory could not be removed because it still has
entries (Directory.remove on a non-empty directory).
Matches ENOTEMPTY on POSIX (39 on Linux, 66 on macOS) and
ERROR_DIR_NOT_EMPTY on Windows.
Returns
- true when the directory is not empty
is_invalid_input
is_invalid_input(): bool
Returns whether an argument was invalid: bad options (such as opening with no access mode), data that is not valid UTF-8 where text was expected, or a malformed path.
Matches EINVAL on POSIX, and ERROR_INVALID_PARAMETER or
ERROR_INVALID_NAME on Windows.
Returns
- true when the input was invalid
is_interrupted
is_interrupted(): bool
Returns whether the operation was interrupted before it finished.
Matches EINTR on POSIX and WSAEINTR on Windows. An aborted
Windows operation (ERROR_OPERATION_ABORTED) is is_cancelled()
instead. The io functions retry interrupted POSIX opens, reads and writes
themselves, so callers rarely see this.
Returns
- true when the operation was interrupted
is_connection_refused
is_connection_refused(): bool
Returns whether a connection attempt was refused: nothing listens on that port (the peer answered with a reset).
Matches ECONNREFUSED on POSIX and WSAECONNREFUSED on Windows.
Returns
- true when the connection was refused
is_connection_reset
is_connection_reset(): bool
Returns whether an established connection was broken by the peer: reset, aborted, or (when writing) already closed.
Matches ECONNRESET, ECONNABORTED or EPIPE on POSIX, and
WSAECONNRESET or WSAECONNABORTED on Windows.
Returns
- true when the connection was reset or closed by the peer
is_address_in_use
is_address_in_use(): bool
Returns whether binding failed because another socket already uses the address and port.
Matches EADDRINUSE on POSIX and WSAEADDRINUSE on Windows.
Returns
- true when the address is in use
is_address_not_available
is_address_not_available(): bool
Returns whether an address cannot be used here: binding to an IP address that is not one of this machine’s, or connecting to port 0.
Matches EADDRNOTAVAIL on POSIX and WSAEADDRNOTAVAIL on Windows.
Returns
- true when the address is not available
is_timed_out
is_timed_out(): bool
Returns whether an operation gave up because the peer did not answer
in time, such as a connection attempt to an unreachable host, or
because an async.timeout scope around it expired.
Matches ETIMEDOUT on POSIX and WSAETIMEDOUT on Windows.
Returns
- true when the operation timed out
is_cancelled
is_cancelled(): bool
Returns whether an operation stopped because the task waiting for it
was cancelled (see async.Task.cancel).
Matches ECANCELED on POSIX, and ERROR_OPERATION_ABORTED or
ERROR_CANCELLED on Windows.
Returns
- true when cancellation ended the operation
IoResult
type IoResult<T> = Result<T, IoError>
The result of an io operation: a value on success, an IoError on
failure. Check is_ok() / is_err() before calling value() or error();
operations that produce nothing return IoResult<void>.
Type parameters
T— the value an operation produces on success
See also
IoError
Example
import io;
var cwd = io.Directory.current();
if (cwd.is_ok()) {
print(cwd.value().to_string());
} else {
print(cwd.error().message);
}