From 9aafb10ab03e010b2ccdf551044a0ffa3e8b817b Mon Sep 17 00:00:00 2001 From: David Mohundro Date: Mon, 5 Feb 2018 20:15:29 -0600 Subject: [PATCH] Fix issue with filter plus serialization See discussion in #174. The issue was related to whether or not filter should return a list or an element... that should depend on if a single element was filtered to or not. --- Source/SWXMLHash.swift | 27 +++++++++---------- ...versionArrayOfNonPrimitiveTypesTests.swift | 15 ++++++++++- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Source/SWXMLHash.swift b/Source/SWXMLHash.swift index b240b7f2..d6b7dccd 100644 --- a/Source/SWXMLHash.swift +++ b/Source/SWXMLHash.swift @@ -570,14 +570,10 @@ public enum XMLIndexer { public func filter(_ included: (_ elem: XMLElement, _ index: Int) -> Bool) -> XMLIndexer { switch self { case .list(let list): - let results = filterWithIndex(seq: list, included: included) - if results.count == 1 { - return XMLIndexer.element(results.first!) - } - return XMLIndexer.list(results) + return handleFilteredResults(list: list, included: included) case .element(let elem): - return XMLIndexer.list(filterWithIndex(seq: elem.xmlChildren, included: included)) + return handleFilteredResults(list: elem.xmlChildren, included: included) case .stream(let ops): let found = ops.findElements() @@ -588,20 +584,21 @@ public enum XMLIndexer { } else { list = found.all.map { $0.element! } } - let results = filterWithIndex(seq: list, included: included) - if results.count == 1 { - return XMLIndexer.element(results.first!) - } - return XMLIndexer.list(results) + + return handleFilteredResults(list: list, included: included) default: - return XMLIndexer.list([]) + return .list([]) } } - private func filterWithIndex(seq: [XMLElement], - included: (_ elem: XMLElement, _ index: Int) -> Bool) -> [XMLElement] { - return zip(seq.indices, seq).filter { included($1, $0) }.map { $1 } + private func handleFilteredResults(list: [XMLElement], + included: (_ elem: XMLElement, _ index: Int) -> Bool) -> XMLIndexer { + let results = zip(list.indices, list).filter { included($1, $0) }.map { $1 } + if results.count == 1 { + return .element(results.first!) + } + return .list(results) } /// All child elements from the currently indexed level diff --git a/Tests/SWXMLHashTests/TypeConversionArrayOfNonPrimitiveTypesTests.swift b/Tests/SWXMLHashTests/TypeConversionArrayOfNonPrimitiveTypesTests.swift index 08869813..53f69cf9 100644 --- a/Tests/SWXMLHashTests/TypeConversionArrayOfNonPrimitiveTypesTests.swift +++ b/Tests/SWXMLHashTests/TypeConversionArrayOfNonPrimitiveTypesTests.swift @@ -212,6 +212,18 @@ class TypeConversionArrayOfNonPrimitiveTypesTests: XCTestCase { } } } + + func testFilterAndSerializationShouldWork() { + do { + let subParser = parser!["root"]["arrayOfGoodBasicItems"].filter({ _, idx in idx == 0 }) + + let value: BasicItem = try subParser.value() + + XCTAssertNotNil(value) + } catch { + XCTFail("\(error)") + } + } } extension TypeConversionArrayOfNonPrimitiveTypesTests { @@ -229,7 +241,8 @@ extension TypeConversionArrayOfNonPrimitiveTypesTests { ("testShouldConvertArrayOfGoodAttributeItemsToArrayOfOptionals", testShouldConvertArrayOfGoodAttributeItemsToArrayOfOptionals), ("testShouldThrowWhenConvertingArrayOfBadAttributeItemsToNonOptional", testShouldThrowWhenConvertingArrayOfBadAttributeItemsToNonOptional), ("testShouldThrowWhenConvertingArrayOfBadAttributeItemsToOptional", testShouldThrowWhenConvertingArrayOfBadAttributeItemsToOptional), - ("testShouldThrowWhenConvertingArrayOfBadAttributeItemsToArrayOfOptionals", testShouldThrowWhenConvertingArrayOfBadAttributeItemsToArrayOfOptionals) + ("testShouldThrowWhenConvertingArrayOfBadAttributeItemsToArrayOfOptionals", testShouldThrowWhenConvertingArrayOfBadAttributeItemsToArrayOfOptionals), + ("testFilterAndSerializationShouldWork", testFilterAndSerializationShouldWork) ] } }