Files
swift-nio/Sources/NIOWebSocket/WebSocketOpcode.swift
Cory Benfield abe4f1bcb6 Replace almost all public static lets with computed vars (#3229)
Motivation:

Public static lets can serve a bunch of roles, but one of them is to
store simple constants: integers, and other trivial types, for example.
This is a nice pattern and for internal and private static lets it works
well, but for public ones it produces some inefficient code.

In particular, it has two downsides. First, it allocates storage for
that value. We don't actually need to allocate a few hundred extra
megabytes for the various integers we want to store.

Secondly, it forces calling code to access the address and call the
dispatch_once code in order to get hold of the value. For trivial types
we don't need that cost: they can just know what the value is directly.

Inlinable computed vars avoid all of these costs: they have no size
overhead for storage, and they are visible to all clients so their
values can be directly assembled.

While I'm here, I added a bunch of other inlinable annotations for a few
trivial data types I stumbled onto.

Modifications:

- Added loads of inlinables. Like, loads.
- Swapped many static lets to static vars.

Result:

Better codegen, smaller memory footprints, more attributes.
2025-05-02 16:08:10 +01:00

145 lines
4.0 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import NIOCore
/// An operation code for a websocket frame.
public struct WebSocketOpcode: Sendable {
@usableFromInline
let networkRepresentation: UInt8
@inlinable
public static var continuation: WebSocketOpcode {
WebSocketOpcode(rawValue: 0x0)
}
@inlinable
public static var text: WebSocketOpcode {
WebSocketOpcode(rawValue: 0x1)
}
@inlinable
public static var binary: WebSocketOpcode {
WebSocketOpcode(rawValue: 0x2)
}
@inlinable
public static var connectionClose: WebSocketOpcode {
WebSocketOpcode(rawValue: 0x8)
}
@inlinable
public static var ping: WebSocketOpcode {
WebSocketOpcode(rawValue: 0x9)
}
@inlinable
public static var pong: WebSocketOpcode {
WebSocketOpcode(rawValue: 0xA)
}
/// Create an opcode from the encoded representation.
///
/// - Parameters
/// - encoded: The encoded representation of the opcode as an 8-bit integer.
/// Must be no more than 4 bits large.
@inlinable
public init?(encodedWebSocketOpcode encoded: UInt8) {
guard encoded < 0x10 else {
return nil
}
self.networkRepresentation = encoded
}
/// Create an opcode directly with no validation.
///
/// Used only to create the static vars on this structure.
@inlinable
init(rawValue: UInt8) {
self.networkRepresentation = rawValue
}
/// Whether the opcode is in the control range: that is, if the
/// high bit of the opcode nibble is `1`.
@inlinable
public var isControlOpcode: Bool {
self.networkRepresentation & 0x8 == 0x8
}
}
extension WebSocketOpcode: Equatable {}
extension WebSocketOpcode: Hashable {}
extension WebSocketOpcode: CaseIterable {
@inlinable
public static var allCases: [WebSocketOpcode] {
get { (0..<0x10).map { WebSocketOpcode(rawValue: $0) } }
@available(*, deprecated)
set {}
}
}
extension WebSocketOpcode: CustomStringConvertible {
public var description: String {
switch self {
case .continuation:
return "WebSocketOpcode.continuation"
case .text:
return "WebSocketOpcode.text"
case .binary:
return "WebSocketOpcode.binary"
case .connectionClose:
return "WebSocketOpcode.connectionClose"
case .ping:
return "WebSocketOpcode.ping"
case .pong:
return "WebSocketOpcode.pong"
case let x where x.isControlOpcode:
return "WebSocketOpcode.unknownControl(\(x.networkRepresentation))"
case let x:
return "WebSocketOpcode.unknownNonControl(\(x.networkRepresentation))"
}
}
}
extension UInt8 {
/// Create a UInt8 corresponding to a given `WebSocketOpcode`.
///
/// This places the opcode in the four least-significant bits, in
/// a form suitable for sending on the wire.
///
/// - Parameters:
/// - opcode: The `WebSocketOpcode`.
@inlinable
public init(webSocketOpcode opcode: WebSocketOpcode) {
precondition(opcode.networkRepresentation < 0x10)
self = opcode.networkRepresentation
}
}
extension Int {
/// Create a UInt8 corresponding to the integer value for a given `WebSocketOpcode`.
///
/// - Parameters:
/// - opcode: The `WebSocketOpcode`.
@inlinable
public init(webSocketOpcode opcode: WebSocketOpcode) {
precondition(opcode.networkRepresentation < 0x10)
self = Int(opcode.networkRepresentation)
}
}