diff --git a/Sources/Reflection/Any+Extensions.swift b/Sources/Reflection/Any+Extensions.swift index 3f620ce..acc5a5f 100644 --- a/Sources/Reflection/Any+Extensions.swift +++ b/Sources/Reflection/Any+Extensions.swift @@ -22,7 +22,7 @@ extension AnyExtensions { return storage.assumingMemoryBound(to: self).pointee } - static func write(_ value: Any, to storage: UnsafeMutableRawPointer) throws { + static func write(_ value: Any?, to storage: UnsafeMutableRawPointer) throws { guard let this = value as? Self else { throw ReflectionError.valueIsNotType(value: value, type: self) } diff --git a/Sources/Reflection/Properties.swift b/Sources/Reflection/Properties.swift index ab10021..930abf7 100644 --- a/Sources/Reflection/Properties.swift +++ b/Sources/Reflection/Properties.swift @@ -24,7 +24,7 @@ public struct Property { public let key: String public let type: Any.Type let offset: Int - func write(_ value: Any, to storage: UnsafeMutableRawPointer) throws { + func write(_ value: Any?, to storage: UnsafeMutableRawPointer) throws { return try extensions(of: type).write(value, to: storage.advanced(by: offset)) } } diff --git a/Sources/Reflection/ReflectionError.swift b/Sources/Reflection/ReflectionError.swift index 2030ad7..2112394 100644 --- a/Sources/Reflection/ReflectionError.swift +++ b/Sources/Reflection/ReflectionError.swift @@ -1,6 +1,6 @@ public enum ReflectionError : Error, CustomStringConvertible, Equatable { case notStruct(type: Any.Type) - case valueIsNotType(value: Any, type: Any.Type) + case valueIsNotType(value: Any?, type: Any.Type) case instanceHasNoKey(type: Any.Type, key: String) case requiredValueMissing(key: String) case unexpected diff --git a/Sources/Reflection/Set.swift b/Sources/Reflection/Set.swift index 264bd33..9c15dfc 100644 --- a/Sources/Reflection/Set.swift +++ b/Sources/Reflection/Set.swift @@ -1,17 +1,17 @@ /// Set value for key of an instance -public func set(_ value: Any, key: String, for instance: inout Any) throws { +public func set(_ value: Any?, key: String, for instance: inout Any) throws { let type = Swift.type(of: instance) try property(type: type, key: key).write(value, to: mutableStorage(instance: &instance, type: type)) } /// Set value for key of an instance -public func set(_ value: Any, key: String, for instance: AnyObject) throws { +public func set(_ value: Any?, key: String, for instance: AnyObject) throws { var copy: Any = instance try set(value, key: key, for: ©) } /// Set value for key of an instance -public func set(_ value: Any, key: String, for instance: inout T) throws { +public func set(_ value: Any?, key: String, for instance: inout T) throws { try property(type: T.self, key: key).write(value, to: mutableStorage(instance: &instance)) } diff --git a/Tests/ReflectionTests/PublicTests.swift b/Tests/ReflectionTests/PublicTests.swift index 4565c18..4277af0 100644 --- a/Tests/ReflectionTests/PublicTests.swift +++ b/Tests/ReflectionTests/PublicTests.swift @@ -2,9 +2,9 @@ import XCTest import Reflection struct Person : Equatable { - var firstName: String + var firstName: String? var lastName: String - var age: Int + var age: Int? init(firstName: String, lastName: String, age: Int) { self.firstName = firstName @@ -133,7 +133,14 @@ public class PublicTests : XCTestCase { func testSetValueForKeyOfInstance() throws { var person = Person(firstName: "Brad", lastName: "Hilton", age: 27) try set("Lawrence", key: "firstName", for: &person) - XCTAssert(person.firstName == "Lawrence") + XCTAssertEqual(person.firstName, "Lawrence") + try set(nil, key: "firstName", for: &person) + XCTAssertNil(person.firstName) + XCTAssertEqual(person.age, 27) + try set(nil, key: "age", for: &person) + XCTAssertNil(person.age) + try set(28, key: "age", for: &person) + XCTAssertEqual(person.age, 28) } func testValueForKeyOfInstance() throws { @@ -204,9 +211,7 @@ public class PublicTests : XCTestCase { XCTFail() } catch let constructionErrors as ConstructionErrors { let expectedErrors: [ReflectionError] = [ - .requiredValueMissing(key: "firstName"), .requiredValueMissing(key: "lastName"), - .requiredValueMissing(key: "age") ] XCTAssertEqual(constructionErrors.errors.compactMap { $0 as? ReflectionError }, expectedErrors) } catch {