Skip to content

Commit

Permalink
Fixed BulkString having to contain UTF-8 String; closes #9
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelvanstraten committed Oct 7, 2023
1 parent 56ce6d0 commit f4cdb34
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 23 deletions.
39 changes: 34 additions & 5 deletions Sources/SwiftyRedis/FromRedisValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ extension FromRedisValue {
extension String: FromRedisValue {
public init(_ value: RedisValue) throws {
switch value {
case let .SimpleString(string), let .BulkString(string):
case let .SimpleString(string):
self = string
case let .BulkString(data):
guard let string = String(data: data, encoding: .utf8) else {
throw RedisError.InvalidUTF8
}
self = string
case let .Int(int):
self = "\(int)"
Expand All @@ -52,7 +57,13 @@ extension String: FromRedisValue {
extension Float64: FromRedisValue {
public init(_ value: RedisValue) throws {
switch value {
case let .BulkString(string), let .SimpleString(string):
case let .BulkString(data):
if let string = String(data: data, encoding: .utf8) {
self = try Self.init(RedisValue.SimpleString(string))
} else {
throw RedisError.make_invalid_type_error(detail: "Could not convert non UTF-8 String to Float64")
}
case let .SimpleString(string):
if let float = Float64(string) {
self = float
} else {
Expand All @@ -69,7 +80,13 @@ extension Float64: FromRedisValue {
extension Float32: FromRedisValue {
public init(_ value: RedisValue) throws {
switch value {
case let .BulkString(string), let .SimpleString(string):
case let .BulkString(data):
if let string = String(data: data, encoding: .utf8) {
self = try Self.init(RedisValue.SimpleString(string))
} else {
throw RedisError.make_invalid_type_error(detail: "Could not convert non UTF-8 String to Float32")
}
case let .SimpleString(string):
if let float = Float(string) {
self = float
} else {
Expand Down Expand Up @@ -98,7 +115,13 @@ extension Float32: FromRedisValue {
extension Int64: FromRedisValue {
public init(_ value: RedisValue) throws {
switch value {
case let .BulkString(string), let .SimpleString(string):
case let .BulkString(data):
if let string = String(data: data, encoding: .utf8) {
self = try Self.init(RedisValue.SimpleString(string))
} else {
throw RedisError.make_invalid_type_error(detail: "Could not convert non UTF-8 String to Int64")
}
case let .SimpleString(string):
if let int = Int64(string) {
self = int
} else {
Expand Down Expand Up @@ -187,7 +210,13 @@ extension Bool: FromRedisValue {
switch value {
case let .Int(int):
self = int != 0
case let .BulkString(string), let .SimpleString(string):
case let .BulkString(data):
if let string = String(data: data, encoding: .utf8) {
self = try Self.init(RedisValue.SimpleString(string))
} else {
throw RedisError.make_invalid_type_error(detail: "Could not convert non UTF-8 String to Bool")
}
case let .SimpleString(string):
if string == "1" {
self = true
} else if string == "0" {
Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftyRedis/JSONValue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ extension JSONValue: FromRedisValue where T: Decodable {
*/
public init(_ value: RedisValue) throws {
switch value {
case let .BulkString(string):
case let .BulkString(data):
let decoder = JSONDecoder()
self.value = try decoder.decode(T.self, from: string.data(using: .utf8)!)
self.value = try decoder.decode(T.self, from: data)
default:
throw RedisError.make_invalid_type_error(detail: "Response type (\(value)), is not JSON compatible")
}
Expand Down
11 changes: 5 additions & 6 deletions Sources/SwiftyRedis/ResponseValueParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,11 @@ class ResponseValueParser {
if length < 0 {
return .Nil
} else {
if let value = try String(data: await stream.next(n: Int(length)), encoding: .utf8) {
try await disgard_crlf_token()
return .BulkString(value)
} else {
throw RedisError.InvalidUTF8
}
let value = Data(try await stream.next(n: Int(length)))

try await disgard_crlf_token()

return .BulkString(value)
}
} else {
unreachable()
Expand Down
10 changes: 2 additions & 8 deletions Sources/SwiftyRedis/Stream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,12 @@ public struct RedisStreamElement<T>: FromRedisValue where T: FromRedisValue {
public init(_ value: RedisValue) throws {
if case var .Array(array) = value {
array = array.reversed()
switch array.popLast() {
case let .BulkString(id), let .SimpleString(id):
if let id = try? String(array.popLast()) {
self.id = id
if let data = array.popLast() {
self.data = try T(data)
return
}
default:
break
}
}
throw RedisError.make_invalid_type_error(detail: "Response type not convertible to RedisStreamElement.")
Expand All @@ -39,15 +36,12 @@ public struct RedisStream<T>: FromRedisValue where T: FromRedisValue {
public init(_ value: RedisValue) throws {
if case var .Array(array) = value {
array = array.reversed()
switch array.popLast() {
case let .BulkString(name), let .SimpleString(name):
if let name = try? String(array.popLast()) {
self.name = name
if case let .Array(elements) = array.popLast() {
self.elements = try elements.map { value in try RedisStreamElement(value) }
return
}
default:
break
}
}
throw RedisError.make_invalid_type_error(detail: "Response type not convertible to RedisStream.")
Expand Down
6 changes: 5 additions & 1 deletion Sources/SwiftyRedis/Value.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ public indirect enum RedisValue: Equatable {
/// Represents integer responses from the server. The returned integer is guaranteed to be within the range of a signed 64-bit integer.
case Int(Int64)
/// Represents a single binary-safe string up to 512 MB in length.
case BulkString(String)
case BulkString(Data)
/// Represents the absence of a value.
case Nil
/// Represents an array of RedisValues, commonly used for commands that return collections of elements.
case Array([RedisValue])

static func BulkString(_ string: String) -> Self {
return .BulkString(string.data(using: .utf8)!)
}
}
2 changes: 1 addition & 1 deletion Tests/SwiftyRedisTests/ConnectionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ final class ConnectionTests: XCTestCase {
try await connection2.xadd("stream1", nil, .AUTO_ID, .init("field1", "Hello, World!"))
}

let value: RedisValue = try await connection.xread(nil, 0, .init("stream1", id: "$"))
let value: XreadResponse<RedisValue> = try await connection.xread(nil, 0, .init("stream1", id: "$"))

print(value)
}
Expand Down

0 comments on commit f4cdb34

Please sign in to comment.