Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.26 KB | None | 0 0
  1. import Foundation
  2.  
  3. @_functionBuilder
  4. struct ContentListBuilder {
  5.  
  6. static func buildBlock() -> ContentList {
  7. return EmptyContentList()
  8. }
  9.  
  10. static func buildBlock(_ list: ContentList) -> ContentList {
  11. return list
  12. }
  13.  
  14. static func buildBlock(_ lists: ContentList...) -> ContentList {
  15. return TupleContentList(lists)
  16. }
  17. }
  18.  
  19. @_functionBuilder
  20. struct ContentBuilder {
  21.  
  22. static func buildBlock() -> Content {
  23. return EmptyContent()
  24. }
  25.  
  26. static func buildBlock(_ content: Content) -> Content {
  27. return content
  28. }
  29.  
  30. static func buildBlock(_ contents: Content...) -> Content {
  31. return TupleContent(contents)
  32. }
  33. }
  34.  
  35. protocol Content: Encodable {}
  36.  
  37. extension Content {
  38. func getAll<T>() -> [T] {
  39. switch self {
  40. case let tuple as TupleContent:
  41. return (tuple.values as? [T]) ?? []
  42. case let content as T:
  43. return [content]
  44. default:
  45. return []
  46. }
  47. }
  48. }
  49.  
  50. protocol ContentList: Content {
  51. var content: Content { get }
  52. }
  53.  
  54. extension ContentList {
  55. var all: [ContentList] {
  56. switch self {
  57. case let tuple as TupleContentList:
  58. return tuple.values
  59. case let list as ContentList:
  60. return [list]
  61. default:
  62. return []
  63. }
  64. }
  65. }
  66.  
  67. struct EmptyContent: Content {}
  68.  
  69. struct EmptyContentList: ContentList {
  70. var content: Content { EmptyContent() }
  71. }
  72.  
  73. protocol Tuple {
  74. associatedtype Body
  75.  
  76. var values: [Body] { get }
  77.  
  78. init(_ values: [Body])
  79. }
  80.  
  81. struct TupleContent: Tuple, Content {
  82. let values: [Content]
  83.  
  84. init(_ values: [Content]) {
  85. self.values = values
  86. }
  87. }
  88.  
  89. extension TupleContent {
  90. func encode(to encoder: Encoder) throws {}
  91. }
  92.  
  93. struct TupleContentList: Tuple, ContentList {
  94. var content: Content {
  95. return self
  96. }
  97.  
  98. let values: [ContentList]
  99.  
  100. init(_ values: [ContentList]) {
  101. self.values = values
  102. }
  103. }
  104.  
  105. extension TupleContentList {
  106. func encode(to encoder: Encoder) throws {}
  107. }
  108.  
  109. struct Package: Content {
  110. enum CodingKeys: CodingKey {
  111. case name
  112. case products
  113. case dependencies
  114. case targets
  115. }
  116.  
  117. let name: String
  118. let contentList: ContentList
  119.  
  120. init(name: String, @ContentListBuilder builder: () -> ContentList) {
  121. self.name = name
  122. self.contentList = builder()
  123. }
  124. }
  125.  
  126. extension Package {
  127. func encode(to encoder: Encoder) throws {
  128. var container = encoder.container(keyedBy: CodingKeys.self)
  129. try container.encode(name, forKey: .name)
  130. let lists = contentList.all
  131. for list in lists {
  132. switch list {
  133. case let productList as ProductList:
  134. try container.encode(productList, forKey: .products)
  135. case let dependencyList as DependencyList:
  136. try container.encode(dependencyList, forKey: .dependencies)
  137. case let targetList as TargetList:
  138. try container.encode(targetList, forKey: .targets)
  139. default:
  140. break
  141. }
  142. }
  143. }
  144. }
  145.  
  146. struct ProductList: ContentList {
  147. let content: Content
  148.  
  149. init(@ContentBuilder builder: () -> Content) {
  150. self.content = builder()
  151. }
  152. }
  153.  
  154. extension ProductList {
  155. func encode(to encoder: Encoder) throws {
  156. var container = encoder.unkeyedContainer()
  157. let products: [Product] = content.getAll()
  158. try container.encode(contentsOf: products)
  159. }
  160. }
  161.  
  162. struct Product: Content {
  163. enum CodingKeys: CodingKey {
  164. case name
  165. case type
  166. case targets
  167. }
  168.  
  169. enum `Type`: String, Codable {
  170. case executable, `static`, dynamic
  171. }
  172.  
  173. let name: String
  174. let type: Type
  175. let targetList: ContentList
  176.  
  177. init(name: String, type: Type = .executable, @ContentListBuilder builder: () -> ContentList = { EmptyContentList() }) {
  178. self.name = name
  179. self.type = type
  180. self.targetList = builder()
  181. }
  182. }
  183.  
  184. extension Product {
  185. func encode(to encoder: Encoder) throws {
  186. var container = encoder.container(keyedBy: CodingKeys.self)
  187. try container.encode(name, forKey: .name)
  188. try container.encode(type, forKey: .type)
  189. try container.encodeIfPresent(targetList as? TargetList, forKey: .targets)
  190. }
  191. }
  192.  
  193. struct TargetList: ContentList {
  194. let content: Content
  195.  
  196. init(@ContentBuilder builder: () -> Content) {
  197. self.content = builder()
  198. }
  199. }
  200.  
  201. extension TargetList {
  202. func encode(to encoder: Encoder) throws {
  203. var container = encoder.unkeyedContainer()
  204. let targets: [Target] = content.getAll()
  205. try container.encode(contentsOf: targets)
  206. }
  207. }
  208.  
  209. struct Target: Content {
  210. enum CodingKeys: CodingKey {
  211. case name
  212. case dependencies
  213. }
  214.  
  215. let name: String
  216. let dependencyList: ContentList
  217.  
  218. init(name: String, @ContentListBuilder builder: () -> ContentList = { EmptyContentList() }) {
  219. self.name = name
  220. self.dependencyList = builder()
  221. }
  222. }
  223.  
  224. extension Target {
  225. func encode(to encoder: Encoder) throws {
  226. var container = encoder.container(keyedBy: CodingKeys.self)
  227. try container.encode(name, forKey: .name)
  228. try container.encodeIfPresent(dependencyList as? TargetDependencyList, forKey: .dependencies)
  229. }
  230. }
  231.  
  232. struct TargetDependencyList: ContentList {
  233. let content: Content
  234.  
  235. init(@ContentBuilder builder: () -> Content) {
  236. self.content = builder()
  237. }
  238. }
  239.  
  240. extension TargetDependencyList {
  241. func encode(to encoder: Encoder) throws {
  242. var container = encoder.unkeyedContainer()
  243. let dependencies: [Content] = content.getAll()
  244. for dependency in dependencies {
  245. switch dependency {
  246. case let value as TargetDependency:
  247. try container.encode(value)
  248. case let value as Target:
  249. try container.encode(value)
  250. case let value as Product:
  251. try container.encode(value)
  252. default:
  253. break
  254. }
  255. }
  256. }
  257. }
  258.  
  259. struct TargetDependency: Content {
  260. let name: String
  261. }
  262.  
  263. struct DependencyList: ContentList {
  264. let content: Content
  265.  
  266. init(@ContentBuilder builder: () -> Content = { EmptyContent() }) {
  267. self.content = builder()
  268. }
  269. }
  270.  
  271. extension DependencyList {
  272. func encode(to encoder: Encoder) throws {
  273. var container = encoder.unkeyedContainer()
  274. let dependencies: [Dependency] = content.getAll()
  275. try container.encode(contentsOf: dependencies)
  276. }
  277. }
  278.  
  279. struct Dependency: Content {
  280. enum CodingKeys: CodingKey {
  281. case url
  282. case from
  283. case exact
  284. }
  285.  
  286. var url: String?
  287. var from: String?
  288. var exact: String?
  289.  
  290. init(url: String) {
  291. self.url = url
  292. }
  293.  
  294. init(url: String, from: String) {
  295. self.url = url
  296. self.from = from
  297. }
  298.  
  299. init(url: String, exact: String) {
  300. self.url = url
  301. self.exact = exact
  302. }
  303. }
  304.  
  305. extension Dependency {
  306. func encode(to encoder: Encoder) throws {
  307. var container = encoder.container(keyedBy: CodingKeys.self)
  308. try container.encodeIfPresent(url, forKey: .url)
  309. try container.encodeIfPresent(from, forKey: .from)
  310. try container.encodeIfPresent(exact, forKey: .exact)
  311. }
  312. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement