From 1f84beb9cba5b639e2837766f2de869dad6ff55f Mon Sep 17 00:00:00 2001 From: Rauhul Varma Date: Mon, 7 Oct 2024 08:32:10 -0700 Subject: [PATCH] Conform integer types to BitFieldProjectable (#129) Adds a default implementation of `BitFieldProjectable` for `FixedWidthInteger` types and conforms all standard sized integer types to `BitFieldProjectable`, e.g. `UInt8`, `UInt16`, `UInt32`, `UInt64`, `Int8`, `Int16`, `Int32`, and `Int64`. Fixes #41 --- Sources/MMIO/BitFieldProjectable.swift | 77 ++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/Sources/MMIO/BitFieldProjectable.swift b/Sources/MMIO/BitFieldProjectable.swift index 73b5b26..f6c5a73 100644 --- a/Sources/MMIO/BitFieldProjectable.swift +++ b/Sources/MMIO/BitFieldProjectable.swift @@ -49,13 +49,80 @@ extension Bool: BitFieldProjectable { } } +/// Default implementation of `BitFieldProjectable` for `FixedWidthInteger` +/// types. +/// +/// Conforming a `FixedWidthInteger` type to `BitFieldProjectable` does not +/// require any customization. +extension BitFieldProjectable where Self: FixedWidthInteger { + @inlinable @inline(__always) + public init(storage: Storage) + where Storage: FixedWidthInteger & UnsignedInteger { + // Ensure the storage type can fully represent all the bits of `Self`. + let storageBitWidth = MemoryLayout.size * 8 + #if hasFeature(Embedded) + // FIXME: Embedded doesn't have static interpolated strings yet + precondition( + storageBitWidth >= Self.bitWidth, + "Value cannot be formed from storage type") + #else + precondition( + storageBitWidth >= Self.bitWidth, + """ + Value type '\(Self.self)' of bit width '\(Self.bitWidth)' cannot be \ + formed from storage '\(storage)' of bit width '\(storageBitWidth)' + """) + #endif + + // Convert the storage integer type to `Self`. + self = Self(storage) + } + + @inlinable @inline(__always) + public func storage(_: Storage.Type) -> Storage + where Storage: FixedWidthInteger & UnsignedInteger { + // Ensure the storage type can fully represent all the bits of `Self`. + let storageBitWidth = MemoryLayout.size * 8 + #if hasFeature(Embedded) + // FIXME: Embedded doesn't have static interpolated strings yet + precondition( + storageBitWidth >= Self.bitWidth, + "Storage type cannot represent value") + #else + precondition( + storageBitWidth >= Self.bitWidth, + """ + Storage type '\(Storage.self)' of bit width '\(storageBitWidth)' cannot \ + represent value '\(self)' of bit width '\(Self.bitWidth)' + """) + #endif + return Storage(self) + } +} + +extension UInt8: BitFieldProjectable {} + +extension UInt16: BitFieldProjectable {} + +extension UInt32: BitFieldProjectable {} + +extension UInt64: BitFieldProjectable {} + +extension Int8: BitFieldProjectable {} + +extension Int16: BitFieldProjectable {} + +extension Int32: BitFieldProjectable {} + +extension Int64: BitFieldProjectable {} + /// Default implementation of `BitFieldProjectable` for `RawRepresentable` /// types. /// /// Conforming a `RawRepresentable` type to `BitFieldProjectable` only needs to /// implement ``BitFieldProjectable.bitWidth``. -extension RawRepresentable -where Self: BitFieldProjectable, RawValue: FixedWidthInteger { +extension BitFieldProjectable +where Self: RawRepresentable, RawValue: FixedWidthInteger { @inlinable @inline(__always) public init(storage: Storage) where Storage: FixedWidthInteger & UnsignedInteger { @@ -70,8 +137,8 @@ where Self: BitFieldProjectable, RawValue: FixedWidthInteger { precondition( storageBitWidth >= Self.bitWidth, """ - Value type '\(Self.self)' of bit width '\(storageBitWidth)' cannot be \ - formed from storage '\(storage)' of bit width '\(Self.bitWidth)' + Value type '\(Self.self)' of bit width '\(Self.bitWidth)' cannot be \ + formed from storage '\(storage)' of bit width '\(storageBitWidth)' """) #endif @@ -112,7 +179,7 @@ where Self: BitFieldProjectable, RawValue: FixedWidthInteger { precondition( storageBitWidth >= Self.bitWidth, """ - Storage type '\(Self.self)' of bit width '\(storageBitWidth)' cannot \ + Storage type '\(Storage.self)' of bit width '\(storageBitWidth)' cannot \ represent value '\(self)' of bit width '\(Self.bitWidth)' """) #endif