[Proposal] Introduces endianness specific type


(Susan Cheng Team Garment) #1

IMO, it has unclear representation when FixedWidthInteger working with
endianness specific type.

so I want to introduce the endianness specific wrapper:

public struct BEInteger<Base : FixedWidthInteger> : FixedWidthInteger {

    public var bigEndian: BEInteger { get }

    public var littleEndian: LEInteger<Base> { get }

}

public struct LEInteger<Base : FixedWidthInteger> : FixedWidthInteger {

    public var bigEndian: BEInteger<Base> { get }

    public var littleEndian: LEInteger { get }

}

also, we should change the FixedWidthInteger as follow:

public protocol FixedWidthInteger : BinaryInteger {

    /// deprecated, we should use value.bigEndian instead

    init(bigEndian value: Self)

    /// deprecated, we should use value.littleEndian instead

    init(littleEndian value: Self)

    associatedtype EndianRepresentingValue : FixedWidthInteger

    var bigEndian: BEInteger<EndianRepresentingValue> { get }

    var littleEndian: LEInteger<EndianRepresentingValue> { get }

}

···

=============================

this is my working alternative implementation:

@_versioned

protocol EndianInteger : FixedWidthInteger {

    associatedtype BitPattern : FixedWidthInteger

    associatedtype RepresentingValue : FixedWidthInteger

    var bitPattern: BitPattern { get }

    init(bitPattern: BitPattern)

    var representingValue : RepresentingValue { get set }

    init(representingValue: RepresentingValue)

}

extension EndianInteger {

    @_transparent

    public init(integerLiteral value: RepresentingValue.IntegerLiteralType)
{

        self.init(representingValue: RepresentingValue(integerLiteral:
value))

    }

    @_transparent

    public init?<T>(exactly source: T) where T : BinaryInteger {

        guard let value = RepresentingValue(exactly: source) else { return
nil }

        self.init(representingValue: value)

    }

    @_transparent

    public init?<T>(exactly source: T) where T : FloatingPoint {

        guard let value = RepresentingValue(exactly: source) else { return
nil }

        self.init(representingValue: value)

    }

    @_transparent

    public init(_ value: RepresentingValue) {

        self.init(representingValue: value)

    }

    @_transparent

    public init<T>(_ source: T) where T : FloatingPoint {

        self.init(representingValue: RepresentingValue(source))

    }

    @_transparent

    public init<T>(_ source: T) where T : BinaryInteger {

        self.init(representingValue: RepresentingValue(source))

    }

    @_transparent

    public init<T>(extendingOrTruncating source: T) where T : BinaryInteger
{

        self.init(representingValue:
RepresentingValue(extendingOrTruncating: source))

    }

    @_transparent

    public init<T>(clamping source: T) where T : BinaryInteger {

        self.init(representingValue: RepresentingValue(clamping: source))

    }

    @_transparent

    public init(_truncatingBits bits: UInt) {

        self.init(representingValue: RepresentingValue(_truncatingBits:
bits))

    }

}

extension EndianInteger {

    @_transparent

    public static var isSigned: Bool {

        return RepresentingValue.isSigned

    }

    @_transparent

    public static var bitWidth: Int {

        return RepresentingValue.bitWidth

    }

    @_transparent

    public static var max: Self {

        return Self(representingValue: RepresentingValue.max)

    }

    @_transparent

    public static var min: Self {

        return Self(representingValue: RepresentingValue.min)

    }

}

extension EndianInteger {

    @_transparent

    public var hashValue: Int {

        return representingValue.hashValue

    }

    @_transparent

    public var description: String {

        return representingValue.description

    }

    @_transparent

    public var bitWidth: Int {

        return representingValue.bitWidth

    }

    @_transparent

    public var magnitude: RepresentingValue.Magnitude {

        return representingValue.magnitude

    }

    @_transparent

    public var trailingZeroBitCount: Int {

        return representingValue.trailingZeroBitCount

    }

    @_transparent

    public var nonzeroBitCount: Int {

        return representingValue.nonzeroBitCount

    }

    @_transparent

    public var leadingZeroBitCount: Int {

        return representingValue.leadingZeroBitCount

    }

    @_transparent

    public var byteSwapped: Self {

        return Self(representingValue: representingValue.byteSwapped)

    }

}

extension EndianInteger {

    @_transparent

    public func _word(at n: Int) -> UInt {

        return representingValue._word(at: n)

    }

    @_transparent

    public func distance(to other: Self) -> RepresentingValue.Stride {

        return self.representingValue.distance(to: other.representingValue)

    }

    @_transparent

    public func advanced(by n: RepresentingValue.Stride) -> Self {

        return Self(representingValue: self.representingValue.advanced(by:
n))

    }

    @_transparent

    public func addingReportingOverflow(_ rhs: Self) -> (partialValue: Self,
overflow: ArithmeticOverflow) {

        let (partialValue, overflow) = representingValue.
addingReportingOverflow(rhs.representingValue)

        return (Self(representingValue: partialValue), overflow)

    }

    @_transparent

    public func subtractingReportingOverflow(_ rhs: Self) -> (partialValue:
Self, overflow: ArithmeticOverflow) {

        let (partialValue, overflow) = representingValue.
subtractingReportingOverflow(rhs.representingValue)

        return (Self(representingValue: partialValue), overflow)

    }

    @_transparent

    public func multipliedReportingOverflow(by rhs: Self) -> (partialValue:
Self, overflow: ArithmeticOverflow) {

        let (partialValue, overflow) = representingValue.
multipliedReportingOverflow(by: rhs.representingValue)

        return (Self(representingValue: partialValue), overflow)

    }

    @_transparent

    public func dividedReportingOverflow(by rhs: Self) -> (partialValue:
Self, overflow: ArithmeticOverflow) {

        let (partialValue, overflow) = representingValue.
dividedReportingOverflow(by: rhs.representingValue)

        return (Self(representingValue: partialValue), overflow)

    }

    @_transparent

    public func remainderReportingOverflow(dividingBy rhs: Self) ->
(partialValue: Self, overflow: ArithmeticOverflow) {

        let (partialValue, overflow) = representingValue.
remainderReportingOverflow(dividingBy: rhs.representingValue)

        return (Self(representingValue: partialValue), overflow)

    }

    @_transparent

    public func multipliedFullWidth(by other: Self) -> (high: Self, low:
RepresentingValue.Magnitude) {

        let (high, low) = representingValue.multipliedFullWidth(by: other.
representingValue)

        return (Self(representingValue: high), low)

    }

    @_transparent

    public func dividingFullWidth(_ dividend: (high: Self, low:
RepresentingValue.Magnitude)) -> (quotient: Self, remainder: Self) {

        let (quotient, remainder) = representingValue.dividingFullWidth
((dividend.high.representingValue, dividend.low))

        return (Self(representingValue: quotient), Self(representingValue:
remainder))

    }

}

extension EndianInteger {

    @_transparent

    public static prefix func +(x: Self) -> Self {

        return x

    }

    @_transparent

    public static func +(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue + rhs.
representingValue)

    }

    @_transparent

    public static func +=(lhs: inout Self, rhs: Self) {

        lhs.representingValue += rhs.representingValue

    }

    @_transparent

    public static func -(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue - rhs.
representingValue)

    }

    @_transparent

    public static func -=(lhs: inout Self, rhs: Self) {

        lhs.representingValue -= rhs.representingValue

    }

    @_transparent

    public static func *(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue * rhs.
representingValue)

    }

    @_transparent

    public static func *=(lhs: inout Self, rhs: Self) {

        lhs.representingValue *= rhs.representingValue

    }

    @_transparent

    public static func /(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue / rhs.
representingValue)

    }

    @_transparent

    public static func /=(lhs: inout Self, rhs: Self) {

        lhs.representingValue /= rhs.representingValue

    }

    @_transparent

    public static func %(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue % rhs.
representingValue)

    }

    @_transparent

    public static func %=(lhs: inout Self, rhs: Self) {

        lhs.representingValue %= rhs.representingValue

    }

    @_transparent

    public static func &(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue & rhs.
representingValue)

    }

    @_transparent

    public static func &=(lhs: inout Self, rhs: Self) {

        lhs.representingValue &= rhs.representingValue

    }

    @_transparent

    public static func |(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue | rhs.
representingValue)

    }

    @_transparent

    public static func |=(lhs: inout Self, rhs: Self) {

        lhs.representingValue |= rhs.representingValue

    }

    @_transparent

    public static func ^(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue ^ rhs.
representingValue)

    }

    @_transparent

    public static func ^=(lhs: inout Self, rhs: Self) {

        lhs.representingValue ^= rhs.representingValue

    }

    @_transparent

    prefix public static func ~(x: Self) -> Self {

        return Self(representingValue: ~x.representingValue)

    }

    @_transparent

    public static func &>>(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue &>> rhs.
representingValue)

    }

    @_transparent

    public static func &<<(lhs: Self, rhs: Self) -> Self {

        return Self(representingValue: lhs.representingValue &<< rhs.
representingValue)

    }

    @_transparent

    public static func ==(lhs: Self, rhs: Self) -> Bool {

        return lhs.bitPattern == rhs.bitPattern

    }

    @_transparent

    public static func !=(lhs: Self, rhs: Self) -> Bool {

        return lhs.bitPattern != rhs.bitPattern

    }

    @_transparent

    public static func >(lhs: Self, rhs: Self) -> Bool {

        return lhs.representingValue > rhs.representingValue

    }

    @_transparent

    public static func <(lhs: Self, rhs: Self) -> Bool {

        return lhs.representingValue < rhs.representingValue

    }

    @_transparent

    public static func >=(lhs: Self, rhs: Self) -> Bool {

        return lhs.representingValue >= rhs.representingValue

    }

    @_transparent

    public static func <=(lhs: Self, rhs: Self) -> Bool {

        return lhs.representingValue <= rhs.representingValue

    }

}

public struct BEInteger<Base : FixedWidthInteger> : FixedWidthInteger,
EndianInteger {

    public var bitPattern: Base

    @_transparent

    public init(bitPattern: Base) {

        self.bitPattern = bitPattern

    }

    @_versioned

    @_transparent

    init(representingValue: Base) {

        self.bitPattern = representingValue.bigEndian

    }

    @_versioned

    @_transparent

    var representingValue: Base {

        get {

            return Base(bigEndian: bitPattern)

        }

        set {

            bitPattern = newValue.bigEndian

        }

    }

    @_transparent

    public init(bigEndian value: BEInteger) {

        self.bitPattern = value.bitPattern

    }

    @_transparent

    public init(littleEndian value: BEInteger) {

        self.bitPattern = value.bitPattern.byteSwapped

    }

    @_transparent

    public var bigEndian: BEInteger {

        return self

    }

    @_transparent

    public var littleEndian: BEInteger {

        return BEInteger(littleEndian: self)

    }

}

public struct LEInteger<Base : FixedWidthInteger> : FixedWidthInteger,
EndianInteger {

    public var bitPattern: Base

    @_transparent

    public init(bitPattern: Base) {

        self.bitPattern = bitPattern

    }

    @_versioned

    @_transparent

    init(representingValue: Base) {

        self.bitPattern = representingValue.littleEndian

    }

    @_versioned

    @_transparent

    var representingValue: Base {

        get {

            return Base(littleEndian: bitPattern)

        }

        set {

            bitPattern = newValue.littleEndian

        }

    }

    @_transparent

    public init(bigEndian value: LEInteger) {

        self.bitPattern = value.bitPattern.byteSwapped

    }

    @_transparent

    public init(littleEndian value: LEInteger) {

        self.bitPattern = value.bitPattern

    }

    @_transparent

    public var bigEndian: LEInteger {

        return LEInteger(bigEndian: self)

    }

    @_transparent

    public var littleEndian: LEInteger {

        return self

    }

}