<commit_before>//
//  Querying.swift
//  App
//
//  Created by <NAME> on 06/06/2018.
//

// Typesafe queries are currently only available if Vapor is available

import MongoKitten
import NIO

public protocol QueryableModel: Model {
    static func makeQueryPath<T>(for key: KeyPath<Self, T>) throws -> String
}

extension KeyPath where Root: QueryableModel {

    func makeQueryPath() throws -> String {
        return try Root.makeQueryPath(for: self)
    }

}

enum MeowQueryEncodingError: Error {
    case noResultingPrimitive
}

public struct ModelQuery<M: QueryableModel> {
    
    public var query: MongoKitten.Query
    
    public init(_ query: MongoKitten.Query) {
        self.query = query
    }
    
}

public extension AggregateCursor {
    public func match<T>(_ query: ModelQuery<T>) -> AggregateCursor<Element> {
        return self.match(query.query)
    }
}

fileprivate struct TargetValueEncodingWrapper<V: Encodable>: Encodable {
    var value: V
}

fileprivate extension QueryableModel {
    static func encode<V: Encodable>(value: V) throws -> Primitive {
        let wrapper = TargetValueEncodingWrapper(value: value)
        let document = try Self.encoder.encode(wrapper)
        
        guard let result = document["value"] else {
            throw MeowQueryEncodingError.noResultingPrimitive
        }
        
        return result
    }
}

public func == <M: QueryableModel, V: Encodable>(lhs: KeyPath<M, V>, rhs: V?) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue: Primitive?
    if let rhs = rhs {
        compareValue = try M.encode(value: rhs)
    } else {
        compareValue = nil
    }
    
    return ModelQuery(path == compareValue)
}

public func == <M: QueryableModel, T: Model>(lhs: KeyPath<M, Reference<T>>, rhs: T?) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue: Primitive?
    if let rhs = rhs {
    compareValue = try M.encode(value: rhs._id)
    } else {
    compareValue = nil
    }
    
    return ModelQuery(path == compareValue)
}

public func != <M: QueryableModel, V: Encodable>(lhs: KeyPath<M, V>, rhs: V?) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue: Primitive?
    if let rhs = rhs {
        compareValue = try M.encode(value: rhs)
    } else {
        compareValue = nil
    }
    
    return ModelQuery(path != compareValue)
}

public func || <M>(lhs: ModelQuery<M>, rhs: ModelQuery<M>) -> ModelQuery<M> {<commit_msg>Operators<commit_after>//
//  Querying.swift
//  App
//
//  Created by <NAME> on 06/06/2018.
//

// Typesafe queries are currently only available if Vapor is available

import MongoKitten
import NIO

public protocol QueryableModel: Model {
    static func makeQueryPath<T>(for key: KeyPath<Self, T>) throws -> String
}

extension KeyPath where Root: QueryableModel {

    func makeQueryPath() throws -> String {
        return try Root.makeQueryPath(for: self)
    }

}

enum MeowQueryEncodingError: Error {
    case noResultingPrimitive
}

public struct ModelQuery<M: QueryableModel> {
    
    public var query: MongoKitten.Query
    
    public init(_ query: MongoKitten.Query) {
        self.query = query
    }
    
}

public extension AggregateCursor {
    public func match<T>(_ query: ModelQuery<T>) -> AggregateCursor<Element> {
        return self.match(query.query)
    }
}

fileprivate struct TargetValueEncodingWrapper<V: Encodable>: Encodable {
    var value: V
}

fileprivate extension QueryableModel {
    static func encode<V: Encodable>(value: V) throws -> Primitive {
        let wrapper = TargetValueEncodingWrapper(value: value)
        let document = try Self.encoder.encode(wrapper)
        
        guard let result = document["value"] else {
            throw MeowQueryEncodingError.noResultingPrimitive
        }
        
        return result
    }
}

public func == <M: QueryableModel, V: Encodable>(lhs: KeyPath<M, V>, rhs: V?) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue: Primitive?
    if let rhs = rhs {
        compareValue = try M.encode(value: rhs)
    } else {
        compareValue = nil
    }
    
    return ModelQuery(path == compareValue)
}

public func == <M: QueryableModel, T: Model>(lhs: KeyPath<M, Reference<T>>, rhs: T?) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue: Primitive?
    if let rhs = rhs {
    compareValue = try M.encode(value: rhs._id)
    } else {
    compareValue = nil
    }
    
    return ModelQuery(path == compareValue)
}

public func != <M: QueryableModel, V: Encodable>(lhs: KeyPath<M, V>, rhs: V?) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue: Primitive?
    if let rhs = rhs {
        compareValue = try M.encode(value: rhs)
    } else {
        compareValue = nil
    }
    
    return ModelQuery(path != compareValue)
}

public func < <M: QueryableModel, V: Encodable>(lhs: KeyPath<M, V>, rhs: V) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue = try M.encode(value: rhs)
    
    return ModelQuery(path < compareValue)
}

public func > <M: QueryableModel, V: Encodable>(lhs: KeyPath<M, V>, rhs: V) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue = try M.encode(value: rhs)
    
    return ModelQuery(path > compareValue)
}

public func <= <M: QueryableModel, V: Encodable>(lhs: KeyPath<M, V>, rhs: V) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue = try M.encode(value: rhs)
    
    return ModelQuery(path <= compareValue)
}

public func >= <M: QueryableModel, V: Encodable>(lhs: KeyPath<M, V>, rhs: V) throws -> ModelQuery<M> {
    let path = try lhs.makeQueryPath()
    let compareValue = try M.encode(value: rhs)
    
    return ModelQuery(path >= compareValue)
}

public func || <M>(lhs: ModelQuery<M>, rhs: ModelQuery<M>) -> ModelQuery<M> {
{'fraction_non_alphanumeric': 0.1134989926124916, 'fraction_numerical': 0.002686366689053056, 'mean_word_length': 2.995305164319249, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 85, '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': '4313856', 'n_tokens_mistral': 1894, 'n_tokens_neox': 1873, 'n_words': 532}