Skip to content

Instantly share code, notes, and snippets.

@YOCKOW
Last active September 7, 2024 02:40
Show Gist options
  • Select an option

  • Save YOCKOW/de6d8599637c001124f28a309091b9e6 to your computer and use it in GitHub Desktop.

Select an option

Save YOCKOW/de6d8599637c001124f28a309091b9e6 to your computer and use it in GitHub Desktop.

ByteOrder type

Introduction

“How do you describe endianness (or byte-order) as a type in your code?”

This proposal is a simple answer to that simple question.

You may often take byte-order into account when you get involved in, for example, stream programming. While network byte-order is defined as big endian, you may have to handle some other stream whose endian is unknown in advance. In such case, you want a type that identifies endianness to write code like let thatEndian = ByteOrder.littleEndian.

Note: This proposal is inspired by the other proposal given the title "Unicode Processing APIs" which includes such a type to be introduced. This proposal focuses on only that type.

Motivation

CoreFoundation has a such type that represents endianness, and its related definitions look like the following from Swift.

public struct __CFByteOrder: RawRepresentable, Equatable {
    public init(_ rawValue: UInt32)
    public init(rawValue: UInt32)
    public var rawValue: UInt32
}
public var CFByteOrderUnknown: __CFByteOrder { get }
public var CFByteOrderLittleEndian: __CFByteOrder { get }
public var CFByteOrderBigEndian: __CFByteOrder { get }
public typealias CFByteOrder = CFIndex

public func CFByteOrderGetCurrent() -> CFByteOrder

Imagine that you have to implement a function that detects byte-order of some stream for UTF-16. Such a function could appear to be as follows if you use directly __CFByteOrder.

import CoreFoundation

func detectByteOrder(_ stream: some Sequence) -> __CFByteOrder? { /* ... */ }

The issues here are:

  • __CFByteOrder is double-underscored. That means this type might not be officially public.
  • CFByteOrder{Unknwon|LittleEndian|BigEndian} is a global variable, not an enum case.
  • You can use CFByteOrder instead, but it is a typealias of CFIndex which is just an integer.
  • There are some platforms on which CoreFoundation is unavailable from Swift in the first place.

Proposed solution

The way to solve the issues is simple. It's to add a type for byte-order.

As descriged above, such kind of type is proposed as a part of the other proposal, but is not realized yet.

Detailed design

The type would be implemented as follows if it corresponds to current CF* definitions described above.

/// A type that identifies byte order.
@frozen
public enum ByteOrder: Equatable, Sendable {
  /// Multi-byte values are stored with the least-significant bytes stored first.
  /// Pentium CPUs are little endian.
  case littleEndian

  /// Multi-byte values are stored with the most-significant bytes stored first.
  /// PowerPC CPUs are big endian.
  case bigEndian

  /// The byte order of the current computer.
  public static var current: ByteOrder! {
    #if _endian(little)
    return .littleEndian
    #elseif _endian(big)
    return .bigEndian
    #else
    return nil
    #endif
  }
}

Then, you can substitute ByteOrder for __CFByteOrder.

Source compatibility

There are no source compatibility concerns because just a new type is added by this proposal.

ABI compatibility

Adding the new type does not affect ABI.

Implications on adoption

This feature can be freely adopted and un-adopted in source code with no deployment constraints and without affecting source or ABI compatibility.

Future directions

Becomes a basis of any other features

Sorry for saying it again, but this proposal is inspired by the other proposal that contains the feature to add this kind of type. This proposal could be a part of that feature.

Furthermore, of course, ByteOrder is so highly versatile (in other words, so simple) that there's the possibility of being adopted by any other features.

Alternatives considered

Type name

We can choose Endianness or other names instead of ByteOrder. However, ByteOrder is preferred since the name of the existing type in CoreFoundation comprises "byte-order".

Current (native, or host) endianness

Name

There could be also some alternative names for static var current: ByteOrder { get } such as host or native, while, same as above, current derives from CFByteOrderGetCurrent.

Type

There are unusual orderings that are generically called "middle-endian" or "mixed-endian". Swift doesn't currently support such architectures. We can adopt ByteOrder instead of ByteOrder! for the type of current if Swift decides never to support such rare endians forever. Otherwise, the type should be Optional.

Raison d'être

For example, types that conform to FixedWidthIntegers have initializers init(bigEndian: Self) and init(littleEndian: Self), and properties var bigEndian: Self { get } and var littleEndian: Self. In case of using that APIs, you don't have to know the host byte order. Namely we may omit a static property that enables to get "current" byte order.

RawRepresentable conformance

ByteOrder type should conform to RawRepresentable where its RawValue is UInt32 if we let it compatible with __CFByteOrder.

Wait for other evolutions

The change by this proposal is so small that it can be a part of other evolution. Indeed, as described above, this proposal is inspired by the other pitch. On the other hand, there are points to discuss about this type, i.g. alternatives mentioned in this section. That's why we should discuss this small change separately from other proposals.

Use other packages

For example, swift-foundation, swift-syntax and swift-nio have their own enum Endianness 1 2 3. Although you can import them, they are not compatible with each other. Generally speaking, it is not desirable that definitions for the same purpose are scattered. In conclusion, this type should be defined in the standard library.

Footnotes

  1. https://github.com/apple/swift-foundation/blob/660f795ad82fe4e5f8a349006a756c09b19d3e16/Sources/FoundationEssentials/String/String%2BEndianAdaptorSequence.swift#L13-L33

  2. https://github.com/swiftlang/swift-syntax/blob/fc03febda6a46b9d10b65af64724627c30339bd9/Sources/SwiftIfConfig/BuildConfiguration.swift#L15-L23

  3. https://github.com/apple/swift-nio/blob/a4e0a13c8b8d5b63e81be2b672230a334e78ed44/Sources/NIOCore/ByteBuffer-int.swift#L173-L189

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment