Skip to content

Commit 50f4c7b

Browse files
fix: share AnyEncodable with DatadogInternal for correct attribute decoding
1 parent f9bc7bd commit 50f4c7b

3 files changed

Lines changed: 20 additions & 86 deletions

File tree

packages/core/ios/Sources/AnyEncodable.swift

Lines changed: 16 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Copyright 2019-2020 Datadog, Inc.
55
*/
66

7+
import DatadogInternal
78
import Foundation
89

910
internal func castAttributesToSwift(_ attributes: NSDictionary) -> [String: Encodable] {
@@ -29,39 +30,39 @@ internal func castValueToSwift(_ value: Any) -> Encodable {
2930
// Otherwise, cast by preserving its encoded value (and loosing type information)
3031
casted = castByPreservingEncodedValue(attributeValue: value)
3132
}
32-
33+
3334
return casted
3435
}
3536

3637
/// Casts `Any` value to `Encodable` by preserving its type information.
3738
private func castByPreservingTypeInformation(attributeValue: Any) -> Encodable? {
3839
switch attributeValue {
39-
case let string as String: // unpacking `NSTaggedPointerString`
40-
return string // cast to String
41-
case let number as NSNumber: // unpacking `__NSCFNumber`
40+
case let string as String: // unpacking `NSTaggedPointerString`
41+
return string // cast to String
42+
case let number as NSNumber: // unpacking `__NSCFNumber`
4243
switch CFNumberGetType(number) {
4344
case .charType:
44-
return number.boolValue // cast to Bool
45+
return number.boolValue // cast to Bool
4546
case .sInt8Type:
46-
return number.int8Value // cast to Int8
47+
return number.int8Value // cast to Int8
4748
case .sInt16Type:
48-
return number.int16Value // cast to Int16
49+
return number.int16Value // cast to Int16
4950
case .sInt32Type:
50-
return number.int32Value // cast to Int32
51+
return number.int32Value // cast to Int32
5152
case .sInt64Type:
52-
return number.int64Value // cast to Int64
53+
return number.int64Value // cast to Int64
5354
case .shortType:
54-
return number.uint16Value // cast to UInt 16
55+
return number.uint16Value // cast to UInt 16
5556
case .longType:
56-
return number.uint32Value // cast to UInt32
57+
return number.uint32Value // cast to UInt32
5758
case .longLongType:
58-
return number.uint64Value // cast to UInt64
59+
return number.uint64Value // cast to UInt64
5960
case .intType, .nsIntegerType, .cfIndexType:
60-
return number.intValue // cast to Int
61+
return number.intValue // cast to Int
6162
case .floatType, .float32Type:
62-
return number.floatValue // cast to Float
63+
return number.floatValue // cast to Float
6364
case .doubleType, .float64Type, .cgFloatType:
64-
return number.doubleValue // cast to Double
65+
return number.doubleValue // cast to Double
6566
@unknown default:
6667
return nil
6768
}
@@ -75,71 +76,3 @@ private func castByPreservingTypeInformation(attributeValue: Any) -> Encodable?
7576
private func castByPreservingEncodedValue(attributeValue: Any) -> Encodable {
7677
return AnyEncodable(attributeValue)
7778
}
78-
79-
/// Type erasing `Encodable` wrapper to bridge Objective-C's `Any` to Swift `Encodable`.
80-
///
81-
/// Inspired by `AnyCodable` by Flight-School (MIT):
82-
/// https://github.com/Flight-School/AnyCodable/blob/master/Sources/AnyCodable/AnyEncodable.swift
83-
internal class AnyEncodable: Encodable {
84-
internal let value: Any
85-
86-
init(_ value: Any) {
87-
self.value = value
88-
}
89-
90-
func encode(to encoder: Encoder) throws {
91-
var container = encoder.singleValueContainer()
92-
93-
switch value {
94-
case let number as NSNumber:
95-
try encodeNSNumber(number, into: &container)
96-
case is NSNull, is Void:
97-
try container.encodeNil()
98-
case let string as String:
99-
try container.encode(string)
100-
case let date as Date:
101-
try container.encode(date)
102-
case let url as URL:
103-
try container.encode(url)
104-
case let array as [Any]:
105-
try container.encode(array.map { AnyEncodable($0) })
106-
case let dictionary as [String: Any]:
107-
try container.encode(dictionary.mapValues { AnyEncodable($0) })
108-
default:
109-
let context = EncodingError.Context(
110-
codingPath: container.codingPath,
111-
debugDescription: "Value \(value) cannot be encoded - \(type(of: value)) is not supported by `AnyEncodable`."
112-
)
113-
throw EncodingError.invalidValue(value, context)
114-
}
115-
}
116-
}
117-
118-
private func encodeNSNumber(_ nsnumber: NSNumber, into container: inout SingleValueEncodingContainer) throws {
119-
switch CFNumberGetType(nsnumber) {
120-
case .charType:
121-
try container.encode(nsnumber.boolValue)
122-
case .sInt8Type:
123-
try container.encode(nsnumber.int8Value)
124-
case .sInt16Type:
125-
try container.encode(nsnumber.int16Value)
126-
case .sInt32Type:
127-
try container.encode(nsnumber.int32Value)
128-
case .sInt64Type:
129-
try container.encode(nsnumber.int64Value)
130-
case .shortType:
131-
try container.encode(nsnumber.uint16Value)
132-
case .longType:
133-
try container.encode(nsnumber.uint32Value)
134-
case .longLongType:
135-
try container.encode(nsnumber.uint64Value)
136-
case .intType, .nsIntegerType, .cfIndexType:
137-
try container.encode(nsnumber.intValue)
138-
case .floatType, .float32Type:
139-
try container.encode(nsnumber.floatValue)
140-
case .doubleType, .float64Type, .cgFloatType:
141-
try container.encode(nsnumber.doubleValue)
142-
@unknown default:
143-
return
144-
}
145-
}

packages/core/ios/Tests/AnyEncodableTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import XCTest
88
@testable import DatadogSDKReactNative
9+
@testable import DatadogInternal
910

1011
internal class AnyEncodableTests: XCTestCase {
1112
// MARK: - Casting attributes

packages/core/ios/Tests/DdSdkTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ class DdSdkTests: XCTestCase {
601601
XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true)
602602

603603
if let extraInfo4Encodable = userInfo.extraInfo["extra-info-4"]
604-
as? DatadogSDKReactNative.AnyEncodable,
604+
as? AnyEncodable,
605605
let extraInfo4Dict = extraInfo4Encodable.value as? [String: Int]
606606
{
607607
XCTAssertEqual(extraInfo4Dict, ["nested-extra-info-1": 456])
@@ -664,7 +664,7 @@ class DdSdkTests: XCTestCase {
664664
XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true)
665665

666666
if let extraInfo4Encodable = userInfo.extraInfo["extra-info-4"]
667-
as? DatadogSDKReactNative.AnyEncodable,
667+
as? AnyEncodable,
668668
let extraInfo4Dict = extraInfo4Encodable.value as? [String: Int]
669669
{
670670
XCTAssertEqual(extraInfo4Dict, ["nested-extra-info-1": 456])
@@ -718,7 +718,7 @@ class DdSdkTests: XCTestCase {
718718
XCTAssertEqual(userInfo.extraInfo["extra-info-3"] as? Bool, true)
719719

720720
if let extraInfo4Encodable = userInfo.extraInfo["extra-info-4"]
721-
as? DatadogSDKReactNative.AnyEncodable,
721+
as? AnyEncodable,
722722
let extraInfo4Dict = extraInfo4Encodable.value as? [String: Int]
723723
{
724724
XCTAssertEqual(extraInfo4Dict, ["nested-extra-info-1": 456])

0 commit comments

Comments
 (0)