SPB Git

spb/os-vault Public

Self-custody, multi-chain crypto wallet for macOS. One recovery phrase, six chain families, zero API keys — nothing leaves your Mac.

Swift 96% Shell 3.4% Makefile 0.6%
14.3 KB · 459 lines swift
Raw Blame History
1import Foundation23@frozen public struct AnyDecodable: Decodable {4    public let value: Any56    public init<T>(_ value: T?) {7        self.value = value ?? ()8    }9}1011@usableFromInline12protocol _AnyDecodable {13    var value: Any { get }14    init<T>(_ value: T?)15}1617extension AnyDecodable: _AnyDecodable {}1819extension _AnyDecodable {20    public init(from decoder: Decoder) throws {21        let container = try decoder.singleValueContainer()2223        if container.decodeNil() {24            #if canImport(Foundation)25                self.init(NSNull())26            #else27                self.init(Self?.none)28            #endif29        } else if let bool = try? container.decode(Bool.self) {30            self.init(bool)31        } else if let int = try? container.decode(Int.self) {32            self.init(int)33        } else if let uint = try? container.decode(UInt.self) {34            self.init(uint)35        } else if let double = try? container.decode(Double.self) {36            self.init(double)37        } else if let string = try? container.decode(String.self) {38            self.init(string)39        } else if let array = try? container.decode([AnyDecodable].self) {40            self.init(array.map(\.value))41        } else if let dictionary = try? container.decode([String: AnyDecodable].self) {42            self.init(dictionary.mapValues { $0.value })43        } else {44            throw DecodingError.dataCorruptedError(45                in: container,46                debugDescription: "AnyDecodable value cannot be decoded"47            )48        }49    }50}5152extension AnyDecodable: Equatable {53    public static func == (lhs: AnyDecodable, rhs: AnyDecodable) -> Bool {54        switch (lhs.value, rhs.value) {55        #if canImport(Foundation)56            case is (NSNull, NSNull), is (Void, Void):57                return true58        #endif59        case let (lhs as Bool, rhs as Bool):60            return lhs == rhs61        case let (lhs as Int, rhs as Int):62            return lhs == rhs63        case let (lhs as Int8, rhs as Int8):64            return lhs == rhs65        case let (lhs as Int16, rhs as Int16):66            return lhs == rhs67        case let (lhs as Int32, rhs as Int32):68            return lhs == rhs69        case let (lhs as Int64, rhs as Int64):70            return lhs == rhs71        case let (lhs as UInt, rhs as UInt):72            return lhs == rhs73        case let (lhs as UInt8, rhs as UInt8):74            return lhs == rhs75        case let (lhs as UInt16, rhs as UInt16):76            return lhs == rhs77        case let (lhs as UInt32, rhs as UInt32):78            return lhs == rhs79        case let (lhs as UInt64, rhs as UInt64):80            return lhs == rhs81        case let (lhs as Float, rhs as Float):82            return lhs == rhs83        case let (lhs as Double, rhs as Double):84            return lhs == rhs85        case let (lhs as String, rhs as String):86            return lhs == rhs87        case let (lhs as [String: AnyDecodable], rhs as [String: AnyDecodable]):88            return lhs == rhs89        case let (lhs as [AnyDecodable], rhs as [AnyDecodable]):90            return lhs == rhs91        default:92            return false93        }94    }95}9697extension AnyDecodable: CustomStringConvertible {98    public var description: String {99        switch value {100        case is Void:101            return String(describing: nil as Any?)102        case let value as CustomStringConvertible:103            return value.description104        default:105            return String(describing: value)106        }107    }108}109110extension AnyDecodable: CustomDebugStringConvertible {111    public var debugDescription: String {112        switch value {113        case let value as CustomDebugStringConvertible:114            return "AnyDecodable(\(value.debugDescription))"115        default:116            return "AnyDecodable(\(description))"117        }118    }119}120121extension AnyDecodable: Hashable {122    public func hash(into hasher: inout Hasher) {123        switch value {124        case let value as Bool:125            hasher.combine(value)126        case let value as Int:127            hasher.combine(value)128        case let value as Int8:129            hasher.combine(value)130        case let value as Int16:131            hasher.combine(value)132        case let value as Int32:133            hasher.combine(value)134        case let value as Int64:135            hasher.combine(value)136        case let value as UInt:137            hasher.combine(value)138        case let value as UInt8:139            hasher.combine(value)140        case let value as UInt16:141            hasher.combine(value)142        case let value as UInt32:143            hasher.combine(value)144        case let value as UInt64:145            hasher.combine(value)146        case let value as Float:147            hasher.combine(value)148        case let value as Double:149            hasher.combine(value)150        case let value as String:151            hasher.combine(value)152        case let value as [String: AnyDecodable]:153            hasher.combine(value)154        case let value as [AnyDecodable]:155            hasher.combine(value)156        default:157            break158        }159    }160}161162#if canImport(Foundation)163    import Foundation164#endif165166/**167 A type-erased `Encodable` value.168169 The `AnyEncodable` type forwards encoding responsibilities170 to an underlying value, hiding its specific underlying type.171172 You can encode mixed-type values in dictionaries173 and other collections that require `Encodable` conformance174 by declaring their contained type to be `AnyEncodable`:175176     let dictionary: [String: AnyEncodable] = [177         "boolean": true,178         "integer": 42,179         "double": 3.141592653589793,180         "string": "string",181         "array": [1, 2, 3],182         "nested": [183             "a": "alpha",184             "b": "bravo",185             "c": "charlie"186         ],187         "null": nil188     ]189190     let encoder = JSONEncoder()191     let json = try! encoder.encode(dictionary)192 */193@frozen public struct AnyEncodable: Encodable {194    public let value: Any195196    public init<T>(_ value: T?) {197        self.value = value ?? ()198    }199}200201@usableFromInline202protocol _AnyEncodable {203    var value: Any { get }204    init<T>(_ value: T?)205}206207extension AnyEncodable: _AnyEncodable {}208209// MARK: - Encodable210211extension _AnyEncodable {212    public func encode(to encoder: Encoder) throws {213        var container = encoder.singleValueContainer()214215        switch value {216        #if canImport(Foundation)217            case is NSNull:218                try container.encodeNil()219        #endif220        case is Void:221            try container.encodeNil()222        case let bool as Bool:223            try container.encode(bool)224        case let int as Int:225            try container.encode(int)226        case let int8 as Int8:227            try container.encode(int8)228        case let int16 as Int16:229            try container.encode(int16)230        case let int32 as Int32:231            try container.encode(int32)232        case let int64 as Int64:233            try container.encode(int64)234        case let uint as UInt:235            try container.encode(uint)236        case let uint8 as UInt8:237            try container.encode(uint8)238        case let uint16 as UInt16:239            try container.encode(uint16)240        case let uint32 as UInt32:241            try container.encode(uint32)242        case let uint64 as UInt64:243            try container.encode(uint64)244        case let float as Float:245            try container.encode(float)246        case let double as Double:247            try container.encode(double)248        case let string as String:249            try container.encode(string)250        #if canImport(Foundation)251            case let number as NSNumber:252                try encode(nsnumber: number, into: &container)253            case let date as Date:254                try container.encode(date)255            case let url as URL:256                try container.encode(url)257        #endif258        case let array as [Any?]:259            try container.encode(array.map { AnyEncodable($0) })260        case let dictionary as [String: Any?]:261            try container.encode(dictionary.mapValues { AnyEncodable($0) })262        case let encodable as Encodable:263            try encodable.encode(to: encoder)264        default:265            let context = EncodingError.Context(266                codingPath: container.codingPath,267                debugDescription: "AnyEncodable value cannot be encoded"268            )269            throw EncodingError.invalidValue(value, context)270        }271    }272273    #if canImport(Foundation)274        private func encode(nsnumber: NSNumber, into container: inout SingleValueEncodingContainer) throws {275            switch Character(Unicode.Scalar(UInt8(nsnumber.objCType.pointee))) {276            case "B":277                try container.encode(nsnumber.boolValue)278            case "c":279                try container.encode(nsnumber.int8Value)280            case "s":281                try container.encode(nsnumber.int16Value)282            case "i", "l":283                try container.encode(nsnumber.int32Value)284            case "q":285                try container.encode(nsnumber.int64Value)286            case "C":287                try container.encode(nsnumber.uint8Value)288            case "S":289                try container.encode(nsnumber.uint16Value)290            case "I", "L":291                try container.encode(nsnumber.uint32Value)292            case "Q":293                try container.encode(nsnumber.uint64Value)294            case "f":295                try container.encode(nsnumber.floatValue)296            case "d":297                try container.encode(nsnumber.doubleValue)298            default:299                let context = EncodingError.Context(300                    codingPath: container.codingPath,301                    debugDescription: "NSNumber cannot be encoded because its type is not handled"302                )303                throw EncodingError.invalidValue(nsnumber, context)304            }305        }306    #endif307}308309extension AnyEncodable: Equatable {310    public static func == (lhs: AnyEncodable, rhs: AnyEncodable) -> Bool {311        switch (lhs.value, rhs.value) {312        case is (Void, Void):313            return true314        case let (lhs as Bool, rhs as Bool):315            return lhs == rhs316        case let (lhs as Int, rhs as Int):317            return lhs == rhs318        case let (lhs as Int8, rhs as Int8):319            return lhs == rhs320        case let (lhs as Int16, rhs as Int16):321            return lhs == rhs322        case let (lhs as Int32, rhs as Int32):323            return lhs == rhs324        case let (lhs as Int64, rhs as Int64):325            return lhs == rhs326        case let (lhs as UInt, rhs as UInt):327            return lhs == rhs328        case let (lhs as UInt8, rhs as UInt8):329            return lhs == rhs330        case let (lhs as UInt16, rhs as UInt16):331            return lhs == rhs332        case let (lhs as UInt32, rhs as UInt32):333            return lhs == rhs334        case let (lhs as UInt64, rhs as UInt64):335            return lhs == rhs336        case let (lhs as Float, rhs as Float):337            return lhs == rhs338        case let (lhs as Double, rhs as Double):339            return lhs == rhs340        case let (lhs as String, rhs as String):341            return lhs == rhs342        case let (lhs as [String: AnyEncodable], rhs as [String: AnyEncodable]):343            return lhs == rhs344        case let (lhs as [AnyEncodable], rhs as [AnyEncodable]):345            return lhs == rhs346        default:347            return false348        }349    }350}351352extension AnyEncodable: CustomStringConvertible {353    public var description: String {354        switch value {355        case is Void:356            return String(describing: nil as Any?)357        case let value as CustomStringConvertible:358            return value.description359        default:360            return String(describing: value)361        }362    }363}364365extension AnyEncodable: CustomDebugStringConvertible {366    public var debugDescription: String {367        switch value {368        case let value as CustomDebugStringConvertible:369            return "AnyEncodable(\(value.debugDescription))"370        default:371            return "AnyEncodable(\(description))"372        }373    }374}375376extension AnyEncodable: ExpressibleByNilLiteral {}377extension AnyEncodable: ExpressibleByBooleanLiteral {}378extension AnyEncodable: ExpressibleByIntegerLiteral {}379extension AnyEncodable: ExpressibleByFloatLiteral {}380extension AnyEncodable: ExpressibleByStringLiteral {}381extension AnyEncodable: ExpressibleByStringInterpolation {}382extension AnyEncodable: ExpressibleByArrayLiteral {}383extension AnyEncodable: ExpressibleByDictionaryLiteral {}384385extension _AnyEncodable {386    public init(nilLiteral _: ()) {387        self.init(nil as Any?)388    }389390    public init(booleanLiteral value: Bool) {391        self.init(value)392    }393394    public init(integerLiteral value: Int) {395        self.init(value)396    }397398    public init(floatLiteral value: Double) {399        self.init(value)400    }401402    public init(extendedGraphemeClusterLiteral value: String) {403        self.init(value)404    }405406    public init(stringLiteral value: String) {407        self.init(value)408    }409410    public init(arrayLiteral elements: Any...) {411        self.init(elements)412    }413414    public init(dictionaryLiteral elements: (AnyHashable, Any)...) {415        self.init([AnyHashable: Any](elements, uniquingKeysWith: { first, _ in first }))416    }417}418419extension AnyEncodable: Hashable {420    public func hash(into hasher: inout Hasher) {421        switch value {422        case let value as Bool:423            hasher.combine(value)424        case let value as Int:425            hasher.combine(value)426        case let value as Int8:427            hasher.combine(value)428        case let value as Int16:429            hasher.combine(value)430        case let value as Int32:431            hasher.combine(value)432        case let value as Int64:433            hasher.combine(value)434        case let value as UInt:435            hasher.combine(value)436        case let value as UInt8:437            hasher.combine(value)438        case let value as UInt16:439            hasher.combine(value)440        case let value as UInt32:441            hasher.combine(value)442        case let value as UInt64:443            hasher.combine(value)444        case let value as Float:445            hasher.combine(value)446        case let value as Double:447            hasher.combine(value)448        case let value as String:449            hasher.combine(value)450        case let value as [String: AnyEncodable]:451            hasher.combine(value)452        case let value as [AnyEncodable]:453            hasher.combine(value)454        default:455            break456        }457    }458}459