public enum PerlOperator: String { case lt, lte, gt, gte, eq } public enum PerlFormat: String { case json, xml, jqm } public struct SearchNutrimentEntry { public let nutriment: SearchNutriment public let op: PerlOperator public let value: Int } public struct SearchTagsEntry { public let tag: SearchTag public let value: String public let contains: Bool = true } //https://wiki.openfoodfacts.org/API/Read/Search#Parameters public struct PerlSearchQuery { public var searchTerms: String public var searchTags: [SearchTagsEntry]? // tagtype_i=SearchTag — i as #element (starting from 0); (tag_contains_i|tag_does_not_contain_i)=String public var searchNutriment: [SearchNutrimentEntry]? // nutriment_i=SearchNutriment — i as #element (starting from 0); nutriment_compare_i=PerlOperator; nutriment_value_i=String public var page: Int = 1 // Pagination public var format: PerlFormat // json=1 | xml=1 | jqm=1 public init( searchTerms: String, searchTags: [SearchTagsEntry]? = nil, searchNutriment: [SearchNutrimentEntry]? = nil, page: Int = 1, format: PerlFormat = .json ) { self.searchTerms = searchTerms self.searchTags = searchTags self.searchNutriment = searchNutriment self.page = page self.format = format } public func makeToRequest() -> String { var _searchTags: String? var _searchNutriment: String? let _format: String = "\(format.rawValue)=1" let _page: String = "page=\(page)" if let tags = searchTags { _searchTags = tags.enumerated().map { i, v in return "tagtype_\(i)=\(v.tag.rawValue)&tag_contains_\(i)=\(v.contains ? "contains" : "does_not_contain")&tag_\(i)=\(v.value)" }.joined(separator: "&") } if let nutriments = searchNutriment { _searchNutriment = nutriments.enumerated().map { i, v in return "nutriment_\(i)=\(v.nutriment.rawValue)&nutriment_compare_\(i)=\(v.op.rawValue)&nutriment_value_\(i)=\(v.nutriment.rawValue)" }.joined(separator: "&") } return "search_terms=\(searchTerms)\(_searchTags != nil ? "&\(_searchTags!)" : "")\(_searchNutriment != nil ? "&\(_searchNutriment!)" : "")&\(_page)&\(_format)" } }