diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 3d2cbc2..00aff72 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -13,7 +13,6 @@ jobs: fail-fast: false matrix: image: - - swift:4.2.4 - swift:5.6.1-bionic - swift:5.9.2-focal container: ${{ matrix.image }} @@ -25,7 +24,7 @@ jobs: - name: Build Swift Release Package run: swift build -c release nextstep: - runs-on: macos-latest + runs-on: macos-13 steps: - name: Select latest available Xcode uses: maxim-lobanov/setup-xcode@v1 diff --git a/.gitignore b/.gitignore index 1a41dca..562b343 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,5 @@ fastlane/test_output .build-linux* Package.resolved dump*.json +.swiftpm diff --git a/.travis.d/before-install.sh b/.travis.d/before-install.sh deleted file mode 100755 index f8d4b74..0000000 --- a/.travis.d/before-install.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -if [[ "$TRAVIS_OS_NAME" == "Linux" ]]; then - sudo apt-get -q update - sudo apt-get install -y wget \ - clang-3.8 libc6-dev make git libicu52 libicu-dev \ - git autoconf libtool pkg-config \ - libblocksruntime-dev \ - libkqueue-dev \ - libpthread-workqueue-dev \ - systemtap-sdt-dev \ - libbsd-dev libbsd0 libbsd0-dbg \ - curl libcurl4-openssl-dev \ - libssl-dev \ - libedit-dev \ - libpython2.7 \ - python2.7 python2.7-dev \ - libxml2 - - sudo update-alternatives --quiet --install /usr/bin/clang clang /usr/bin/clang-3.8 100 - sudo update-alternatives --quiet --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.8 100 -fi diff --git a/.travis.d/install.sh b/.travis.d/install.sh deleted file mode 100755 index 2d1b622..0000000 --- a/.travis.d/install.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Install Swift - -wget "${SWIFT_SNAPSHOT_NAME}" - -TARBALL="`ls swift-*.tar.gz`" -echo "Tarball: $TARBALL" - -TARPATH="$PWD/$TARBALL" - -cd $HOME # expand Swift tarball in $HOME -tar zx --strip 1 --file=$TARPATH -pwd - -export PATH="$PWD/usr/bin:$PATH" -which swift - -if [ `which swift` ]; then - echo "Installed Swift: `which swift`" -else - echo "Failed to install Swift?" - exit 42 -fi -swift --version - - -# Environment - -TT_SWIFT_BINARY=`which swift` - -echo "${TT_SWIFT_BINARY}" diff --git a/Package.swift b/Package.swift index 0372e0b..b0dac14 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.0 +// swift-tools-version:5.0 import PackageDescription @@ -10,10 +10,11 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/SwiftNIOExtras/swift-nio-redis.git", - from: "0.9.0") + from: "0.11.0"), + .package(url: "https://github.com/apple/swift-atomics", from: "1.0.0") ], targets: [ - .target(name: "RedisServer", dependencies: [ "NIORedis" ]), + .target(name: "RedisServer", dependencies: [ "NIORedis", "Atomics" ]), .target(name: "redi-s", dependencies: [ "RedisServer" ]) ] ) diff --git a/README.md b/README.md index d9c05aa..6f09b16 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,25 @@ Contributions welcome!! A lot of the missing stuff is really easy to add! Performance differs, e.g. lists are implemented using arrays (hence RPUSH is okayish, LPUSH is very slow). But looking at just the simple GET/SET, it is surprisingly close to the -highly optimized C implementation: +highly optimized C implementation. + +### 2024-01-30 Swift 5.9.2 + +Redi/S (1 NIO thread on M1 Mac Mini): +``` +helge@M1ni ~ $ redis-benchmark -p 1337 -t SET,GET,RPUSH,INCR -n 500000 -q +WARNING: Could not fetch server CONFIG +SET: 163345.31 requests per second, p50=0.255 msec +GET: 167336.02 requests per second, p50=0.239 msec +INCR: 158780.56 requests per second, p50=0.239 msec +RPUSH: 157480.31 requests per second, p50=0.271 msec +``` + +Note that more threads end up being worse. Not entirely sure why. + +### Those Are Older Numbers from 2018 + +- using Swift 4.2 on Intel, IIRC Redi/S (2 NIO threads on MacPro 3,7 GHz Quad-Core Intel Xeon E5): ``` diff --git a/Sources/RedisServer/Commands/CommandTable.swift b/Sources/RedisServer/Commands/CommandTable.swift index 3ed27d1..0db1d84 100644 --- a/Sources/RedisServer/Commands/CommandTable.swift +++ b/Sources/RedisServer/Commands/CommandTable.swift @@ -23,7 +23,7 @@ extension RedisServer { static let defaultCommandTable : RedisCommandTable = [ // command is funny in that arity is 0 Command(name : "COMMAND", - type : .optionalValue(Commands.COMMAND), // FIXME: multivalue + type : .optionalValue(Commands.COMMAND), // FIXME: multivalue! flags : [ .loading, .stale ]), Command(name : "PING", diff --git a/Sources/RedisServer/Commands/ServerCommands.swift b/Sources/RedisServer/Commands/ServerCommands.swift index 966efcb..86ef1d0 100644 --- a/Sources/RedisServer/Commands/ServerCommands.swift +++ b/Sources/RedisServer/Commands/ServerCommands.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -24,13 +24,27 @@ extension Commands { let commandTable = ctx.handler.server.commandTable if let value = value { + // TODO: Only supports one parameter here. guard let s = value.stringValue else { throw RedisError.unknownSubcommand // TBD? ProtocolError? } switch s.uppercased() { - case "COUNT": ctx.write(commandTable.count) - default: throw RedisError.unknownSubcommand + case "COUNT": + ctx.write(commandTable.count) + case "LIST": + // TODO: [FILTERBY ] + ctx.write(commandTable.map(\.name)) + case "DOCS": + throw RedisError.unsupportedSubcommand + case "GETKEYS": + throw RedisError.unsupportedSubcommand + case "GETKEYSANDFLAGS": + throw RedisError.unsupportedSubcommand + case "INFO": + throw RedisError.unsupportedSubcommand + default: + throw RedisError.unknownSubcommand } } else { @@ -91,10 +105,12 @@ extension Commands { static func MONITOR(_ ctx: CommandContext) throws { let client = ctx.handler - guard !client.isMonitoring.load() else { return ctx.write(RESPValue.ok) } + guard !client.isMonitoring.load(ordering: .relaxed) else { + return ctx.write(RESPValue.ok) + } - client.isMonitoring.store(true) - _ = client.server.monitors.add(1) + client.isMonitoring.store(true, ordering: .relaxed) + client.server.monitors.wrappingIncrement(ordering: .relaxed) ctx.write(RESPValue.ok) } @@ -102,7 +118,7 @@ extension Commands { ctx.context.channel.close(mode: .input, promise: nil) ctx.context.writeAndFlush(NIOAny(RESPValue.ok)) - .whenComplete { + .whenComplete { _ in ctx.context.channel.close(promise: nil) } } @@ -167,7 +183,6 @@ extension Commands { // do not block the server listQueue.async { - let nl : [ UInt8 ] = [ 10 ] var count = clients.count guard count > 0 else { return ctx.write("") } // Never @@ -177,8 +192,8 @@ extension Commands { assert(count > 0) count -= 1 - result.write(string: info.redisClientLogLine) - result.write(bytes: nl) + result.writeString(info.redisClientLogLine) + result.writeInteger(10 as UInt8) if count == 0 { ctx.write(.bulkString(result)) diff --git a/Sources/RedisServer/Commands/StringCommands.swift b/Sources/RedisServer/Commands/StringCommands.swift index 8c54ad2..1bfe649 100644 --- a/Sources/RedisServer/Commands/StringCommands.swift +++ b/Sources/RedisServer/Commands/StringCommands.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -25,10 +25,10 @@ extension Commands { { guard var bb = value.byteBuffer else { throw RedisError.wrongType } - let result : Int = try ctx.writeInDatabase { db in - if let oldValue = db[key] { + let result : Int = try ctx.writeInDatabase { ( db : Databases.Database ) in + if let oldValue : RedisValue = db[key] { guard case .string(var s) = oldValue else { throw RedisError.wrongType } - s.write(buffer: &bb) + s.writeBuffer(&bb) db[key] = .string(s) return s.readableBytes } @@ -253,11 +253,11 @@ extension Commands { if index > s.readableBytes { // if index > count, 0-padded!!! let countToWrite = index - s.readableBytes - s.write(bytes: repeatElement(UInt8(0), count: countToWrite)) + s.writeRepeatingByte(0, count: countToWrite) } s.moveWriterIndex(to: s.readerIndex + index) - s.write(buffer: &bb) + s.writeBuffer(&bb) db[key] = .string(s) return s.readableBytes diff --git a/Sources/RedisServer/Helpers/RedisLogger.swift b/Sources/RedisServer/Helpers/RedisLogger.swift index dd17e88..6be2006 100644 --- a/Sources/RedisServer/Helpers/RedisLogger.swift +++ b/Sources/RedisServer/Helpers/RedisLogger.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -22,22 +22,26 @@ public protocol RedisLogger { public extension RedisLogger { - public func error(_ msg: @autoclosure () -> String, _ values: Any?...) { + @inlinable + func error(_ msg: @autoclosure () -> String, _ values: Any?...) { primaryLog(.Error, msg, values) } - public func warn (_ msg: @autoclosure () -> String, _ values: Any?...) { + @inlinable + func warn (_ msg: @autoclosure () -> String, _ values: Any?...) { primaryLog(.Warn, msg, values) } - public func log (_ msg: @autoclosure () -> String, _ values: Any?...) { + @inlinable + func log (_ msg: @autoclosure () -> String, _ values: Any?...) { primaryLog(.Log, msg, values) } - public func info (_ msg: @autoclosure () -> String, _ values: Any?...) { + @inlinable + func info (_ msg: @autoclosure () -> String, _ values: Any?...) { primaryLog(.Info, msg, values) } - public func trace(_ msg: @autoclosure () -> String, _ values: Any?...) { + @inlinable + func trace(_ msg: @autoclosure () -> String, _ values: Any?...) { primaryLog(.Trace, msg, values) } - } public enum RedisLogLevel : Int8 { @@ -86,10 +90,13 @@ fileprivate let redisLogDateFmt : DateFormatter = { return formatter }() +private let pid = getpid() + public struct RedisPrintLogger : RedisLogger { public let logLevel : LogLevel + @inlinable public init(logLevel: LogLevel = .Log) { self.logLevel = logLevel } @@ -100,7 +107,6 @@ public struct RedisPrintLogger : RedisLogger { { guard logLevel.rawValue <= self.logLevel.rawValue else { return } - let pid = getpid() let now = Date() let prefix = diff --git a/Sources/RedisServer/Server/PubSub.swift b/Sources/RedisServer/Server/PubSub.swift index 8fb639d..576f4f9 100644 --- a/Sources/RedisServer/Server/PubSub.swift +++ b/Sources/RedisServer/Server/PubSub.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -138,7 +138,9 @@ class PubSub { guard var loopToSubscribers = registry[key] else { return } guard var subscribers = loopToSubscribers[loopID] else { return } - guard let idx = subscribers.index(where: { $0 === handler }) else { return } + guard let idx = subscribers.firstIndex(where: { $0 === handler }) else { + return + } subscribers.remove(at: idx) if subscribers.isEmpty { diff --git a/Sources/RedisServer/Server/RedisCommandContext.swift b/Sources/RedisServer/Server/RedisCommandContext.swift index 1e95f92..98f03b1 100644 --- a/Sources/RedisServer/Server/RedisCommandContext.swift +++ b/Sources/RedisServer/Server/RedisCommandContext.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -118,12 +118,13 @@ public struct RedisCommandContext { let handler = self.handler if eventLoop.inEventLoop { - handler.write(ctx: context, value: value.toRESPValue(), promise: nil) + handler.write(context: context, value: value.toRESPValue(), promise: nil) if flush { context.channel.flush() } } else { eventLoop.execute { - handler.write(ctx: context, value: value.toRESPValue(), promise: nil) + handler.write(context: context, value: value.toRESPValue(), + promise: nil) if flush { context.channel.flush() } } } @@ -134,12 +135,12 @@ public struct RedisCommandContext { let handler = self.handler if eventLoop.inEventLoop { - handler.write(ctx: context, value: value, promise: nil) + handler.write(context: context, value: value, promise: nil) if flush { context.channel.flush() } } else { eventLoop.execute { - handler.write(ctx: context, value: value, promise: nil) + handler.write(context: context, value: value, promise: nil) if flush { context.channel.flush() } } } diff --git a/Sources/RedisServer/Server/RedisCommandHandler.swift b/Sources/RedisServer/Server/RedisCommandHandler.swift index 453c13f..d1b5078 100644 --- a/Sources/RedisServer/Server/RedisCommandHandler.swift +++ b/Sources/RedisServer/Server/RedisCommandHandler.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -14,7 +14,7 @@ import NIO import NIORedis -import class NIOConcurrencyHelpers.Atomic +import class Atomics.ManagedAtomic import struct Foundation.Data import struct Foundation.Date import struct Foundation.TimeInterval @@ -50,7 +50,7 @@ final class RedisCommandHandler : RESPChannelHandler { var lastCommand : String? var name : String? var databaseIndex = 0 - var isMonitoring = Atomic(value: false) + var isMonitoring = ManagedAtomic(false) var subscribedChannels : Set? var subscribedPatterns : Set? @@ -65,15 +65,15 @@ final class RedisCommandHandler : RESPChannelHandler { // MARK: - Channel Activation - override public func channelActive(ctx: ChannelHandlerContext) { - eventLoop = ctx.eventLoop - remoteAddress = ctx.remoteAddress - channel = ctx.channel + override public func channelActive(context: ChannelHandlerContext) { + eventLoop = context.eventLoop + remoteAddress = context.remoteAddress + channel = context.channel - super.channelActive(ctx: ctx) + super.channelActive(context: context) } - override public func channelInactive(ctx: ChannelHandlerContext) { + override public func channelInactive(context: ChannelHandlerContext) { if let channels = subscribedChannels, !channels.isEmpty { subscribedChannels = nil @@ -93,7 +93,7 @@ final class RedisCommandHandler : RESPChannelHandler { } } - super.channelInactive(ctx: ctx) + super.channelInactive(context: context) server.Q.async { self.server._unregisterClient(self) @@ -116,13 +116,14 @@ final class RedisCommandHandler : RESPChannelHandler { // MARK: - Reading - override public func channelRead(ctx: ChannelHandlerContext, value: RESPValue) + override public func channelRead(context: ChannelHandlerContext, + value: RESPValue) { lastActivity = Date() do { let ( command, args ) = try parseCommandCall(value) - if server.monitors.load() > 0 { + if server.monitors.load(ordering: .relaxed) > 0 { let info = MonitorInfo(db: databaseIndex, addr: remoteAddress, call: value) server.notifyMonitors(info: info) @@ -137,26 +138,26 @@ final class RedisCommandHandler : RESPChannelHandler { let cmdctx = RedisCommandContext(command : command, handler : self, - context : ctx, + context : context, databases : dbs) try callCommand(command, with: args, in: cmdctx) } catch let error as RESPError { - self.write(ctx: ctx, value: error.toRESPValue(), promise: nil) + self.write(context: context, value: error.toRESPValue(), promise: nil) } catch let error as RESPEncodable { - self.write(ctx: ctx, value: error.toRESPValue(), promise: nil) + self.write(context: context, value: error.toRESPValue(), promise: nil) } catch { let respError = RESPError(message: "\(error)") - self.write(ctx: ctx, value: respError.toRESPValue(), promise: nil) + self.write(context: context, value: respError.toRESPValue(), promise: nil) } } - override public func errorCaught(ctx: ChannelHandlerContext, error: Error) { - super.errorCaught(ctx: ctx, error: error) + override public func errorCaught(context: ChannelHandlerContext, error: Error) { + super.errorCaught(context: context, error: error) server.logger.error("Channel", error) - ctx.close(promise: nil) + context.close(promise: nil) } diff --git a/Sources/RedisServer/Server/RedisServer.swift b/Sources/RedisServer/Server/RedisServer.swift index e37187a..43d3494 100644 --- a/Sources/RedisServer/Server/RedisServer.swift +++ b/Sources/RedisServer/Server/RedisServer.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -17,7 +17,7 @@ import struct Foundation.URL import struct Foundation.TimeInterval import class Foundation.FileManager import class Foundation.JSONDecoder -import class NIOConcurrencyHelpers.Atomic +import class Atomics.ManagedAtomic import enum NIORedis.RESPValue import NIO @@ -66,9 +66,9 @@ open class RedisServer { var databases : Databases? let Q = DispatchQueue(label: "de.zeezide.nio.redisd.clients") - let clientID = Atomic(value: 0) + let clientID = ManagedAtomic(0) var clients = [ ObjectIdentifier : RedisCommandHandler ]() - var monitors = Atomic(value: 0) + var monitors = ManagedAtomic(0) let pubSub : PubSub public init(configuration: Configuration = Configuration()) { @@ -135,7 +135,7 @@ open class RedisServer { if let host = configuration.host { address = try SocketAddress - .newAddressResolving(host: host, port: configuration.port) + .makeAddressResolvingHost(host, port: configuration.port) } else { var addr = sockaddr_in() @@ -206,7 +206,9 @@ open class RedisServer { func _unregisterClient(_ client: RedisCommandHandler) { // Q! let oid = ObjectIdentifier(client) clients.removeValue(forKey: oid) - if client.isMonitoring.load() { _ = monitors.add(-1) } + if client.isMonitoring.load(ordering: .relaxed) { + monitors.wrappingDecrement(ordering: .relaxed) + } } @@ -217,16 +219,14 @@ open class RedisServer { let logPacket : RESPValue = { let logStr = info.redisClientLogLine - - var bb = ByteBufferAllocator().buffer(capacity: logStr.utf8.count + 1) - bb.write(string: logStr) + let bb = ByteBuffer(string: logStr) return RESPValue.simpleString(bb) }() Q.async { for ( _, client ) in self.clients { - guard client.isMonitoring.load() else { continue } - guard let channel = client.channel else { continue } + guard client.isMonitoring.load(ordering: .relaxed) else { continue } + guard let channel = client.channel else { continue } channel.writeAndFlush(logPacket, promise: nil) } } @@ -248,19 +248,18 @@ open class RedisServer { // Set the handlers that are applied to the accepted Channels .childChannelInitializer { channel in channel.pipeline - .add(name: "com.apple.nio.backpressure", - handler: BackPressureHandler()) // Oh well :-) - .then { - let cid = clientID.add(1) + .addHandler(BackPressureHandler() /* Oh well :-) */, + name: "com.apple.nio.backpressure") + .flatMap { + let cid = clientID.wrappingIncrementThenLoad(ordering: .relaxed) let handler = RedisCommandHandler(id: cid, server: self) self.Q.async { self._registerClient(handler) } - return channel.pipeline.add(name: - "de.zeezide.nio.redis.server.client", - handler: handler) + return channel.pipeline + .addHandler(handler, name:"de.zeezide.nio.redis.server.client") } } diff --git a/Sources/RedisServer/Values/RedisError.swift b/Sources/RedisServer/Values/RedisError.swift index d78fd70..a28ac83 100644 --- a/Sources/RedisServer/Values/RedisError.swift +++ b/Sources/RedisServer/Values/RedisError.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -21,6 +21,7 @@ enum RedisError : Swift.Error, RESPEncodable { case indexOutOfRange case notAnInteger case unknownSubcommand + case unsupportedSubcommand case syntaxError case dbIndexOutOfRange case invalidDBIndex @@ -58,7 +59,9 @@ enum RedisError : Swift.Error, RESPEncodable { return "value is not an integer or out of range" case .unknownSubcommand: return "Unknown subcommand or wrong number of arguments." - + case .unsupportedSubcommand: + return "The subcommand is known, but unsupported." + case .wrongNumberOfArguments(let command): if let command = command { return "wrong number of arguments for: \(command.uppercased())" diff --git a/Sources/RedisServer/Values/RedisValue.swift b/Sources/RedisServer/Values/RedisValue.swift index 60eaf49..258a794 100644 --- a/Sources/RedisServer/Values/RedisValue.swift +++ b/Sources/RedisServer/Values/RedisValue.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -219,10 +219,7 @@ extension Collection where Element == RESPValue { extension ByteBuffer { static func makeFromIntAsString(_ value: Int) -> ByteBuffer { - let utf8 = String(value).utf8 - var buffer = sharedAllocator.buffer(capacity: utf8.count) - buffer.write(bytes: utf8) - return buffer + return ByteBuffer(string: String(value)) } var stringAsInteger: Int? { guard readableBytes > 0 else { return nil } diff --git a/Sources/RedisServer/Values/RedisValueCoding.swift b/Sources/RedisServer/Values/RedisValueCoding.swift index 0c02e81..efffd36 100644 --- a/Sources/RedisServer/Values/RedisValueCoding.swift +++ b/Sources/RedisServer/Values/RedisValueCoding.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -17,50 +17,33 @@ import struct NIO.ByteBuffer import struct NIO.ByteBufferAllocator import NIOFoundationCompat -extension ByteBuffer : Encodable { - - public func encode(to encoder: Encoder) throws { - let data = getData(at: readerIndex, length: readableBytes)! - var container = encoder.singleValueContainer() - try container.encode(data) - } -} - extension KeyedDecodingContainer { func decodeByteBuffer(forKey key: Key) throws -> ByteBuffer { let data = try decode(Data.self, forKey: key) - var bb = ByteBufferAllocator().buffer(capacity: data.count + 1) - bb.write(bytes: data) - return bb + return ByteBuffer(data: data) } func decodeByteBufferArray(forKey key: Key) throws -> ContiguousArray { let datas = try decode(Array.self, forKey: key) - let alloc = ByteBufferAllocator() var buffers = ContiguousArray() buffers.reserveCapacity(datas.count + 1) for data in datas { - var bb = alloc.buffer(capacity: data.count + 1) - bb.write(bytes: data) - buffers.append(bb) + buffers.append(ByteBuffer(data: data)) } return buffers } func decodeByteBufferHash(forKey key: Key) throws -> [ Data : ByteBuffer ] { let datas = try decode(Dictionary.self, forKey: key) - let alloc = ByteBufferAllocator() var buffers = [ Data : ByteBuffer ]() buffers.reserveCapacity(datas.count + 1) for ( key, data ) in datas { - var bb = alloc.buffer(capacity: data.count + 1) - bb.write(bytes: data) - buffers[key] = bb + buffers[key] = ByteBuffer(data: data) } return buffers } diff --git a/Sources/redi-s/main.swift b/Sources/redi-s/main.swift index 2b9dc8c..7d87554 100644 --- a/Sources/redi-s/main.swift +++ b/Sources/redi-s/main.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2024 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -34,7 +34,9 @@ if args.contains("--help") || args.contains("-h") { } let cmdLinePort : Int? = { - guard let idx = args.index(where: { [ "-p", "--port" ].contains($0) }) else { + guard let idx = + args.firstIndex(where: { [ "-p", "--port" ].contains($0) }) else + { return nil } guard (idx + 1) < args.endIndex, let port = UInt16(args[idx + 1]) else {