Coverage Report

Created: 2026-02-14 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/swift-protobuf/Sources/SwiftProtobuf/BinaryEncoder.swift
Line
Count
Source
1
// Sources/SwiftProtobuf/BinaryEncoder.swift - Binary encoding support
2
//
3
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
4
// Licensed under Apache License v2.0 with Runtime Library Exception
5
//
6
// See LICENSE.txt for license information:
7
// https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
8
//
9
// -----------------------------------------------------------------------------
10
///
11
/// Core support for protobuf binary encoding.  Note that this is built
12
/// on the general traversal machinery.
13
///
14
// -----------------------------------------------------------------------------
15
16
import Foundation
17
18
/// Encoder for Binary Protocol Buffer format
19
internal struct BinaryEncoder {
20
    private var pointer: UnsafeMutableRawPointer
21
    private var buffer: UnsafeMutableRawBufferPointer
22
23
5.40M
    init(forWritingInto buffer: UnsafeMutableRawBufferPointer) {
24
5.40M
        self.buffer = buffer
25
5.40M
        self.pointer = buffer.baseAddress!
26
5.40M
    }
27
28
2.18G
    private mutating func append(_ byte: UInt8) {
29
2.18G
        pointer.storeBytes(of: byte, as: UInt8.self)
30
2.18G
        pointer = pointer.advanced(by: 1)
31
2.18G
    }
32
33
2.39M
    private mutating func append<Bytes: SwiftProtobufContiguousBytes>(contentsOf bytes: Bytes) {
34
2.39M
        bytes.withUnsafeBytes { dataPointer in
35
2.39M
            if let baseAddress = dataPointer.baseAddress, dataPointer.count > 0 {
36
2.04M
                pointer.copyMemory(from: baseAddress, byteCount: dataPointer.count)
37
2.04M
                advance(dataPointer.count)
38
2.04M
            }
39
2.39M
        }
40
2.39M
    }
41
42
48.6k
    internal var used: Int {
43
48.6k
        buffer.baseAddress!.distance(to: pointer)
44
48.6k
    }
45
46
6.08k
    internal var remainder: UnsafeMutableRawBufferPointer {
47
6.08k
        UnsafeMutableRawBufferPointer(
48
6.08k
            start: pointer,
49
6.08k
            count: buffer.count - used
50
6.08k
        )
51
6.08k
    }
52
53
4.25M
    internal mutating func advance(_ bytes: Int) {
54
4.25M
        pointer = pointer.advanced(by: bytes)
55
4.25M
    }
56
57
    @discardableResult
58
527k
    private mutating func append(contentsOf bufferPointer: UnsafeRawBufferPointer) -> Int {
59
527k
        let count = bufferPointer.count
60
527k
        if let baseAddress = bufferPointer.baseAddress, count > 0 {
61
152k
            pointer.copyMemory(from: baseAddress, byteCount: count)
62
152k
        }
63
527k
        pointer = pointer.advanced(by: count)
64
527k
        return count
65
527k
    }
66
67
337k
    mutating func appendUnknown(data: Data) {
68
337k
        append(contentsOf: data)
69
337k
    }
70
71
171M
    mutating func startField(fieldNumber: Int, wireFormat: WireFormat) {
72
171M
        startField(tag: FieldTag(fieldNumber: fieldNumber, wireFormat: wireFormat))
73
171M
    }
74
75
306M
    mutating func startField(tag: FieldTag) {
76
306M
        putVarInt(value: UInt64(tag.rawValue))
77
306M
    }
78
79
1.58G
    mutating func putVarInt(value: UInt64) {
80
1.58G
        var v = value
81
2.17G
        while v > 127 {
82
589M
            append(UInt8(v & 0x7f | 0x80))
83
589M
            v >>= 7
84
1.58G
        }
85
1.58G
        append(UInt8(v))
86
1.58G
    }
87
88
636M
    mutating func putVarInt(value: Int64) {
89
636M
        putVarInt(value: UInt64(bitPattern: value))
90
636M
    }
91
92
146M
    mutating func putVarInt(value: Int) {
93
146M
        putVarInt(value: Int64(value))
94
146M
    }
95
96
1.58M
    mutating func putZigZagVarInt(value: Int64) {
97
1.58M
        let coded = ZigZag.encoded(value)
98
1.58M
        putVarInt(value: coded)
99
1.58M
    }
100
101
0
    mutating func putBoolValue(value: Bool) {
102
0
        append(value ? 1 : 0)
103
0
    }
104
105
9.52M
    mutating func putFixedUInt64(value: UInt64) {
106
9.52M
        var v = value.littleEndian
107
9.52M
        let n = MemoryLayout<UInt64>.size
108
9.52M
        pointer.copyMemory(from: &v, byteCount: n)
109
9.52M
        pointer = pointer.advanced(by: n)
110
9.52M
    }
111
112
9.72M
    mutating func putFixedUInt32(value: UInt32) {
113
9.72M
        var v = value.littleEndian
114
9.72M
        let n = MemoryLayout<UInt32>.size
115
9.72M
        pointer.copyMemory(from: &v, byteCount: n)
116
9.72M
        pointer = pointer.advanced(by: n)
117
9.72M
    }
118
119
3.61M
    mutating func putFloatValue(value: Float) {
120
3.61M
        let n = MemoryLayout<Float>.size
121
3.61M
        var v = value.bitPattern.littleEndian
122
3.61M
        pointer.copyMemory(from: &v, byteCount: n)
123
3.61M
        pointer = pointer.advanced(by: n)
124
3.61M
    }
125
126
3.20M
    mutating func putDoubleValue(value: Double) {
127
3.20M
        let n = MemoryLayout<Double>.size
128
3.20M
        var v = value.bitPattern.littleEndian
129
3.20M
        pointer.copyMemory(from: &v, byteCount: n)
130
3.20M
        pointer = pointer.advanced(by: n)
131
3.20M
    }
132
133
    // Write a string field, including the leading index/tag value.
134
469k
    mutating func putStringValue(value: String) {
135
469k
        let utf8 = value.utf8
136
469k
        // If the String does not support an internal representation in a form
137
469k
        // of contiguous storage, body is not called and nil is returned.
138
527k
        let isAvailable = utf8.withContiguousStorageIfAvailable { (body: UnsafeBufferPointer<UInt8>) -> Int in
139
527k
            putVarInt(value: body.count)
140
527k
            return append(contentsOf: UnsafeRawBufferPointer(body))
141
527k
        }
142
469k
        if isAvailable == nil {
143
0
            let count = utf8.count
144
0
            putVarInt(value: count)
145
0
            for b in utf8 {
146
0
                pointer.storeBytes(of: b, as: UInt8.self)
147
0
                pointer = pointer.advanced(by: 1)
148
0
            }
149
0
        }
150
469k
    }
151
152
3.39M
    mutating func putBytesValue<Bytes: SwiftProtobufContiguousBytes>(value: Bytes) {
153
3.39M
        putVarInt(value: value.count)
154
3.39M
        append(contentsOf: value)
155
3.39M
    }
156
}