Skip to content

Commit 107b2c1

Browse files
authored
Return ByteBuffer when expect a bulk string (#112)
* Added RESPString for holding a bulk or simple string When we know a command returns a String but we don't want to convert to a String straight away we can return a RESPString Also renamed RESPBulkString to RESPBulkStringRenderer * RESPString -> RESPToken.String * Replace RESPToken.String.decode(as:) with String(_:) * User RESPToken in stream commands * SortedSetEntry used RESPToken.String * Revert RESPBulkString rename * Missed a file * Add comment about RESPToken.String * Use ByteBuffer instead of RESPToken.String
1 parent 8bdf7b6 commit 107b2c1

22 files changed

+188
-120
lines changed

Benchmarks/ValkeyBenchmarks/ValkeyBenchmarks.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ let benchmarks: @Sendable () -> Void = {
5252
benchmark.startMeasurement()
5353

5454
for _ in benchmark.scaledIterations {
55-
let foo = try await connection.get(key: "foo")?.decode(as: String.self)
56-
precondition(foo == "Bar")
55+
let foo = try await connection.get(key: "foo")
56+
precondition(foo.map { String(buffer: $0) } == "Bar")
5757
}
5858

5959
benchmark.stopMeasurement()

Sources/Valkey/Cluster/ValkeyMovedError.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,6 @@ extension RESPToken {
112112
return nil
113113
}
114114

115-
return ValkeyMovedError(slot: slot, endpoint: String(endpoint), port: port)
115+
return ValkeyMovedError(slot: slot, endpoint: Swift.String(endpoint), port: port)
116116
}
117117
}

Sources/Valkey/Commands/ClusterCommands.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ public enum CLUSTER {
7676
/// Advances the cluster config epoch.
7777
@_documentation(visibility: internal)
7878
public struct BUMPEPOCH: ValkeyCommand {
79+
public typealias Response = ByteBuffer
80+
7981
@inlinable public init() {
8082
}
8183

@@ -252,6 +254,8 @@ public enum CLUSTER {
252254
/// Returns information about the state of a node.
253255
@_documentation(visibility: internal)
254256
public struct INFO: ValkeyCommand {
257+
public typealias Response = ByteBuffer
258+
255259
@inlinable public init() {
256260
}
257261

@@ -310,6 +314,8 @@ public enum CLUSTER {
310314
/// Returns the ID of a node.
311315
@_documentation(visibility: internal)
312316
public struct MYID: ValkeyCommand {
317+
public typealias Response = ByteBuffer
318+
313319
@inlinable public init() {
314320
}
315321

@@ -321,6 +327,8 @@ public enum CLUSTER {
321327
/// Returns the shard ID of a node.
322328
@_documentation(visibility: internal)
323329
public struct MYSHARDID: ValkeyCommand {
330+
public typealias Response = ByteBuffer
331+
324332
@inlinable public init() {
325333
}
326334

@@ -332,6 +340,8 @@ public enum CLUSTER {
332340
/// Returns the cluster configuration for a node.
333341
@_documentation(visibility: internal)
334342
public struct NODES: ValkeyCommand {
343+
public typealias Response = ByteBuffer
344+
335345
@inlinable public init() {
336346
}
337347

@@ -677,7 +687,7 @@ extension ValkeyConnectionProtocol {
677687
/// * [String]: If the epoch was incremented.
678688
/// * [String]: If the node already has the greatest config epoch in the cluster.
679689
@inlinable
680-
public func clusterBumpepoch() async throws -> CLUSTER.BUMPEPOCH.Response {
690+
public func clusterBumpepoch() async throws -> ByteBuffer {
681691
try await send(command: CLUSTER.BUMPEPOCH())
682692
}
683693

@@ -782,7 +792,7 @@ extension ValkeyConnectionProtocol {
782792
/// - Complexity: O(1)
783793
/// - Returns: [String]: A map between named fields and values in the form of <field>:<value> lines separated by newlines composed by the two bytes CRLF
784794
@inlinable
785-
public func clusterInfo() async throws -> CLUSTER.INFO.Response {
795+
public func clusterInfo() async throws -> ByteBuffer {
786796
try await send(command: CLUSTER.INFO())
787797
}
788798

@@ -827,7 +837,7 @@ extension ValkeyConnectionProtocol {
827837
/// - Complexity: O(1)
828838
/// - Returns: [String]: The node id.
829839
@inlinable
830-
public func clusterMyid() async throws -> CLUSTER.MYID.Response {
840+
public func clusterMyid() async throws -> ByteBuffer {
831841
try await send(command: CLUSTER.MYID())
832842
}
833843

@@ -838,7 +848,7 @@ extension ValkeyConnectionProtocol {
838848
/// - Complexity: O(1)
839849
/// - Returns: [String]: The node's shard id.
840850
@inlinable
841-
public func clusterMyshardid() async throws -> CLUSTER.MYSHARDID.Response {
851+
public func clusterMyshardid() async throws -> ByteBuffer {
842852
try await send(command: CLUSTER.MYSHARDID())
843853
}
844854

@@ -849,7 +859,7 @@ extension ValkeyConnectionProtocol {
849859
/// - Complexity: O(N) where N is the total number of Cluster nodes
850860
/// - Returns: [String]: The serialized cluster configuration.
851861
@inlinable
852-
public func clusterNodes() async throws -> CLUSTER.NODES.Response {
862+
public func clusterNodes() async throws -> ByteBuffer {
853863
try await send(command: CLUSTER.NODES())
854864
}
855865

Sources/Valkey/Commands/ConnectionCommands.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ extension CLIENT {
6969
/// Returns the name of the connection.
7070
@_documentation(visibility: internal)
7171
public struct GETNAME: ValkeyCommand {
72-
public typealias Response = RESPToken?
72+
public typealias Response = ByteBuffer?
7373

7474
@inlinable public init() {
7575
}
@@ -150,6 +150,8 @@ extension CLIENT {
150150
/// Returns information about the connection.
151151
@_documentation(visibility: internal)
152152
public struct INFO: ValkeyCommand {
153+
public typealias Response = ByteBuffer
154+
153155
@inlinable public init() {
154156
}
155157

@@ -304,6 +306,8 @@ extension CLIENT {
304306
}
305307
}
306308
}
309+
public typealias Response = ByteBuffer
310+
307311
public var clientType: ClientType?
308312
public var clientId: [Int]
309313
public var username: String?
@@ -625,6 +629,8 @@ public struct CLIENT: ValkeyCommand {
625629
/// Returns the given string.
626630
@_documentation(visibility: internal)
627631
public struct ECHO<Message: RESPStringRenderable>: ValkeyCommand {
632+
public typealias Response = ByteBuffer
633+
628634
public var message: Message
629635

630636
@inlinable public init(message: Message) {
@@ -799,7 +805,7 @@ extension ValkeyConnectionProtocol {
799805
/// * [String]: The connection name of the current connection
800806
/// * [Null]: Connection name was not set
801807
@inlinable
802-
public func clientGetname() async throws -> RESPToken? {
808+
public func clientGetname() async throws -> ByteBuffer? {
803809
try await send(command: CLIENT.GETNAME())
804810
}
805811

@@ -856,7 +862,7 @@ extension ValkeyConnectionProtocol {
856862
/// - Complexity: O(1)
857863
/// - Returns: [String]: A unique string, as described at the CLIENT LIST page, for the current client.
858864
@inlinable
859-
public func clientInfo() async throws -> CLIENT.INFO.Response {
865+
public func clientInfo() async throws -> ByteBuffer {
860866
try await send(command: CLIENT.INFO())
861867
}
862868

@@ -898,7 +904,7 @@ extension ValkeyConnectionProtocol {
898904
/// - Complexity: O(N) where N is the number of client connections
899905
/// - Returns: [String]: Information and statistics about client connections
900906
@inlinable
901-
public func clientList(clientType: CLIENT.LIST.ClientType? = nil, clientId: [Int] = [], username: String? = nil, addr: String? = nil, laddr: String? = nil, skipme: CLIENT.LIST.Skipme? = nil, maxage: Int? = nil) async throws -> CLIENT.LIST.Response {
907+
public func clientList(clientType: CLIENT.LIST.ClientType? = nil, clientId: [Int] = [], username: String? = nil, addr: String? = nil, laddr: String? = nil, skipme: CLIENT.LIST.Skipme? = nil, maxage: Int? = nil) async throws -> ByteBuffer {
902908
try await send(command: CLIENT.LIST(clientType: clientType, clientId: clientId, username: username, addr: addr, laddr: laddr, skipme: skipme, maxage: maxage))
903909
}
904910

@@ -1016,7 +1022,7 @@ extension ValkeyConnectionProtocol {
10161022
/// - Complexity: O(1)
10171023
/// - Returns: [String]: The given string
10181024
@inlinable
1019-
public func echo<Message: RESPStringRenderable>(message: Message) async throws -> RESPToken {
1025+
public func echo<Message: RESPStringRenderable>(message: Message) async throws -> ByteBuffer {
10201026
try await send(command: ECHO(message: message))
10211027
}
10221028

Sources/Valkey/Commands/Custom/SortedSetCustomCommands.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import NIOCore
16+
1517
/// Sorted set entry
1618
@_documentation(visibility: internal)
1719
public struct SortedSetEntry: RESPTokenDecodable, Sendable {
18-
public let value: RESPToken
20+
public let value: ByteBuffer
1921
public let score: Double
2022

2123
public init(fromRESP token: RESPToken) throws {

Sources/Valkey/Commands/Custom/StreamCustomCommands.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
import NIOCore
16+
1517
@_documentation(visibility: internal)
1618
public struct XREADMessage: RESPTokenDecodable, Sendable {
1719
public let id: String
18-
public let fields: [(key: String, value: RESPToken)]
20+
public let fields: [(key: String, value: ByteBuffer)]
1921

2022
public init(fromRESP token: RESPToken) throws {
2123
switch token.value {
2224
case .array(let array):
2325
let (id, values) = try array.decodeElements(as: (String, RESPToken.Array).self)
24-
let keyValuePairs = try values.asMap().map { try ($0.key.decode(as: String.self), $0.value) }
26+
let keyValuePairs = try values.asMap()
27+
.map { try ($0.key.decode(as: String.self), $0.value.decode(as: ByteBuffer.self)) }
2528
self.id = id
2629
self.fields = keyValuePairs
2730
default:
@@ -43,7 +46,7 @@ public struct XREADMessage: RESPTokenDecodable, Sendable {
4346
///
4447
/// - Parameter key: The field key to look up.
4548
/// - Returns: The `RESPToken` value associated with the given key, or `nil` if the key does not exist.
46-
public subscript(field key: String) -> RESPToken? {
49+
public subscript(field key: String) -> ByteBuffer? {
4750
fields.first(where: { $0.key == key })?.value
4851
}
4952

@@ -54,7 +57,7 @@ public struct XREADMessage: RESPTokenDecodable, Sendable {
5457
///
5558
/// - Parameter key: The field key to retrieve values for.
5659
/// - Returns: An array of `RESPToken` values associated with the given field key.
57-
public subscript(fields key: String) -> [RESPToken] {
60+
public subscript(fields key: String) -> [ByteBuffer] {
5861
fields.compactMap {
5962
if $0.key == key {
6063
$0.value
@@ -68,13 +71,16 @@ public struct XREADMessage: RESPTokenDecodable, Sendable {
6871
@_documentation(visibility: internal)
6972
public struct XREADGroupMessage: RESPTokenDecodable, Sendable {
7073
public let id: String
71-
public let fields: [(key: String, value: RESPToken)]?
74+
public let fields: [(key: String, value: ByteBuffer)]?
7275

7376
public init(fromRESP token: RESPToken) throws {
7477
switch token.value {
7578
case .array(let array):
7679
let (id, values) = try array.decodeElements(as: (String, RESPToken.Array?).self)
77-
let keyValuePairs = try values.map { try $0.asMap().map { try ($0.key.decode(as: String.self), $0.value) } }
80+
let keyValuePairs = try values.map {
81+
try $0.asMap()
82+
.map { try ($0.key.decode(as: String.self), $0.value.decode(as: ByteBuffer.self)) }
83+
}
7884
self.id = id
7985
self.fields = keyValuePairs
8086
default:

Sources/Valkey/Commands/GenericCommands.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public enum OBJECT {
2828
/// Returns the internal encoding of an object.
2929
@_documentation(visibility: internal)
3030
public struct ENCODING: ValkeyCommand {
31-
public typealias Response = RESPToken?
31+
public typealias Response = ByteBuffer?
3232

3333
public var key: ValkeyKey
3434

@@ -165,7 +165,7 @@ public struct DEL: ValkeyCommand {
165165
/// Returns a serialized representation of the value stored at a key.
166166
@_documentation(visibility: internal)
167167
public struct DUMP: ValkeyCommand {
168-
public typealias Response = RESPToken?
168+
public typealias Response = ByteBuffer?
169169

170170
public var key: ValkeyKey
171171

@@ -579,7 +579,7 @@ public struct PTTL: ValkeyCommand {
579579
/// Returns a random key name from the database.
580580
@_documentation(visibility: internal)
581581
public struct RANDOMKEY: ValkeyCommand {
582-
public typealias Response = RESPToken?
582+
public typealias Response = ByteBuffer?
583583

584584
@inlinable public init() {
585585
}
@@ -852,7 +852,7 @@ public struct TTL: ValkeyCommand {
852852
/// Determines the type of value stored at a key.
853853
@_documentation(visibility: internal)
854854
public struct TYPE: ValkeyCommand {
855-
public typealias Response = RESPToken?
855+
public typealias Response = ByteBuffer?
856856

857857
public var key: ValkeyKey
858858

@@ -963,7 +963,7 @@ extension ValkeyConnectionProtocol {
963963
/// * [String]: The serialized value.
964964
/// * [Null]: Key does not exist.
965965
@inlinable
966-
public func dump(key: ValkeyKey) async throws -> RESPToken? {
966+
public func dump(key: ValkeyKey) async throws -> ByteBuffer? {
967967
try await send(command: DUMP(key: key))
968968
}
969969

@@ -1075,7 +1075,7 @@ extension ValkeyConnectionProtocol {
10751075
/// * [Null]: Key doesn't exist.
10761076
/// * [String]: Encoding of the object.
10771077
@inlinable
1078-
public func objectEncoding(key: ValkeyKey) async throws -> RESPToken? {
1078+
public func objectEncoding(key: ValkeyKey) async throws -> ByteBuffer? {
10791079
try await send(command: OBJECT.ENCODING(key: key))
10801080
}
10811081

@@ -1205,7 +1205,7 @@ extension ValkeyConnectionProtocol {
12051205
/// * [Null]: When the database is empty.
12061206
/// * [String]: Random key in db.
12071207
@inlinable
1208-
public func randomkey() async throws -> RESPToken? {
1208+
public func randomkey() async throws -> ByteBuffer? {
12091209
try await send(command: RANDOMKEY())
12101210
}
12111211

@@ -1321,7 +1321,7 @@ extension ValkeyConnectionProtocol {
13211321
/// * [Null]: Key doesn't exist
13221322
/// * [String]: Type of the key
13231323
@inlinable
1324-
public func type(key: ValkeyKey) async throws -> RESPToken? {
1324+
public func type(key: ValkeyKey) async throws -> ByteBuffer? {
13251325
try await send(command: TYPE(key: key))
13261326
}
13271327

Sources/Valkey/Commands/GeoCommands.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public struct GEODIST<Member1: RESPStringRenderable, Member2: RESPStringRenderab
106106
}
107107
}
108108
}
109-
public typealias Response = RESPToken?
109+
public typealias Response = ByteBuffer?
110110

111111
public var key: ValkeyKey
112112
public var member1: Member1
@@ -1012,7 +1012,7 @@ extension ValkeyConnectionProtocol {
10121012
/// * [Null]: One or both of elements are missing.
10131013
/// * [String]: Distance as a double (represented as a string) in the specified units.
10141014
@inlinable
1015-
public func geodist<Member1: RESPStringRenderable, Member2: RESPStringRenderable>(key: ValkeyKey, member1: Member1, member2: Member2, unit: GEODIST<Member1, Member2>.Unit? = nil) async throws -> RESPToken? {
1015+
public func geodist<Member1: RESPStringRenderable, Member2: RESPStringRenderable>(key: ValkeyKey, member1: Member1, member2: Member2, unit: GEODIST<Member1, Member2>.Unit? = nil) async throws -> ByteBuffer? {
10161016
try await send(command: GEODIST(key: key, member1: member1, member2: member2, unit: unit))
10171017
}
10181018

Sources/Valkey/Commands/HashCommands.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public struct HEXISTS<Field: RESPStringRenderable>: ValkeyCommand {
6767
/// Returns the value of a field in a hash.
6868
@_documentation(visibility: internal)
6969
public struct HGET<Field: RESPStringRenderable>: ValkeyCommand {
70-
public typealias Response = RESPToken?
70+
public typealias Response = ByteBuffer?
7171

7272
public var key: ValkeyKey
7373
public var field: Field
@@ -131,6 +131,8 @@ public struct HINCRBY<Field: RESPStringRenderable>: ValkeyCommand {
131131
/// Increments the floating point value of a field by a number. Uses 0 as initial value if the field doesn't exist.
132132
@_documentation(visibility: internal)
133133
public struct HINCRBYFLOAT<Field: RESPStringRenderable>: ValkeyCommand {
134+
public typealias Response = ByteBuffer
135+
134136
public var key: ValkeyKey
135137
public var field: Field
136138
public var increment: Double
@@ -458,7 +460,7 @@ extension ValkeyConnectionProtocol {
458460
/// * [String]: The value associated with the field.
459461
/// * [Null]: If the field is not present in the hash or key does not exist.
460462
@inlinable
461-
public func hget<Field: RESPStringRenderable>(key: ValkeyKey, field: Field) async throws -> RESPToken? {
463+
public func hget<Field: RESPStringRenderable>(key: ValkeyKey, field: Field) async throws -> ByteBuffer? {
462464
try await send(command: HGET(key: key, field: field))
463465
}
464466

@@ -491,7 +493,7 @@ extension ValkeyConnectionProtocol {
491493
/// - Complexity: O(1)
492494
/// - Returns: [String]: The value of the field after the increment operation.
493495
@inlinable
494-
public func hincrbyfloat<Field: RESPStringRenderable>(key: ValkeyKey, field: Field, increment: Double) async throws -> RESPToken {
496+
public func hincrbyfloat<Field: RESPStringRenderable>(key: ValkeyKey, field: Field, increment: Double) async throws -> ByteBuffer {
495497
try await send(command: HINCRBYFLOAT(key: key, field: field, increment: increment))
496498
}
497499

0 commit comments

Comments
 (0)