Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates #3

Merged
merged 6 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## What type of PR is this? (check all applicable)

- [ ] Refactor
- [ ] Feature
- [ ] Bug Fix
- [ ] Optimization
- [ ] Documentation Update

## Description

_Please replace this line with a description of what this PR does, and why._

## Related Issues Tickets

- Related Issue #
- Closes #

## Instructions, Screenshots, Recordings (If Applicable)

_Please replace this line with instructions on how to test your changes, a note
on the devices this has been tested on, as well as any relevant instructions._

## Added/updated tests?
_We encourage you to keep the code coverage percentage at 80% and above._

- [ ] Yes
- [ ] No, They aren't needed.
- [ ] No, I need help with writing tests.

## [optional] Other information:
20 changes: 10 additions & 10 deletions Sources/SGSerializable/Helpers/SGSerializable+FallBack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ import UIKit
#endif

extension SGSerializable {
func getFallBack<Value>(_ type: Value.Type) -> Value {
func getFallBack<V>(_ type: V.Type) -> V {
switch self.type {
case .int: return 0 as! Value
case .double: return 0 as! Value
case .bool: return false as! Value
case .float: return 0 as! Value
case .string: return "" as! Value
case .auto: return processAuto(Value.self)
case .none: fatalError("\(Value.self) has been used before initialization.")
case .int: return 0 as! V
case .double: return 0 as! V
case .bool: return false as! V
case .float: return 0 as! V
case .string: return "" as! V
case .auto: return processAuto(V.self)
case .none: fatalError("\(V.self) has been used before initialization.")
}
}
}

extension SGTransformSerializable {
func getFallBack<Value>(_ type: Value.Type) -> Value {
return processAuto(Value.self)
func getFallBack<W>(_ type: W.Type) -> W {
return processAuto(W.self)
}
}

Expand Down
7 changes: 3 additions & 4 deletions Sources/SGSerializable/Transformable/SGTransformDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@

import Foundation

extension SGTransformSerializable: SGDecoder where Value.FromType: Decodable {
extension SGTransformSerializable: SGDecoder where Transform.FromType: Decodable {
func decodeValue(from container: DecodeContainer, with key: String) throws {
if let value = try? container.decodeIfPresent(Value.FromType.self, forKey: getKey(with: key)) {
wrappedValue = Value.transform(from: value)
}
let value = try container.decodeIfPresent(Transform.FromType.self, forKey: getKey(with: key))
wrappedValue = Transform.transform(from: value)
}
}
4 changes: 2 additions & 2 deletions Sources/SGSerializable/Transformable/SGTransformEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import Foundation

extension SGTransformSerializable: SGEncoder where Value.FromType: Encodable {
extension SGTransformSerializable: SGEncoder where Transform.FromType: Encodable {
func encodeValue(from container: inout EncodeContainer, with key: String) throws {
try container.encodeIfPresent(Value.transform(from: wrappedValue), forKey: getKey(with: key))
try container.encodeIfPresent(Transform.transform(from: wrappedValue), forKey: getKey(with: key))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,29 @@ import Foundation
///
/// You must provide custom implementation of `SGTranformable` which is needed for transformation.
@propertyWrapper
public final class SGTransformSerializable<Value: SGTranformable> {
public var wrappedValue: Value.ToType?
public final class SGTransformSerializable<Transform: SGTranformable> {
public var wrappedValue: Transform.ToType?
public var name: String?

public var projectedValue: Value.ToType {
public var projectedValue: Transform.ToType {
set { wrappedValue = newValue }
get {
guard let wrappedValue = wrappedValue else {
return getFallBack(Value.ToType.self)
return getFallBack(Transform.ToType.self)
}
return wrappedValue
}
}

public init(default value: Value.ToType? = nil, key: String? = nil) {
public init(default value: Transform.ToType? = nil, key: String? = nil) {
self.wrappedValue = value
self.name = key
}
}

extension SGTransformSerializable {
internal func getKey(with key: String) -> SGCodingKey {
let cKey: SGCodingKey!
let cKey: SGCodingKey
if let name = name, !name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
cKey = SGCodingKey(name: name)
}else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// MilliSecondsToDate.swift
// SGSerializable
//
// Created by Rehan Ali on 02/11/2023 at 12:49 AM.
// Copyright © 2022 Rehan Ali. All rights reserved.
//

import Foundation

public struct MilliSecondsToDate: SGTranformable {
public typealias FromType = TimeInterval
public typealias ToType = Date

public static func transform(from value: TimeInterval?) -> Date? {
guard let value = value else { return nil }
return Date(timeIntervalSince1970: value / 1000)
}

public static func transform(from value: Date?) -> TimeInterval? {
guard let value = value else { return nil }
return value.timeIntervalSince1970 * 1000
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,61 @@ class SGAdvancedTransformSerializable: QuickSpec, EncodableTestSpec, DecodableTe
expect(dict?["time"] as? TimeInterval).to(equal(1263008235))
}
}

context("Milliseconds Date") {
var object: MilliSecondDate?
it("should access default value before [En/De]Coding") {
object = MilliSecondDate()
expect(object).toNot(beNil())
expect(object?.date).to(beNil())
expect(object?.$date).to(equal(Date(timeIntervalSince1970: 0)))
}

it("should decode properly using Default") {
object = try? self.jsonDecoder.decode(MilliSecondDate.self, from: jsonData)

let calendar = Calendar.current
let actualDate = calendar.date(from: .init(timeZone: .init(secondsFromGMT: 0), year: 2010, month: 1, day: 9, hour: 3, minute: 37, second: 15))

expect(object).toNot(beNil())
expect(object?.date).to(equal(actualDate))
expect(object?.$date).to(equal(actualDate!))
}

it("should decode properly using custom") {
object = try? MilliSecondDate.initialize(with: jsonData)

let calendar = Calendar.current
let actualDate = calendar.date(from: .init(timeZone: .init(secondsFromGMT: 0), year: 2010, month: 1, day: 9, hour: 3, minute: 37, second: 15))

expect(object).toNot(beNil())
expect(object?.date).to(equal(actualDate))
expect(object?.$date).to(equal(actualDate!))
}

it("should encode propery using default") {
object = try? MilliSecondDate.initialize(with: jsonData)
let data = try? self.jsonEncoder.encode(object)

guard let data = data , let string = String(data: data, encoding: .utf8) else {
fail("Unable to get valid string")
return
}

let nsDict = try? JSONSerializer.toDictionary(string)
let dict = nsDict?.swiftDictionary
expect(dict).toNot(beNil())
expect(dict?["timeMilli"] as? TimeInterval).to(equal(1263008235000))
}

it("should encode propery using custom") {
object = try? MilliSecondDate.initialize(with: jsonData)

let dict = object?.dictionary
expect(dict).toNot(beNil())
expect(dict?["timeMilli"] as? TimeInterval).to(equal(1263008235000))
}
}
}
}
}
Expand All @@ -279,7 +334,8 @@ fileprivate let jsonData = """
"base64Encoded": "SGkhIHRoZXJlLiBJJ20gaGFwcHkgdG8gc2VlIHlvdS4=",
"url": "https://www.apple.com",
"datetime": "2021-09-12T23:43:33Z",
"time": 1263008235
"time": 1263008235,
"timeMilli": 1263008235000
}
""".data(using: .utf8)!

Expand All @@ -303,6 +359,11 @@ fileprivate struct TimeIntervalDate: SGCodable {
var date: Date?
}

fileprivate struct MilliSecondDate: SGCodable {
@SGTransformSerializable<MilliSecondsToDate>(key: "timeMilli")
var date: Date?
}

fileprivate struct StringURL: SGCodable {
@SGTransformSerializable<StringToURL>
var url: URL?
Expand Down