Browse Source

Allow non-string values in profiles

Profiles were not loading from other clients because some fields were
not strings

Changelog-Fixed: Fixed profiles sometimes not loading from other clients
translations_damus-localizations-en-us-xcloc-localized-contents-en-us-xliff--master_ar
William Casarin 2 years ago
parent
commit
d559dd3a13
  1. 20
      damus.xcodeproj/project.pbxproj
  2. 69
      damus/Nostr/Nostr.swift
  3. 147
      damus/Util/AnyCodable/AnyCodable.swift
  4. 188
      damus/Util/AnyCodable/AnyDecodable.swift
  5. 291
      damus/Util/AnyCodable/AnyEncodable.swift

20
damus.xcodeproj/project.pbxproj

@ -166,6 +166,9 @@
4CF0ABE12981A83900D66079 /* MutelistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE02981A83900D66079 /* MutelistView.swift */; };
4CF0ABE32981BC7D00D66079 /* UserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE22981BC7D00D66079 /* UserView.swift */; };
4CF0ABE52981EE0C00D66079 /* EULAView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE42981EE0C00D66079 /* EULAView.swift */; };
4CF0ABE929844AF100D66079 /* AnyCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE829844AF100D66079 /* AnyCodable.swift */; };
4CF0ABEC29844B4700D66079 /* AnyDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABEB29844B4700D66079 /* AnyDecodable.swift */; };
4CF0ABEE29844B5500D66079 /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABED29844B5500D66079 /* AnyEncodable.swift */; };
4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE60CDC295E1C5E00105A1F /* Wallet.swift */; };
6439E014296790CF0020672B /* ProfileZoomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6439E013296790CF0020672B /* ProfileZoomView.swift */; };
647D9A8D2968520300A295DE /* SideMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647D9A8C2968520300A295DE /* SideMenuView.swift */; };
@ -419,6 +422,9 @@
4CF0ABE02981A83900D66079 /* MutelistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutelistView.swift; sourceTree = "<group>"; };
4CF0ABE22981BC7D00D66079 /* UserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserView.swift; sourceTree = "<group>"; };
4CF0ABE42981EE0C00D66079 /* EULAView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EULAView.swift; sourceTree = "<group>"; };
4CF0ABE829844AF100D66079 /* AnyCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyCodable.swift; sourceTree = "<group>"; };
4CF0ABEB29844B4700D66079 /* AnyDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyDecodable.swift; sourceTree = "<group>"; };
4CF0ABED29844B5500D66079 /* AnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
4FE60CDC295E1C5E00105A1F /* Wallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wallet.swift; sourceTree = "<group>"; };
6439E013296790CF0020672B /* ProfileZoomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileZoomView.swift; sourceTree = "<group>"; };
647D9A8C2968520300A295DE /* SideMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuView.swift; sourceTree = "<group>"; };
@ -662,6 +668,7 @@
4C7FF7D628233637009601DB /* Util */ = {
isa = PBXGroup;
children = (
4CF0ABEA29844B2F00D66079 /* AnyCodable */,
4C3A1D322960DB0500558C0F /* Markdown.swift */,
4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */,
4CE4F8CC281352B30009DFBB /* Notifications.swift */,
@ -824,6 +831,16 @@
path = Muting;
sourceTree = "<group>";
};
4CF0ABEA29844B2F00D66079 /* AnyCodable */ = {
isa = PBXGroup;
children = (
4CF0ABE829844AF100D66079 /* AnyCodable.swift */,
4CF0ABEB29844B4700D66079 /* AnyDecodable.swift */,
4CF0ABED29844B5500D66079 /* AnyEncodable.swift */,
);
path = AnyCodable;
sourceTree = "<group>";
};
F7F0BA23297892AE009531F3 /* Modifiers */ = {
isa = PBXGroup;
children = (
@ -1003,6 +1020,7 @@
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
4C5C7E68284ED36500A22DF5 /* SearchHomeModel.swift in Sources */,
4C75EFB728049D990006080F /* RelayPool.swift in Sources */,
4CF0ABEE29844B5500D66079 /* AnyEncodable.swift in Sources */,
4CB8838D296F710400DC99E7 /* Reposted.swift in Sources */,
4C3EA67728FF7A9800C48A62 /* talstr.c in Sources */,
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */,
@ -1053,6 +1071,7 @@
4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */,
4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */,
7C45AE71297353390031D7BC /* KFImageModel.swift in Sources */,
4CF0ABE929844AF100D66079 /* AnyCodable.swift in Sources */,
4C0A3F8F280F640A000448DE /* ThreadModel.swift in Sources */,
4CC7AAF2297F129C00430951 /* EmbeddedEventView.swift in Sources */,
4C3AC79F2833115300E1F516 /* FollowButtonView.swift in Sources */,
@ -1122,6 +1141,7 @@
4C3AC79B28306D7B00E1F516 /* Contacts.swift in Sources */,
4C3EA63D28FF52D600C48A62 /* bolt11.c in Sources */,
4CB55EF3295E5D59007FD187 /* RecommendedRelayView.swift in Sources */,
4CF0ABEC29844B4700D66079 /* AnyDecodable.swift in Sources */,
4C5F9118283D88E40052CD1C /* FollowingModel.swift in Sources */,
4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */,
4C363A8E28236FE4006E126D /* NoteContentView.swift in Sources */,

69
damus/Nostr/Nostr.swift

@ -8,7 +8,7 @@
import Foundation
struct Profile: Codable {
var value: [String: String]
var value: [String: AnyCodable]
init (name: String?, display_name: String?, about: String?, picture: String?, banner: String?, website: String?, lud06: String?, lud16: String?, nip05: String?) {
self.value = [:]
@ -23,48 +23,69 @@ struct Profile: Codable {
self.nip05 = nip05
}
private func str(_ str: String) -> String? {
guard let val = self.value[str] else{
return nil
}
guard let s = val.value as? String else {
return nil
}
return s
}
private mutating func set_str(_ key: String, _ val: String?) {
if val == nil {
self.value.removeValue(forKey: key)
return
}
self.value[key] = AnyCodable.init(val)
}
var display_name: String? {
get { return value["display_name"]; }
set(s) { value["display_name"] = s }
get { return str("display_name"); }
set(s) { set_str("display_name", s) }
}
var name: String? {
get { return value["name"]; }
set(s) { value["name"] = s }
get { return str("name"); }
set(s) { set_str("name", s) }
}
var about: String? {
get { return value["about"]; }
set(s) { value["about"] = s }
get { return str("about"); }
set(s) { set_str("about", s) }
}
var picture: String? {
get { return value["picture"]; }
set(s) { value["picture"] = s }
get { return str("picture"); }
set(s) { set_str("picture", s) }
}
var banner: String? {
get { return value["banner"]; }
set(s) { value["banner"] = s }
get { return str("banner"); }
set(s) { set_str("banner", s) }
}
var website: String? {
get { return value["website"]; }
set(s) { value["website"] = s }
}
var website_url: URL? {
return self.website.flatMap { URL(string: $0) }
get { return str("website"); }
set(s) { set_str("website", s) }
}
var lud06: String? {
get { return value["lud06"]; }
set(s) { value["lud06"] = s }
get { return str("lud06"); }
set(s) { set_str("lud06", s) }
}
var lud16: String? {
get { return value["lud16"]; }
set(s) { value["lud16"] = s }
get { return str("lud16"); }
set(s) { set_str("lud16", s) }
}
var website_url: URL? {
return self.website.flatMap { URL(string: $0) }
}
var lnurl: String? {
@ -80,8 +101,8 @@ struct Profile: Codable {
}
var nip05: String? {
get { return value["nip05"]; }
set(s) { value["nip05"] = s }
get { return str("nip05"); }
set(s) { set_str("nip05", s) }
}
var lightning_uri: URL? {
@ -90,7 +111,7 @@ struct Profile: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.value = try container.decode([String: String].self)
self.value = try container.decode([String: AnyCodable].self)
}
func encode(to encoder: Encoder) throws {

147
damus/Util/AnyCodable/AnyCodable.swift

@ -0,0 +1,147 @@
import Foundation
/**
A type-erased `Codable` value.
The `AnyCodable` type forwards encoding and decoding responsibilities
to an underlying value, hiding its specific underlying type.
You can encode or decode mixed-type values in dictionaries
and other collections that require `Encodable` or `Decodable` conformance
by declaring their contained type to be `AnyCodable`.
- SeeAlso: `AnyEncodable`
- SeeAlso: `AnyDecodable`
*/
@frozen public struct AnyCodable: Codable {
public let value: Any
public init<T>(_ value: T?) {
self.value = value ?? ()
}
}
extension AnyCodable: _AnyEncodable, _AnyDecodable {}
extension AnyCodable: Equatable {
public static func == (lhs: AnyCodable, rhs: AnyCodable) -> Bool {
switch (lhs.value, rhs.value) {
case is (Void, Void):
return true
case let (lhs as Bool, rhs as Bool):
return lhs == rhs
case let (lhs as Int, rhs as Int):
return lhs == rhs
case let (lhs as Int8, rhs as Int8):
return lhs == rhs
case let (lhs as Int16, rhs as Int16):
return lhs == rhs
case let (lhs as Int32, rhs as Int32):
return lhs == rhs
case let (lhs as Int64, rhs as Int64):
return lhs == rhs
case let (lhs as UInt, rhs as UInt):
return lhs == rhs
case let (lhs as UInt8, rhs as UInt8):
return lhs == rhs
case let (lhs as UInt16, rhs as UInt16):
return lhs == rhs
case let (lhs as UInt32, rhs as UInt32):
return lhs == rhs
case let (lhs as UInt64, rhs as UInt64):
return lhs == rhs
case let (lhs as Float, rhs as Float):
return lhs == rhs
case let (lhs as Double, rhs as Double):
return lhs == rhs
case let (lhs as String, rhs as String):
return lhs == rhs
case let (lhs as [String: AnyCodable], rhs as [String: AnyCodable]):
return lhs == rhs
case let (lhs as [AnyCodable], rhs as [AnyCodable]):
return lhs == rhs
case let (lhs as [String: Any], rhs as [String: Any]):
return NSDictionary(dictionary: lhs) == NSDictionary(dictionary: rhs)
case let (lhs as [Any], rhs as [Any]):
return NSArray(array: lhs) == NSArray(array: rhs)
case is (NSNull, NSNull):
return true
default:
return false
}
}
}
extension AnyCodable: CustomStringConvertible {
public var description: String {
switch value {
case is Void:
return String(describing: nil as Any?)
case let value as CustomStringConvertible:
return value.description
default:
return String(describing: value)
}
}
}
extension AnyCodable: CustomDebugStringConvertible {
public var debugDescription: String {
switch value {
case let value as CustomDebugStringConvertible:
return "AnyCodable(\(value.debugDescription))"
default:
return "AnyCodable(\(description))"
}
}
}
extension AnyCodable: ExpressibleByNilLiteral {}
extension AnyCodable: ExpressibleByBooleanLiteral {}
extension AnyCodable: ExpressibleByIntegerLiteral {}
extension AnyCodable: ExpressibleByFloatLiteral {}
extension AnyCodable: ExpressibleByStringLiteral {}
extension AnyCodable: ExpressibleByStringInterpolation {}
extension AnyCodable: ExpressibleByArrayLiteral {}
extension AnyCodable: ExpressibleByDictionaryLiteral {}
extension AnyCodable: Hashable {
public func hash(into hasher: inout Hasher) {
switch value {
case let value as Bool:
hasher.combine(value)
case let value as Int:
hasher.combine(value)
case let value as Int8:
hasher.combine(value)
case let value as Int16:
hasher.combine(value)
case let value as Int32:
hasher.combine(value)
case let value as Int64:
hasher.combine(value)
case let value as UInt:
hasher.combine(value)
case let value as UInt8:
hasher.combine(value)
case let value as UInt16:
hasher.combine(value)
case let value as UInt32:
hasher.combine(value)
case let value as UInt64:
hasher.combine(value)
case let value as Float:
hasher.combine(value)
case let value as Double:
hasher.combine(value)
case let value as String:
hasher.combine(value)
case let value as [String: AnyCodable]:
hasher.combine(value)
case let value as [AnyCodable]:
hasher.combine(value)
default:
break
}
}
}

188
damus/Util/AnyCodable/AnyDecodable.swift

@ -0,0 +1,188 @@
#if canImport(Foundation)
import Foundation
#endif
/**
A type-erased `Decodable` value.
The `AnyDecodable` type forwards decoding responsibilities
to an underlying value, hiding its specific underlying type.
You can decode mixed-type values in dictionaries
and other collections that require `Decodable` conformance
by declaring their contained type to be `AnyDecodable`:
let json = """
{
"boolean": true,
"integer": 42,
"double": 3.141592653589793,
"string": "string",
"array": [1, 2, 3],
"nested": {
"a": "alpha",
"b": "bravo",
"c": "charlie"
},
"null": null
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
let dictionary = try! decoder.decode([String: AnyDecodable].self, from: json)
*/
@frozen public struct AnyDecodable: Decodable {
public let value: Any
public init<T>(_ value: T?) {
self.value = value ?? ()
}
}
@usableFromInline
protocol _AnyDecodable {
var value: Any { get }
init<T>(_ value: T?)
}
extension AnyDecodable: _AnyDecodable {}
extension _AnyDecodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if container.decodeNil() {
#if canImport(Foundation)
self.init(NSNull())
#else
self.init(Optional<Self>.none)
#endif
} else if let bool = try? container.decode(Bool.self) {
self.init(bool)
} else if let int = try? container.decode(Int.self) {
self.init(int)
} else if let uint = try? container.decode(UInt.self) {
self.init(uint)
} else if let double = try? container.decode(Double.self) {
self.init(double)
} else if let string = try? container.decode(String.self) {
self.init(string)
} else if let array = try? container.decode([AnyDecodable].self) {
self.init(array.map { $0.value })
} else if let dictionary = try? container.decode([String: AnyDecodable].self) {
self.init(dictionary.mapValues { $0.value })
} else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyDecodable value cannot be decoded")
}
}
}
extension AnyDecodable: Equatable {
public static func == (lhs: AnyDecodable, rhs: AnyDecodable) -> Bool {
switch (lhs.value, rhs.value) {
#if canImport(Foundation)
case is (NSNull, NSNull), is (Void, Void):
return true
#endif
case let (lhs as Bool, rhs as Bool):
return lhs == rhs
case let (lhs as Int, rhs as Int):
return lhs == rhs
case let (lhs as Int8, rhs as Int8):
return lhs == rhs
case let (lhs as Int16, rhs as Int16):
return lhs == rhs
case let (lhs as Int32, rhs as Int32):
return lhs == rhs
case let (lhs as Int64, rhs as Int64):
return lhs == rhs
case let (lhs as UInt, rhs as UInt):
return lhs == rhs
case let (lhs as UInt8, rhs as UInt8):
return lhs == rhs
case let (lhs as UInt16, rhs as UInt16):
return lhs == rhs
case let (lhs as UInt32, rhs as UInt32):
return lhs == rhs
case let (lhs as UInt64, rhs as UInt64):
return lhs == rhs
case let (lhs as Float, rhs as Float):
return lhs == rhs
case let (lhs as Double, rhs as Double):
return lhs == rhs
case let (lhs as String, rhs as String):
return lhs == rhs
case let (lhs as [String: AnyDecodable], rhs as [String: AnyDecodable]):
return lhs == rhs
case let (lhs as [AnyDecodable], rhs as [AnyDecodable]):
return lhs == rhs
default:
return false
}
}
}
extension AnyDecodable: CustomStringConvertible {
public var description: String {
switch value {
case is Void:
return String(describing: nil as Any?)
case let value as CustomStringConvertible:
return value.description
default:
return String(describing: value)
}
}
}
extension AnyDecodable: CustomDebugStringConvertible {
public var debugDescription: String {
switch value {
case let value as CustomDebugStringConvertible:
return "AnyDecodable(\(value.debugDescription))"
default:
return "AnyDecodable(\(description))"
}
}
}
extension AnyDecodable: Hashable {
public func hash(into hasher: inout Hasher) {
switch value {
case let value as Bool:
hasher.combine(value)
case let value as Int:
hasher.combine(value)
case let value as Int8:
hasher.combine(value)
case let value as Int16:
hasher.combine(value)
case let value as Int32:
hasher.combine(value)
case let value as Int64:
hasher.combine(value)
case let value as UInt:
hasher.combine(value)
case let value as UInt8:
hasher.combine(value)
case let value as UInt16:
hasher.combine(value)
case let value as UInt32:
hasher.combine(value)
case let value as UInt64:
hasher.combine(value)
case let value as Float:
hasher.combine(value)
case let value as Double:
hasher.combine(value)
case let value as String:
hasher.combine(value)
case let value as [String: AnyDecodable]:
hasher.combine(value)
case let value as [AnyDecodable]:
hasher.combine(value)
default:
break
}
}
}

291
damus/Util/AnyCodable/AnyEncodable.swift

@ -0,0 +1,291 @@
#if canImport(Foundation)
import Foundation
#endif
/**
A type-erased `Encodable` value.
The `AnyEncodable` type forwards encoding responsibilities
to an underlying value, hiding its specific underlying type.
You can encode mixed-type values in dictionaries
and other collections that require `Encodable` conformance
by declaring their contained type to be `AnyEncodable`:
let dictionary: [String: AnyEncodable] = [
"boolean": true,
"integer": 42,
"double": 3.141592653589793,
"string": "string",
"array": [1, 2, 3],
"nested": [
"a": "alpha",
"b": "bravo",
"c": "charlie"
],
"null": nil
]
let encoder = JSONEncoder()
let json = try! encoder.encode(dictionary)
*/
@frozen public struct AnyEncodable: Encodable {
public let value: Any
public init<T>(_ value: T?) {
self.value = value ?? ()
}
}
@usableFromInline
protocol _AnyEncodable {
var value: Any { get }
init<T>(_ value: T?)
}
extension AnyEncodable: _AnyEncodable {}
// MARK: - Encodable
extension _AnyEncodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch value {
#if canImport(Foundation)
case is NSNull:
try container.encodeNil()
#endif
case is Void:
try container.encodeNil()
case let bool as Bool:
try container.encode(bool)
case let int as Int:
try container.encode(int)
case let int8 as Int8:
try container.encode(int8)
case let int16 as Int16:
try container.encode(int16)
case let int32 as Int32:
try container.encode(int32)
case let int64 as Int64:
try container.encode(int64)
case let uint as UInt:
try container.encode(uint)
case let uint8 as UInt8:
try container.encode(uint8)
case let uint16 as UInt16:
try container.encode(uint16)
case let uint32 as UInt32:
try container.encode(uint32)
case let uint64 as UInt64:
try container.encode(uint64)
case let float as Float:
try container.encode(float)
case let double as Double:
try container.encode(double)
case let string as String:
try container.encode(string)
#if canImport(Foundation)
case let number as NSNumber:
try encode(nsnumber: number, into: &container)
case let date as Date:
try container.encode(date)
case let url as URL:
try container.encode(url)
#endif
case let array as [Any?]:
try container.encode(array.map { AnyEncodable($0) })
case let dictionary as [String: Any?]:
try container.encode(dictionary.mapValues { AnyEncodable($0) })
case let encodable as Encodable:
try encodable.encode(to: encoder)
default:
let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "AnyEncodable value cannot be encoded")
throw EncodingError.invalidValue(value, context)
}
}
#if canImport(Foundation)
private func encode(nsnumber: NSNumber, into container: inout SingleValueEncodingContainer) throws {
switch Character(Unicode.Scalar(UInt8(nsnumber.objCType.pointee))) {
case "B":
try container.encode(nsnumber.boolValue)
case "c":
try container.encode(nsnumber.int8Value)
case "s":
try container.encode(nsnumber.int16Value)
case "i", "l":
try container.encode(nsnumber.int32Value)
case "q":
try container.encode(nsnumber.int64Value)
case "C":
try container.encode(nsnumber.uint8Value)
case "S":
try container.encode(nsnumber.uint16Value)
case "I", "L":
try container.encode(nsnumber.uint32Value)
case "Q":
try container.encode(nsnumber.uint64Value)
case "f":
try container.encode(nsnumber.floatValue)
case "d":
try container.encode(nsnumber.doubleValue)
default:
let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "NSNumber cannot be encoded because its type is not handled")
throw EncodingError.invalidValue(nsnumber, context)
}
}
#endif
}
extension AnyEncodable: Equatable {
public static func == (lhs: AnyEncodable, rhs: AnyEncodable) -> Bool {
switch (lhs.value, rhs.value) {
case is (Void, Void):
return true
case let (lhs as Bool, rhs as Bool):
return lhs == rhs
case let (lhs as Int, rhs as Int):
return lhs == rhs
case let (lhs as Int8, rhs as Int8):
return lhs == rhs
case let (lhs as Int16, rhs as Int16):
return lhs == rhs
case let (lhs as Int32, rhs as Int32):
return lhs == rhs
case let (lhs as Int64, rhs as Int64):
return lhs == rhs
case let (lhs as UInt, rhs as UInt):
return lhs == rhs
case let (lhs as UInt8, rhs as UInt8):
return lhs == rhs
case let (lhs as UInt16, rhs as UInt16):
return lhs == rhs
case let (lhs as UInt32, rhs as UInt32):
return lhs == rhs
case let (lhs as UInt64, rhs as UInt64):
return lhs == rhs
case let (lhs as Float, rhs as Float):
return lhs == rhs
case let (lhs as Double, rhs as Double):
return lhs == rhs
case let (lhs as String, rhs as String):
return lhs == rhs
case let (lhs as [String: AnyEncodable], rhs as [String: AnyEncodable]):
return lhs == rhs
case let (lhs as [AnyEncodable], rhs as [AnyEncodable]):
return lhs == rhs
default:
return false
}
}
}
extension AnyEncodable: CustomStringConvertible {
public var description: String {
switch value {
case is Void:
return String(describing: nil as Any?)
case let value as CustomStringConvertible:
return value.description
default:
return String(describing: value)
}
}
}
extension AnyEncodable: CustomDebugStringConvertible {
public var debugDescription: String {
switch value {
case let value as CustomDebugStringConvertible:
return "AnyEncodable(\(value.debugDescription))"
default:
return "AnyEncodable(\(description))"
}
}
}
extension AnyEncodable: ExpressibleByNilLiteral {}
extension AnyEncodable: ExpressibleByBooleanLiteral {}
extension AnyEncodable: ExpressibleByIntegerLiteral {}
extension AnyEncodable: ExpressibleByFloatLiteral {}
extension AnyEncodable: ExpressibleByStringLiteral {}
extension AnyEncodable: ExpressibleByStringInterpolation {}
extension AnyEncodable: ExpressibleByArrayLiteral {}
extension AnyEncodable: ExpressibleByDictionaryLiteral {}
extension _AnyEncodable {
public init(nilLiteral _: ()) {
self.init(nil as Any?)
}
public init(booleanLiteral value: Bool) {
self.init(value)
}
public init(integerLiteral value: Int) {
self.init(value)
}
public init(floatLiteral value: Double) {
self.init(value)
}
public init(extendedGraphemeClusterLiteral value: String) {
self.init(value)
}
public init(stringLiteral value: String) {
self.init(value)
}
public init(arrayLiteral elements: Any...) {
self.init(elements)
}
public init(dictionaryLiteral elements: (AnyHashable, Any)...) {
self.init([AnyHashable: Any](elements, uniquingKeysWith: { first, _ in first }))
}
}
extension AnyEncodable: Hashable {
public func hash(into hasher: inout Hasher) {
switch value {
case let value as Bool:
hasher.combine(value)
case let value as Int:
hasher.combine(value)
case let value as Int8:
hasher.combine(value)
case let value as Int16:
hasher.combine(value)
case let value as Int32:
hasher.combine(value)
case let value as Int64:
hasher.combine(value)
case let value as UInt:
hasher.combine(value)
case let value as UInt8:
hasher.combine(value)
case let value as UInt16:
hasher.combine(value)
case let value as UInt32:
hasher.combine(value)
case let value as UInt64:
hasher.combine(value)
case let value as Float:
hasher.combine(value)
case let value as Double:
hasher.combine(value)
case let value as String:
hasher.combine(value)
case let value as [String: AnyEncodable]:
hasher.combine(value)
case let value as [AnyEncodable]:
hasher.combine(value)
default:
break
}
}
}
Loading…
Cancel
Save