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:
@@ -1,4 +1,4 @@
|
|||||||
// swift-tools-version:5.7
|
// swift-tools-version:5.9
|
||||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
import PackageDescription
|
import PackageDescription
|
||||||
@@ -13,5 +13,6 @@ let package = Package(
|
|||||||
targets: [
|
targets: [
|
||||||
.target(name: "Mustache", dependencies: []),
|
.target(name: "Mustache", dependencies: []),
|
||||||
.testTarget(name: "MustacheTests", dependencies: ["Mustache"]),
|
.testTarget(name: "MustacheTests", dependencies: ["Mustache"]),
|
||||||
]
|
],
|
||||||
|
swiftLanguageVersions: [.v5, .version("6")]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
/// Protocol for content types
|
/// Protocol for content types
|
||||||
public protocol MustacheContentType: Sendable {
|
public protocol MustacheContentType: Sendable {
|
||||||
/// escape text for this content type eg for HTML replace "<" with "<"
|
/// escape text for this content type eg for HTML replace "<" with "<"
|
||||||
@@ -38,8 +40,13 @@ struct HTMLContentType: MustacheContentType {
|
|||||||
/// the content type required. The default available types are `TEXT` and `HTML`. You can register your own
|
/// the content type required. The default available types are `TEXT` and `HTML`. You can register your own
|
||||||
/// with `MustacheContentTypes.register`.
|
/// with `MustacheContentTypes.register`.
|
||||||
public enum MustacheContentTypes {
|
public enum MustacheContentTypes {
|
||||||
|
|
||||||
|
private static let lock = NSLock()
|
||||||
|
|
||||||
static func get(_ name: String) -> MustacheContentType? {
|
static func get(_ name: String) -> MustacheContentType? {
|
||||||
self.types[name]
|
lock.withLock {
|
||||||
|
self.types[name]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register new content type
|
/// Register new content type
|
||||||
@@ -47,11 +54,19 @@ public enum MustacheContentTypes {
|
|||||||
/// - contentType: Content type
|
/// - contentType: Content type
|
||||||
/// - name: String to identify it
|
/// - name: String to identify it
|
||||||
public static func register(_ contentType: MustacheContentType, named name: String) {
|
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(),
|
"HTML": HTMLContentType(),
|
||||||
"TEXT": TextContentType(),
|
"TEXT": TextContentType(),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
#if compiler(>=6.0)
|
||||||
|
nonisolated(unsafe) static var types: [String: MustacheContentType] = _types
|
||||||
|
#else
|
||||||
|
static var types: [String: MustacheContentType] = _types
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import Foundation
|
|||||||
|
|
||||||
extension MustacheLibrary {
|
extension MustacheLibrary {
|
||||||
/// Load templates from a folder
|
/// 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
|
var directory = directory
|
||||||
if !directory.hasSuffix("/") {
|
if !directory.hasSuffix("/") {
|
||||||
directory += "/"
|
directory += "/"
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public struct MustacheLibrary: Sendable {
|
|||||||
/// - Parameter directory: Directory to look for mustache templates
|
/// - Parameter directory: Directory to look for mustache templates
|
||||||
/// - Parameter extension: Extension of files to look for
|
/// - Parameter extension: Extension of files to look for
|
||||||
public init(directory: String, withExtension extension: String = "mustache") async throws {
|
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
|
/// Register template under name
|
||||||
|
|||||||
27
Sources/Mustache/NSLock+Backport.swift
Normal file
27
Sources/Mustache/NSLock+Backport.swift
Normal 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
|
||||||
@@ -303,7 +303,7 @@ extension Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// context used in parser error
|
/// context used in parser error
|
||||||
public struct MustacheParserContext {
|
public struct MustacheParserContext: Sendable {
|
||||||
public let line: String
|
public let line: String
|
||||||
public let lineNumber: Int
|
public let lineNumber: Int
|
||||||
public let columnNumber: Int
|
public let columnNumber: Int
|
||||||
|
|||||||
@@ -65,11 +65,7 @@ extension MustacheTemplate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if hasFeature(RetroactiveAttribute)
|
|
||||||
extension MustacheTemplate: @retroactive Equatable {}
|
|
||||||
#else
|
|
||||||
extension MustacheTemplate: Equatable {}
|
extension MustacheTemplate: Equatable {}
|
||||||
#endif
|
|
||||||
|
|
||||||
extension MustacheTemplate.Token {
|
extension MustacheTemplate.Token {
|
||||||
public static func == (lhs: MustacheTemplate.Token, rhs: MustacheTemplate.Token) -> Bool {
|
public static func == (lhs: MustacheTemplate.Token, rhs: MustacheTemplate.Token) -> Bool {
|
||||||
@@ -92,8 +88,4 @@ extension MustacheTemplate.Token {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if hasFeature(RetroactiveAttribute)
|
|
||||||
extension MustacheTemplate.Token: @retroactive Equatable {}
|
|
||||||
#else
|
|
||||||
extension MustacheTemplate.Token: Equatable {}
|
extension MustacheTemplate.Token: Equatable {}
|
||||||
#endif
|
|
||||||
|
|||||||
Reference in New Issue
Block a user