Coverage Report

Created: 2025-09-08 06:42

/src/swift-nio/Sources/NIOCore/IOData.swift
Line
Count
Source (jump to first uncovered line)
1
//===----------------------------------------------------------------------===//
2
//
3
// This source file is part of the SwiftNIO open source project
4
//
5
// Copyright (c) 2017-2024 Apple Inc. and the SwiftNIO project authors
6
// Licensed under Apache License v2.0
7
//
8
// See LICENSE.txt for license information
9
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
10
//
11
// SPDX-License-Identifier: Apache-2.0
12
//
13
//===----------------------------------------------------------------------===//
14
15
/// `IOData` unifies standard SwiftNIO types that are raw bytes of data; currently `ByteBuffer` and `FileRegion`.
16
///
17
/// - warning: `IOData` is a legacy API, please avoid using it as much as possible.
18
///
19
/// Many `ChannelHandler`s receive or emit bytes and in most cases this can be either a `ByteBuffer` or a `FileRegion`
20
/// from disk. To still form a well-typed `ChannelPipeline` such handlers should receive and emit value of type `IOData`.
21
public enum IOData: Sendable {
22
    /// A `ByteBuffer`.
23
    case byteBuffer(ByteBuffer)
24
25
    /// A `FileRegion`.
26
    ///
27
    /// - warning: `IOData.fileRegion` is a legacy API, please avoid using it. It cannot work with TLS and `FileRegion`
28
    ///            and the underlying `NIOFileHandle` objects are very difficult to hold correctly.
29
    ///
30
    /// Sending a `FileRegion` through the `ChannelPipeline` using `write` can be useful because some `Channel`s can
31
    /// use `sendfile` to send a `FileRegion` more efficiently.
32
    case fileRegion(FileRegion)
33
}
34
35
/// `IOData` objects are comparable just like the values they wrap.
36
extension IOData: Equatable {}
37
38
/// `IOData` provide a number of readable bytes.
39
extension IOData {
40
    /// Returns the number of readable bytes in this `IOData`.
41
0
    public var readableBytes: Int {
42
0
        switch self {
43
0
        case .byteBuffer(let buf):
44
0
            return buf.readableBytes
45
0
        case .fileRegion(let region):
46
0
            return region.readableBytes
47
0
        }
48
0
    }
49
50
    /// Move the readerIndex forward by `offset`.
51
0
    public mutating func moveReaderIndex(forwardBy: Int) {
52
0
        switch self {
53
0
        case .byteBuffer(var buffer):
54
0
            buffer.moveReaderIndex(forwardBy: forwardBy)
55
0
            self = .byteBuffer(buffer)
56
0
        case .fileRegion(var fileRegion):
57
0
            fileRegion.moveReaderIndex(forwardBy: forwardBy)
58
0
            self = .fileRegion(fileRegion)
59
0
        }
60
0
    }
61
}
62
63
extension IOData: CustomStringConvertible {
64
0
    public var description: String {
65
0
        switch self {
66
0
        case .byteBuffer(let byteBuffer):
67
0
            return "IOData { \(byteBuffer) }"
68
0
        case .fileRegion(let fileRegion):
69
0
            return "IOData { \(fileRegion) }"
70
0
        }
71
0
    }
72
}