Latest version is available at gist: ByteOrderType.md · GitHub
ByteOrder type
Introduction
You may often take endianness (or 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 if theStream.byteOrder == .littleEndian { ... }.
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
You can implement a type of stream representation as below, if you use directly __CFByteOrder.
import CoreFoundation
public struct TheirStream {
// Some implementation here.
/// The byte order of this stream.
public var byteOrder: __CFByteOrder {
// returns CFByteOrderUnknown, CFByteOrderLittleEndian, or CFByteOrderBigEndian
}
}
The issues here are:
__CFByteOrderis double-underscored. That means this type might not be officially public.CFByteOrder{Unknwon|LittleEndian|BigEndian}is a global variable, not aenumcase.- You can use
CFByteOrderinstead, but it is atypealiasofCFIndexwhich is just an integer. - There are some platforms on which
CoreFoundationis 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.
Such kind of type is proposed as a part of the other pitch 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: /* UInt32, */ Equatable, Sendable {
/// The byte order is unknown.
case unknown // = 0
/// Multi-byte values are stored with the least-significant bytes stored first.
/// Pentium CPUs are little endian.
case littleEndian // = 1
/// Multi-byte values are stored with the most-significant bytes stored first.
/// PowerPC CPUs are big endian.
case bigEndian // = 2
/// The byte order of the current computer.
public static var current: ByteOrder {
#if _endian(little)
return .littleEndian
#elseif _endian(big)
return .bigEndian
#else
return .unknown
#endif
}
}
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
This proposal is inspired by the other pitch 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.
For example, you can use it when you want to implement something like Data.View.
Alternatives considered
Other type name
We can choose Endianness or other names instead of ByteOrder.
However, ByteOrder is preferred since the name of the existing type from CoreFoundation comprises "byte-order".
Other static property name
There could be also some alternative names for static var current: ByteOrder { get } such as host or native. However, same as above, current derives from CFByteOrderGetCurrent.
Omit unknown endian
There are unusual orderings that are generically called "middle-endian" or "mixed-endian". Swift doesn't currently support such architectures.
We can leave out unknown case if Swift decides never to support such rare endians forever. Otherwise, the type should include unknown case to be @frozen.
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-syntax and swift-nio have their own enum Endianness [1] [2]. 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.