Thanks, but we can implement Codable for BEInteger and LEInteger types.
public struct BEInteger<BitPattern : FixedWidthInteger> : FixedWidthInteger { public var bitPattern: BitPattern public init(bitPattern: BitPattern) public var bigEndian: BEInteger { get } public var littleEndian: LEInteger<BitPattern> { get } } public struct LEInteger<BitPattern : FixedWidthInteger> : FixedWidthInteger { public var bitPattern: BitPattern public init(bitPattern: BitPattern) public var bigEndian: BEInteger<BitPattern> { get } public var littleEndian: LEInteger { get } } extension BEInteger : Encodable where BitPattern : Encodable { public func encode(to encoder: Encoder) throws { try self.bitPattern.encode(to: encoder) } } extension BEInteger : Decodable where BitPattern : Decodable { public init(from decoder: Decoder) throws { self.init(bitPattern: try BitPattern(from: decoder)) } } extension LEInteger : Encodable where BitPattern : Encodable { public func encode(to encoder: Encoder) throws { try self.bitPattern.encode(to: encoder) } } extension LEInteger : Decodable where BitPattern : Decodable { public init(from decoder: Decoder) throws { self.init(bitPattern: try BitPattern(from: decoder)) } } 2017-07-09 0:27 GMT+08:00 Chris Lattner <clatt...@nondot.org>: > Hi Susan, > > Swift does not currently specify a layout for Swift structs. You > shouldn’t be using them for memory mapped i/o or writing to a file, because > their layout can change. When ABI stability for fragile structs lands, you > will be able to count on it, but until then something like this is probably > a bad idea. > > -Chris > > On Jul 7, 2017, at 6:16 PM, Susan Cheng via swift-evolution < > swift-evolution@swift.org> wrote: > > 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 <mois...@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@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 : BinaryInt > eger { > 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.addingRepo > rtingOverflow(rhs.representingValue) > return (Self(representingValue: partialValue), overflow) > } > > @_transparent > public func subtractingReportingOverflow(_ rhs: Self) -> > (partialValue: Self, overflow: ArithmeticOverflow) { > let (partialValue, overflow) = representingValue.subtractin > gReportingOverflow(rhs.representingValue) > return (Self(representingValue: partialValue), overflow) > } > > @_transparent > public func multipliedReportingOverflow(by rhs: Self) -> > (partialValue: Self, overflow: ArithmeticOverflow) { > let (partialValue, overflow) = representingValue.multiplied > ReportingOverflow(by: rhs.representingValue) > return (Self(representingValue: partialValue), overflow) > } > > @_transparent > public func dividedReportingOverflow(by rhs: Self) -> (partialValue: > Self, overflow: ArithmeticOverflow) { > let (partialValue, overflow) = representingValue.dividedRep > ortingOverflow(by: rhs.representingValue) > return (Self(representingValue: partialValue), overflow) > } > > @_transparent > public func remainderReportingOverflow(dividingBy rhs: Self) -> > (partialValue: Self, overflow: ArithmeticOverflow) { > let (partialValue, overflow) = representingValue.remainderR > eportingOverflow(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@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution