<commit_before>//
//  GAPDataEncoder.swift
//  Bluetooth
//
//  Created by <NAME> on 8/25/18.
//  Copyright © 2018 PureSwift. All rights reserved.
//

import Foundation

/// GAP Data Decoder
public struct GAPDataEncoder {
    
    /// GAP Data Decoder Error
    public enum Error: Swift.Error {
        
        /// Invalid data size.
        case invalidSize(Int)
    }
    
    // MARK: - Initialization
    
    /// Initialize encoder.
    public init() { }
    
    // MARK: - Methods
    
    public func encode(_ encodables: [GAPData]) -> Data {
        do { return try _encode(encodables) }
        catch { fatalError("Unable to encode GAP Data: \(error)") }
    }
    
    public func encode(_ encodables: GAPData...) -> Data {
        return encode(encodables)
    }
    
    public func encodeAdvertisingData(_ encodables: GAPData...) throws -> LowEnergyAdvertisingData {
        return try _encode(encodables)
    }
    
    @inline(__always)
    internal func _encode<S, DataType>(_ encodables: S) throws -> DataType where S: Sequence, S.Element == GAPData, DataType: GAPDataContainer {
        
        let dataLengths = encodables.map { $0.dataLength }
        let length = dataLengths.reduce(0, { $0 + $1 + 2 })
        guard length <= DataType.maxCapacity else {
            throw Error.invalidSize(length)
        }
        var data = DataType(capacity: length)
        for (index, encodable) in encodables.enumerated() {
            let dataLength = dataLengths[index]
            data += UInt8(dataLength + 1)
            data += type(of: encodable).dataType.rawValue
            data.append(encodable)
        }
        assert(data.count == length, "Invalid data length")
        return data
    }
}

/// GAP Data Decoder
public struct GAPDataDecoder {
    
    /// GAP Data Decoder Error
    public enum Error: Swift.Error {
        
        case insufficientBytes(expected: Int, actual: Int)
        case cannotDecode(GAPDataType, index: Int)
        case unknownType(GAPDataType)
    }
    
    // MARK: - Initialization
    
    /// Initialize with default data types.
    public init() {
        
        /// initialize with default precomputed values
        self.types = GAPDataDecoder.defaultTypes
        self.dataTypes = GAPDataDecoder.defaultDataTypes<commit_msg>Optimized `GAPDataEncoder`<commit_after>//
//  GAPDataEncoder.swift
//  Bluetooth
//
//  Created by <NAME> on 8/25/18.
//  Copyright © 2018 PureSwift. All rights reserved.
//

import Foundation

/// GAP Data Decoder
public struct GAPDataEncoder {
    
    /// GAP Data Decoder Error
    public enum Error: Swift.Error {
        
        /// Invalid data size.
        case invalidSize(Int)
    }
    
    // MARK: - Initialization
    
    /// Initialize encoder.
    public init() { }
    
    // MARK: - Methods
    
    public func encode(_ encodables: [GAPData]) -> Data {
        do { return try Self.encode(encodables) }
        catch { fatalError("Unable to encode GAP Data: \(error)") }
    }
    
    public func encode(_ encodables: GAPData...) -> Data {
        return encode(encodables)
    }
    
    public func encodeAdvertisingData(_ encodables: [GAPData]) throws -> LowEnergyAdvertisingData {
        return try Self.encode(encodables)
    }
    
    @inline(__always)
    internal static func encode<S, DataType>(_ encodables: S) throws -> DataType where S: Sequence, S.Element == GAPData, DataType: GAPDataContainer {
        
        let dataLengths = encodables.map { $0.dataLength }
        let length = dataLengths.reduce(0, { $0 + $1 + 2 })
        guard length <= DataType.maxCapacity else {
            throw Error.invalidSize(length)
        }
        var data = DataType(capacity: length)
        for (index, encodable) in encodables.enumerated() {
            let length = dataLengths[index]
            encode(encodable, length: length, to: &data)
        }
        assert(data.count == length, "Invalid data length")
        return data
    }
    
    internal static func encode<T: GAPData>(_ value: T, to data: inout LowEnergyAdvertisingData) throws {
        let length = value.dataLength
        data += UInt8(length + 1)
        data += T.dataType.rawValue
        value.append(to: &data)
        guard data.count <= LowEnergyAdvertisingData.maxCapacity else {
            throw Error.invalidSize(data.count)
        }
    }
    
    internal static func encode<D: GAPDataContainer>(_ value: GAPData, length: Int, to data: inout D) {
        data += UInt8(length + 1)
        data += type(of: value).dataType.rawValue
        data.append(value)
    }
}

/// Generic specializations
public extension GAPDataEncoder {
    
    func encodeAdvertisingData<T: GAPData>(_ value: T) throws -> LowEnergyAdvertisingData {
        var data = LowEnergyAdvertisingData()
        try Self.encode(value, to: &data)
        return data
    }
    
    func encodeAdvertisingData<T0: GAPData, T1: GAPData>(_ value0: T0, _ value1: T1) throws -> LowEnergyAdvertisingData {
        var data = LowEnergyAdvertisingData()
        try Self.encode(value0, to: &data)
        try Self.encode(value1, to: &data)
        return data
    }
    
    func encodeAdvertisingData<T0: GAPData, T1: GAPData, T2: GAPData>(_ value0: T0, _ value1: T1, _ value2: T2) throws -> LowEnergyAdvertisingData {
        var data = LowEnergyAdvertisingData()
        try Self.encode(value0, to: &data)
        try Self.encode(value1, to: &data)
        try Self.encode(value2, to: &data)
        return data
    }
}

/// GAP Data Decoder
public struct GAPDataDecoder {
    
    /// GAP Data Decoder Error
    public enum Error: Swift.Error {
        
        case insufficientBytes(expected: Int, actual: Int)
        case cannotDecode(GAPDataType, index: Int)
        case unknownType(GAPDataType)
    }
    
    // MARK: - Initialization
    
    /// Initialize with default data types.
    public init() {
        
        /// initialize with default precomputed values
        self.types = GAPDataDecoder.defaultTypes
        self.dataTypes = GAPDataDecoder.defaultDataTypes
{'fraction_non_alphanumeric': 0.10130341527800693, 'fraction_numerical': 0.008909420887642303, 'mean_word_length': 2.2142099681866383, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 23, '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': '6332501', 'n_tokens_mistral': 1848, 'n_tokens_neox': 1783, 'n_words': 484}