Skip to content

generate roundtripping logic for RawRepresentable, LosslessStringConvertible, and more!

License

Notifications You must be signed in to change notification settings

ordo-one/bijection

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tests Documentation

@Bijection is a Swift macro that generates an initializer from a switch-case mapping of an enum’s cases to set of corresponding values. It is useful for generating roundtripping logic for things like binary encodings and string representations, in situations where relying on native raw value-backed enums is insufficient, experiences poor performance due to lack of inlining, or would interfere with other compiler features, such as synthesized Comparable.

documentation · license

Requirements

The @Bijection library requires Swift 6.1 or later.

Platform Status
🐧 Linux Tests
🍏 Darwin Tests

Check deployment minimums

Examples

Generate a plain, unlabeled initializer:

enum Enum: CaseIterable, Equatable {
    case a, b, c

    @Bijection
    var value: Unicode.Scalar {
        switch self {
        case .a: "a"
        case .b: "b"
        case .c: "c"
        }
    }
}

/* --- EXPANDS TO --- */
extension Enum {
    init?(_ $value: borrowing Unicode.Scalar) {
        switch $value {
        case "a":
            self = .a
        case "b":
            self = .b
        case "c":
            self = .c
        default:
            return nil
        }
    }
}

Generate an initializer with a custom argument label:

extension Enum {
    @Bijection(label: "index")
    var index: Int {
        switch self {
        case .a: 1
        case .b: 2
        case .c: 3
        }
    }
}

/* --- EXPANDS TO --- */
extension Enum {
    init?(index $value: borrowing Int) {
        switch $value {
        case 1:
            self = .a
        case 2:
            self = .b
        case 3:
            self = .c
        default:
            return nil
        }
    }
}

Generate an initializer from a getter in a property with multiple accessors:

extension Enum: LosslessStringConvertible {
    @Bijection
    var description: String {
        get {
            switch self {
            case .a: "A"
            case .b: "B"
            case .c: "C"
            }
        }
        set(value) {
            if let value: Self = .init(value) {
                self = value
            }
        }
    }
}
/* --- EXPANDS TO --- */
extension Enum {
    init?(_ $value: borrowing String) {
        switch $value {
        case "A":
            self = .a
        case "B":
            self = .b
        case "C":
            self = .c
        default:
            return nil
        }
    }
}

The @Bijection macro will mirror the access control (and other modifiers, such as nonisolated) of the property it is applied to. It will also copy the following attributes, if present:

  1. @available
  2. @backDeployed
  3. @inlinable
  4. @inline
  5. @usableFromInline

About

generate roundtripping logic for RawRepresentable, LosslessStringConvertible, and more!

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •