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:
__CFByteOrder
is double-underscored. That means this type might not be officially public.CFByteOrder{Unknwon|LittleEndian|BigEndian}
is a global variable, not aenum
case.- You can use
CFByteOrder
instead, but it is atypealias
ofCFIndex
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.
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.