import Foundation import Units @dynamicMemberLookup public struct Nutriments: Codable, ObjectDebugger { private var nutrients: [String: Nutrient] = [:] private var iterator: Dictionary.Iterator? = nil private var keys: [String] = [] public init() {} public subscript(dynamicMember member: String) -> Nutrient? { nutrients[member] } // MARK: - Decoding public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: AnyCodingKey.self) for key in container.allKeys { let keyStr = key.stringValue let parts = keyStr.components(separatedBy: "_") var nutrientName = "" // Original with - var field = "" var isPrepared = false if let preparedIdx = parts.firstIndex(of: "prepared") { isPrepared = true nutrientName = parts[0..? { guard let rawValue = per100g ?? value ?? valueComputed, let unitString = unit, let unitEnum = Unit(rawValue: unitString) else { return nil } return UnitValue(value: rawValue, unit: unitEnum) } // Computed UnitValue for perServing public var perServingUnitValue: UnitValue? { guard let rawValue = perServing, let unitString = unit, let unitEnum = Unit(rawValue: unitString) else { return nil } return UnitValue(value: rawValue, unit: unitEnum) } // Computed UnitValue for preparedPer100g (fallback similar) public var preparedPer100gUnitValue: UnitValue? { guard let rawValue = preparedPer100g ?? preparedValue ?? preparedValueComputed, let unitString = preparedUnit ?? unit, // Fallback to main unit if preparedUnit nil let unitEnum = Unit(rawValue: unitString) else { return nil } return UnitValue(value: rawValue, unit: unitEnum) } // Computed UnitValue for preparedPerServing public var preparedPerServingUnitValue: UnitValue? { guard let rawValue = preparedPerServing, let unitString = preparedUnit ?? unit, let unitEnum = Unit(rawValue: unitString) else { return nil } return UnitValue(value: rawValue, unit: unitEnum) } } // MARK: - Helper for Dynamic Coding Keys struct AnyCodingKey: CodingKey, Hashable { var stringValue: String var intValue: Int? init(stringValue: String) { self.stringValue = stringValue self.intValue = nil } init(intValue: Int) { self.intValue = intValue self.stringValue = String(intValue) } } extension Nutriments { public var alcohol: Nutrient? { nutrients["alcohol"] } public var carbohydrates: Nutrient? { nutrients["carbohydrates"] } public var energy: Nutrient? { nutrients["energy"] } public var energyKj: Nutrient? { nutrients["energy_kj"] } public var energyKcal: Nutrient? { nutrients["energy_kcal"] } public var fat: Nutrient? { nutrients["fat"] } public var fruitsVegetablesNuts: Nutrient? { nutrients["fruits_vegetables_nuts_estimate_from_ingredients"] } public var novaGroup: Nutrient? { nutrients["nova_group"] } public var proteins: Nutrient? { nutrients["proteins"] } public var salt: Nutrient? { nutrients["salt"] } public var saturatedFat: Nutrient? { nutrients["saturated_fat"] } public var sodium: Nutrient? { nutrients["sodium"] } public var sugars: Nutrient? { nutrients["sugars"] } public var calcium: Nutrient? { nutrients["calcium"] } } extension Nutriments: Sequence, IteratorProtocol { public mutating func next() -> Element? { if iterator == nil { iterator = nutrients.makeIterator() keys = Array(nutrients.keys).sorted() } guard let nextElement = iterator?.next() else { iterator = nil return nil } return (item: nextElement.key, nutrient: nextElement.value) } public typealias Element = (item: String, nutrient: Nutrient) }