I am aware of the OptionSet protocol, that is used to represent a
"mathematical bit set".  But I found it too be a bit "too much" for a simple
bitmap.  So I created my own, called RawBits.  This is the first protocol
I've written in Swift, so I'd be interested in any constructive criticism
anyone might have.

 

Thanks!

 

extension String {

    public func pad(with padding: Character, toLength length: Int) -> String
{

        let paddingWidth = length - self.count

        guard 0 < paddingWidth else { return self }

        return String(repeating: padding, count: paddingWidth) + self

    }

}

 

extension Bool: ExpressibleByIntegerLiteral {

    public init(integerLiteral value: Int) {

        self = value != 0

    }

}

 

public enum Bit: Bool {

    case off = 0

    case on = 1

}

 

public protocol RawBits: RawRepresentable, CustomStringConvertible {

    associatedtype Element = Self

    init(rawValue: RawValue)

}

 

extension RawBits {

    public init(_ rawValue: RawValue) {

        self.init(rawValue: rawValue)

    }

}

 

extension RawBits where RawValue: FixedWidthInteger, RawValue:
UnsignedInteger {

    public init() {

        self.init(rawValue: 0)

    }

 

    public func asRadix(_ radix: Int) -> String {

        let s = String(self.rawValue, radix: radix, uppercase: true)

        var x: Int

        switch radix {

        case 16: x = 4

        case 2: x = 1

        default: x = 0

        }

        return x == 0 ?  s : s.pad(with: "0", toLength: rawValue.bitWidth /
x)

    }

 

    public var asBinary: String     { return asRadix(2) }

    public var asDecimal: String    { return asRadix(10) }

    public var asHex: String        { return asRadix(16) }

    public var description: String  { return asBinary }

    public var bitWidth: Int        { return rawValue.bitWidth }

 

    private func rangeCheck(_ bit: UInt) {

        guard bit < rawValue.bitWidth else { fatalError("Index out of
range") }

    }

 

    public func get(bit: UInt) -> Bool {

        rangeCheck(bit)

        return (rawValue >> bit) & 1 == 1

    }

 

    public func setOn(bit: UInt) -> RawValue {

        rangeCheck(bit)

        return rawValue | 1 << bit

    }

 

    public func setOff(bit: UInt) -> RawValue {

        rangeCheck(bit)

        return rawValue & ~(1 << bit)

    }

 

    public subscript(x: UInt) -> Bit {

        get { return Bit(rawValue: get(bit: x))! }

        set { self = Self(newValue == .on ? setOn(bit: x) : setOff(bit: x))
}

    }

}

 

struct RawBits64: RawBits {

    let rawValue: UInt64

}

 

var bitmap = RawBits64(0xF33AC401A8E08062)

print(bitmap.bitWidth)

print(bitmap)

print(bitmap.asHex)

print(bitmap.asDecimal)

 

bitmap[0] = Bit.on

print(bitmap[0])

print(bitmap)

print(bitmap.asHex)

bitmap[0] = Bit.off

print(bitmap[0])

print(bitmap)

 

bitmap[7] = .on

print(bitmap[7])

print(bitmap)

bitmap[7] = .off

print(bitmap[7])

print(bitmap)

bitmap[63] = .off

print(bitmap)

#if OOR

    print(bitmap[64])  // fatal error, out of range

#endif

 

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to