File: File.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (116 lines) | stat: -rw-r--r-- 3,896 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import Foundation
import SystemPackage

protocol FdWASIEntry: WASIEntry {
    var fd: FileDescriptor { get }
}

protocol FdWASIFile: WASIFile, FdWASIEntry {
    var accessMode: FileAccessMode { get }
}

extension FdWASIFile {
    func fdStat() throws -> WASIAbi.FdStat {
        var fsRightsBase: WASIAbi.Rights = []
        if accessMode.contains(.read) {
            fsRightsBase.insert(.FD_READ)
        }
        if accessMode.contains(.write) {
            fsRightsBase.insert(.FD_WRITE)
        }
        return try WASIAbi.FdStat(
            fsFileType: self.fileType(),
            fsFlags: self.status(),
            fsRightsBase: fsRightsBase, fsRightsInheriting: []
        )
    }

    @inlinable
    func write<Buffer: Sequence>(vectored buffer: Buffer) throws -> WASIAbi.Size where Buffer.Element == WASIAbi.IOVec {
        guard accessMode.contains(.write) else {
            throw WASIAbi.Errno.EBADF
        }
        // TODO: Use `writev`
        let handle = FileHandle(fileDescriptor: fd.rawValue)
        var bytesWritten: UInt32 = 0
        for iovec in buffer {
            try iovec.withHostBufferPointer {
                try handle.write(contentsOf: $0)
            }
            bytesWritten += iovec.length
        }
        return bytesWritten
    }

    @inlinable
    func pwrite<Buffer: Sequence>(vectored buffer: Buffer, offset: WASIAbi.FileSize) throws -> WASIAbi.Size where Buffer.Element == WASIAbi.IOVec {
        // TODO: Use `pwritev`
        let handle = FileHandle(fileDescriptor: fd.rawValue)
        let savedOffset = try handle.offset()
        try handle.seek(toOffset: offset)
        let nwritten = try write(vectored: buffer)
        try handle.seek(toOffset: savedOffset)
        return nwritten
    }

    @inlinable
    func read<Buffer: Sequence>(into buffer: Buffer) throws -> WASIAbi.Size where Buffer.Element == WASIAbi.IOVec {
        // TODO: Use `readv`
        let handle = FileHandle(fileDescriptor: fd.rawValue)
        var nread: UInt32 = 0
        for iovec in buffer {
            try iovec.buffer.withHostPointer { rawBufferStart in
                var bufferStart = rawBufferStart.bindMemory(
                    to: UInt8.self, capacity: Int(iovec.length)
                )
                let bufferEnd = bufferStart + Int(iovec.length)
                while bufferStart < bufferEnd {
                    let remaining = bufferEnd - bufferStart
                    guard let bytes = try handle.read(upToCount: remaining) else {
                        break
                    }
                    bytes.copyBytes(to: bufferStart, count: bytes.count)
                    bufferStart += bytes.count
                }
                nread += iovec.length - UInt32(bufferEnd - bufferStart)
            }
        }
        return nread
    }

    @inlinable
    func pread<Buffer: Sequence>(into buffer: Buffer, offset: WASIAbi.FileSize) throws -> WASIAbi.Size where Buffer.Element == WASIAbi.IOVec {
        // TODO: Use `preadv`
        let handle = FileHandle(fileDescriptor: fd.rawValue)
        let savedOffset = try handle.offset()
        try handle.seek(toOffset: offset)
        let nread = try read(into: buffer)
        try handle.seek(toOffset: savedOffset)
        return nread
    }
}

struct RegularFileEntry: FdWASIFile {
    let fd: FileDescriptor
    let accessMode: FileAccessMode
}

extension FdWASIFile {
    func setFdStatFlags(_ flags: WASIAbi.Fdflags) throws {
        try WASIAbi.Errno.translatingPlatformErrno {
            try fd.setStatus(flags.platformOpenOptions)
        }
    }
}

struct StdioFileEntry: FdWASIFile {
    let fd: FileDescriptor
    let accessMode: FileAccessMode

    func attributes() throws -> WASIAbi.Filestat {
        return WASIAbi.Filestat(
            dev: 0, ino: 0, filetype: .CHARACTER_DEVICE,
            nlink: 0, size: 0, atim: 0, mtim: 0, ctim: 0
        )
    }
}