Files
swiftpm-mustache/Sources/HummingbirdMustache/Method.swift
Adam Fowler 66edcba185 swift format
2021-03-15 18:24:06 +00:00

152 lines
4.3 KiB
Swift

/// Objects that can have a methods run on them. Mustache methods are specific to this implementation
/// of Mustache. They allow you to process objects before they are rendered.
///
/// The syntax for applying methods is `{{method(variable)}}`. Methods can be applied to both
/// variables and sections.
///
/// A simple example would be ensuring a string is lowercase.
/// ```
/// {{lowercased(myString)}}
/// ```
/// If applying a method to a sequence then the closing element of the sequence should not include the
/// method name eg
/// ```
/// {{#reversed(sequence)}}{{.}}{{\sequence}}
/// ```
public protocol HBMustacheMethods {
func runMethod(_ name: String) -> Any?
}
public extension StringProtocol {
/// Apply method to String/Substring
///
/// Methods available are `capitalized`, `lowercased`, `uppercased` and `reversed`
/// - Parameter name: Method name
/// - Returns: Result
func runMethod(_ name: String) -> Any? {
switch name {
case "capitalized":
return capitalized
case "lowercased":
return lowercased()
case "uppercased":
return uppercased()
case "reversed":
return reversed()
default:
return nil
}
}
}
extension String: HBMustacheMethods {}
extension Substring: HBMustacheMethods {}
/// Protocol for sequence that can be sorted
private protocol HBComparableSequence {
func runComparableMethod(_ name: String) -> Any?
}
extension Array: HBMustacheMethods {
/// Apply method to Array.
///
/// Methods available are `first`, `last`, `reversed`, `count` and for arrays
/// with comparable elements `sorted`.
/// - Parameter name: method name
/// - Returns: Result
public func runMethod(_ name: String) -> Any? {
switch name {
case "first":
return first
case "last":
return last
case "reversed":
return reversed()
case "count":
return count
default:
if let comparableSeq = self as? HBComparableSequence {
return comparableSeq.runComparableMethod(name)
}
return nil
}
}
}
extension Array: HBComparableSequence where Element: Comparable {
func runComparableMethod(_ name: String) -> Any? {
switch name {
case "sorted":
return sorted()
default:
return nil
}
}
}
extension Dictionary: HBMustacheMethods {
/// Apply method to Dictionary
///
/// Methods available are `count`, `enumerated` and for dictionaries
/// with comparable keys `sorted`.
/// - Parameter name: method name
/// - Returns: Result
public func runMethod(_ name: String) -> Any? {
switch name {
case "count":
return count
case "enumerated":
return map { (key: $0.key, value: $0.value) }
default:
if let comparableSeq = self as? HBComparableSequence {
return comparableSeq.runComparableMethod(name)
}
return nil
}
}
}
extension Dictionary: HBComparableSequence where Key: Comparable {
func runComparableMethod(_ name: String) -> Any? {
switch name {
case "sorted":
return map { (key: $0.key, value: $0.value) }.sorted { $0.key < $1.key }
default:
return nil
}
}
}
public extension FixedWidthInteger {
/// Apply method to FixedWidthInteger
///
/// Methods available are `plusone`, `minusone`, `odd`, `even`
/// - Parameter name: method name
/// - Returns: Result
func runMethod(_ name: String) -> Any? {
switch name {
case "plusone":
return self + 1
case "minusone":
return self - 1
case "even":
return (self & 1) == 0
case "odd":
return (self & 1) == 1
default:
return nil
}
}
}
extension Int: HBMustacheMethods {}
extension Int8: HBMustacheMethods {}
extension Int16: HBMustacheMethods {}
extension Int32: HBMustacheMethods {}
extension Int64: HBMustacheMethods {}
extension UInt: HBMustacheMethods {}
extension UInt8: HBMustacheMethods {}
extension UInt16: HBMustacheMethods {}
extension UInt32: HBMustacheMethods {}
extension UInt64: HBMustacheMethods {}