Skip to content

Commit

Permalink
Result builder router in separate module
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-fowler committed Dec 5, 2023
1 parent 9207774 commit 0921e19
Show file tree
Hide file tree
Showing 10 changed files with 671 additions and 16 deletions.
5 changes: 5 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let package = Package(
.library(name: "HummingbirdTLS", targets: ["HummingbirdTLS"]),
.library(name: "HummingbirdFoundation", targets: ["HummingbirdFoundation"]),
.library(name: "HummingbirdJobs", targets: ["HummingbirdJobs"]),
.library(name: "HummingbirdRouter", targets: ["HummingbirdRouter"]),
.library(name: "HummingbirdXCT", targets: ["HummingbirdXCT"]),
.executable(name: "PerformanceTest", targets: ["PerformanceTest"]),
],
Expand Down Expand Up @@ -65,6 +66,10 @@ let package = Package(
.byName(name: "Hummingbird"),
.product(name: "Logging", package: "swift-log"),
]),
.target(name: "HummingbirdRouter", dependencies: [
.byName(name: "Hummingbird"),
.product(name: "Logging", package: "swift-log"),
]),
.target(name: "HummingbirdXCT", dependencies: [
.byName(name: "Hummingbird"),
.byName(name: "HummingbirdCoreXCT"),
Expand Down
22 changes: 11 additions & 11 deletions Sources/Hummingbird/Router/RouterPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//

/// Split router path into components
struct RouterPath: ExpressibleByStringLiteral {
enum Element: Equatable {
public struct RouterPath: Sendable, ExpressibleByStringLiteral {
public enum Element: Equatable, Sendable {
case path(Substring)
case capture(Substring)
case prefixCapture(suffix: Substring, parameter: Substring) // *.jpg
Expand All @@ -25,7 +25,7 @@ struct RouterPath: ExpressibleByStringLiteral {
case recursiveWildcard
case null

static func ~= <S: StringProtocol>(lhs: Element, rhs: S) -> Bool {
static func ~= (lhs: Element, rhs: some StringProtocol) -> Bool {
switch lhs {
case .path(let lhs):
return lhs == rhs
Expand All @@ -48,7 +48,7 @@ struct RouterPath: ExpressibleByStringLiteral {
}
}

static func == <S: StringProtocol>(lhs: Element, rhs: S) -> Bool {
static func == (lhs: Element, rhs: some StringProtocol) -> Bool {
switch lhs {
case .path(let lhs):
return lhs == rhs
Expand All @@ -58,9 +58,9 @@ struct RouterPath: ExpressibleByStringLiteral {
}
}

let components: [Element]
public let components: [Element]

init(_ value: String) {
public init(_ value: String) {
let split = value.split(separator: "/", omittingEmptySubsequences: true)
self.components = split.map { component in
if component.first == ":" {
Expand Down Expand Up @@ -97,20 +97,20 @@ struct RouterPath: ExpressibleByStringLiteral {
}
}

init(stringLiteral value: String) {
public init(stringLiteral value: String) {
self.init(value)
}
}

extension RouterPath: Collection {
func index(after i: Int) -> Int {
public func index(after i: Int) -> Int {
return self.components.index(after: i)
}

subscript(_ index: Int) -> RouterPath.Element {
public subscript(_ index: Int) -> RouterPath.Element {
return self.components[index]
}

var startIndex: Int { self.components.startIndex }
var endIndex: Int { self.components.endIndex }
public var startIndex: Int { self.components.startIndex }
public var endIndex: Int { self.components.endIndex }
}
8 changes: 3 additions & 5 deletions Sources/Hummingbird/Server/RequestContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public struct EndpointPath: Sendable {
}

/// Endpoint path
public internal(set) var value: String? {
public var value: String? {
get { self._value.withLockedValue { $0 } }
nonmutating set { self._value.withLockedValue { $0 = newValue } }
}
Expand Down Expand Up @@ -55,11 +55,9 @@ public struct HBCoreRequestContext: Sendable {
@usableFromInline
var logger: Logger
/// Endpoint path
@usableFromInline
var endpointPath: EndpointPath
public var endpointPath: EndpointPath
/// Parameters extracted from URI
@usableFromInline
var parameters: HBParameters
public var parameters: HBParameters

@inlinable
public init(
Expand Down
73 changes: 73 additions & 0 deletions Sources/HummingbirdRouter/MiddlewareModule/MiddlewareStack.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the swift-middleware open source project
//
// Copyright (c) 2023 Apple Inc. and the swift-middleware project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of swift-middleware project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import Hummingbird

public struct MiddlewareClosure<Input, Output, Context>: MiddlewareProtocol {
@usableFromInline
var closure: Middleware<Input, Output, Context>

@inlinable
public init(_ middleware: @escaping Middleware<Input, Output, Context>) {
self.closure = middleware
}

@inlinable
public func handle(_ input: Input, context: Context, next: (Input, Context) async throws -> Output) async throws -> Output {
try await self.closure(input, context, next)
}
}

public struct _Middleware2<M0: MiddlewareProtocol, M1: MiddlewareProtocol>: MiddlewareProtocol where M0.Input == M1.Input, M0.Context == M1.Context, M0.Output == M1.Output {
public typealias Input = M0.Input
public typealias Output = M0.Output
public typealias Context = M0.Context

@usableFromInline let m0: M0
@usableFromInline let m1: M1

@inlinable
public init(_ m0: M0, _ m1: M1) {
self.m0 = m0
self.m1 = m1
}

@inlinable
public func handle(_ input: M0.Input, context: M0.Context, next: (M0.Input, M0.Context) async throws -> M0.Output) async throws -> M0.Output {
try await self.m0.handle(input, context: context) { input, context in
try await self.m1.handle(input, context: context, next: next)
}
}
}

@resultBuilder
public enum MiddlewareFixedTypeBuilder<Input, Output, Context> {
public static func buildExpression<M0: MiddlewareProtocol>(_ m0: M0) -> M0 where M0.Input == Input, M0.Output == Output, M0.Context == Context {
return m0
}

public static func buildBlock<M0: MiddlewareProtocol>(_ m0: M0) -> M0 {
return m0
}

public static func buildPartialBlock<M0: MiddlewareProtocol>(first: M0) -> M0 {
first
}

public static func buildPartialBlock<M0: MiddlewareProtocol, M1: MiddlewareProtocol>(
accumulated m0: M0,
next m1: M1
) -> _Middleware2<M0, M1> where M0.Input == M1.Input, M0.Output == M1.Output, M0.Context == M1.Context {
_Middleware2(m0, m1)
}
}
Loading

0 comments on commit 0921e19

Please sign in to comment.