Support Swift 6 mode (#65)

* Enable swift 6 mode

* Attach Sendable

* Stop async context because enumerator can use only synchronous contexts

* Fix global shared mutable state for MustacheContentTypes

* Revert "Fix global shared mutable state for MustacheContentTypes"

This reverts commit d4ccc83e07aeb48f4aa4024b71eb8e5f70131bc5.

* Use  instead of lock

* Support 5 and 6 versions

* Lock on access in Swift 6

* Support 5.9

* Revert "Support 5.9"

This reverts commit 9845b3bc448b2af7238c3ac88aabe6d764b2e667.

* Fix 5.9 compatibility

* Unify to manage the same lock logic in 5.9 and 6

* Add withLock backport in NSLock
This commit is contained in:
Go Takagi
2025-03-26 18:53:44 +09:00
committed by GitHub
parent eeb4eec97f
commit 2add8847a1
7 changed files with 51 additions and 16 deletions

View File

@@ -12,6 +12,8 @@
//
//===----------------------------------------------------------------------===//
import Foundation
/// Protocol for content types
public protocol MustacheContentType: Sendable {
/// escape text for this content type eg for HTML replace "<" with "&lt;"
@@ -38,8 +40,13 @@ struct HTMLContentType: MustacheContentType {
/// the content type required. The default available types are `TEXT` and `HTML`. You can register your own
/// with `MustacheContentTypes.register`.
public enum MustacheContentTypes {
private static let lock = NSLock()
static func get(_ name: String) -> MustacheContentType? {
self.types[name]
lock.withLock {
self.types[name]
}
}
/// Register new content type
@@ -47,11 +54,19 @@ public enum MustacheContentTypes {
/// - contentType: Content type
/// - name: String to identify it
public static func register(_ contentType: MustacheContentType, named name: String) {
self.types[name] = contentType
lock.withLock {
self.types[name] = contentType
}
}
static var types: [String: MustacheContentType] = [
private static let _types: [String: MustacheContentType] = [
"HTML": HTMLContentType(),
"TEXT": TextContentType(),
]
#if compiler(>=6.0)
nonisolated(unsafe) static var types: [String: MustacheContentType] = _types
#else
static var types: [String: MustacheContentType] = _types
#endif
}

View File

@@ -16,7 +16,7 @@ import Foundation
extension MustacheLibrary {
/// Load templates from a folder
static func loadTemplates(from directory: String, withExtension extension: String = "mustache") async throws -> [String: MustacheTemplate] {
static func loadTemplates(from directory: String, withExtension extension: String = "mustache") throws -> [String: MustacheTemplate] {
var directory = directory
if !directory.hasSuffix("/") {
directory += "/"

View File

@@ -39,7 +39,7 @@ public struct MustacheLibrary: Sendable {
/// - Parameter directory: Directory to look for mustache templates
/// - Parameter extension: Extension of files to look for
public init(directory: String, withExtension extension: String = "mustache") async throws {
self.templates = try await Self.loadTemplates(from: directory, withExtension: `extension`)
self.templates = try Self.loadTemplates(from: directory, withExtension: `extension`)
}
/// Register template under name

View File

@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Hummingbird server framework project
//
// Copyright (c) 2021-2021 the Hummingbird authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
#if compiler(<6.0)
import Foundation
extension NSLock {
func withLock<Value>(_ operation: () throws -> Value) rethrows -> Value {
self.lock()
defer {
self.unlock()
}
return try operation()
}
}
#endif

View File

@@ -303,7 +303,7 @@ extension Parser {
}
/// context used in parser error
public struct MustacheParserContext {
public struct MustacheParserContext: Sendable {
public let line: String
public let lineNumber: Int
public let columnNumber: Int