Moved BindingGenerator from gen html project. It makes more sense here.
This commit is contained in:
171
Sources/BindingGenerator/Internal/String+Escaping.swift
Normal file
171
Sources/BindingGenerator/Internal/String+Escaping.swift
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* Plot
|
||||
* Copyright (c) John Sundell 2019
|
||||
* MIT license, see LICENSE file for details
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
/// let someUrl:URL = try URL("hello") ?! AppError("What")
|
||||
infix operator ?!: NilCoalescingPrecedence
|
||||
|
||||
public func ?!<T>(value: T?, error: @autoclosure () -> Error) throws -> T {
|
||||
if let value = value { return value }
|
||||
throw error()
|
||||
}
|
||||
|
||||
|
||||
internal extension String {
|
||||
func asSubstring() -> Substring {
|
||||
return self[self.startIndex..<self.endIndex]
|
||||
}
|
||||
func escaped() -> String {
|
||||
var pendingAmpersandString: String?
|
||||
|
||||
func flushPendingAmpersandString(
|
||||
withSuffix suffix: String? = nil,
|
||||
resettingTo newValue: String? = nil
|
||||
) -> String {
|
||||
let pending = pendingAmpersandString
|
||||
pendingAmpersandString = newValue
|
||||
return pending.map { "&\($0)\(suffix ?? "")" } ?? suffix ?? ""
|
||||
}
|
||||
|
||||
return String(flatMap { character -> String in
|
||||
switch character {
|
||||
case "<":
|
||||
return flushPendingAmpersandString(withSuffix: "<")
|
||||
case ">":
|
||||
return flushPendingAmpersandString(withSuffix: ">")
|
||||
case "&":
|
||||
return flushPendingAmpersandString(resettingTo: "")
|
||||
case ";":
|
||||
let pending = pendingAmpersandString.map { "&\($0);" }
|
||||
pendingAmpersandString = nil
|
||||
return pending ?? ";"
|
||||
case "#" where pendingAmpersandString?.isEmpty == true:
|
||||
pendingAmpersandString = "#"
|
||||
return ""
|
||||
default:
|
||||
if let pending = pendingAmpersandString {
|
||||
guard character.isLetter || character.isNumber else {
|
||||
return flushPendingAmpersandString(withSuffix: String(character))
|
||||
}
|
||||
|
||||
pendingAmpersandString = "\(pending)\(character)"
|
||||
return ""
|
||||
}
|
||||
|
||||
return "\(character)"
|
||||
}
|
||||
}) + flushPendingAmpersandString()
|
||||
}
|
||||
|
||||
static func parseList(_ value:String?, _ separator:String = " ") throws -> [String] {
|
||||
guard let value = value else { return [] }
|
||||
var iterator = value.componentsIterator(separatedBy: separator)
|
||||
return iterator.map({String($0)})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Array where Element: RawRepresentable, Element.RawValue == String {
|
||||
/// Converts an array of String-backed enums to an array of their raw string values.
|
||||
func toStringList(_ seperator:String) -> String {
|
||||
let strList = self.map { $0.rawValue }
|
||||
return strList.joined(separator: seperator)
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == String {
|
||||
/// Converts an array of String-backed enums to an array of their raw string values.
|
||||
func toStringList(_ seperator:String) -> String {
|
||||
let strList = self.map { $0 }
|
||||
return strList.joined(separator: seperator)
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == URL {
|
||||
/// Converts an array of String-backed enums to an array of their raw string values.
|
||||
func toStringList(_ seperator:String) -> String {
|
||||
let strList = self.map { $0.absoluteString }
|
||||
return strList.joined(separator: seperator)
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == Float {
|
||||
/// Converts an array of String-backed enums to an array of their raw string values.
|
||||
func toStringList(_ seperator:String) -> String {
|
||||
let strList = self.map { String($0) }
|
||||
return strList.joined(separator: seperator)
|
||||
}
|
||||
}
|
||||
|
||||
extension Set where Element: RawRepresentable, Element.RawValue == String {
|
||||
/// Converts an array of String-backed enums to an array of their raw string values.
|
||||
func toStringList(_ seperator:String) -> String {
|
||||
let strList = self.map { $0.rawValue }
|
||||
return strList.joined(separator: seperator)
|
||||
}
|
||||
}
|
||||
|
||||
extension Float {
|
||||
static func parseList(_ value:String?, _ separator:String = " ") throws -> [Float] {
|
||||
guard let value = value else { return [] }
|
||||
var iterator = value.componentsIterator(separatedBy: separator)
|
||||
return try iterator.map({ try Float.expect($0) })
|
||||
}
|
||||
|
||||
static func expect(_ value:String) throws -> Float {
|
||||
if let result = Float(value) {
|
||||
return result
|
||||
}
|
||||
throw AppError("Unable to map value to float")
|
||||
}
|
||||
|
||||
static func expect(_ value:Substring) throws -> Float {
|
||||
if let result = Float(value) {
|
||||
return result
|
||||
}
|
||||
throw AppError("Unable to map value to float")
|
||||
}
|
||||
}
|
||||
|
||||
extension URL {
|
||||
static func parseList(_ value:String?, _ separator:String = " ") throws -> [URL] {
|
||||
guard let value = value else { return [] }
|
||||
var iterator = value.componentsIterator(separatedBy: separator)
|
||||
return try iterator.map({
|
||||
guard let result = URL(string:String($0)) else {
|
||||
throw AppError("Invalid URL: \(String($0))")
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
extension Bool {
|
||||
public init(expect: String) throws {
|
||||
if (expect == "true") {
|
||||
self = true
|
||||
return
|
||||
}
|
||||
if (expect == "false") {
|
||||
self = false
|
||||
return
|
||||
}
|
||||
throw AppError("Unexpected value for bool: \(expect)")
|
||||
}
|
||||
|
||||
public init(expectYesOrNo: String) throws {
|
||||
if (expectYesOrNo == "yes") {
|
||||
self = true
|
||||
return
|
||||
}
|
||||
if (expectYesOrNo == "no") {
|
||||
self = false
|
||||
return
|
||||
}
|
||||
throw AppError("Unexpected value for bool: \(expectYesOrNo)")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user