<commit_before>//
// Copyright (c) 2015 <NAME>. All rights reserved.
//

import UIKit

public typealias ImageDownloaderCompletion = (ImageInstance?, NSError?) -> Void

public protocol ImageDownloaderDelegate {
    func imageDownloaderDelegate(downloader: ImageDownloadOperation, didReportProgress progress: NSProgress);
}

public class ImageDownloadOperation: NSOperation {

    private var imageURL: NSURL
    private var delegate: ImageDownloaderDelegate?
    private var session: NSURLSession!
    private var task: NSURLSessionDownloadTask!
    private var resumeData: NSData?
    private var progress: NSProgress {
        return NSProgress()
    }
    public var completionHandler: ImageDownloaderCompletion?

    public convenience init(imageURL: NSURL) {
        self.init(imageURL: imageURL, delegate: nil)
    }

    public init(imageURL: NSURL, delegate: ImageDownloaderDelegate?) {
        self.imageURL = imageURL
        self.delegate = delegate
        super.init()
    }

    public override func start() {
        let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
        session = NSURLSession(configuration: sessionConfiguration, delegate: self,
                delegateQueue: NSOperationQueue.mainQueue())
        resumeDownload()
    }

    public override func cancel() {
        task.cancelByProducingResumeData {
            [unowned self] data in
            self.resumeData = data
        }
    }

    private func resumeDownload() {
        task = session.downloadTaskWithURL(imageURL)
        task.resume()
    }

}

extension ImageDownloadOperation: NSURLSessionDownloadDelegate {

    public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask,
                           didWriteData bytesWritten: Int64, totalBytesWritten: Int64,
                           totalBytesExpectedToWrite: Int64) {
        progress.totalUnitCount = totalBytesWritten
        progress.completedUnitCount = bytesWritten
        delegate?.imageDownloaderDelegate(self, didReportProgress: progress)
    }

    public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask,
        didFinishDownloadingToURL location: NSURL) {
            var error: NSError?
            if let newData = NSData(contentsOfURL: location, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &error) {
                let newImage = UIImage.imageWithCachedData(newData)
                let newImageInstance = ImageInstance(image: newImage, data: newData, state: .New, url: imageURL)
                completionHandler?(newImageInstance, nil)
            } else {
                completionHandler?(nil, error)
            }
    }

    public func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        if let error = error {
            println("Remote error: \(error), \(error.userInfo)")
            completionHandler?(nil, error)
        }
    }

    public func URLSession(session: NSURLSession, task: NSURLSessionTask,
                           willPerformHTTPRedirection response: NSHTTPURLResponse,
                           newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
        self.completionHandler?(nil, nil)
        self.imageURL = request.URL!
        resumeDownload()
    }

}

public enum ImageInstanceState {
    case New, Cached, Downloading
}

public struct ImageInstance {

    public let image: UIImage?
    public let data: NSData?
    public let state: ImageInstanceState
    public let url: NSURL?

    init(image: UIImage?, data: NSData? = nil, state: ImageInstanceState, url: NSURL?) {
        self.image = image
        self.state = state
        self.url = url
        self.data = data
    }

}
<commit_msg>make session and task optionals<commit_after>//
// Copyright (c) 2015 <NAME>. All rights reserved.
//

import UIKit

public typealias ImageDownloaderCompletion = (ImageInstance?, NSError?) -> Void

public protocol ImageDownloaderDelegate {
    func imageDownloaderDelegate(downloader: ImageDownloadOperation, didReportProgress progress: NSProgress);
}

public class ImageDownloadOperation: NSOperation {

    private var imageURL: NSURL
    private var delegate: ImageDownloaderDelegate?
    private var session: NSURLSession?
    private var task: NSURLSessionDownloadTask?
    private var resumeData: NSData?
    private var progress: NSProgress {
        return NSProgress()
    }
    public var completionHandler: ImageDownloaderCompletion?

    public convenience init(imageURL: NSURL) {
        self.init(imageURL: imageURL, delegate: nil)
    }

    public init(imageURL: NSURL, delegate: ImageDownloaderDelegate?) {
        self.imageURL = imageURL
        self.delegate = delegate
        super.init()
    }

    public override func start() {
        let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
        session = NSURLSession(configuration: sessionConfiguration, delegate: self,
                delegateQueue: NSOperationQueue.mainQueue())
        resumeDownload()
    }

    public override func cancel() {
        task?.cancelByProducingResumeData {
            [unowned self] data in
            self.resumeData = data
        }
    }

    private func resumeDownload() {
        if let session = session {
            let newTask = session.downloadTaskWithURL(imageURL)
            newTask.resume()
            task = newTask
        }
    }

}

extension ImageDownloadOperation: NSURLSessionDownloadDelegate {

    public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask,
                           didWriteData bytesWritten: Int64, totalBytesWritten: Int64,
                           totalBytesExpectedToWrite: Int64) {
        progress.totalUnitCount = totalBytesWritten
        progress.completedUnitCount = bytesWritten
        delegate?.imageDownloaderDelegate(self, didReportProgress: progress)
    }

    public func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask,
        didFinishDownloadingToURL location: NSURL) {
            var error: NSError?
            if let newData = NSData(contentsOfURL: location, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &error) {
                let newImage = UIImage.imageWithCachedData(newData)
                let newImageInstance = ImageInstance(image: newImage, data: newData, state: .New, url: imageURL)
                completionHandler?(newImageInstance, nil)
            } else {
                completionHandler?(nil, error)
            }
    }

    public func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        if let error = error {
            println("Remote error: \(error), \(error.userInfo)")
            completionHandler?(nil, error)
        }
    }

    public func URLSession(session: NSURLSession, task: NSURLSessionTask,
                           willPerformHTTPRedirection response: NSHTTPURLResponse,
                           newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
        self.completionHandler?(nil, nil)
        self.imageURL = request.URL!
        resumeDownload()
    }

}

public enum ImageInstanceState {
    case New, Cached, Downloading
}

public struct ImageInstance {

    public let image: UIImage?
    public let data: NSData?
    public let state: ImageInstanceState
    public let url: NSURL?

    init(image: UIImage?, data: NSData? = nil, state: ImageInstanceState, url: NSURL?) {
        self.image = image
        self.state = state
        self.url = url
        self.data = data
    }

}

{'fraction_non_alphanumeric': 0.07542515902894976, 'fraction_numerical': 0.002596391016487083, 'mean_word_length': 2.776470588235294, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6437262', 'n_tokens_mistral': 2004, 'n_tokens_neox': 1965, 'n_words': 517}