Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions Sources/SwiftNetwork/Protocols/Frame.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,34 @@ public struct Frame: ~Copyable {
case customFinalizer(buffer: UnsafeMutableRawBufferPointer, finalizer: (UnsafeMutableRawBufferPointer) -> Void)
}

public var buffer: Buffer

var _bytes: NetworkUniqueArray<UInt8> = .init()
var protocolMetadatas: NetworkUniqueDeque<FrameProtocolMetadata> = .init(minimumCapacity: 0)
var ipPacketValues: IPPacketValues? = nil
public var buffer: Buffer
var appMetadata: AppMetadata? = nil

private var _startOffset: UInt32 = 0

var timestamp: FrameTimestamp? = nil
var flags: Flags = Flags()
var _metadataComplete: Bool = false
public var connectionComplete: Bool = false
private var _endOffset: UInt32 = 0
private var _effectiveBufferLength: UInt32 = 0
private var _aggregateBufferLength: UInt32 = 0

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So because of the out of order arrangement of these properties extra padding was being added, is that what was happening?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was the order the properties were in: Swift lays out types in the order they're declared in.

As an example the Buffer enum was stored first and is 33 bytes in size with an 8 byte alignment. It was followed by a NetworkUniqueArray<UInt8> which is 24 bytes (also 8 byte alignment). Because of the alignment there's 7 bytes of padding between the two, instead you can move smaller types (e.g. 7 booleans) into that space that would otherwise be padding.


@usableFromInline var startOffset: Int {
get { Int(_startOffset) }
set { _startOffset = UInt32(newValue) }
}
private var _endOffset: UInt32 = 0
@usableFromInline var endOffset: Int {
get { Int(_endOffset) }
set { _endOffset = UInt32(newValue) }
}
private var _effectiveBufferLength: UInt32 = 0
var effectiveBufferLength: Int {
get { Int(_effectiveBufferLength) }
set { _effectiveBufferLength = UInt32(newValue) }
}
private var _aggregateBufferLength: UInt32 = 0
var aggregateBufferLength: Int {
get { Int(_aggregateBufferLength) }
set { _aggregateBufferLength = UInt32(newValue) }
Expand Down Expand Up @@ -464,7 +472,6 @@ public struct Frame: ~Copyable {
static let isBackground = Frame.Flags(rawValue: 1 << 5)
static let isRealtime = Frame.Flags(rawValue: 1 << 6)
}
var flags: Flags = Flags()

struct IPPacketValues {
struct Flags: OptionSet {
Expand Down Expand Up @@ -507,13 +514,11 @@ public struct Frame: ~Copyable {
}
}
}
var ipPacketValues: IPPacketValues? = nil

struct AppMetadata: ~Copyable {
let appType: UInt8
let appMetadata: UInt8
}
var appMetadata: AppMetadata? = nil

var isSingleIPAggregate: Bool {
get { flags.contains(.isSingleIPAggregate) }
Expand Down Expand Up @@ -671,15 +676,13 @@ public struct Frame: ~Copyable {
var metadata: AbstractProtocolMetadata
var metadataComplete: Bool = false
}
var protocolMetadatas: NetworkUniqueDeque<FrameProtocolMetadata> = .init(minimumCapacity: 0)

public var firstMetadata: AbstractProtocolMetadata? {
guard protocolMetadatas.count > 0 else {
return nil
}
return protocolMetadatas[0].metadata
}
var _metadataComplete: Bool = false
var metadataComplete: Bool {
get {
if protocolMetadatas.count > 0 {
Expand All @@ -689,13 +692,11 @@ public struct Frame: ~Copyable {
}
set { _metadataComplete = newValue }
}
public var connectionComplete: Bool = false

enum FrameTimestamp {
case receiveTime(_ timestamp: NetworkClock.Instant)
case expireTime(_ timestamp: NetworkClock.Instant)
}
var timestamp: FrameTimestamp? = nil

mutating func reduceAggregateBufferLength(by length: Int) {
if isSingleIPAggregate {
Expand Down
24 changes: 24 additions & 0 deletions Tests/SwiftNetworkTests/SwiftNetworkFrameTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift open source project
//
// Copyright (c) 2026 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

@_spi(Essentials) @_spi(ProtocolProvider) import SwiftNetwork
import XCTest

@available(anyAppleOS 27, *)
final class SwiftNetworkFrameTests: XCTestCase {
func testFrameLayout() {
XCTAssertEqual(MemoryLayout<Frame>.size, 136)
XCTAssertEqual(MemoryLayout<Frame>.stride, 136)
}
}
Loading