<commit_before>//
//  ASN1Object+Helper.swift
//  TPInAppReceipt iOS
//
//  Created by <NAME> on 24/06/2019.
//  Copyright © 2019 <NAME>. All rights reserved.
//

import Foundation

///
/// Utils methods
extension ASN1Object
{
    static var identifierLenght: Int { return 1 }
    
    static func isDataValid(checkingLength: Bool = true, _ data: inout Data) -> Bool
    {
        let c = data.count
        
        if c == 0 { return false }
        
        guard let _ = try? extractIdentifier(from: &data),
            let length = try? ASN1Object.extractLenght(from: &data) else
        {
            return false
        }
        
        if checkingLength
        {
            return (identifierLenght + length.offset + length.value) == c
        }
        
        return true
    }

    static func extractIdentifier(from asn1data: inout Data) throws -> Identifier
    {
        guard asn1data.count > 0 else
        {
            throw ASN1Error.initializationFailed(reason: .dataIsInvalid)
        }
        
        let raw = asn1data[asn1data.startIndex]
        let tagNumber = raw & 0b11111
        
        guard let c = Identifier.Class(rawValue: (raw >> 6) & 0b11),
            let e = Identifier.EncodingType(rawValue: (raw >> 5) & 0b1) else
        {
            throw ASN1Error.initializationFailed(reason: .dataIsInvalid)
        }
        
        return Identifier(raw: raw, tagNumber: tagNumber, class: c, encodingType: e)
    }
    
    static func extractLenght(from asn1data: inout Data) throws -> Length
    {
        if asn1data.count < 3 { return Length.short(value: 0) } //invalid data
        
        
        let startIdx = asn1data.startIndex
        
        let lByte = asn1data[startIdx + 1] // Skip identifier
        
        if ((lByte & 0x80) != 0)
        {
            let l: Int = Int(lByte - 0x80)
            let start = startIdx + identifierLenght + 1 // Skip identifier and lenght header
            let end = start + l
            var d = asn1data[start..<end]
            
            let r = ASN1.readInt(from: &d, l: l)
            return Length.long(length: l, value: r)
        }else{
            return Length.short(value: Int(lByte))
        }
    }
}<commit_msg>ASN1: fix issue with parsing octet string<commit_after>//
//  ASN1Object+Helper.swift
//  TPInAppReceipt iOS
//
//  Created by <NAME> on 24/06/2019.
//  Copyright © 2019 <NAME>. All rights reserved.
//

import Foundation

///
/// Utils methods
extension ASN1Object
{
    static var identifierLenght: Int { return 1 }
    
    static func isDataValid(checkingLength: Bool = true, _ data: inout Data) -> Bool
    {
        let c = data.count
        
        if c == 0 { return false }
        
        guard let _ = try? extractIdentifier(from: &data),
            let length = try? ASN1Object.extractLenght(from: &data) else
        {
            return false
        }
        
        if checkingLength
        {
            return (identifierLenght + length.offset + length.value) == c
        }
        
        return true
    }

    static func extractIdentifier(from asn1data: inout Data) throws -> Identifier
    {
        guard asn1data.count > 0 else
        {
            throw ASN1Error.initializationFailed(reason: .dataIsInvalid)
        }
        
        let raw = asn1data[asn1data.startIndex]
        let tagNumber = raw & 0b11111
        
        guard let c = Identifier.Class(rawValue: (raw >> 6) & 0b11),
            let e = Identifier.EncodingType(rawValue: (raw >> 5) & 0b1) else
        {
            throw ASN1Error.initializationFailed(reason: .dataIsInvalid)
        }
        
        return Identifier(raw: raw, tagNumber: tagNumber, class: c, encodingType: e)
    }
    
    static func extractLenght(from asn1data: inout Data) throws -> Length
    {
        if asn1data.count < 3 { return Length.short(value: -1) } //invalid data
        
        
        let startIdx = asn1data.startIndex
        
        let lByte = asn1data[startIdx + 1] // Skip identifier
        
        if ((lByte & 0x80) != 0)
        {
            let l: Int = Int(lByte - 0x80)
            let offset = identifierLenght + 1 // Skip identifier and lenght header
            
            if (offset + l) > asn1data.endIndex
            {
                return Length.short(value: -1) //invalid data
            }
            
            let start = startIdx + offset
            
            
        
            let end = start + l
            
            var d = asn1data[start..<end]
            
            let r = ASN1.readInt(from: &d, l: l)
            return Length.long(length: l, value: r)
        }else{
            return Length.short(value: Int(lByte))
        }
    }
}
{'fraction_non_alphanumeric': 0.09468332980300784, 'fraction_numerical': 0.023511967803431476, 'mean_word_length': 1.574700109051254, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 24, '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': '361000', 'n_tokens_mistral': 1484, 'n_tokens_neox': 1403, 'n_words': 380}