Skip to content

Instantly share code, notes, and snippets.

@mrgrauel
Created January 9, 2021 07:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrgrauel/61e5120f3843ca5352a5377551312499 to your computer and use it in GitHub Desktop.
Save mrgrauel/61e5120f3843ca5352a5377551312499 to your computer and use it in GitHub Desktop.
Type-Safe Identifier in Swift
//
// Identifier.swift
//
// Created by Andreas Osberghaus on 09.01.21.
//
import Foundation
public protocol Identifiable {
associatedtype RawIdentifier: Codable & Hashable = String
var id: Identifier<Self> { get }
}
public struct Identifier<Value: Identifiable>: RawRepresentable {
public let rawValue: Value.RawIdentifier
public init(rawValue: Value.RawIdentifier) {
self.rawValue = rawValue
}
}
// MARK: - Codable
extension Identifier: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let rawValue = try container.decode(Value.RawIdentifier.self)
self.init(rawValue: rawValue)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(rawValue)
}
}
// MARK: - ExpressibleByStringLiteral
extension Identifier: ExpressibleByUnicodeScalarLiteral where Value.RawIdentifier == String {
public init(unicodeScalarLiteral value: UnicodeScalar) {
rawValue = String(describing: Character(value))
}
}
extension Identifier: ExpressibleByExtendedGraphemeClusterLiteral where Value.RawIdentifier == String {
public init(extendedGraphemeClusterLiteral value: Character) {
rawValue = String(describing: value)
}
}
extension Identifier: ExpressibleByStringLiteral where Value.RawIdentifier == String {
public init(stringLiteral value: Value.RawIdentifier) {
rawValue = value
}
}
// MARK: - ExpressibleByIntegerLiteral
extension Identifier: ExpressibleByIntegerLiteral where Value.RawIdentifier == Int {
public init(integerLiteral value: Value.RawIdentifier) {
rawValue = value
}
}
// MARK: - Hashable
extension Identifier: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(rawValue)
}
}
// MARK: - CustomStringConvertible
extension Identifier: CustomStringConvertible {
public var description: String {
if let stringValue = rawValue as? String {
return stringValue
} else {
return "\(rawValue)"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment