diff --git a/Frameworks/RSParser/Feeds/JSON/JSONFeedParser.swift b/Frameworks/RSParser/Feeds/JSON/JSONFeedParser.swift index a31f1deb5..4ec70f628 100644 --- a/Frameworks/RSParser/Feeds/JSON/JSONFeedParser.swift +++ b/Frameworks/RSParser/Feeds/JSON/JSONFeedParser.swift @@ -111,7 +111,10 @@ private extension JSONFeedParser { let dateModified = parseDate(itemDictionary["date_modified"] as? String) let authors = parseAuthors(itemDictionary) - let tags = itemDictionary["tags"] as? [String] + var tags: Set? = nil + if let tagsArray = itemDictionary["tags"] as? [String] { + tags = Set(tagsArray) + } let attachments = parseAttachments(itemDictionary) return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: feedURL, url: url, externalURL: externalURL, title: title, contentHTML: contentHTML, contentText: contentText, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, authors: authors, tags: tags, attachments: attachments) @@ -140,14 +143,14 @@ private extension JSONFeedParser { return RSDateWithString(dateString) } - static func parseAttachments(_ itemDictionary: JSONDictionary) -> [ParsedAttachment]? { + static func parseAttachments(_ itemDictionary: JSONDictionary) -> Set? { guard let attachmentsArray = itemDictionary["attachments"] as? JSONArray else { return nil } - return attachmentsArray.flatMap { (oneAttachmentObject) -> ParsedAttachment? in + return Set(attachmentsArray.flatMap { (oneAttachmentObject) -> ParsedAttachment? in return parseAttachment(oneAttachmentObject) - } + }) } static func parseAttachment(_ attachmentObject: JSONDictionary) -> ParsedAttachment? { diff --git a/Frameworks/RSParser/Feeds/JSON/RSSInJSONParser.swift b/Frameworks/RSParser/Feeds/JSON/RSSInJSONParser.swift index a37bf1770..8a510f711 100644 --- a/Frameworks/RSParser/Feeds/JSON/RSSInJSONParser.swift +++ b/Frameworks/RSParser/Feeds/JSON/RSSInJSONParser.swift @@ -141,23 +141,21 @@ private extension RSSInJSONParser { return Set([parsedAuthor]) } - static func parseTags(_ itemDictionary: JSONDictionary) -> [String]? { + static func parseTags(_ itemDictionary: JSONDictionary) -> Set? { if let categoryObject = itemDictionary["category"] as? JSONDictionary { if let oneTag = categoryObject["#value"] as? String { - return [oneTag] + return Set([oneTag]) } return nil } else if let categoryArray = itemDictionary["category"] as? JSONArray { - return categoryArray.flatMap{ (categoryObject) in - return categoryObject["#value"] as? String - } + return Set(categoryArray.flatMap{ $0["#value"] as? String }) } return nil } - static func parseAttachments(_ itemDictionary: JSONDictionary) -> [ParsedAttachment]? { + static func parseAttachments(_ itemDictionary: JSONDictionary) -> Set? { guard let enclosureObject = itemDictionary["enclosure"] as? JSONDictionary else { return nil @@ -175,6 +173,6 @@ private extension RSSInJSONParser { let type = enclosureObject["type"] as? String let oneAttachment = ParsedAttachment(url: attachmentURL, mimeType: type, title: nil, sizeInBytes: attachmentSize, durationInSeconds: nil) - return [oneAttachment] + return Set([oneAttachment]) } } diff --git a/Frameworks/RSParser/Feeds/ParsedAttachment.swift b/Frameworks/RSParser/Feeds/ParsedAttachment.swift index e3d369659..29520033a 100644 --- a/Frameworks/RSParser/Feeds/ParsedAttachment.swift +++ b/Frameworks/RSParser/Feeds/ParsedAttachment.swift @@ -8,14 +8,15 @@ import Foundation -public struct ParsedAttachment { +public struct ParsedAttachment: Hashable { public let url: String? public let mimeType: String? public let title: String? public let sizeInBytes: Int? public let durationInSeconds: Int? - + public let hashValue: Int + init(url: String?, mimeType: String?, title: String?, sizeInBytes: Int?, durationInSeconds: Int?) { self.url = url @@ -23,5 +24,23 @@ public struct ParsedAttachment { self.title = title self.sizeInBytes = sizeInBytes self.durationInSeconds = durationInSeconds + + var stringToHash = "" + stringToHash += url ?? "" + stringToHash += mimeType ?? "" + stringToHash += title ?? "" + var h = stringToHash.hashValue + if let sizeInBytes = sizeInBytes { + h = h ^ sizeInBytes.hashValue + } + if let durationInSeconds = durationInSeconds { + h = h ^ durationInSeconds.hashValue + } + self.hashValue = h + } + + public static func ==(lhs: ParsedAttachment, rhs: ParsedAttachment) -> Bool { + + return lhs.hashValue == rhs.hashValue && lhs.url == rhs.url && lhs.mimeType == rhs.mimeType && lhs.title == rhs.title && lhs.sizeInBytes == rhs.sizeInBytes && lhs.durationInSeconds == rhs.durationInSeconds } } diff --git a/Frameworks/RSParser/Feeds/ParsedItem.swift b/Frameworks/RSParser/Feeds/ParsedItem.swift index 1d90f47a7..ee37ddbe3 100644 --- a/Frameworks/RSParser/Feeds/ParsedItem.swift +++ b/Frameworks/RSParser/Feeds/ParsedItem.swift @@ -24,11 +24,11 @@ public struct ParsedItem: Hashable { public let datePublished: Date? public let dateModified: Date? public let authors: Set? - public let tags: [String]? - public let attachments: [ParsedAttachment]? + public let tags: Set? + public let attachments: Set? public let hashValue: Int - init(syncServiceID: String?, uniqueID: String, feedURL: String, url: String?, externalURL: String?, title: String?, contentHTML: String?, contentText: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: Set?, tags: [String]?, attachments: [ParsedAttachment]?) { + init(syncServiceID: String?, uniqueID: String, feedURL: String, url: String?, externalURL: String?, title: String?, contentHTML: String?, contentText: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: Set?, tags: Set?, attachments: Set?) { self.syncServiceID = syncServiceID self.uniqueID = uniqueID @@ -51,6 +51,7 @@ public struct ParsedItem: Hashable { public static func ==(lhs: ParsedItem, rhs: ParsedItem) -> Bool { + // TODO: compare all properties. return lhs.hashValue == rhs.hashValue && lhs.uniqueID == rhs.uniqueID && lhs.feedURL == rhs.feedURL } }