Skip to content

Instantly share code, notes, and snippets.

@kateinoigakukun
Last active November 22, 2016 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kateinoigakukun/5f281819056ecb8d6a52788d81e16584 to your computer and use it in GitHub Desktop.
Save kateinoigakukun/5f281819056ecb8d6a52788d81e16584 to your computer and use it in GitHub Desktop.
import Foundation
enum FormatType {
case intType(Int.Type)
case stringType(String.Type)
case string(String)
}
enum MatchedType {
case string(String)
case int(Int)
}
class RoutingFormat {
var matching: [FormatType] = []
init(first: String, second: Int.Type) {
self.matching.append(.string(first))
self.matching.append(.intType(second))
}
init(first: String, second: String.Type) {
self.matching.append(.string(first))
self.matching.append(.stringType(second))
}
init(first: String.Type, second: String) {
self.matching.append(.stringType(first))
self.matching.append(.string(second))
}
init(first: String.Type, second: Int.Type) {
self.matching.append(.stringType(first))
self.matching.append(.intType(second))
}
init(first: Int.Type, second: String) {
self.matching.append(.intType(first))
self.matching.append(.string(second))
}
init(first: Int.Type, second: Int.Type) {
self.matching.append(.intType(first))
self.matching.append(.intType(second))
}
func `is`(pathComponent: [String]) -> Bool {
var pathComponent = pathComponent
pathComponent.remove(at: 0)
if matching.count != pathComponent.count { return false }
return (0..<matching.count).contains {
let expect = matching[$0]
let actual = pathComponent[$0]
switch expect {
case .string(let string):
return string == actual
case .intType(let type):
return type.init(actual) != nil
case .stringType( _):
return true
}
}
}
func `is`(_ url: URL) -> Bool {
return self.is(pathComponent: url.pathComponents)
}
func match(_ url: URL) -> [MatchedType] {
return self.match(pathComponent: url.pathComponents)
}
func match(pathComponent: [String]) -> [MatchedType] {
if !self.is(pathComponent: pathComponent) {
return []
}
var pathComponent = pathComponent
pathComponent.remove(at: 0)
return (0..<matching.count).flatMap {
let expect = matching[$0]
let actual = pathComponent[$0]
switch expect {
case .string( _):
return nil
case .intType( _):
return MatchedType.int(Int(actual)!)
case .stringType( _):
return MatchedType.string(actual)
}
}
}
}
func /(rhs: String, lhs: Int.Type) -> RoutingFormat {
return RoutingFormat(first: rhs, second: lhs)
}
func /(rhs: String, lhs: String.Type) -> RoutingFormat {
return RoutingFormat(first: rhs, second: lhs)
}
func /(rhs: RoutingFormat, lhs: String) -> RoutingFormat {
rhs.matching.append(.string(lhs))
return rhs
}
func /(rhs: RoutingFormat, lhs: String.Type) -> RoutingFormat {
rhs.matching.append(.stringType(lhs))
return rhs
}
func /(rhs: RoutingFormat, lhs: Int.Type) -> RoutingFormat {
rhs.matching.append(.intType(lhs))
return rhs
}
func /(rhs: String.Type, lhs: Int.Type) -> RoutingFormat {
return RoutingFormat(first: rhs, second: lhs)
}
func /(rhs: String.Type, lhs: String) -> RoutingFormat {
return RoutingFormat(first: rhs, second: lhs)
}
let url = URL(string: "http://twitter.com/kateinoigakukun/status/32825943461888")!
(String.self/"status"/Int.self).is(url)
// true
(String.self/"status"/Int.self).match(url)
// [{string "kateinoigakukun"}, {int 32825943461888}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment