Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save YannisDC/c3fef28ff24684797bbdeb85f82eec55 to your computer and use it in GitHub Desktop.
Save YannisDC/c3fef28ff24684797bbdeb85f82eec55 to your computer and use it in GitHub Desktop.
import Cocoa
fileprivate extension CodingUserInfoKey {
static let fragmentBoxedType = CodingUserInfoKey(rawValue: "CodingUserInfoKey.fragmentBoxedType")!
}
extension JSONDecoder {
private struct FragmentDecodingBox<T : Decodable> : Decodable {
var value: T
init(from decoder: Decoder) throws {
let type = decoder.userInfo[.fragmentBoxedType] as! T.Type
var container = try decoder.unkeyedContainer()
self.value = try container.decode(type)
}
}
private func copy() -> JSONDecoder {
let decoder = JSONDecoder()
decoder.dataDecodingStrategy = dataDecodingStrategy
decoder.dateDecodingStrategy = dateDecodingStrategy
decoder.keyDecodingStrategy = keyDecodingStrategy
decoder.nonConformingFloatDecodingStrategy = nonConformingFloatDecodingStrategy
decoder.userInfo = userInfo
return decoder
}
public func decode<T : Decodable> ( _ type: T.Type, from data: Data, allowFragments: Bool ) throws -> T {
guard allowFragments else { return try decode(type, from: data) }
if "\(T.self)" == "String" { return String(data: data, encoding: .utf8) as! T }
let jsonObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
let boxedData = try JSONSerialization.data(withJSONObject: [jsonObject])
let decoder = copy()
decoder.userInfo[.fragmentBoxedType] = type
return try decoder.decode(FragmentDecodingBox<T>.self, from: boxedData).value
}
}
struct Person: Codable {
let name: String
let age: Int
let friends: [Person]?
}
let person = Person(name: "Brad", age: 53, friends: nil)
protocol Identifiable {
var uuid: String { get set }
}
protocol Encryptable {
var encrypted: Bool { get }
func encrypt()
func decrypt()
}
public class EncryptableProperty<T: Codable>: Encryptable, Codable {
var value: T
var encryptedValue: String
var encrypted: Bool
init(value: T, encrypted: Bool) {
self.value = value
self.encrypted = encrypted
self.encryptedValue = ""
}
func encrypt() {
if value is LosslessStringConvertible, let value = value as? LosslessStringConvertible {
self.encryptedValue = value.description
} else {
do {
let object = try JSONEncoder().encode(value)
// Do actual encryption and get the signature back
if let string = String(data: object, encoding: .utf8) {
print(string)
encryptedValue = string
} else {
print("not a valid UTF-8 sequence")
}
} catch{
print("Encoding failed")
}
}
}
func decrypt() {
do {
let data : [UInt8] = [UInt8](self.encryptedValue.utf8)
// Do actual decryption and get the data back
let object = try JSONDecoder().decode(T.self, from: Data(data), allowFragments: true)
self.value = object
} catch{
print("Decoding failed")
}
}
}
protocol EncryptableObject: Codable {
func encryptObject()
func decryptObject()
}
struct Test: EncryptableObject, Identifiable {
public let array: EncryptableProperty<Array<String>>
public let person: EncryptableProperty<Person>
public let string: EncryptableProperty<String>
var uuid: String
init(uuid: String = UUID().uuidString) {
self.array = EncryptableProperty<Array<String>>(value: ["one", "two"], encrypted: true)
self.person = EncryptableProperty<Person>(value: Person(name: "Brad", age: 53, friends: nil), encrypted: true)
self.string = EncryptableProperty<String>(value: "Test", encrypted: true)
self.uuid = uuid
}
func encryptObject() {
print("\nEncryption happens")
Mirror(reflecting: self)
.children
.forEach { (property) in
if let encryptableValue = property.value as? Encryptable {
encryptableValue.encrypt()
}
}
}
func decryptObject() {
print("\nDecryption happens")
Mirror(reflecting: self)
.children
.forEach { (property) in
if let encryptableValue = property.value as? Encryptable {
encryptableValue.decrypt()
}
}
}
}
let test = Test()
print("Value= \(test.array.value) EncryptedValue= \(test.array.encryptedValue)")
test.encryptObject()
print("Value= \(test.array.value) EncryptedValue= \(test.array.encryptedValue)")
print("\nDecrypted value gets updated")
test.array.encryptedValue = #"["sir", "yannis"]"#
print("Value= \(test.array.value) EncryptedValue= \(test.array.encryptedValue)")
test.decryptObject()
print("Value= \(test.array.value) EncryptedValue= \(test.array.encryptedValue)")
do {
let testJson = try JSONEncoder().encode(test)
if let string = String(data: testJson, encoding: .utf8) {
print(string)
} else {
print("not a valid UTF-8 sequence")
}
} catch {
print("FAIL")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment