diff --git a/README.md b/README.md index 4cce41d..81b5b9a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # SwiftNIO Redis -![Swift4](https://img.shields.io/badge/swift-4-blue.svg) ![Swift5](https://img.shields.io/badge/swift-5-blue.svg) ![macOS](https://img.shields.io/badge/os-macOS-green.svg?style=flat) ![tuxOS](https://img.shields.io/badge/os-tuxOS-green.svg?style=flat) diff --git a/Sources/NIORedis/RESPChannelHandler.swift b/Sources/NIORedis/RESPChannelHandler.swift index b06cd6d..1a3f264 100644 --- a/Sources/NIORedis/RESPChannelHandler.swift +++ b/Sources/NIORedis/RESPChannelHandler.swift @@ -133,7 +133,7 @@ open class RESPChannelHandler : ChannelDuplexHandler { context.write(wrapOutboundOut(out), promise: promise) } - @inline(__always) + @inlinable final func encode(simpleString bytes: S, out: inout ByteBuffer) where S.Element == UInt8 @@ -143,7 +143,7 @@ open class RESPChannelHandler : ChannelDuplexHandler { out.writeBytes(eol) } - @inline(__always) + @inlinable final func encode(simpleString bytes: ByteBuffer, out: inout ByteBuffer) { var s = bytes out.writeInteger(UInt8(43)) // + @@ -151,7 +151,7 @@ open class RESPChannelHandler : ChannelDuplexHandler { out.writeBytes(eol) } - @inline(__always) + @inlinable final func encode(bulkString bytes: ByteBuffer?, out: inout ByteBuffer) { if var s = bytes { out.writeInteger(UInt8(36)) // $ @@ -165,7 +165,7 @@ open class RESPChannelHandler : ChannelDuplexHandler { } } - @inline(__always) + @inlinable final func encode(bulkString bytes: S?, out: inout ByteBuffer) where S.Element == UInt8 @@ -182,14 +182,14 @@ open class RESPChannelHandler : ChannelDuplexHandler { } } - @inline(__always) + @inlinable final func encode(integer i: Int, out: inout ByteBuffer) { out.writeInteger(UInt8(58)) // : out.write(integerAsString : i) out.writeBytes(eol) } - @inline(__always) + @inlinable final func encode(error: RESPError, out: inout ByteBuffer) { out.writeInteger(UInt8(45)) // - out.writeString(error.code) @@ -241,8 +241,10 @@ open class RESPChannelHandler : ChannelDuplexHandler { } } -private let eol : ContiguousArray = [ 13, 10 ] // \r\n -private let nilString : ContiguousArray = [ 36, 45, 49, 13, 10 ] // $-1\r\n +@usableFromInline +let eol : ContiguousArray = [ 13, 10 ] // \r\n +@usableFromInline +let nilString : ContiguousArray = [ 36, 45, 49, 13, 10 ] // $-1\r\n private let nilArray : ContiguousArray = [ 42, 45, 49, 13, 10 ] // *-1\r\n fileprivate enum ConstantBuffers { diff --git a/Sources/NIORedis/RESPEncodable.swift b/Sources/NIORedis/RESPEncodable.swift index 496ebe8..7331016 100644 --- a/Sources/NIORedis/RESPEncodable.swift +++ b/Sources/NIORedis/RESPEncodable.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-2021 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -18,68 +18,58 @@ import struct NIO.ByteBuffer public protocol RESPEncodable { func toRESPValue() -> RESPValue - } extension RESPValue : RESPEncodable { - public func toRESPValue() -> RESPValue { - return self - } - + @inlinable + public func toRESPValue() -> RESPValue { return self } } extension RESPError : RESPEncodable { - - public func toRESPValue() -> RESPValue { - return .error(self) - } + @inlinable + public func toRESPValue() -> RESPValue { return .error(self) } } extension Int : RESPEncodable { - public func toRESPValue() -> RESPValue { - return .integer(self) - } - + @inlinable + public func toRESPValue() -> RESPValue { return .integer(self) } } extension Bool : RESPEncodable { - public func toRESPValue() -> RESPValue { - return .integer(self ? 1 : 0) - } - + @inlinable + public func toRESPValue() -> RESPValue { return .integer(self ? 1 : 0) } } extension String : RESPEncodable { + @inlinable public func toRESPValue() -> RESPValue { return .bulkString(self.utf8.asByteBuffer) } - } extension Data : RESPEncodable { + @inlinable public func toRESPValue() -> RESPValue { return .bulkString(self.asByteBuffer) } - } extension ByteBuffer : RESPEncodable { - - public func toRESPValue() -> RESPValue { - return .bulkString(self) - } - + + @inlinable + public func toRESPValue() -> RESPValue { return .bulkString(self) } } extension Array where Element: RESPEncodable { + @inlinable public func toRESPValue() -> RESPValue { let arrayOfRedisValues = self.map { $0.toRESPValue() } return .array(ContiguousArray(arrayOfRedisValues)) @@ -89,6 +79,7 @@ extension Array where Element: RESPEncodable { extension Array: RESPEncodable { + @inlinable public func toRESPValue() -> RESPValue { let array : [ RESPValue ] = self.map { v in if let rv = (v as? RESPEncodable) { diff --git a/Sources/NIORedis/RESPParser.swift b/Sources/NIORedis/RESPParser.swift index b678826..22e9b60 100644 --- a/Sources/NIORedis/RESPParser.swift +++ b/Sources/NIORedis/RESPParser.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018-2020 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2021 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -35,7 +35,6 @@ public struct RESPParser { let count = bp.count var i = 0 - @inline(__always) func doSkipNL() { if i >= count { overflowSkipNL = true @@ -238,7 +237,6 @@ public struct RESPParser { // MARK: - Parsing - @inline(__always) private mutating func pushArrayContext(expectedCount: Int) { if ctxIndex == ctxCapacity { for _ in 0..<4 { @@ -252,7 +250,6 @@ public struct RESPParser { arrayContextBuffer[ctxIndex].values.reserveCapacity(expectedCount) } - @inline(__always) private mutating func decoded(value: RESPValue, yield: Yield) { if ctxIndex < 0 { return yield(value) @@ -313,11 +310,8 @@ public struct RESPParser { values.reserveCapacity(expectedCount + 1) } - var isDone : Bool { - @inline(__always) get { return expectedCount <= values.count } - } + var isDone : Bool { return expectedCount <= values.count } - @inline(__always) mutating func append(value v: RESPValue) -> Bool { assert(!isDone, "attempt to add to a context which is not TL or done") values.append(v) @@ -331,5 +325,4 @@ public struct RESPParser { private var countValue = 0 private var overflowSkipNL = false private var overflowBuffer : ByteBuffer? - } diff --git a/Sources/NIORedis/RESPPipelineSetup.swift b/Sources/NIORedis/RESPPipelineSetup.swift index 6529d73..e897b0b 100644 --- a/Sources/NIORedis/RESPPipelineSetup.swift +++ b/Sources/NIORedis/RESPPipelineSetup.swift @@ -2,7 +2,7 @@ // // This source file is part of the swift-nio-redis open source project // -// Copyright (c) 2018-2020 ZeeZide GmbH. and the swift-nio-redis project authors +// Copyright (c) 2018-2021 ZeeZide GmbH. and the swift-nio-redis project authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information @@ -17,6 +17,7 @@ import class NIO.EventLoopFuture public extension ChannelPipeline { + @inlinable func configureRedisPipeline(first : Bool = false, name : String = "de.zeezide.nio.RESP") -> EventLoopFuture diff --git a/Sources/NIORedis/RESPValue.swift b/Sources/NIORedis/RESPValue.swift index 9c04b8a..a9e0c94 100644 --- a/Sources/NIORedis/RESPValue.swift +++ b/Sources/NIORedis/RESPValue.swift @@ -49,14 +49,14 @@ public struct RESPError : Error, CustomStringConvertible { // MARK: - Initializers -fileprivate let sharedAllocator = ByteBufferAllocator() +@usableFromInline let sharedAllocator = ByteBufferAllocator() public extension RESPValue { - init(_ v: Int) { - self = .integer(v) - } + @inlinable + init(_ v: Int) { self = .integer(v) } + @inlinable init(bulkString s: String?) { if let s = s { let utf8 = s.utf8 @@ -68,12 +68,14 @@ public extension RESPValue { self = .bulkString(nil) } } + @inlinable init(bulkString s: Data) { var buffer = sharedAllocator.buffer(capacity: s.count) buffer.writeBytes(s) self = .bulkString(buffer) } + @inlinable init(bulkString s: Int) { let s = String(s) let utf8 = s.utf8 @@ -82,45 +84,48 @@ public extension RESPValue { self = .bulkString(buffer) } + @inlinable init(simpleString s: String) { self = .simpleString(s.utf8.asByteBuffer) } + @inlinable init(errorCode code: String, message: String? = nil) { self = .error(RESPError(code: code, message: message ?? "Failed: \(code)")) } + @inlinable init(array: T) where T.Element == RESPValue { self = .array(ContiguousArray(array)) } + +} +public extension RESPValue { // MARK: - Content Accessors + + @inlinable var byteBuffer : ByteBuffer? { - @inline(__always) - get { - switch self { - case .simpleString(let cs), .bulkString(.some(let cs)): return cs - default: return nil - } + switch self { + case .simpleString(let cs), .bulkString(.some(let cs)): return cs + default: return nil } } + @inlinable var stringValue : String? { - @inline(__always) - get { - switch self { - case .simpleString(let cs), .bulkString(.some(let cs)): - return cs.getString(at: cs.readerIndex, length: cs.readableBytes) - - case .integer(let i): - return String(i) - - default: return nil - } + switch self { + case .simpleString(let cs), .bulkString(.some(let cs)): + return cs.getString(at: cs.readerIndex, length: cs.readableBytes) + + case .integer(let i): + return String(i) + + default: return nil } } + @inlinable var dataValue : Data? { - @inline(__always) get { switch self { case .simpleString(let cs), .bulkString(.some(let cs)): @@ -131,12 +136,10 @@ public extension RESPValue { } } - var keyValue : Data? { - @inline(__always) - get { return self.dataValue } - } + @inlinable + var keyValue : Data? { return self.dataValue } - @inline(__always) + @inlinable func withKeyValue(_ cb: ( Data? ) throws -> Void) rethrows { // SR-7378 switch self { @@ -154,28 +157,27 @@ public extension RESPValue { } } + @inlinable var intValue : Int? { - @inline(__always) - get { - switch self { - case .integer(let i): - return i - - case .simpleString(let cs), .bulkString(.some(let cs)): - // PERF: inline atoi instead of constructing a string! - guard let s = cs.getString(at: cs.readerIndex, - length: cs.readableBytes) else { - return nil - } - return Int(s) - - default: + switch self { + case .integer(let i): + return i + + case .simpleString(let cs), .bulkString(.some(let cs)): + // PERF: inline atoi instead of constructing a string! + guard let s = cs.getString(at: cs.readerIndex, + length: cs.readableBytes) else { return nil - } + } + return Int(s) + + default: + return nil } } } +@inlinable public func ==(lhs: RESPValue, rhs: String) -> Bool { switch lhs { case .simpleString, .bulkString: @@ -191,6 +193,8 @@ public func ==(lhs: RESPValue, rhs: String) -> Bool { // MARK: - Parse Literals extension RESPValue : ExpressibleByIntegerLiteral { + + @inlinable public init(integerLiteral value: IntegerLiteralType) { self = .integer(value) } @@ -199,6 +203,8 @@ extension RESPValue : ExpressibleByIntegerLiteral { import NIOFoundationCompat extension Data { + + @usableFromInline var asByteBuffer : ByteBuffer { var bb = sharedAllocator.buffer(capacity: count) bb.writeBytes(self) @@ -207,6 +213,8 @@ extension Data { } extension String.UTF8View { + + @usableFromInline var asByteBuffer : ByteBuffer { var bb = sharedAllocator.buffer(capacity: count) bb.writeBytes(self) @@ -216,20 +224,23 @@ extension String.UTF8View { extension RESPValue : ExpressibleByStringLiteral { + @inlinable public init(stringLiteral value: String) { self = .bulkString(value.utf8.asByteBuffer) } + @inlinable public init(extendedGraphemeClusterLiteral value: StringLiteralType) { self = .bulkString(value.utf8.asByteBuffer) } + @inlinable public init(unicodeScalarLiteral value: StringLiteralType) { self = .bulkString(value.utf8.asByteBuffer) } - } extension RESPValue : CustomStringConvertible { + @inlinable public var description : String { switch self { case .simpleString(let cs): return stringValue ?? "\(cs)" @@ -249,12 +260,14 @@ extension RESPValue : CustomStringConvertible { extension String { // FIXME: we can probably do this in the buffer + @inlinable static func decode(utf8 ba: I) -> String? where I.Iterator.Element == UInt8 { return decode(units: ba, decoder: UTF8()) } + @inlinable static func decode (units b: I, decoder d: Codec) -> String? where I.Iterator.Element == Codec.CodeUnit