Skip to content

Instantly share code, notes, and snippets.

@KaQuMiQ
Last active March 4, 2021 17:28
Show Gist options
  • Select an option

  • Save KaQuMiQ/c23bf54c2948833a4933a6dc4c0bc2ec to your computer and use it in GitHub Desktop.

Select an option

Save KaQuMiQ/c23bf54c2948833a4933a6dc4c0bc2ec to your computer and use it in GitHub Desktop.
Type safe generic identifiers
@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