Приведите Any к RawRepresentable, где RawValue == Строка - PullRequest
0 голосов
/ 14 апреля 2020

Я пытаюсь закодировать данные. В качестве примера я буду использовать кодировку JSON, хотя для этого есть и другие решения.

Я бы хотел обработать перечисления, которые поддерживаются String или Int как если бы они были просто String и Int:

struct UnhandledValueError: Error {}

enum Foo: String {
  case bar
}

func encode(_ data: Any?) throws -> String {
  guard let data = data else {
    return "null"
  }
  if let string = data as? String {
    return "\"\(string)\""
  }
  if let int = data as? Int {
    return String(int)
  }
  // represent String and Int based enums there

  if let array = data as? [Any?] {
    return try "[\(array.map({ try encode($0) }).joined(separator: ","))]"
  }
  if let dict = data as? [String: Any?] {
    return try "{\(dict.map({ "\"\($0.key)\": \(try encode($0.value))" }).joined(separator: ","))}"
  }

  throw UnhandledValueError()
}

let value: Any? = ["foo": Foo.bar]
try encode(value)

Поскольку RawRepresentable является обобщенным c протоколом, я не думаю, что смогу сделать либо

if let value = data as? RawRepresentable

или

if let value = data as? RawRepresentable where RawValue == String

Как получить доступ к необработанному значению (как Any?) из объекта, который может быть RawRepresentable?

1 Ответ

2 голосов
/ 14 апреля 2020

Вы можете создать универсальный c метод и ограничить его тип до RawRepresentable, где его RawValue соответствует LosslessStringConvertible:

func encode<T>(object: T) -> String where T: RawRepresentable, T.RawValue: LosslessStringConvertible {
    .init(object.rawValue)
}

Тестирование игровой площадки:

enum IntEnum: Int {
    case a = 1, b, c
}

enum StringEnum: String {
    case a, b , c
}

let int: IntEnum = .c
let string: StringEnum = .c

encode(object: int)      // "3"
encode(object: string)   // "c"
...