Last active
March 4, 2021 17:28
-
-
Save KaQuMiQ/c23bf54c2948833a4933a6dc4c0bc2ec to your computer and use it in GitHub Desktop.
Type safe generic identifiers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @dynamicMemberLookup | |
| public struct Identifier<RawValue: Hashable, Type>: Hashable, RawRepresentable { | |
| public var rawValue: RawValue | |
| public init(rawValue: RawValue) { | |
| self.rawValue = rawValue | |
| } | |
| public subscript<Value>(dynamicMember keyPath: KeyPath<RawValue, Value>) -> Value { | |
| get { rawValue[keyPath: keyPath] } | |
| } | |
| public subscript<Value>(dynamicMember keyPath: WritableKeyPath<RawValue, Value>) -> Value { | |
| get { rawValue[keyPath: keyPath] } | |
| set { rawValue[keyPath: keyPath] = newValue } | |
| } | |
| public subscript<Value>(dynamicMember keyPath: ReferenceWritableKeyPath<RawValue, Value>) -> Value { | |
| get { rawValue[keyPath: keyPath] } | |
| set { rawValue[keyPath: keyPath] = newValue } | |
| } | |
| } | |
| extension Identifier: CustomStringConvertible where RawValue: CustomStringConvertible { | |
| public var description: String { | |
| rawValue.description | |
| } | |
| } | |
| extension Identifier: LosslessStringConvertible where RawValue: LosslessStringConvertible { | |
| public init?(_ description: String) { | |
| guard let rawValue = RawValue(description) else { return nil } | |
| self.init(rawValue: rawValue) | |
| } | |
| } | |
| extension Identifier: ExpressibleByUnicodeScalarLiteral where RawValue: ExpressibleByUnicodeScalarLiteral { | |
| public init(unicodeScalarLiteral value: RawValue.UnicodeScalarLiteralType) { | |
| self.init(rawValue: RawValue(unicodeScalarLiteral: value)) | |
| } | |
| } | |
| extension Identifier: ExpressibleByExtendedGraphemeClusterLiteral where RawValue: ExpressibleByExtendedGraphemeClusterLiteral { | |
| public init(extendedGraphemeClusterLiteral value: RawValue.ExtendedGraphemeClusterLiteralType) { | |
| self.init(rawValue: RawValue(extendedGraphemeClusterLiteral: value)) | |
| } | |
| } | |
| extension Identifier: ExpressibleByStringLiteral where RawValue: ExpressibleByStringLiteral { | |
| public init(stringLiteral value: RawValue.StringLiteralType) { | |
| self.init(rawValue: RawValue(stringLiteral: value)) | |
| } | |
| } | |
| extension Identifier: ExpressibleByStringInterpolation where RawValue: ExpressibleByStringInterpolation { | |
| public init(stringInterpolation value: RawValue.StringInterpolation) { | |
| self.init(rawValue: RawValue(stringInterpolation: value)) | |
| } | |
| } | |
| extension Identifier: ExpressibleByIntegerLiteral where RawValue: ExpressibleByIntegerLiteral { | |
| public init(integerLiteral value: RawValue.IntegerLiteralType) { | |
| self.init(rawValue: RawValue(integerLiteral: value)) | |
| } | |
| } | |
| extension Identifier: ExpressibleByFloatLiteral where RawValue: ExpressibleByFloatLiteral { | |
| public init(floatLiteral value: RawValue.FloatLiteralType) { | |
| self.init(rawValue: RawValue(floatLiteral: value)) | |
| } | |
| } | |
| extension Identifier: ExpressibleByNilLiteral where RawValue: ExpressibleByNilLiteral { | |
| public init(nilLiteral: Void) { | |
| self.init(rawValue: RawValue(nilLiteral: Void())) | |
| } | |
| } | |
| public func ~=<RawValue: Hashable, Type>( | |
| _ lhs: RawValue, | |
| _ rhs: Identifier<RawValue, Type> | |
| ) -> Bool { | |
| lhs == rhs.rawValue | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment