Skip to content

Commit

Permalink
Give Headers an API that’s consistent with JSONValue
Browse files Browse the repository at this point in the history
Resolves #13.
  • Loading branch information
lawrence-forooghian committed Dec 18, 2024
1 parent 0159c48 commit 2e95cbb
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 12 deletions.
69 changes: 63 additions & 6 deletions Sources/AblyChat/Headers.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,71 @@
// TODO: https://github.com/ably-labs/ably-chat-swift/issues/13 - try to improve this type

/// A value that can be used in ``Headers``. It is the same as ``JSONValue`` except it does not have the `object` or `array` cases.
public enum HeadersValue: Sendable, Equatable {
case string(String)
case number(Double)
case bool(Bool)
case null

// MARK: - Convenience getters for associated values

/// If this `HeadersValue` has case `string`, this returns the associated value. Else, it returns `nil`.
public var stringValue: String? {
if case let .string(stringValue) = self {
stringValue
} else {
nil
}
}

/// If this `HeadersValue` has case `number`, this returns the associated value. Else, it returns `nil`.
public var numberValue: Double? {
if case let .number(numberValue) = self {
numberValue
} else {
nil
}
}

/// If this `HeadersValue` has case `bool`, this returns the associated value. Else, it returns `nil`.
public var boolValue: Bool? {
if case let .bool(boolValue) = self {
boolValue
} else {
nil
}
}

/// Returns true if and only if this `HeadersValue` has case `null`.
public var isNull: Bool {
if case .null = self {
true
} else {
false
}
}
}

extension HeadersValue: ExpressibleByStringLiteral {
public init(stringLiteral value: String) {
self = .string(value)
}
}

extension HeadersValue: ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
self = .number(Double(value))
}
}

extension HeadersValue: ExpressibleByFloatLiteral {
public init(floatLiteral value: Double) {
self = .number(value)
}
}

extension HeadersValue: ExpressibleByBooleanLiteral {
public init(booleanLiteral value: Bool) {
self = .bool(value)
}
}

extension HeadersValue: JSONDecodable {
Expand Down Expand Up @@ -43,10 +104,6 @@ extension HeadersValue: JSONEncodable {
}
}

// The corresponding type in TypeScript is
// Record<string, number | string | boolean | null | undefined>
// There may be a better way to represent it in Swift; this will do for now. Have omitted `undefined` because I don’t know how that would occur.

/**
* Headers are a flat key-value map that can be attached to chat messages.
*
Expand Down
2 changes: 1 addition & 1 deletion Tests/AblyChatTests/ChatAPITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ struct ChatAPITests {
params: .init(
text: "", // arbitrary
// The exact value here is arbitrary, just want to check it gets serialized
headers: ["numberKey": .number(10), "stringKey": .string("hello")]
headers: ["numberKey": 10, "stringKey": "hello"]
)
)

Expand Down
2 changes: 1 addition & 1 deletion Tests/AblyChatTests/DefaultRoomReactionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct DefaultRoomReactionsTests {
let sendReactionParams = SendReactionParams(
type: "like",
metadata: ["someMetadataKey": "someMetadataValue"],
headers: ["someHeadersKey": HeadersValue.string("someHeadersValue")]
headers: ["someHeadersKey": "someHeadersValue"]
)

// When
Expand Down
4 changes: 2 additions & 2 deletions Tests/AblyChatTests/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ struct IntegrationTests {
params: .init(
text: "Hello from txRoom, after rxRoom subscribe",
metadata: ["someMetadataKey": 123, "someOtherMetadataKey": "foo"],
headers: ["someHeadersKey": .number(456), "someOtherHeadersKey": .string("bar")]
headers: ["someHeadersKey": 456, "someOtherHeadersKey": "bar"]
)
)
let rxMessageFromSubscription = try #require(await rxMessageSubscription.first { _ in true })
Expand Down Expand Up @@ -169,7 +169,7 @@ struct IntegrationTests {
params: .init(
type: "heart",
metadata: ["someMetadataKey": 123, "someOtherMetadataKey": "foo"],
headers: ["someHeadersKey": .number(456), "someOtherHeadersKey": .string("bar")]
headers: ["someHeadersKey": 456, "someOtherHeadersKey": "bar"]
)
)
let rxReactionFromSubscription = try #require(await rxReactionSubscription.first { _ in true })
Expand Down
4 changes: 2 additions & 2 deletions Tests/AblyChatTests/RoomReactionDTOTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ enum RoomReactionDTOTests {
]
)

#expect(data == .init(headers: ["someStringKey": .string("someStringValue"), "someNumberKey": .number(123)]))
#expect(data == .init(headers: ["someStringKey": "someStringValue", "someNumberKey": 123]))
}

// MARK: - JSONCodable
Expand All @@ -100,7 +100,7 @@ enum RoomReactionDTOTests {

@Test
func toJSONValue() {
let data = RoomReactionDTO.Extras(headers: ["someStringKey": .string("someStringValue"), "someNumberKey": .number(123)])
let data = RoomReactionDTO.Extras(headers: ["someStringKey": "someStringValue", "someNumberKey": 123])

#expect(data.toJSONValue == [
"headers": [
Expand Down

0 comments on commit 2e95cbb

Please sign in to comment.