[swift-evolution] [Proposal] Introduces endianness specific type
susan.doggie at gmail.com
susan.doggie at gmail.com
Fri Jul 7 20:16:03 CDT 2017
Here are two problems being fixed.
First, considering the example:
struct MyRawDataStruct {
var size: UInt32
var signature: UInt32
var width: UInt32
var height: UInt32
}
The type UInt32 doesn't tall us the endianness of the value. Also, if we read the value of it, the value is being byte-swapped when endianness is not matching with the system.
This causes us have to manual convert the value from/to correct endianness.
struct MyRawDataStruct {
var size: BEInteger<UInt32>
var signature: BEInteger<UInt32>
var width: BEInteger<UInt32>
var height: BEInteger<UInt32>
}
So, my proposal fix the problem. We can easily to get the value.
let header: MyRawDataStruct = data.withUnsafePointer { $0.pointee }
print(header.size) // print the representing value
Second, it's misleading means of bigEndian and littleEndian from FixedWidthInteger
if we do this
let a = 1
print(a.bigEndian.bigEndian)
It's just swap bytes twice but not converting value to big-endian
My proposal solves the problem
let b = a.bigEndian // BEInteger<Int>
b.bigEndian // remain big-endian of a
> Max Moiseev <moiseev at apple.com> 於 2017年7月8日 上午1:48 寫道:
>
> Hi Susan,
>
> Was there any motivation for this proposal that I missed? If not then, can you please provide it in a few sentences? Otherwise it’s not clear to me what problem it is supposed to fix.
>
> Thanks,
> Max
>
>
>> On Jul 6, 2017, at 8:21 PM, Susan Cheng via swift-evolution <swift-evolution at swift.org> wrote:
>>
>> 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
>> }
>> }
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170708/d20308c7/attachment.html>
More information about the swift-evolution
mailing list