std.fmt: breaking API changes
added adapter to AnyWriter and GenericWriter to help bridge the gap
between old and new API
make std.testing.expectFmt work at compile-time
std.fmt no longer has a dependency on std.unicode. Formatted printing
was never properly unicode-aware. Now it no longer pretends to be.
Breakage/deprecations:
* std.fs.File.reader -> std.fs.File.deprecatedReader
* std.fs.File.writer -> std.fs.File.deprecatedWriter
* std.io.GenericReader -> std.io.Reader
* std.io.GenericWriter -> std.io.Writer
* std.io.AnyReader -> std.io.Reader
* std.io.AnyWriter -> std.io.Writer
* std.fmt.format -> std.fmt.deprecatedFormat
* std.fmt.fmtSliceEscapeLower -> std.ascii.hexEscape
* std.fmt.fmtSliceEscapeUpper -> std.ascii.hexEscape
* std.fmt.fmtSliceHexLower -> {x}
* std.fmt.fmtSliceHexUpper -> {X}
* std.fmt.fmtIntSizeDec -> {B}
* std.fmt.fmtIntSizeBin -> {Bi}
* std.fmt.fmtDuration -> {D}
* std.fmt.fmtDurationSigned -> {D}
* {} -> {f} when there is a format method
* format method signature
- anytype -> *std.io.Writer
- inferred error set -> error{WriteFailed}
- options -> (deleted)
* std.fmt.Formatted
- now takes context type explicitly
- no fmt string
This commit is contained in:
@@ -9420,4 +9420,132 @@ pub const msghdr_const = extern struct {
|
||||
control: ?*const anyopaque,
|
||||
controllen: usize,
|
||||
flags: u32,
|
||||
};
|
||||
};
|
||||
|
||||
/// The syscalls, but with Zig error sets, going through libc if linking libc,
|
||||
/// and with some footguns eliminated.
|
||||
pub const wrapped = struct {
|
||||
pub const lfs64_abi = builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid());
|
||||
const system = if (builtin.link_libc) std.c else std.os.linux;
|
||||
|
||||
pub const SendfileError = std.posix.UnexpectedError || error{
|
||||
/// `out_fd` is an unconnected socket, or out_fd closed its read end.
|
||||
BrokenPipe,
|
||||
/// Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd.
|
||||
UnsupportedOperation,
|
||||
/// Nonblocking I/O has been selected but the write would block.
|
||||
WouldBlock,
|
||||
/// Unspecified error while reading from in_fd.
|
||||
InputOutput,
|
||||
/// Insufficient kernel memory to read from in_fd.
|
||||
SystemResources,
|
||||
/// `offset` is not `null` but the input file is not seekable.
|
||||
Unseekable,
|
||||
};
|
||||
|
||||
pub fn sendfile(
|
||||
out_fd: fd_t,
|
||||
in_fd: fd_t,
|
||||
in_offset: ?*off_t,
|
||||
in_len: usize,
|
||||
) SendfileError!usize {
|
||||
const adjusted_len = @min(in_len, 0x7ffff000); // Prevents EOVERFLOW.
|
||||
const sendfileSymbol = if (lfs64_abi) system.sendfile64 else system.sendfile;
|
||||
const rc = sendfileSymbol(out_fd, in_fd, in_offset, adjusted_len);
|
||||
switch (errno(rc)) {
|
||||
.SUCCESS => return @intCast(rc),
|
||||
.BADF => return invalidApiUsage(), // Always a race condition.
|
||||
.FAULT => return invalidApiUsage(), // Segmentation fault.
|
||||
.OVERFLOW => return unexpectedErrno(.OVERFLOW), // We avoid passing too large of a `count`.
|
||||
.NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
|
||||
.INVAL => return error.UnsupportedOperation,
|
||||
.AGAIN => return error.WouldBlock,
|
||||
.IO => return error.InputOutput,
|
||||
.PIPE => return error.BrokenPipe,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.NXIO => return error.Unseekable,
|
||||
.SPIPE => return error.Unseekable,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
|
||||
pub const CopyFileRangeError = std.posix.UnexpectedError || error{
|
||||
/// One of:
|
||||
/// * One or more file descriptors are not valid.
|
||||
/// * fd_in is not open for reading; or fd_out is not open for writing.
|
||||
/// * The O_APPEND flag is set for the open file description referred
|
||||
/// to by the file descriptor fd_out.
|
||||
BadFileFlags,
|
||||
/// One of:
|
||||
/// * An attempt was made to write at a position past the maximum file
|
||||
/// offset the kernel supports.
|
||||
/// * An attempt was made to write a range that exceeds the allowed
|
||||
/// maximum file size. The maximum file size differs between
|
||||
/// filesystem implementations and can be different from the maximum
|
||||
/// allowed file offset.
|
||||
/// * An attempt was made to write beyond the process's file size
|
||||
/// resource limit. This may also result in the process receiving a
|
||||
/// SIGXFSZ signal.
|
||||
FileTooBig,
|
||||
/// One of:
|
||||
/// * either fd_in or fd_out is not a regular file
|
||||
/// * flags argument is not zero
|
||||
/// * fd_in and fd_out refer to the same file and the source and target ranges overlap.
|
||||
InvalidArguments,
|
||||
/// A low-level I/O error occurred while copying.
|
||||
InputOutput,
|
||||
/// Either fd_in or fd_out refers to a directory.
|
||||
IsDir,
|
||||
OutOfMemory,
|
||||
/// There is not enough space on the target filesystem to complete the copy.
|
||||
NoSpaceLeft,
|
||||
/// (since Linux 5.19) the filesystem does not support this operation.
|
||||
OperationNotSupported,
|
||||
/// The requested source or destination range is too large to represent
|
||||
/// in the specified data types.
|
||||
Overflow,
|
||||
/// fd_out refers to an immutable file.
|
||||
PermissionDenied,
|
||||
/// Either fd_in or fd_out refers to an active swap file.
|
||||
SwapFile,
|
||||
/// The files referred to by fd_in and fd_out are not on the same
|
||||
/// filesystem, and the source and target filesystems are not of the
|
||||
/// same type, or do not support cross-filesystem copy.
|
||||
NotSameFileSystem,
|
||||
};
|
||||
|
||||
pub fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_out: ?*i64, len: usize, flags: u32) CopyFileRangeError!usize {
|
||||
const rc = system.copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
|
||||
switch (errno(rc)) {
|
||||
.SUCCESS => return @intCast(rc),
|
||||
.BADF => return error.BadFileFlags,
|
||||
.FBIG => return error.FileTooBig,
|
||||
.INVAL => return error.InvalidArguments,
|
||||
.IO => return error.InputOutput,
|
||||
.ISDIR => return error.IsDir,
|
||||
.NOMEM => return error.OutOfMemory,
|
||||
.NOSPC => return error.NoSpaceLeft,
|
||||
.OPNOTSUPP => return error.OperationNotSupported,
|
||||
.OVERFLOW => return error.Overflow,
|
||||
.PERM => return error.PermissionDenied,
|
||||
.TXTBSY => return error.SwapFile,
|
||||
.XDEV => return error.NotSameFileSystem,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
|
||||
const unexpectedErrno = std.posix.unexpectedErrno;
|
||||
|
||||
fn invalidApiUsage() error{Unexpected} {
|
||||
if (builtin.mode == .Debug) @panic("invalid API usage");
|
||||
return error.Unexpected;
|
||||
}
|
||||
|
||||
fn errno(rc: anytype) E {
|
||||
if (builtin.link_libc) {
|
||||
return if (rc == -1) @enumFromInt(std.c._errno().*) else .SUCCESS;
|
||||
} else {
|
||||
return errnoFromSyscall(rc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user