File: OpenWritableFile.swift

package info (click to toggle)
swiftlang 6.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 2,791,532 kB
  • sloc: cpp: 9,901,743; ansic: 2,201,431; asm: 1,091,827; python: 308,252; objc: 82,166; f90: 80,126; lisp: 38,358; pascal: 25,559; sh: 20,429; ml: 5,058; perl: 4,745; makefile: 4,484; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (79 lines) | stat: -rw-r--r-- 2,917 bytes parent folder | download | duplicates (2)
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
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

internal import class Dispatch.DispatchQueue
@preconcurrency internal import struct SystemPackage.FileDescriptor
internal import struct SystemPackage.FilePath

/// A write-only thread-safe handle to an open file.
package actor OpenWritableFile: WritableStream {
    /// Underlying storage for this file handle, dependent on the file system type that produced it.
    enum Storage {
        /// Operating system file descriptor and a queue used for reading from that file descriptor without blocking
        /// the Swift Concurrency thread pool.
        case real(FileDescriptor, DispatchQueue)
        
        /// Reference to the ``MockFileSystem`` actor that provides file storage.
        case mock(MockFileSystem)
    }
    
    /// Concrete instance of underlying storage.
    let storage: Storage

    /// Absolute path to the file represented by this file handle.
    let path: FilePath

    /// Whether the underlying file descriptor has been closed.
    private var isClosed = false
    
    /// Creates a new write-only file handle.
    /// - Parameters:
    ///   - storage: Underlying storage for the file.
    ///   - path: Absolute path to the file on the file system that provides `storage`.
    init(storage: OpenWritableFile.Storage, path: FilePath) {
        self.storage = storage
        self.path = path
    }
    
    /// Writes a sequence of bytes to the buffer.
    package func write(_ bytes: some Collection<UInt8> & Sendable) async throws {
        assert(!isClosed)
        switch self.storage {
        case let .real(fileDescriptor, queue):
            let path = self.path
            try await queue.scheduleOnQueue {
                do {
                    let writtenBytesCount = try fileDescriptor.writeAll(bytes)
                    assert(bytes.count == writtenBytesCount)
                } catch {
                    throw error.attach(path)
                }
            }
        case let .mock(storage):
            await storage.write(path: self.path, bytes: bytes)
        }
    }

    /// Closes the underlying stream handle. It is a programmer error to write to a stream after it's closed.
    package func close() async throws {
        isClosed = true

        guard case let .real(fileDescriptor, queue) = self.storage else {
            return
        }

        try await queue.scheduleOnQueue {
            try fileDescriptor.close()
        }
    }
}