<commit_before>import Foundation
import NIO

enum KeyPathUpdateError: Error {
    case invalidRootOrValue
}

public struct DecoderExtractor: Decodable {
    public let decoder: Decoder
    
    public init(from decoder: Decoder) throws {
        self.decoder = decoder
    }
}

public struct UpdateCodingKey: CodingKey {
    public var stringValue: String
    
    public init?(stringValue: String) {
        self.stringValue = stringValue
    }
    
    init(_ value: String) {
        self.stringValue = value
    }
    
    public var intValue: Int?
    
    public init?(intValue: Int) {
        return nil
    }
}

public protocol MeowWritableKeyPath {
    func write<T: KeyPathQueryable>(to: inout T, from container: KeyedDecodingContainer<UpdateCodingKey>) throws -> Bool
}

extension WritableKeyPath: MeowWritableKeyPath where Root: KeyPathQueryable, Value: Decodable {
    /// - returns: `true` if the value was changed
    public func write<T: KeyPathQueryable>(to: inout T, from container: KeyedDecodingContainer<UpdateCodingKey>) throws -> Bool {
        var didUpdate = false
        
        guard var root = to as? Root else {
            throw KeyPathUpdateError.invalidRootOrValue
        }
        
        let keyString = try Root.makeQueryPath(for: self)
        let key = UpdateCodingKey(keyString)
        if let newValue = try container.decodeIfPresent(Value.self, forKey: key) {
            root[keyPath: self] = newValue
            didUpdate = true
        }
        // TODO: decode null
        
        // root is converted from T above so this does not fail
        // swiftlint:disable force_cast
        to = root as! T
        
        return didUpdate
    }
}

public extension Decoder {
    /// - returns: An array containing the key paths that were updated
    public func update<T: QueryableModel>(_ instance: T, withAllowedKeyPaths keyPaths: [MeowWritableKeyPath]) throws -> [PartialKeyPath<T>] {
        let container = try self.container(keyedBy: UpdateCodingKey.self)
        
        // must pass as inout to the KeyPath, hence the var
        // models are always classes
        var instance = instance
        
        var updatedKeyPaths = [PartialKeyPath<T>]()
        
        for keyPath in keyPaths {
            let didUpdate = try keyPath.write(to: &instance, from: container)
            if didUpdate {
                // this should never fail, it would make no sense
                // swiftlint:disable force_cast
                updatedKeyPaths.append(keyPath as! PartialKeyPath<T>)
            }
        }
        
        return updatedKeyPaths
    }
}

public extension JSONDecoder {
    func decoder(from data: Data) throws -> Decoder {
        return try self.decode(DecoderExtractor.self, from: data).decoder
    }
    
    /// - returns: An array containing the key paths that were updated
    public func update<T: QueryableModel>(_ instance: T, from data: Data, withAllowedKeyPaths keyPaths: [MeowWritableKeyPath]) throws -> [PartialKeyPath<T>] {
        // It seems not ideal that MeowWritableKeyPath currently is not restricted to Root == T
        assert(keyPaths.allSatisfy { $0 as? PartialKeyPath<T> != nil }, "Calling update for a certain model with allowed key paths of a different type does not make sense")
        
        let decoder = try self.decoder(from: data)
        return try decoder.update(instance, withAllowedKeyPaths: keyPaths)
    }
}
<commit_msg>Public init codingkey<commit_after>import Foundation
import NIO

enum KeyPathUpdateError: Error {
    case invalidRootOrValue
}

public struct DecoderExtractor: Decodable {
    public let decoder: Decoder
    
    public init(from decoder: Decoder) throws {
        self.decoder = decoder
    }
}

public struct UpdateCodingKey: CodingKey {
    public var stringValue: String
    
    public init?(stringValue: String) {
        self.stringValue = stringValue
    }
    
    public init(_ value: String) {
        self.stringValue = value
    }
    
    public var intValue: Int?
    
    public init?(intValue: Int) {
        return nil
    }
}

public protocol MeowWritableKeyPath {
    func write<T: KeyPathQueryable>(to: inout T, from container: KeyedDecodingContainer<UpdateCodingKey>) throws -> Bool
}

extension WritableKeyPath: MeowWritableKeyPath where Root: KeyPathQueryable, Value: Decodable {
    /// - returns: `true` if the value was changed
    public func write<T: KeyPathQueryable>(to: inout T, from container: KeyedDecodingContainer<UpdateCodingKey>) throws -> Bool {
        var didUpdate = false
        
        guard var root = to as? Root else {
            throw KeyPathUpdateError.invalidRootOrValue
        }
        
        let keyString = try Root.makeQueryPath(for: self)
        let key = UpdateCodingKey(keyString)
        if let newValue = try container.decodeIfPresent(Value.self, forKey: key) {
            root[keyPath: self] = newValue
            didUpdate = true
        }
        // TODO: decode null
        
        // root is converted from T above so this does not fail
        // swiftlint:disable force_cast
        to = root as! T
        
        return didUpdate
    }
}

public extension Decoder {
    /// - returns: An array containing the key paths that were updated
    public func update<T: QueryableModel>(_ instance: T, withAllowedKeyPaths keyPaths: [MeowWritableKeyPath]) throws -> [PartialKeyPath<T>] {
        let container = try self.container(keyedBy: UpdateCodingKey.self)
        
        // must pass as inout to the KeyPath, hence the var
        // models are always classes
        var instance = instance
        
        var updatedKeyPaths = [PartialKeyPath<T>]()
        
        for keyPath in keyPaths {
            let didUpdate = try keyPath.write(to: &instance, from: container)
            if didUpdate {
                // this should never fail, it would make no sense
                // swiftlint:disable force_cast
                updatedKeyPaths.append(keyPath as! PartialKeyPath<T>)
            }
        }
        
        return updatedKeyPaths
    }
}

public extension JSONDecoder {
    func decoder(from data: Data) throws -> Decoder {
        return try self.decode(DecoderExtractor.self, from: data).decoder
    }
    
    /// - returns: An array containing the key paths that were updated
    public func update<T: QueryableModel>(_ instance: T, from data: Data, withAllowedKeyPaths keyPaths: [MeowWritableKeyPath]) throws -> [PartialKeyPath<T>] {
        // It seems not ideal that MeowWritableKeyPath currently is not restricted to Root == T
        assert(keyPaths.allSatisfy { $0 as? PartialKeyPath<T> != nil }, "Calling update for a certain model with allowed key paths of a different type does not make sense")
        
        let decoder = try self.decoder(from: data)
        return try decoder.update(instance, withAllowedKeyPaths: keyPaths)
    }
}

{'fraction_non_alphanumeric': 0.07550457383476114, 'fraction_numerical': 0.0002904022070567736, 'mean_word_length': 2.4405594405594404, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1048605', 'n_tokens_mistral': 1883, 'n_tokens_neox': 1860, 'n_words': 615}