Skip to content

Commit

Permalink
Add CStyleEnum[Binding] and support [Flags] bitwise ops
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlabelle committed Oct 7, 2024
1 parent a114ac7 commit 37c6a8e
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 53 deletions.
18 changes: 8 additions & 10 deletions Generator/Sources/SwiftWinRT/Writing/EnumDefinition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,20 @@ internal func writeEnumDefinition(_ enumDefinition: EnumDefinition, projection:
}

fileprivate func writeOpenEnumDefinition(_ enumDefinition: EnumDefinition, projection: Projection, to writer: SwiftSourceFileWriter) throws {
// Enums are syntactic sugar for integers in .NET,
// By default, enums are syntactic sugar for integers in .NET,
// so we cannot guarantee that the enumerants are exhaustive,
// therefore we cannot project them to Swift enums
// since they would be unable to represent unknown values.
var protocolConformances: [SwiftType] = [ .identifier("CStyleEnum") ]
if try enumDefinition.isFlags {
protocolConformances.append(.identifier("OptionSet"))
}

try writer.writeStruct(
documentation: projection.getDocumentationComment(enumDefinition),
visibility: Projection.toVisibility(enumDefinition.visibility),
name: try projection.toTypeName(enumDefinition),
protocolConformances: [
.identifier(name: enumDefinition.isFlags ? "OptionSet" : "RawRepresentable"),
.identifier("Codable"),
.identifier("Hashable"),
.identifier("Sendable") ]) { writer throws in
protocolConformances: protocolConformances) { writer throws in

let rawValueType = try projection.toType(enumDefinition.underlyingType.bindNode())
writer.writeStoredProperty(visibility: .public, declarator: .var, name: "rawValue", type: rawValueType)
Expand Down Expand Up @@ -59,10 +60,7 @@ fileprivate func writeClosedEnumDefinition(_ enumDefinition: EnumDefinition, pro
visibility: Projection.toVisibility(enumDefinition.visibility),
name: try projection.toTypeName(enumDefinition),
rawValueType: try projection.toType(enumDefinition.underlyingType.bindNode()),
protocolConformances: [
.identifier("Codable"),
.identifier("Hashable"),
.identifier("Sendable") ]) { writer throws in
protocolConformances: [ .identifier("ClosedEnum") ]) { writer throws in
for field in enumDefinition.fields.filter({ $0.visibility == .public && $0.isStatic }) {
try writer.writeEnumCase(
documentation: projection.getDocumentationComment(field),
Expand Down
10 changes: 5 additions & 5 deletions InteropTests/Tests/EnumTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ class EnumTests: WinRTTestCase {
XCTAssertEqual(FlagsEnum.all.rawValue, 0xFFFFFFFF)
}

func testFlagsSetAlgebra() throws {
XCTAssertEqual(FlagsEnum.all.intersection(FlagsEnum.bit16), try Enums.bitwiseAnd(FlagsEnum.all, FlagsEnum.bit16))
XCTAssertEqual(FlagsEnum.bit16.intersection(FlagsEnum.all), try Enums.bitwiseAnd(FlagsEnum.bit16, FlagsEnum.all))
XCTAssertEqual(FlagsEnum.bit0.union(FlagsEnum.bit16), try Enums.bitwiseOr(FlagsEnum.bit0, FlagsEnum.bit16))
XCTAssertEqual(FlagsEnum.bit16.union(FlagsEnum.bit0), try Enums.bitwiseOr(FlagsEnum.bit16, FlagsEnum.bit0))
func testFlagsBitwiseOperators() throws {
XCTAssertEqual(FlagsEnum.all & FlagsEnum.bit16, try Enums.bitwiseAnd(FlagsEnum.all, FlagsEnum.bit16))
XCTAssertEqual(FlagsEnum.bit16 & FlagsEnum.all, try Enums.bitwiseAnd(FlagsEnum.bit16, FlagsEnum.all))
XCTAssertEqual(FlagsEnum.bit0 | FlagsEnum.bit16, try Enums.bitwiseOr(FlagsEnum.bit0, FlagsEnum.bit16))
XCTAssertEqual(FlagsEnum.bit16 | FlagsEnum.bit0, try Enums.bitwiseOr(FlagsEnum.bit16, FlagsEnum.bit0))
}
}
21 changes: 21 additions & 0 deletions Support/Sources/ABIBindings/CStyleEnum.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/// Protocol for Swift structs which represent C-style enums:
/// backed by a fixed-width integer, and allowing for arbitrary values.
public protocol CStyleEnum: RawRepresentable, Codable, Hashable, Sendable
where RawValue: FixedWidthInteger {
init(rawValue value: RawValue)
}

// Bitwise operators for C-style enums used as bitfields.
extension CStyleEnum where Self: OptionSet {
public static prefix func~(value: Self) -> Self {
Self(rawValue: ~value.rawValue)
}

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

public static func&(lhs: Self, rhs: Self) -> Self {
Self(rawValue: lhs.rawValue & rhs.rawValue)
}
}
10 changes: 10 additions & 0 deletions Support/Sources/ABIBindings/CStyleEnumBinding.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// Binding for an a type implementing CStyleEnum
public protocol CStyleEnumBinding: CStyleEnum, PODBinding
where ABIValue == RawValue, SwiftValue == Self {
}

extension CStyleEnumBinding {
public static var abiDefaultValue: RawValue { RawValue.zero }
public static func fromABI(_ value: RawValue) -> Self { Self(rawValue: value) }
public static func toABI(_ value: Self) -> RawValue { value.rawValue }
}
11 changes: 0 additions & 11 deletions Support/Sources/ABIBindings/ClosedEnumBinding.swift

This file was deleted.

13 changes: 0 additions & 13 deletions Support/Sources/ABIBindings/OpenEnumBinding.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import WindowsRuntime_ABI
import SWRT_WindowsFoundation

extension ClosedEnumBinding {
public static var abiDefaultValue: RawValue { RawValue.zero }
public static func fromABI(_ value: RawValue) -> Self { Self(rawValue: value)! }
public static func toABI(_ value: Self) -> RawValue { value.rawValue }
}

extension IReferenceableBinding {
public typealias IReferenceToOptional = IReferenceToOptionalBinding<Self>

Expand Down
23 changes: 13 additions & 10 deletions Support/Sources/WindowsRuntime/BindingProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,33 @@ public protocol IReferenceableBinding: WinRTBinding {
static func createIReferenceArray(_ value: [SwiftValue]) throws -> WindowsFoundation_IReferenceArray<SwiftValue>
}

/// Marker protocol for bindings of WinRT value types into Swift.
/// Protocol for bindings of WinRT value types into Swift.
/// Value types implement the binding protocol directly since they can't define clashing static members.
public protocol ValueTypeBinding: IReferenceableBinding where SwiftValue == Self {}

/// Convenience protocol for bindings of WinRT enums into Swift.
public protocol OpenEnumBinding: ValueTypeBinding, COM.OpenEnumBinding {}
public protocol ClosedEnumBinding: ValueTypeBinding, COM.ClosedEnumBinding {}
/// Protocol for bindings of WinRT enums into Swift, where the enum can take any integer value.
public protocol OpenEnumBinding: ValueTypeBinding, CStyleEnumBinding {}

/// Convenience protocol for bindings of WinRT structs into Swift.
/// Protocol for bindings of WinRT enums into Swift enums, disallowing unspecified values.
public protocol ClosedEnumBinding: ClosedEnum, PODBinding, ValueTypeBinding
where SwiftValue == Self, ABIValue == RawValue {}

/// Protocol for bindings of WinRT structs into Swift.
public protocol StructBinding: ValueTypeBinding {} // Inert structs will also conform to PODBinding

/// Marker protocol for bindings of WinRT reference types into Swift.
/// Protocol for bindings of WinRT reference types into Swift.
public protocol ReferenceTypeBinding: WinRTBinding, COMBinding {}

/// Convenience protocol for bindings of WinRT interfaces into Swift.
/// Protocol for bindings of WinRT interfaces into Swift.
public protocol InterfaceBinding: ReferenceTypeBinding, COMTwoWayBinding {} // where SwiftObject: any IInspectable

/// Convenience protocol for bindings of WinRT delegates into Swift.
/// Protocol for bindings of WinRT delegates into Swift.
public protocol DelegateBinding: ReferenceTypeBinding, IReferenceableBinding, COMTwoWayBinding {}

/// Convenience protocol for bindings of WinRT activatable classes into Swift.
/// Protocol for bindings of WinRT activatable classes into Swift.
public protocol ActivatableClassBinding: ReferenceTypeBinding {} // where SwiftObject: IInspectable

/// Convenience protocol for bindings of WinRT composable classes into Swift.
/// Protocol for bindings of WinRT composable classes into Swift.
/// Conforms to AnyObject so that conforming types must be classes, which can be looked up using NSClassFromString.
public protocol ComposableClassBinding: ReferenceTypeBinding, AnyObject { // where SwiftObject: IInspectable
static func _wrapObject(_ reference: consuming IInspectableReference) -> IInspectable
Expand Down
3 changes: 3 additions & 0 deletions Support/Sources/WindowsRuntime/ClosedEnum.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/// Protocol for Swift enums which represent WinRT enums but do not allow arbitrary values.
public protocol ClosedEnum: RawRepresentable, Codable, Hashable, Sendable
where RawValue: FixedWidthInteger {}
11 changes: 8 additions & 3 deletions Support/Sources/WindowsRuntime/Projection/TrustLevel.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import WindowsRuntime_ABI
import COM

public struct TrustLevel: Hashable, RawRepresentable, Sendable {
/// Represents the trust level of an activatable class.
public struct TrustLevel: CStyleEnum {
public var rawValue: Int32
public init(rawValue: Int32 = 0) { self.rawValue = rawValue }

/// The component has access to resources that are not protected.
public static let base = Self(rawValue: 0)

/// The component has access to resources requested in the app manifest and approved by the user.
public static let partial = Self(rawValue: 1)

/// The component requires the full privileges of the user.
public static let full = Self(rawValue: 2)
}

extension TrustLevel: COM.OpenEnumBinding {
}
extension TrustLevel: CStyleEnumBinding {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// Specifies property value types.
public struct WindowsFoundation_PropertyType: RawRepresentable, Hashable, Codable, Sendable {
public struct WindowsFoundation_PropertyType: CStyleEnum {
public var rawValue: Swift.Int32

public init(rawValue: Swift.Int32 = 0) {
Expand Down

0 comments on commit 37c6a8e

Please sign in to comment.