From 1a6e4ad5e8c13110e362338731b3583b8c305162 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Tue, 8 Nov 2022 23:28:23 +0100
Subject: [PATCH] Add Stored.userDefaults implementation

---
 Sources/XXMessengerClient/Utils/Stored.swift  | 21 ++++++++++++
 .../Utils/StoredTests.swift                   | 34 ++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/Sources/XXMessengerClient/Utils/Stored.swift b/Sources/XXMessengerClient/Utils/Stored.swift
index 052d6387..ab0de7e1 100644
--- a/Sources/XXMessengerClient/Utils/Stored.swift
+++ b/Sources/XXMessengerClient/Utils/Stored.swift
@@ -1,3 +1,4 @@
+import Foundation
 import XCTestDynamicOverlay
 
 public struct Stored<Value> {
@@ -31,6 +32,26 @@ private final class Memory<Value> {
   var value: Value
 }
 
+extension Stored {
+  public static func userDefaults<T>(
+    key: String,
+    userDefaults: UserDefaults = .standard
+  ) -> Stored<T?> where T: Codable {
+    let encoder = JSONEncoder()
+    let decoder = JSONDecoder()
+    return Stored<T?>(
+      get: {
+        guard let data = userDefaults.data(forKey: key) else { return nil }
+        return try? decoder.decode(T.self, from: data)
+      },
+      set: { newValue in
+        let data = try? encoder.encode(newValue)
+        userDefaults.set(data, forKey: key)
+      }
+    )
+  }
+}
+
 extension Stored {
   public struct MissingValueError: Error, Equatable {
     public init(typeDescription: String) {
diff --git a/Tests/XXMessengerClientTests/Utils/StoredTests.swift b/Tests/XXMessengerClientTests/Utils/StoredTests.swift
index 154f6196..834097ef 100644
--- a/Tests/XXMessengerClientTests/Utils/StoredTests.swift
+++ b/Tests/XXMessengerClientTests/Utils/StoredTests.swift
@@ -1,8 +1,9 @@
+import CustomDump
 import XCTest
 @testable import XXMessengerClient
 
 final class StoredTests: XCTestCase {
-  func testInMemory() throws {
+  func testInMemory() {
     let stored: Stored<String?> = .inMemory()
 
     XCTAssertNil(stored())
@@ -15,4 +16,35 @@ final class StoredTests: XCTestCase {
 
     XCTAssertNil(stored())
   }
+
+  func testUserDefaults() {
+    struct Value: Equatable, Codable {
+      var id = UUID()
+    }
+
+    let key = "key"
+    let userDefaults = UserDefaults(suiteName: "XXMessengerClient_StoredTests")!
+    userDefaults.removeObject(forKey: key)
+    let stored: Stored<Value?> = .userDefaults(
+      key: key,
+      userDefaults: userDefaults
+    )
+
+    XCTAssertNoDifference(stored.get(), nil)
+
+    let value = Value()
+    stored.set(value)
+
+    XCTAssertNoDifference(
+      userDefaults.data(forKey: key).map { data in
+        try? JSONDecoder().decode(Value.self, from: data)
+      },
+      value
+    )
+    XCTAssertNoDifference(stored.get(), value)
+
+    userDefaults.set(nil, forKey: key)
+
+    XCTAssertNoDifference(stored.get(), nil)
+  }
 }
-- 
GitLab