<commit_before>//
//  ObservableArray.swift
//  SignalKit
//
//  Created by <NAME> on 9/28/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import Foundation

public enum ObservableArrayEvent {
    case Reset
    case Insert (Set<Int>)
    case Update (Set<Int>)
    case Remove (Set<Int>)
    case Batch (inserted: Set<Int>, updated: Set<Int>, removed: Set<Int>)
}

public final class ObservableArray<ElementType>: Observable {
    
    public typealias ObservationType = ObservableArrayEvent
    public let dispatcher: Dispatcher<ObservableArrayEvent>
    public var elements: [ElementType]
    
    internal var eventStrategy: ArrayEventStrategyType
    
    public init(elements: [ElementType], lock: LockType) {
        
        self.elements = elements
        self.dispatcher = Dispatcher(dispatchRule: { _ in return { return nil }}, lock: lock)
        self.eventStrategy = ArraySerialEventStrategy(dispatcher: dispatcher)
    }
    
    public convenience init(_ elements: [ElementType]) {
        
        self.init(elements: elements, lock: SpinLock())
    }
    
    public convenience init() {
        
        self.init([ElementType]())
    }
}

public extension ObservableArray {
    
    public func insertElements(newElements: [ElementType], atIndex index: Int) {
        
        elements.insertContentsOf(newElements, at: index)
        eventStrategy.insertedElementsAtIndex(index, count: newElements.count)
    }
    
    public func replaceElementAtIndex(index: Int, withElement newElement: ElementType) {
        
        elements[index] = newElement
        eventStrategy.updatedElementAtIndex(index)
    }
    
    public func removeElementAtIndex(index: Int) -> ElementType {
        
        let element = elements.removeAtIndex(index)
        
        eventStrategy.removedElementAtIndex(index)
        
        return element
    }
    
    public func removeAllElements(keepCapacity: Bool = false) {
        
        elements.removeAll(keepCapacity: keepCapacity)
        eventStrategy.replacedAllElements()
    }
    
    public func replaceElementsWith(newElements: [ElementType]) {
        
        elements = newElements
        eventStrategy.replacedAllElements()
    }
    
    public func performBatchUpdate(update: (collection: ObservableArray<ElementType>) -> Void) {
        
        let batchStrategy = ArrayBatchEventStrategy(elementsCount: elements.count)
        
        eventStrategy = batchStrategy
        
        update(collection: self)
        
        eventStrategy = ArraySerialEventStrategy(dispatcher: dispatcher)
        dispatcher.dispatch(batchStrategy.event)
    }
}

extension ObservableArray: CollectionType {
    
    public var startIndex: Int {
        return elements.startIndex
    }
    
    public var endIndex: Int {
        return elements.endIndex
    }
    
    public var isEmpty: Bool {
        return elements.isEmpty
    }
    
    public var count: Int {
        return elements.count
    }
    
    public func underestimateCount() -> Int {
        return elements.underestimateCount()
    }
    
    public func generate() -> IndexingGenerator<Array<ElementType>> {
        return elements.generate()
    }
    
    public subscript(index: Int) -> ElementType {
        get {
            return elements[index]
        }
        set {
            replaceElementAtIndex(index, withElement: newValue)
        }
    }
}

extension ObservableArray {
    
    public func append(newElement: ElementType) {
        insertElements([newElement], atIndex: count)
    }
    
    public func appendContentsOf(newElements: [ElementType]) {<commit_msg>Made the ObservableArray extensions public<commit_after>//
//  ObservableArray.swift
//  SignalKit
//
//  Created by <NAME> on 9/28/15.
//  Copyright © 2015 <NAME>. All rights reserved.
//

import Foundation

public enum ObservableArrayEvent {
    case Reset
    case Insert (Set<Int>)
    case Update (Set<Int>)
    case Remove (Set<Int>)
    case Batch (inserted: Set<Int>, updated: Set<Int>, removed: Set<Int>)
}

public final class ObservableArray<ElementType>: Observable {
    
    public typealias ObservationType = ObservableArrayEvent
    public let dispatcher: Dispatcher<ObservableArrayEvent>
    public var elements: [ElementType]
    
    internal var eventStrategy: ArrayEventStrategyType
    
    public init(elements: [ElementType], lock: LockType) {
        
        self.elements = elements
        self.dispatcher = Dispatcher(dispatchRule: { _ in return { return nil }}, lock: lock)
        self.eventStrategy = ArraySerialEventStrategy(dispatcher: dispatcher)
    }
    
    public convenience init(_ elements: [ElementType]) {
        
        self.init(elements: elements, lock: SpinLock())
    }
    
    public convenience init() {
        
        self.init([ElementType]())
    }
}

public extension ObservableArray {
    
    public func insertElements(newElements: [ElementType], atIndex index: Int) {
        
        elements.insertContentsOf(newElements, at: index)
        eventStrategy.insertedElementsAtIndex(index, count: newElements.count)
    }
    
    public func replaceElementAtIndex(index: Int, withElement newElement: ElementType) {
        
        elements[index] = newElement
        eventStrategy.updatedElementAtIndex(index)
    }
    
    public func removeElementAtIndex(index: Int) -> ElementType {
        
        let element = elements.removeAtIndex(index)
        
        eventStrategy.removedElementAtIndex(index)
        
        return element
    }
    
    public func removeAllElements(keepCapacity: Bool = false) {
        
        elements.removeAll(keepCapacity: keepCapacity)
        eventStrategy.replacedAllElements()
    }
    
    public func replaceElementsWith(newElements: [ElementType]) {
        
        elements = newElements
        eventStrategy.replacedAllElements()
    }
    
    public func performBatchUpdate(update: (collection: ObservableArray<ElementType>) -> Void) {
        
        let batchStrategy = ArrayBatchEventStrategy(elementsCount: elements.count)
        
        eventStrategy = batchStrategy
        
        update(collection: self)
        
        eventStrategy = ArraySerialEventStrategy(dispatcher: dispatcher)
        dispatcher.dispatch(batchStrategy.event)
    }
}

extension ObservableArray: CollectionType {
    
    public var startIndex: Int {
        return elements.startIndex
    }
    
    public var endIndex: Int {
        return elements.endIndex
    }
    
    public var isEmpty: Bool {
        return elements.isEmpty
    }
    
    public var count: Int {
        return elements.count
    }
    
    public func underestimateCount() -> Int {
        return elements.underestimateCount()
    }
    
    public func generate() -> IndexingGenerator<Array<ElementType>> {
        return elements.generate()
    }
    
    public subscript(index: Int) -> ElementType {
        get {
            return elements[index]
        }
        set {
            replaceElementAtIndex(index, withElement: newValue)
        }
    }
}

public extension ObservableArray {
    
    public func append(newElement: ElementType) {
        insertElements([newElement], atIndex: count)
    }
    
    public func appendContentsOf(newElements: [ElementType]) {
{'fraction_non_alphanumeric': 0.08203017832647462, 'fraction_numerical': 0.0024691358024691358, 'mean_word_length': 2.5052884615384614, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 39, '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': '3422688', 'n_tokens_mistral': 1928, 'n_tokens_neox': 1878, 'n_words': 453}