scout/Sources/Scout/ExplorerValue/ExplorerValue+Add.swift

76 lines
2.4 KiB
Swift

//
// Scout
// Copyright (c) 2020-present Alexis Bridoux
// MIT license, see LICENSE file for details
import Foundation
extension ExplorerValue {
// MARK: PathExplorer
public mutating func add(_ value: ExplorerValue, at path: Path) throws {
self = try _add(path: Slice(path), value: value)
}
public func adding(_ value: ExplorerValue, at path: Path) throws -> ExplorerValue {
try _add(path: Slice(path), value: value)
}
// MARK: General function
/// Return the value if it should be added to the parent
private func _add(path: SlicePath, value: ExplorerValue) throws -> Self {
guard let (head, tail) = path.headAndTail() else { return value }
return try doSettingPath(tail.leftPart) {
switch head {
case .key(let key): return try add(key: key, value: value, tail: tail)
case .index(let index): return try add(index: index, value: value, tail: tail)
case .count: return try addCount(value: value, tail: tail)
default: throw ExplorerError.wrongUsage(of: head)
}
}
}
// MARK: PathElement
private func add(key: String, value: ExplorerValue, tail: SlicePath) throws -> ExplorerValue {
var dict = try dictionary.unwrapOrThrow(.subscriptKeyNoDict)
if tail.isEmpty, dict[key] == nil {
dict[key] = value
} else {
dict[key] = try dict.getJaroWinkler(key: key)._add(path: tail, value: value)
}
return .dictionary(dict)
}
private func add(index: Int, value: ExplorerValue, tail: SlicePath) throws -> ExplorerValue {
var array = try self.array.unwrapOrThrow(.subscriptIndexNoArray)
if index == array.count {
return try addCount(value: value, tail: tail)
}
let index = try Self.computeIndex(from: index, arrayCount: array.count)
let newValue = try array[index]._add(path: tail, value: value)
if tail.isEmpty {
array.insert(newValue, at: index)
} else {
array[index] = newValue
}
return .array(array)
}
private func addCount(value: ExplorerValue, tail: SlicePath) throws -> ExplorerValue {
guard tail.isEmpty else {
throw ExplorerError.wrongUsage(of: .count)
}
var array = try self.array.unwrapOrThrow(.subscriptIndexNoArray)
array.append(value)
return .array(array)
}
}