diff --git a/Sources/MapboxDirections/Intersection.swift b/Sources/MapboxDirections/Intersection.swift index a618f3a72..291190e3e 100644 --- a/Sources/MapboxDirections/Intersection.swift +++ b/Sources/MapboxDirections/Intersection.swift @@ -15,7 +15,7 @@ public struct Intersection { approachLanes: [LaneIndication]?, usableApproachLanes: IndexSet?, preferredApproachLanes: IndexSet?, - usableLaneIndication: LaneIndication?, + usableLaneIndication: ManeuverDirection?, outletRoadClasses: RoadClasses? = nil, tollCollection: TollCollection? = nil, tunnelName: String? = nil, @@ -165,7 +165,7 @@ public struct Intersection { If no lane information is available for the intersection, this property’s value is `nil` */ - public let usableLaneIndication: LaneIndication? + public let usableLaneIndication: ManeuverDirection? } extension Intersection: Codable { @@ -260,15 +260,16 @@ extension Intersection: Codable { try container.encode(outletArray, forKey: .outletIndexes) var lanes: [Lane]? + print("lanes: \(String(describing: lanes))") if let approachLanes = approachLanes, let usableApproachLanes = usableApproachLanes, - let preferredApproachLanes = preferredApproachLanes, - let usableLaneIndication = usableLaneIndication { + let preferredApproachLanes = preferredApproachLanes + { lanes = approachLanes.map { Lane(indications: $0) } for i in usableApproachLanes { lanes![i].isValid = true - if lanes![i].indications.contains(usableLaneIndication){ - lanes![i].validIndication = usableLaneIndication + if usableLaneIndication != nil && lanes![i].indications.descriptions.contains(usableLaneIndication!.rawValue) { + lanes![i].validIndication = usableLaneIndication } } for j in preferredApproachLanes { @@ -319,8 +320,12 @@ extension Intersection: Codable { approachLanes = lanes.map { $0.indications } usableApproachLanes = lanes.indices { $0.isValid } preferredApproachLanes = lanes.indices { ($0.isActive ?? false) } - let usableIndications = lanes.compactMap { $0.validIndication } - usableLaneIndication = usableIndications.reduce(LaneIndication(rawValue: 0)) { $0.union($1) } + let validIndications = lanes.compactMap { $0.validIndication} + if Set(validIndications).count > 1 { + let context = EncodingError.Context(codingPath: decoder.codingPath, debugDescription: "Inconsistent valid indications.") + throw EncodingError.invalidValue(validIndications, context) + } + usableLaneIndication = validIndications.first } else { approachLanes = nil usableApproachLanes = nil diff --git a/Sources/MapboxDirections/Lane.swift b/Sources/MapboxDirections/Lane.swift index 8a5964266..8549a45cb 100644 --- a/Sources/MapboxDirections/Lane.swift +++ b/Sources/MapboxDirections/Lane.swift @@ -23,9 +23,9 @@ struct Lane: Equatable { /** Which of the `indications` is applicable to the current route, when there is more than one */ - var validIndication: LaneIndication? + var validIndication: ManeuverDirection? - init(indications: LaneIndication, valid: Bool = false, active: Bool? = false, preferred: LaneIndication? = nil) { + init(indications: LaneIndication, valid: Bool = false, active: Bool? = false, preferred: ManeuverDirection? = nil) { self.indications = indications self.isValid = valid self.isActive = active @@ -46,7 +46,7 @@ extension Lane: Codable { try container.encode(indications, forKey: .indications) try container.encode(isValid, forKey: .valid) try container.encodeIfPresent(isActive, forKey: .active) - try container.encodeIfPresent(validIndication?.descriptions.first, forKey: .preferred) + try container.encodeIfPresent(validIndication, forKey: .preferred) } init(from decoder: Decoder) throws { @@ -54,8 +54,6 @@ extension Lane: Codable { indications = try container.decode(LaneIndication.self, forKey: .indications) isValid = try container.decode(Bool.self, forKey: .valid) isActive = try container.decodeIfPresent(Bool.self, forKey: .active) - if let validIndicationDescription = try container.decodeIfPresent(String.self, forKey: .preferred) { - validIndication = LaneIndication(descriptions: [validIndicationDescription]) - } + validIndication = try container.decodeIfPresent(ManeuverDirection.self, forKey: .preferred) } } diff --git a/Sources/MapboxDirections/LaneIndication.swift b/Sources/MapboxDirections/LaneIndication.swift index fc6d216c7..57ecfb887 100644 --- a/Sources/MapboxDirections/LaneIndication.swift +++ b/Sources/MapboxDirections/LaneIndication.swift @@ -69,6 +69,11 @@ public struct LaneIndication: OptionSet, CustomStringConvertible { self.init(rawValue: laneIndication.rawValue) } + init?(from direction: ManeuverDirection) { + // Assuming that every possible raw value of ManeuverDirection matches valid raw value of LaneIndication + self.init(descriptions: [direction.rawValue]) + } + public var descriptions: [String] { if isEmpty { return [] diff --git a/Sources/MapboxDirections/VisualInstructionComponent.swift b/Sources/MapboxDirections/VisualInstructionComponent.swift index d7e75ac09..b2c446721 100644 --- a/Sources/MapboxDirections/VisualInstructionComponent.swift +++ b/Sources/MapboxDirections/VisualInstructionComponent.swift @@ -74,7 +74,7 @@ public extension VisualInstruction { - parameter isUsable: Whether the user can use this lane to continue along the current route. - parameter preferredDirection: Which of the `indications` is applicable to the current route when there is more than one */ - case lane(indications: LaneIndication, isUsable: Bool, preferredDirection: LaneIndication?) + case lane(indications: LaneIndication, isUsable: Bool, preferredDirection: ManeuverDirection?) } } @@ -217,10 +217,7 @@ extension VisualInstruction.Component: Codable { if kind == .lane { let indications = try container.decode(LaneIndication.self, forKey: .directions) let isUsable = try container.decode(Bool.self, forKey: .isActive) - var preferredDirection: LaneIndication? = nil - if let preferredDirectionDescription = try container.decodeIfPresent(String.self, forKey: .activeDirection) { - preferredDirection = LaneIndication(descriptions: [preferredDirectionDescription]) - } + let preferredDirection = try container.decodeIfPresent(ManeuverDirection.self, forKey: .activeDirection) self = .lane(indications: indications, isUsable: isUsable, preferredDirection: preferredDirection) return } @@ -284,7 +281,7 @@ extension VisualInstruction.Component: Codable { textRepresentation = .init(text: "", abbreviation: nil, abbreviationPriority: nil) try container.encode(indications, forKey: .directions) try container.encode(isUsable, forKey: .isActive) - try container.encodeIfPresent(preferredDirection?.descriptions.first, forKey: .activeDirection) + try container.encodeIfPresent(preferredDirection, forKey: .activeDirection) case .guidanceView(let image, let alternativeText): try container.encode(Kind.guidanceView, forKey: .kind) textRepresentation = alternativeText diff --git a/Tests/MapboxDirectionsTests/IntersectionTests.swift b/Tests/MapboxDirectionsTests/IntersectionTests.swift index 81c46354c..baa095daa 100644 --- a/Tests/MapboxDirectionsTests/IntersectionTests.swift +++ b/Tests/MapboxDirectionsTests/IntersectionTests.swift @@ -96,7 +96,7 @@ class IntersectionTests: XCTestCase { approachLanes: [.straightAhead, [.straightAhead, .right]], usableApproachLanes: IndexSet([0, 1]), preferredApproachLanes: IndexSet([1]), - usableLaneIndication: [.straightAhead], + usableLaneIndication: .straightAhead, outletRoadClasses: nil, tollCollection: nil, tunnelName: nil,