[
  {
    "path": ".codecov.yml",
    "content": "ignore:\n- \"/Tests/*\"\ncomment:\n  layout: \"header, diff\"\n  behavior: default\n  require_changes: no\ncoverage:\n  status:\n    project:\n      default:\n        target: auto\n        threshold: null\n        base: auto\n        paths: \"Sources/*\"\n"
  },
  {
    "path": ".gitignore",
    "content": ".build\n/Carthage/Build\n/Packages\nxcuserdata\n/Package.resolved\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"Carthage/Checkouts/BTree\"]\n\tpath = Carthage/Checkouts/BTree\n\turl = https://github.com/attaswift/BTree.git\n[submodule \"Carthage/Checkouts/SipHash\"]\n\tpath = Carthage/Checkouts/SipHash\n\turl = https://github.com/attaswift/SipHash.git\n"
  },
  {
    "path": ".swift-version",
    "content": "3.0.1\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: objective-c\nosx_image: xcode9\nscript:\n- xcrun xcodebuild -workspace GlueKit.xcworkspace -scheme GlueKit-macOS test\n- xcrun xcodebuild -quiet -workspace GlueKit.xcworkspace -scheme GlueKit-iOS\n- xcrun xcodebuild -quiet -workspace GlueKit.xcworkspace -scheme GlueKit-watchOS\n- xcrun xcodebuild -quiet -workspace GlueKit.xcworkspace -scheme GlueKit-tvOS\n- swift test\nafter_success: bash <(curl -s https://codecov.io/bash)\n"
  },
  {
    "path": "Cartfile",
    "content": "github \"attaswift/BTree\" ~> 4.1\ngithub \"attaswift/SipHash\" ~> 1.2\n"
  },
  {
    "path": "Cartfile.resolved",
    "content": "github \"attaswift/BTree\" \"v4.1.0\"\ngithub \"attaswift/SipHash\" \"v1.2.0\"\n"
  },
  {
    "path": "Demo.playground/Pages/Untitled Page.xcplaygroundpage/Contents.swift",
    "content": "import GlueKit\nimport XCPlayground\n\n// Let's suppose we're writing an app for maintaining a catalogue for your books.\n// Here is what the model could look like.\n\nclass Author: Hashable, CustomStringConvertible {\n    let name: Variable<String>\n    let yearOfBirth: Variable<Int>\n\n    init(name: String, yearOfBirth: Int) {\n        self.name = .init(name)\n        self.yearOfBirth = .init(yearOfBirth)\n    }\n\n    var hashValue: Int { return name.value.hashValue }\n    static func == (a: Author, b: Author) -> Bool {\n        return a.name.value == b.name.value && a.yearOfBirth.value == b.yearOfBirth.value\n    }\n    var description: String { return \"Author(\\(name.value))\" }\n}\n\nclass Book: Hashable, CustomStringConvertible {\n    let title: Variable<String>\n    let authors: SetVariable<Author>\n    let publicationYear: Variable<Int>\n    let pages: Variable<Int>\n\n    init(title: String, authors: Set<Author>, publicationYear: Int, pages: Int) {\n        self.title = .init(title)\n        self.authors = .init(authors)\n        self.publicationYear = .init(pages)\n        self.pages = .init(pages)\n    }\n\n    var hashValue: Int { return title.value.hashValue }\n    static func == (a: Book, b: Book) -> Bool {\n        return (a.title.value == b.title.value\n            && a.authors.value == b.authors.value\n            && a.publicationYear.value == b.publicationYear.value\n            && a.pages.value == b.pages.value)\n    }\n    var description: String { return \"Book(\\(title.value))\" }\n}\n\nclass Bookshelf {\n    let location: Variable<String>\n    let books: ArrayVariable<Book>\n\n    init(location: String, books: [Book] = []) {\n        self.location = .init(location)\n        self.books = .init(books)\n    }\n}\n\n// Let's create a couple of example books and arrange them on some bookshelves.\n\nlet stephenson = Author(name: \"Neal Stephenson\", yearOfBirth: 1959)\nlet pratchett = Author(name: \"Terry Pratchett\", yearOfBirth: 1948)\nlet gaiman = Author(name: \"Neil Gaiman\", yearOfBirth: 1960)\nlet knuth = Author(name: \"Donald E. Knuth\", yearOfBirth: 1938)\n\nlet colourOfMagic = Book(title: \"The Colour of Magic\", authors: [pratchett], publicationYear: 1983, pages: 206)\nlet smallGods = Book(title: \"Small Gods\", authors: [pratchett], publicationYear: 1992, pages: 284)\nlet seveneves = Book(title: \"Seveneves\", authors: [stephenson], publicationYear: 2015, pages: 880)\nlet goodOmens = Book(title: \"Good Omens\", authors: [pratchett, gaiman], publicationYear: 1990, pages: 288)\nlet americanGods = Book(title: \"American Gods\", authors: [gaiman], publicationYear: 2001, pages: 465)\nlet cryptonomicon = Book(title: \"Cryptonomicon\", authors: [stephenson], publicationYear: 1999, pages: 918)\nlet anathem = Book(title: \"Anathem\", authors: [stephenson], publicationYear: 2008, pages: 928)\nlet texBook = Book(title: \"The TeXBook\", authors: [knuth], publicationYear: 1984, pages: 483)\nlet taocp1 = Book(title: \"The Art of Computer Programming vol. 1: Fundamental Algorithms. 3rd ed.\", authors: [knuth], publicationYear: 1997, pages: 650)\n\nlet topShelf = Bookshelf(location: \"Top\", books: [colourOfMagic, smallGods, seveneves, goodOmens, americanGods])\nlet bottomShelf = Bookshelf(location: \"Bottom\", books: [cryptonomicon, anathem, texBook, taocp1])\n\nlet shelves = ArrayVariable<Bookshelf>([topShelf, bottomShelf])\n\n\n// Now let's create some interesting queries on this small library of books!\n\n\n// Let's get an array of the title of each book in the library.\nlet allTitles = shelves.flatMap{$0.books}.map{$0.title}\nallTitles.value\n\nlet allAuthors = shelves.flatMap{$0.books}.distinctUnion().flatMap{$0.authors}\nallAuthors.value\n\n// Here are all books that have Neal Stephenson as one of their authors.\nlet booksByStephenson = shelves.flatMap{$0.books}.filter { book in book.authors.observableContains(stephenson) }\nbooksByStephenson.value\n\n// Let's imagine Stephenson was a co-author of The TeXBook, and add him to its author list.\ntexBook.authors.insert(stephenson)\n\n// `booksByStephenson` automatically updates to reflect the change.\nbooksByStephenson.value\n\n\n// How many books do I have?\nlet bookCount = shelves.flatMap{$0.books}.observableCount\nbookCount.value\n\n// What if I buy a new book?\nlet mort = Book(title: \"Mort\", authors: [pratchett], publicationYear: 1987, pages: 315)\ntopShelf.books.append(mort)\n\nbookCount\nallTitles\n\n"
  },
  {
    "path": "Demo.playground/Pages/Untitled Page.xcplaygroundpage/timeline.xctimeline",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Timeline\n   version = \"3.0\">\n   <TimelineItems>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=0&amp;CharacterRangeLoc=4445&amp;EndingColumnNumber=24&amp;EndingLineNumber=89&amp;StartingColumnNumber=1&amp;StartingLineNumber=89&amp;Timestamp=497543455.651167\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=0&amp;CharacterRangeLoc=4445&amp;EndingColumnNumber=8&amp;EndingLineNumber=89&amp;StartingColumnNumber=5&amp;StartingLineNumber=89&amp;Timestamp=497543455.651368\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=0&amp;CharacterRangeLoc=4445&amp;EndingColumnNumber=8&amp;EndingLineNumber=89&amp;StartingColumnNumber=5&amp;StartingLineNumber=89&amp;Timestamp=497543455.651513\"\n         lockedSize = \"{500, 128}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=0&amp;CharacterRangeLoc=4445&amp;EndingColumnNumber=2&amp;EndingLineNumber=89&amp;StartingColumnNumber=1&amp;StartingLineNumber=89&amp;Timestamp=497543455.651658\"\n         lockedSize = \"{524, 87}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=0&amp;CharacterRangeLoc=4445&amp;EndingColumnNumber=21&amp;EndingLineNumber=89&amp;StartingColumnNumber=1&amp;StartingLineNumber=89&amp;Timestamp=497543455.651804\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=0&amp;CharacterRangeLoc=4445&amp;EndingColumnNumber=45&amp;EndingLineNumber=89&amp;StartingColumnNumber=1&amp;StartingLineNumber=89&amp;Timestamp=497543455.651939\"\n         lockedSize = \"{568, 170}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=15&amp;CharacterRangeLoc=3500&amp;EndingColumnNumber=16&amp;EndingLineNumber=83&amp;StartingColumnNumber=1&amp;StartingLineNumber=83&amp;Timestamp=497496046.579232\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=23&amp;CharacterRangeLoc=3800&amp;EndingColumnNumber=24&amp;EndingLineNumber=90&amp;StartingColumnNumber=1&amp;StartingLineNumber=90&amp;Timestamp=497496046.579372\"\n         lockedSize = \"{425, 93}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=23&amp;CharacterRangeLoc=4020&amp;EndingColumnNumber=24&amp;EndingLineNumber=96&amp;StartingColumnNumber=1&amp;StartingLineNumber=96&amp;Timestamp=497496046.579512\"\n         lockedSize = \"{422, 110}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=15&amp;CharacterRangeLoc=4133&amp;EndingColumnNumber=16&amp;EndingLineNumber=101&amp;StartingColumnNumber=1&amp;StartingLineNumber=101&amp;Timestamp=497496046.579648\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=9&amp;CharacterRangeLoc=4306&amp;EndingColumnNumber=10&amp;EndingLineNumber=108&amp;StartingColumnNumber=1&amp;StartingLineNumber=108&amp;Timestamp=497496046.579778\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=9&amp;CharacterRangeLoc=4296&amp;EndingColumnNumber=10&amp;EndingLineNumber=107&amp;StartingColumnNumber=1&amp;StartingLineNumber=107&amp;Timestamp=497496046.579911\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=16&amp;CharacterRangeLoc=3596&amp;EndingColumnNumber=17&amp;EndingLineNumber=86&amp;StartingColumnNumber=1&amp;StartingLineNumber=86&amp;Timestamp=497496046.580041\"\n         lockedSize = \"{346, 109}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=3&amp;CharacterRangeLoc=4372&amp;EndingColumnNumber=8&amp;EndingLineNumber=112&amp;StartingColumnNumber=5&amp;StartingLineNumber=112&amp;Timestamp=497543455.653085\"\n         lockedSize = \"{417, 98}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"#CharacterRangeLen=3&amp;CharacterRangeLoc=4321&amp;EndingColumnNumber=8&amp;EndingLineNumber=110&amp;StartingColumnNumber=5&amp;StartingLineNumber=110&amp;Timestamp=497543455.663465\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n   </TimelineItems>\n</Timeline>\n"
  },
  {
    "path": "Demo.playground/contents.xcplayground",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<playground version='6.0' target-platform='macos'/>"
  },
  {
    "path": "Documentation/Language Enhancements.md",
    "content": "# Potential Swift Improvements That Would Help GlueKit\n\nThis document lists a couple of potential improvements to the Swift language and compiler that would simplify the design/implementation of GlueKit.\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**\n\n- [Property Behaviors ([SE-0030])](#property-behaviors-se-0030)\n- [More Complete Support for Generics](#more-complete-support-for-generics)\n  - [Generalized Protocol Existentials](#generalized-protocol-existentials)\n  - [Permitting `where` clauses to constrain associated types ([SE-0142])](#permitting-where-clauses-to-constrain-associated-types-se-0142)\n  - [Conditional Conformances ([SE-0143])](#conditional-conformances-se-0143)\n  - [Nested generics](#nested-generics)\n  - [Allowing subclasses to override requirements satisfied by defaults](#allowing-subclasses-to-override-requirements-satisfied-by-defaults)\n- [Abstract Methods](#abstract-methods)\n- [Relaxed Superclass Visibility Requirements](#relaxed-superclass-visibility-requirements)\n- [Closure Contexts With Inline Storage (Related issue: [SR-3106])](#closure-contexts-with-inline-storage-related-issue-sr-3106)\n- [Assorted Bugfixes](#assorted-bugfixes)\n  - [Generic subclass cannot override methos in non-generic superclass, and vice versa ([SR-2427])](#generic-subclass-cannot-override-methos-in-non-generic-superclass-and-vice-versa-sr-2427)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n\n## Property Behaviors ([SE-0030])\n\n> There are property implementation patterns that come up repeatedly. Rather than hardcode a fixed set of patterns into the compiler, we should provide a general \"property behavior\" mechanism to allow these patterns to be defined as libraries. -- [SE-0030]\n\n\nTo declare observable properties in GlueKit, you currently need to declare them with a  `Variable` type, and you have to access their values through an inconvenient `value` property:\n\n```swift\nclass Book {\n    let title: Variable<String>\n    let pageCount: Variable<Int>\n}\n\nlet book: Book = ...\nbook.title.value = \"The Colour of Magic\"\nlet c = book.pageCount.futureValues.subscribe { print(\"Page count is now \\($0)\" }\n```\n\nIt is possible to make this a little less painful by judicious use of computed properties:\n\n```swift\nclass Book {\n\tlet observableTitle: Variable<String>\n    var title: String {\n        get { return observableTitle.value }\n        set { observableTitle.value = newValue }\n    }\n    \n    let observablePageCount: Variable<Int>\n    var pageCount: Int {\n        get { return observablePageCount.value }\n        set { observablePageCount.value = newValue }\n    }\n}\n\nlet book: Book = ...\nbook.title = \"The Colour of Magic\"\nlet c = book.observablePageCount.futureValues.subscribe { print(\"Page count is now \\($0)\" }\n```\n\nThis makes usage of these properties nicer, but it adds extra boilerplate to the definition of your model classes.\n\nIf the [proposal for Property Behaviors][SE-0030] would be implemented, we could\neliminate this boilerplate and have observable properties that approach (or arguably even exceed) the readability of Cocoa:\n\n```swift\nclass Book {\n\tvar [observable] title: String\n    var [observable] pageCount: Int\n}\n\nlet book: Book = ...\nbook.title = \"The Colour of Magic\"\nlet c = book.pageCount.[observable].subscribe { print(\"Page count is now \\($0)\" }\n```\n\nProperty Behaviors also allow storage for the Signals associated with these \nvariables to be embedded directly in the `Book` class, instead of being allocated separately. (Each such observable variable needs to count open transactions and keep track of subscribed observers somehow.)\n\n\n[SE-0030]: https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md\n\n\n## More Complete Support for Generics\n\nGlueKit heavily relies on Swift's generic types and protocols with associated values. Any and all \nlanguage improvements relating to these concepts would find immediate use in GlueKit.\nFor example, the implementation of pretty much any item in the [Generics Manifesto][gm] \nwould have immediate impact on GlueKit. (Some of these are explicitly mentioned below.)\n\n[gm]: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md\n\nGlueKit was designed with the assumption that most items in the Generic Manifesto will be implemented at some point. I sometimes chose a less convenient way \nto express things so that when/if a particular item on this list gets implemented, GlueKit will find itself immediately\nat home in the new language, with minimal design changes.\n\n\n### Generalized Protocol Existentials\n\n> The restrictions on existential types came from an implementation limitation, but it is reasonable to allow a value of protocol type even when the protocol has Self constraints or associated types. -- [GenericsManifesto.md][gm-generalized-existentials]\n\n[gm-generalized-existentials]: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials\n \nGlueKit is largely about the exploration of possible interactions between a handful of concepts, all which are \ncaptured by protocols with associated types: `SourceType`, `SinkType`, `ObservableType`, `UpdatableType`,\n`ObservableValueType`, `ObservableArrayType`, `UpdatableSetType`, etc.\n\nThe language does not provide existentials for these protocols -- so type erasure needs to be implemented manually.\nThis leads to the proliferation of the various `Any*` types -- see `AnySource`, `AnySink`, `AnyObservableValue`,\n`AnyUpdatableValue`, `AnyObservableArray`, `AnyUpdatableSetType`, etc. These are all implemented manually, \nusing subclass polymorphism.\n\nSometimes the need for type erasure can be eliminated by expanding the public API surface. For example, wherever \nan `Any*` type is used as a return value, we could substitute the (currently private/internal) concrete type instead.\nThere are good reasons to do this whether or not we get generalized existentials: having transformation methods\nreturn concrete types enables static method dispatch. It might be worthwhile to do this for at least some of the \ntransformations.\n(The class names and their exposed API surface need to be carefully reviewed and updated, though.)\nConcrete return types do make life a little more difficult for users, though: they will have to explicitly \nspecify the type in, say, a property declaration.\n\nHowever, the need for `Any*` cannot be entirely eliminated. For example, `Signal` needs to be able to store its\nsubscribers in a collection, which is only possible with some form of type erasure. (The current `Source` API\nalso needs `Signal` to be able to reify type-erased values, getting the original type back. This is similar to [opening a generalized existential][gm-open].)\n\nDoing type erasure by subclass polymorphism implies that GlueKit's `Any*` types always need to heap-allocate a box. On the other hand, Swift's protocol existentials include some space to store small value types inline, which makes them work without allocation in a lot of cases. This optimization is hard (even impossible?) to emulate in Swift code, but it would be very much desirable to have it for e.g. `AnySink`.\n\n[gm-open]: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#opening-existentials\n\n### Permitting `where` clauses to constrain associated types ([SE-0142])\n\n> This proposal seeks to introduce a where clause to associated type declarations and improvements to protocol constraints to bring associated types the same expressive power as generic type parameters. -- [SE-0142]\n\n[SE-0142]: https://github.com/apple/swift-evolution/blob/master/proposals/0142-associated-types-constraints.md\n\nThis is a biggie! Not having the ability to specify that e.g. an `ObservableArrayType` must have\n`Change == ArrayChange<Element>` means that this constraint has to be explicitly specified by almost every consumer\nof an observable array. I currently have ~300 such explicit constraints in the source code, making working on GlueKit an exercise in patience.\n\nThe proposal to implement this improvement has been accepted, so presumably it'll get implemented relatively soon.\n\nMeanwhile, we can mostly work around the issue by having the child protocol include\nproperty requirements that specialize on the requirements of the parent:\n\n```swift\n protocol ObservableType { // Not the real definition\n     associatedtype Change: ChangeType \n \n     var value: Change.Value { get }\n     var changes: AnySource<Change> { get }\n }\n\n protocol ObservableArrayType {\n     associatedtype Element: Hashable  \n\n     var value: [Element] { get }\n     var changes: AnySource<ArrayChange<Element>> { get }\n }\n```\n\nIn most (maybe all) contexts, the type inference engine sees that `changes` in\n`ObservableArrayType` refines the similar requirement in `ObservableType` \nand concludes that `Change` can only be an `ArrayChange` there. In the current\ncodebase, `ObservableType` doesn't have a property requirement in like `changes` \nabove -- the update source is implemented by two methods. However, it would be \neasy enough to define a dummy property that is never actually used.\n\n\n### Conditional Conformances ([SE-0143])\n\n> Conditional conformances express the notion that a generic type will conform to a particular protocol only when its type arguments meet certain requirements.\" -- [SE-0143]\n\nThis is a popular Swift feature request that seems to be on track for implementation.\n\n[SE-0143]: https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md\n\nAt first glance, it looks like conditional conformances might allow us to express deep relationships between our \nconcepts: for example, we might want to say that an `ObservableType` whose `Change` is an `ArrayChange` is\nautomatically an `ObservableArrayType`. But that's not the case:\n\n1. The proposal allows conditional conformances for generic types only, not protocols. It enables us to specify that\n   `Array` should implement `Equatable` when its elements do, but we won't be able to do the same for `Collection`.\n\n2. Even if we could do that, an `ObservableArrayType` is more than just an observable whose delta type matches \n   a specific structure; it also defines a more efficient API for array access. Without this, we lose what makes \n   observable arrays (reasonably) efficient.\n\nConditional conformances will, however, help a great deal with small annoying details -- for example, we could say that a `Variable` with an integer value automatically implements `ExpressibleByIntegerLiteral`, eliminating the need \nfor `IntVariable`. We could have `ValueChange`, `SetChange` and `ArrayChange` explicitly implement `Equatable`, \nwhich would help unit tests.\n\n### Nested generics\n\n> There isn't much to say about this: the compiler simply needs to be improved to handle nested generics throughout. -- [GenericsManifesto.md][gm-nested-generics]\n\n[gm-nested-generics]: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#nested-generics\n\nCurrently Swift does not support declaring nested types in generics, which means some helper types (like method forwarding structs that implement `SinkType`) need to be declared outside the generic struct/class. This means the type parameters of the parent generic and (most annoyingly) the constraints of these parameters need to be repeated on every such helper type. Assuming types nested in generics would implicitly inherit the type parameters of their parents, nested generics would eliminate such boring repetitions.\n\n### Allowing subclasses to override requirements satisfied by defaults\n\n> When a superclass conforms to a protocol and has one of the protocol's requirements satisfied by a member of a protocol extension, that member currently cannot be overridden by a subclass. -- [GenericsManifesto.md][gm-overriding-extensions]\n\n[gm-overriding-extensions]: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#allowing-subclasses-to-override-requirements-satisfied-by-defaults-\n\nFor each protocol requirement that has a default implementation in a protocol extension, we currently need to duplicate that implementation in the (abstract) base class that is used to implement boxing for type erasure. This is error-prone and ugly.\n\n## Abstract Methods\n\nThere is currently no way to mark an overridable member as abstract in Swift. I've not seen proposals to add support for this, but it seems obvious Swift needs this -- abstract classes and members are an important part of OOP. Without the help of the compiler, it is all too easy to forget a required method override.\n\nProtocols supply an alternative, often better, way to express the things we used to model with abstract methods. But in some contexts (particularly when implementing type-erasure for protocols with associated types), abstract methods are still useful.\n(Obviously, generalized existentials would remove this usecase.)\n\n## Relaxed Superclass Visibility Requirements\n\nSwift currently requires the superclasses of public classes to be also exposed as public, even if they're just an implementation detail. This is why GlueKit exposes some underscored classes like `_BaseObservableArray` in its public interface.\n\nThis restriction is not consistently enforced by the compiler, but breaking it can lead to misleading errors and/or strange behavior at runtime. (I can't remember which.)\n\n## Closure Contexts With Inline Storage (Related issue: [SR-3106])\n\n[SR-3106]: https://bugs.swift.org/browse/SR-3106\n\nIn the current version of Swift, a variable of a function type has storage for just two machine words, which is enough to hold function pointer and a single-word context containing the values captured by the closure.\n\nThis means that the context of most escaping closures needs to be heap-allocated, even if they capture only a couple of constants. The compiler may be able to optimize away the allocation if the closure is non-escaping, but if we need to store the closure for later execution, the context needs to be on the heap.\n\nClosures that capture only a single-word constant may at some point store that value directly in the context word. This isn't currently implemented, though. (Note that the captured value may or may not need to be reference counted. `self` is refcounted, but a captured `Float` wouldn't be. Some bits need to be reserved somewhere to keep track of this.)\n\nSwift's partially applied methods are closures that capture `self`. It would be possible to special-case them such that the `self` reference is stored directly in context word; but this is not currently implemented. So partially applied methods always incur the cost of a heap allocation when used in escaping contexts. This makes them slower than representing the method call with a forwarding struct like this:\n\n```swift\nclass Foo {\n\tfunc greet(_ name: String) {\n\t\tprint(\"Hello, \\(name)!\")\n\t}\n}\n\nstruct FooForwarder {\n\tlet foo: Foo\n\tfunc apply(_ name: String) {\n\t\tfoo.greet(name)\n\t}\n}\n\nlet foo = Foo()\nlet greeter1 = FooForwarder(foo)\nlet greeter2 = foo.greet\n```\n\nCreating `greeter1` is measurably faster than creating `greeter2`, because the latter needs to do an allocation.\nThis is the primary reason why GlueKit defines the `SinkType` protocol instead of just defining a typealias for a function type.\n(The other reason is that it is useful to be able to add extra requirements (i.e., `Hashable`) and extensions to sinks. But we could live without those!)\n\nIf the size of function types would be widened to include space for more bits of context, lots of simple closures would fit inline, without the need for context allocation. There is precedent for this with `Any`, which currently includes space for inline storage of data up to three words in size.\n\nAggregate observation in GlueKit (e.g., `ArrayMappingForValueField`) needs to register observer sinks that capture two refcounted pointers -- one for the `self` pointer of the aggregate observable itself, the other for keeping track of the particular element that is the source of the change. If these would be represented by closures, then they would be heap-allocated, making them much more expensive -- unless Swift's function types would be widened & the inline storage optimization was implemented. \n\n(We could leave some of the captures uncaptured and store them alongside the closure, but it seems easier to just define a forwarding struct -- which achieves exactly the same thing.)\n\n\n## Assorted Bugfixes\n\nThis section lists compiler bugs that have a direct effect on GlueKit.\n\n### Generic subclass cannot override methos in non-generic superclass, and vice versa ([SR-2427])\n\nThis compiler bug affects the design of `TimerSource`. To work around it, I had to add a dummy unusued type parameter to it, \nand define a typealias to paper over the ugliness.\n\n[SR-2427]: https://bugs.swift.org/browse/SR-2427\n\nThis bug [has been fixed][PR-5424] on Swift's master branch.\n\n[PR-5424]: https://github.com/apple/swift/pull/5424\n"
  },
  {
    "path": "Documentation/Overview.md",
    "content": "\n# Overview of GlueKit\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**\n\n- [Sources, Sinks and Connections](#sources-sinks-and-connections)\n- [Signals](#signals)\n- [Observables, Updatables and Variable](#observables-updatables-and-variable)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Sources, Sinks and Connections\n\nIn GlueKit, the `SourceType` protocol models a thing that you can subscribe to receive a stream of values. \n\n```Swift\nprotocol SourceType {\n    typealias Value\n    func subscribe(sink: Value->Void) -> Connection\n}\n```\n\nIt is not easy to work with associated types, so GlueKit generally uses the struct `Source<Value>` to represent sources. `Source<Value>` is a type-erased wrapper around some `SourceType` for the same type of value.\n\nFor example, you can create a source for the `NSCalendarDayChangedNotification` notification\nand run some code whenever midnight passes:\n\n```Swift\nlet center = NSNotificationCenter.defaultCenter()\nlet midnightSource = center.source(forName: NSCalendarDayChangedNotification)\n\nlet connection = midnightSource.subscribe { notification in \n    print(\"Ding dong!\") \n}\n```\n\nThe subscription (and the source) is kept alive until the connection object is deinitalized\nor until its `disconnect` method is called. Thus, active connections hold strong\nreferences to their source and sink---this is a general rule in GlueKit.\n\nThere is a `Connector` class that is a convenient place to store connections that you need to keep\nalive without creating a property for each individual connection:\n\n```Swift\nclass ClockViewController: UIViewController {\n    private connectionsWhileVisible = Connector()\n    \n    // TimerSource is a source that periodically broadcasts a Void value as long as it is connected.\n    private let tickSource = TimerSource(start: NSDate(), interval: 1.0)\n\n    private var midnightSource: Source<NSNotification> {\n        let center = NSNotificationCenter.defaultCenter()\n\t\treturn center.source(forName: NSCalendarDayChangedNotification)\n    }\n    \n    override func viewWillAppear() {\n        super.viewWillAppear()\n        tickSource.subscribe(self.onTick).putInto(connectionsWhileVisible)\n        midnightSource.subscribe { _ in self.onMidnight() }.putInto(connectionsWhileVisible)\n    }\n    \n    override func viewDidDisappear() {\n        super.viewDidDisappear()\n        connectionsWhileVisible.disconnect()\n    }\n    \n    func onTick() {\n        print(\"Tick!\")\n    }\n    \n    func onMidnight() {\n        print(\"Ding dong!\")\n    }\n}\n```\n\n## Signals\n\nThe `Signal` class lets you easily create your own sources. \nIt implements `SourceType`, keeps track of its connections, and provides a `send` method for you to send values to all its connected sinks:\n\n```Swift\nlet signal = Signal<Int>()\n\nsignal.send(42) // Does nothing, no subscribers\n\nlet connection = signal.subscribe { i in print(\"Got \\(i\\)!\") }\n\nsignal.send(23) // Prints \"Got 23!\"\nsignal.send(7)  // Prints \"Got 7!\"\n\nconnection.disconnect()\n```\n\nFor example, a button's implementation might have a Void-valued signal that triggers whenever the user\ntaps on it. In such cases, it's best to not let outside code send values to the signal, so the \n`Signal` instance is frequently stored in a private property and the class exposes only a \n\"read-only\" source view of it:\n\n```Swift\nclass Button: UIButton {\n    private let activationSignal: Signal<Void>()\n    public var activationSource: Source<Void> { return activationSignal.source }\n    \n\tinit() {\n\t    super.init(...)\n\t    addTarget(self, action: \"didTouchUpInside\", forControlEvents: UIControlEventTouchUpInside)\n\t}\n    \n    @objc func didTouchUpInside() {\n        activationSignal.send()\n    }\n}\n```\n\nThis is the way most sources are implemented in GlueKit.\n\n## Observables, Updatables and Variable\n\nA concrete implementation of this protocol is the generic class `Variable`, which directly holds such a value. \n\nLet's create a class with an observable property.\n\n```Swift\nclass Person {\n    let name: Variable<String>\n    init(name: String) { self.name.value = name }\n}\n\nlet fred = Person(name: \"Fred\")\n\n// The variable's value property let's you get Fred's name or update it:\nprint(fred.name.value)         \nfred.name.value = \"Freddie\"\n```\n\n`let foo: Variable<Type>` is the GlueKit equivalent to Cocoa's `dynamic var foo: Type`.\n\nOnce you have an observable value, you can start observing it:\n\n```Swift\n\nlet connection = fred.name.subscribe { name in print(\"Fred's name is \\(name)\") }\n```\n\nThis will immediately print `Fred's name is Fred` to the console, because by default variables \nsend their current values to each new observer. If you don't want this, you can subscribe to the\nvariable's `futureValues` property instead.\n\n"
  },
  {
    "path": "GlueKit.podspec",
    "content": "Pod::Spec.new do |spec|\n  spec.name         = 'GlueKit'\n  spec.version      = '0.2.0'\n  spec.ios.deployment_target = \"9.3\"\n  spec.osx.deployment_target = \"10.11\"\n  spec.tvos.deployment_target = \"10.0\"\n  spec.watchos.deployment_target = \"3.0\"\n  spec.summary      = 'Type-safe observable values and collections in Swift'\n  spec.author       = 'Károly Lőrentey'\n  spec.homepage     = 'https://github.com/attaswift/GlueKit'\n  spec.license      = { :type => 'MIT', :file => 'LICENSE.md' }\n  spec.source       = { :git => 'https://github.com/attaswift/GlueKit.git', :tag => 'v' + String(spec.version) }\n  spec.source_files = 'Sources/*.swift'\n  spec.social_media_url = 'https://twitter.com/lorentey'\n  #spec.documentation_url = 'http://lorentey.github.io/GlueKit/'\n  spec.dependency 'BTree', '~> 4.1'\n  spec.dependency 'SipHash', '~> 1.2'\nend\n"
  },
  {
    "path": "GlueKit.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\tBB015F2E1DC4F5BA00C8C05A /* ObservableSetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E411DABD4BE00E85FB9 /* ObservableSetTests.swift */; };\n\t\tBB015F2F1DC4F5C200C8C05A /* UpdatableArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B341C8FCC820050DDA9 /* UpdatableArray.swift */; };\n\t\tBB015F301DC4F64200C8C05A /* UpdatableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB89901A1D5F6AAE0097F350 /* UpdatableSet.swift */; };\n\t\tBB015F311DC4F90200C8C05A /* MockSetObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AF21DA6942700BC4B58 /* MockSetObserver.swift */; };\n\t\tBB015F321DC4FC3100C8C05A /* SetVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB89901F1D5F6F980097F350 /* SetVariable.swift */; };\n\t\tBB015F331DC4FC3700C8C05A /* ArrayVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B201C8FCC810050DDA9 /* ArrayVariable.swift */; };\n\t\tBB015F341DC4FDCE00C8C05A /* SetMappingBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF5B1DA55DA3005EC162 /* SetMappingBase.swift */; };\n\t\tBB015F351DC4FDD300C8C05A /* ObservableContains.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF400631DA108E900DA0B2C /* ObservableContains.swift */; };\n\t\tBB015F361DC5004F00C8C05A /* ValueMappingForSetField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E1D1DAAC7E600E85FB9 /* ValueMappingForSetField.swift */; };\n\t\tBB015F371DC506B400C8C05A /* ValueMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E131DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift */; };\n\t\tBB015F381DC508AC00C8C05A /* BufferedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A7FF1D6B2377001D2821 /* BufferedArray.swift */; };\n\t\tBB015F391DC509D000C8C05A /* SetMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF561DA55384005EC162 /* SetMappingForValue.swift */; };\n\t\tBB015F3A1DC50B1200C8C05A /* ArrayMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A83F1D6B9A7E001D2821 /* ArrayMappingForValue.swift */; };\n\t\tBB015F3B1DC50C6700C8C05A /* MockArrayObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AF61DA6A9EE00BC4B58 /* MockArrayObserver.swift */; };\n\t\tBB015F3C1DC5106B00C8C05A /* ArrayMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2D1C8FCC810050DDA9 /* ArrayMappingForValueField.swift */; };\n\t\tBB015F3D1DC512D600C8C05A /* ArrayMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04C71DA7233B00BE3051 /* ArrayMappingForArrayField.swift */; };\n\t\tBB015F3E1DC5147700C8C05A /* ArrayMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9F1C8FCE2C0050DDA9 /* ArrayMappingTests.swift */; };\n\t\tBB015F3F1DC51D8300C8C05A /* ArrayVariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B981C8FCE2C0050DDA9 /* ArrayVariableTests.swift */; };\n\t\tBB015F401DC5261900C8C05A /* ArrayFilteringIndexmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04E01DA7255D00BE3051 /* ArrayFilteringIndexmap.swift */; };\n\t\tBB015F411DC5262400C8C05A /* ArrayFilteringOnPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB82E3E01D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift */; };\n\t\tBB015F421DC526BF00C8C05A /* ArrayFilteringOnObservableBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04E51DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift */; };\n\t\tBB015F431DC5281F00C8C05A /* ArrayReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D929A1D64862D003BEDBF /* ArrayReference.swift */; };\n\t\tBB015F441DC529CF00C8C05A /* ArrayFilteringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC4AE4D1D9A829500FF7DE0 /* ArrayFilteringTests.swift */; };\n\t\tBB015F451DC52ADD00C8C05A /* ArrayFolding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DF81DAA885E00E85FB9 /* ArrayFolding.swift */; };\n\t\tBB015F461DC52B4500C8C05A /* ArrayFoldingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DFD1DAA8F7800E85FB9 /* ArrayFoldingTests.swift */; };\n\t\tBB015F471DC52B6200C8C05A /* ArrayConcatenation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A83A1D6B90F5001D2821 /* ArrayConcatenation.swift */; };\n\t\tBB015F481DC52CE200C8C05A /* ArrayConcatenationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E491DABFA2900E85FB9 /* ArrayConcatenationTests.swift */; };\n\t\tBB015F491DC52D3500C8C05A /* DistinctUnion.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF491DA409EE005EC162 /* DistinctUnion.swift */; };\n\t\tBB015F4A1DC52DC500C8C05A /* DistinctUnionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF4E1DA412A0005EC162 /* DistinctUnionTests.swift */; };\n\t\tBB015F4B1DC52FA000C8C05A /* ObservableArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E451DABEA5500E85FB9 /* ObservableArrayTests.swift */; };\n\t\tBB015F4C1DC6233E00C8C05A /* SetMappingForSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04D11DA7240C00BE3051 /* SetMappingForSequence.swift */; };\n\t\tBB015F4F1DC677A900C8C05A /* SetMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04CC1DA723F300BE3051 /* SetMappingForValueField.swift */; };\n\t\tBB015F501DC678C200C8C05A /* SetMappingForSetField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04D61DA7242F00BE3051 /* SetMappingForSetField.swift */; };\n\t\tBB015F511DC679F000C8C05A /* SetMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04DB1DA7244A00BE3051 /* SetMappingForArrayField.swift */; };\n\t\tBB015F531DC67A6400C8C05A /* SetVariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E4D1DABFE8800E85FB9 /* SetVariableTests.swift */; };\n\t\tBB015F541DC67ACA00C8C05A /* SetMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF611DA5654F005EC162 /* SetMappingTests.swift */; };\n\t\tBB015F551DC67C1000C8C05A /* SetFilteringOnPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B231C8FCC810050DDA9 /* SetFilteringOnPredicate.swift */; };\n\t\tBB015F561DC67C3F00C8C05A /* SetReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D92951D647E83003BEDBF /* SetReference.swift */; };\n\t\tBB015F571DC67DA900C8C05A /* SetFilteringOnObservableBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033561DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift */; };\n\t\tBB015F581DC67F0500C8C05A /* SetFilteringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AEE1DA693F700BC4B58 /* SetFilteringTests.swift */; };\n\t\tBB015F591DC684DC00C8C05A /* SetFoldingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E061DAA918400E85FB9 /* SetFoldingTests.swift */; };\n\t\tBB015F5A1DC684E200C8C05A /* SetFolding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E011DAA910500E85FB9 /* SetFolding.swift */; };\n\t\tBB015F5C1DC6868F00C8C05A /* SetSortingByMappingToComparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1E4D691D61EA5200F1831F /* SetSortingByMappingToComparable.swift */; };\n\t\tBB015F5D1DC686CD00C8C05A /* SetSortingByMappingToObservableComparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033601DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift */; };\n\t\tBB015F5E1DC687B100C8C05A /* SetSortingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB471D991DA57FF8002550B0 /* SetSortingTests.swift */; };\n\t\tBB015F5F1DC687EE00C8C05A /* SetSortingByComparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA0335B1DA7276200E83AC1 /* SetSortingByComparator.swift */; };\n\t\tBB015F601DC689F600C8C05A /* Bookshelf.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8D366D1DA116CB000D44C5 /* Bookshelf.swift */; };\n\t\tBB1657E71D71D65900094BAC /* ArrayChangeSeparation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1657E61D71D65900094BAC /* ArrayChangeSeparation.swift */; };\n\t\tBB1657E91D71D65900094BAC /* ArrayChangeSeparation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1657E61D71D65900094BAC /* ArrayChangeSeparation.swift */; };\n\t\tBB1657EA1D71D65900094BAC /* ArrayChangeSeparation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1657E61D71D65900094BAC /* ArrayChangeSeparation.swift */; };\n\t\tBB170F241DC1066D0000443E /* UpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F231DC1066D0000443E /* UpdateTests.swift */; };\n\t\tBB170F251DC1066D0000443E /* UpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F231DC1066D0000443E /* UpdateTests.swift */; };\n\t\tBB170F261DC1066D0000443E /* UpdateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F231DC1066D0000443E /* UpdateTests.swift */; };\n\t\tBB170F281DC106DE0000443E /* TestChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F271DC106DE0000443E /* TestChange.swift */; };\n\t\tBB170F291DC106DE0000443E /* TestChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F271DC106DE0000443E /* TestChange.swift */; };\n\t\tBB170F2A1DC106DE0000443E /* TestChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F271DC106DE0000443E /* TestChange.swift */; };\n\t\tBB170F2C1DC10D350000443E /* TestObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F2B1DC10D350000443E /* TestObservable.swift */; };\n\t\tBB170F2D1DC10D350000443E /* TestObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F2B1DC10D350000443E /* TestObservable.swift */; };\n\t\tBB170F2E1DC10D350000443E /* TestObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F2B1DC10D350000443E /* TestObservable.swift */; };\n\t\tBB170F301DC10DDB0000443E /* ChangesSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F2F1DC10DDB0000443E /* ChangesSourceTests.swift */; };\n\t\tBB170F311DC10DDB0000443E /* ChangesSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F2F1DC10DDB0000443E /* ChangesSourceTests.swift */; };\n\t\tBB170F321DC10DDB0000443E /* ChangesSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F2F1DC10DDB0000443E /* ChangesSourceTests.swift */; };\n\t\tBB170F341DC110BD0000443E /* TestUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F331DC110BD0000443E /* TestUpdatable.swift */; };\n\t\tBB170F351DC110BD0000443E /* TestUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F331DC110BD0000443E /* TestUpdatable.swift */; };\n\t\tBB170F361DC110BD0000443E /* TestUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F331DC110BD0000443E /* TestUpdatable.swift */; };\n\t\tBB170F381DC1545E0000443E /* TransactionStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F371DC1545E0000443E /* TransactionStateTests.swift */; };\n\t\tBB170F391DC1545E0000443E /* TransactionStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F371DC1545E0000443E /* TransactionStateTests.swift */; };\n\t\tBB170F3A1DC1545E0000443E /* TransactionStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F371DC1545E0000443E /* TransactionStateTests.swift */; };\n\t\tBB170F3B1DC220A80000443E /* MockUpdateSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E0A1DAAB6E700E85FB9 /* MockUpdateSink.swift */; };\n\t\tBB170F3C1DC220B20000443E /* ObservableValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9D1C8FCE2C0050DDA9 /* ObservableValueTests.swift */; };\n\t\tBB170F3E1DC221180000443E /* ValueChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F3D1DC221180000443E /* ValueChangeTests.swift */; };\n\t\tBB170F3F1DC221180000443E /* ValueChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F3D1DC221180000443E /* ValueChangeTests.swift */; };\n\t\tBB170F401DC221180000443E /* ValueChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F3D1DC221180000443E /* ValueChangeTests.swift */; };\n\t\tBB170F421DC22A300000443E /* UpdatableValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F411DC22A300000443E /* UpdatableValueTests.swift */; };\n\t\tBB170F431DC22A300000443E /* UpdatableValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F411DC22A300000443E /* UpdatableValueTests.swift */; };\n\t\tBB170F441DC22A300000443E /* UpdatableValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB170F411DC22A300000443E /* UpdatableValueTests.swift */; };\n\t\tBB170F451DC239BC0000443E /* DistinctTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9E1C8FCE2C0050DDA9 /* DistinctTests.swift */; };\n\t\tBB170F461DC255200000443E /* TwoWayBindingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA61C8FCE2C0050DDA9 /* TwoWayBindingTests.swift */; };\n\t\tBB23E63D1C90DEB6005EFD0A /* GlueKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB55AB21C8F80020050DDA9 /* GlueKit.framework */; };\n\t\tBB318F6B1CB992300086EE83 /* UIBarButtonItem Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB318F6A1CB9922F0086EE83 /* UIBarButtonItem Extensions.swift */; };\n\t\tBB351B011DB81E67005F083F /* GlueKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB55AD41C8F88F20050DDA9 /* GlueKit.framework */; };\n\t\tBB351B071DB81EE1005F083F /* GlueKitPerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BEA1C8FD25F0050DDA9 /* GlueKitPerformanceTests.swift */; };\n\t\tBB3982ED1EC109C4000CDCB5 /* UISearchBar Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3982EC1EC109C4000CDCB5 /* UISearchBar Glue.swift */; };\n\t\tBB3982EE1EC109C7000CDCB5 /* UISearchBar Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3982EC1EC109C4000CDCB5 /* UISearchBar Glue.swift */; };\n\t\tBB3982EF1EC109C8000CDCB5 /* UISearchBar Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3982EC1EC109C4000CDCB5 /* UISearchBar Glue.swift */; };\n\t\tBB3982F01EC109C8000CDCB5 /* UISearchBar Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3982EC1EC109C4000CDCB5 /* UISearchBar Glue.swift */; };\n\t\tBB3D12B21E49FC5A00097510 /* BTree.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB3D12B11E49FC5A00097510 /* BTree.framework */; };\n\t\tBB3D12B41E49FC5E00097510 /* SipHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB3D12B31E49FC5E00097510 /* SipHash.framework */; };\n\t\tBB3D12B71E49FC7600097510 /* BTree.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB3D12B51E49FC7600097510 /* BTree.framework */; };\n\t\tBB3D12B81E49FC7600097510 /* SipHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB3D12B61E49FC7600097510 /* SipHash.framework */; };\n\t\tBB3D12BB1E49FC8000097510 /* BTree.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB3D12B91E49FC8000097510 /* BTree.framework */; };\n\t\tBB3D12BC1E49FC8000097510 /* SipHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB3D12BA1E49FC8000097510 /* SipHash.framework */; };\n\t\tBB3D12BF1E49FC8700097510 /* BTree.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB3D12BD1E49FC8700097510 /* BTree.framework */; };\n\t\tBB3D12C01E49FC8700097510 /* SipHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB3D12BE1E49FC8700097510 /* SipHash.framework */; };\n\t\tBB3D12C11E49FD1700097510 /* GlueKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB55AD41C8F88F20050DDA9 /* GlueKit.framework */; };\n\t\tBB4052021C958712003D8F5B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB4052011C958712003D8F5B /* UIKit.framework */; };\n\t\tBB471D9A1DA57FF8002550B0 /* SetSortingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB471D991DA57FF8002550B0 /* SetSortingTests.swift */; };\n\t\tBB471D9C1DA57FF8002550B0 /* SetSortingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB471D991DA57FF8002550B0 /* SetSortingTests.swift */; };\n\t\tBB568AEF1DA693F700BC4B58 /* SetFilteringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AEE1DA693F700BC4B58 /* SetFilteringTests.swift */; };\n\t\tBB568AF11DA693F700BC4B58 /* SetFilteringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AEE1DA693F700BC4B58 /* SetFilteringTests.swift */; };\n\t\tBB568AF31DA6942700BC4B58 /* MockSetObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AF21DA6942700BC4B58 /* MockSetObserver.swift */; };\n\t\tBB568AF51DA6942700BC4B58 /* MockSetObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AF21DA6942700BC4B58 /* MockSetObserver.swift */; };\n\t\tBB568AF91DA6A9EE00BC4B58 /* MockArrayObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AF61DA6A9EE00BC4B58 /* MockArrayObserver.swift */; };\n\t\tBB5B02DB1F5E3FC50084D86B /* ArrayGatheringSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B02DA1F5E3FC50084D86B /* ArrayGatheringSource.swift */; };\n\t\tBB5B02DC1F5E3FC50084D86B /* ArrayGatheringSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B02DA1F5E3FC50084D86B /* ArrayGatheringSource.swift */; };\n\t\tBB5B02DD1F5E3FC50084D86B /* ArrayGatheringSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B02DA1F5E3FC50084D86B /* ArrayGatheringSource.swift */; };\n\t\tBB5B02DE1F5E3FC50084D86B /* ArrayGatheringSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B02DA1F5E3FC50084D86B /* ArrayGatheringSource.swift */; };\n\t\tBB5B02E01F5E3FDE0084D86B /* SetGatheringSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B02DF1F5E3FDE0084D86B /* SetGatheringSource.swift */; };\n\t\tBB5B02E11F5E3FDE0084D86B /* SetGatheringSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B02DF1F5E3FDE0084D86B /* SetGatheringSource.swift */; };\n\t\tBB5B02E21F5E3FDE0084D86B /* SetGatheringSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B02DF1F5E3FDE0084D86B /* SetGatheringSource.swift */; };\n\t\tBB5B02E31F5E3FDE0084D86B /* SetGatheringSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5B02DF1F5E3FDE0084D86B /* SetGatheringSource.swift */; };\n\t\tBB6139831F5E1B3F005455D5 /* NSTextField Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6139821F5E1B3F005455D5 /* NSTextField Glue.swift */; };\n\t\tBB67E5521C9B6A63002B0AB5 /* CADisplayLink Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB67E5511C9B6A63002B0AB5 /* CADisplayLink Extensions.swift */; };\n\t\tBB67E5531C9B6A63002B0AB5 /* CADisplayLink Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB67E5511C9B6A63002B0AB5 /* CADisplayLink Extensions.swift */; };\n\t\tBB69A7EF1D6AFF1A001D2821 /* Abstract.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A7EE1D6AFF1A001D2821 /* Abstract.swift */; };\n\t\tBB69A7F01D6AFF1A001D2821 /* Abstract.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A7EE1D6AFF1A001D2821 /* Abstract.swift */; };\n\t\tBB69A7F11D6AFF1A001D2821 /* Abstract.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A7EE1D6AFF1A001D2821 /* Abstract.swift */; };\n\t\tBB69A7F21D6AFF1A001D2821 /* Abstract.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A7EE1D6AFF1A001D2821 /* Abstract.swift */; };\n\t\tBB69A7F31D6B1D7B001D2821 /* Change.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990041D5DF8630097F350 /* Change.swift */; };\n\t\tBB69A7F51D6B1D7C001D2821 /* Change.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990041D5DF8630097F350 /* Change.swift */; };\n\t\tBB69A7F61D6B1D7C001D2821 /* Change.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990041D5DF8630097F350 /* Change.swift */; };\n\t\tBB69A7F71D6B1D82001D2821 /* ArrayChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B1F1C8FCC810050DDA9 /* ArrayChange.swift */; };\n\t\tBB69A7F91D6B1D83001D2821 /* ArrayChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B1F1C8FCC810050DDA9 /* ArrayChange.swift */; };\n\t\tBB69A7FA1D6B1D83001D2821 /* ArrayChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B1F1C8FCC810050DDA9 /* ArrayChange.swift */; };\n\t\tBB69A7FB1D6B1D94001D2821 /* ObservableArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2A1C8FCC810050DDA9 /* ObservableArray.swift */; };\n\t\tBB69A7FD1D6B1D95001D2821 /* ObservableArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2A1C8FCC810050DDA9 /* ObservableArray.swift */; };\n\t\tBB69A7FE1D6B1D95001D2821 /* ObservableArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2A1C8FCC810050DDA9 /* ObservableArray.swift */; };\n\t\tBB69A8001D6B2377001D2821 /* BufferedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A7FF1D6B2377001D2821 /* BufferedArray.swift */; };\n\t\tBB69A8021D6B2377001D2821 /* BufferedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A7FF1D6B2377001D2821 /* BufferedArray.swift */; };\n\t\tBB69A8031D6B2377001D2821 /* BufferedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A7FF1D6B2377001D2821 /* BufferedArray.swift */; };\n\t\tBB69A8041D6B344C001D2821 /* UpdatableArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B341C8FCC820050DDA9 /* UpdatableArray.swift */; };\n\t\tBB69A8061D6B344D001D2821 /* UpdatableArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B341C8FCC820050DDA9 /* UpdatableArray.swift */; };\n\t\tBB69A8071D6B344E001D2821 /* UpdatableArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B341C8FCC820050DDA9 /* UpdatableArray.swift */; };\n\t\tBB69A8081D6B442B001D2821 /* ArrayVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B201C8FCC810050DDA9 /* ArrayVariable.swift */; };\n\t\tBB69A80A1D6B442C001D2821 /* ArrayVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B201C8FCC810050DDA9 /* ArrayVariable.swift */; };\n\t\tBB69A80B1D6B442D001D2821 /* ArrayVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B201C8FCC810050DDA9 /* ArrayVariable.swift */; };\n\t\tBB69A80C1D6B472D001D2821 /* ArrayMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2D1C8FCC810050DDA9 /* ArrayMappingForValueField.swift */; };\n\t\tBB69A80E1D6B472F001D2821 /* ArrayMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2D1C8FCC810050DDA9 /* ArrayMappingForValueField.swift */; };\n\t\tBB69A80F1D6B472F001D2821 /* ArrayMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2D1C8FCC810050DDA9 /* ArrayMappingForValueField.swift */; };\n\t\tBB69A8101D6B5397001D2821 /* ValueMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2C1C8FCC810050DDA9 /* ValueMappingForValueField.swift */; };\n\t\tBB69A8131D6B539A001D2821 /* ValueMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2C1C8FCC810050DDA9 /* ValueMappingForValueField.swift */; };\n\t\tBB69A8141D6B539A001D2821 /* ValueMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2C1C8FCC810050DDA9 /* ValueMappingForValueField.swift */; };\n\t\tBB69A8191D6B6A99001D2821 /* ArrayReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D929A1D64862D003BEDBF /* ArrayReference.swift */; };\n\t\tBB69A81B1D6B6A9A001D2821 /* ArrayReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D929A1D64862D003BEDBF /* ArrayReference.swift */; };\n\t\tBB69A81C1D6B6A9B001D2821 /* ArrayReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D929A1D64862D003BEDBF /* ArrayReference.swift */; };\n\t\tBB69A81D1D6B71F9001D2821 /* SetChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990021D5DF2D20097F350 /* SetChange.swift */; };\n\t\tBB69A81F1D6B71FA001D2821 /* SetChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990021D5DF2D20097F350 /* SetChange.swift */; };\n\t\tBB69A8201D6B71FB001D2821 /* SetChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990021D5DF2D20097F350 /* SetChange.swift */; };\n\t\tBB69A8231D6B7203001D2821 /* ObservableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990091D5DF88C0097F350 /* ObservableSet.swift */; };\n\t\tBB69A8241D6B7203001D2821 /* ObservableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990091D5DF88C0097F350 /* ObservableSet.swift */; };\n\t\tBB69A8281D6B779A001D2821 /* UpdatableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB89901A1D5F6AAE0097F350 /* UpdatableSet.swift */; };\n\t\tBB69A8291D6B779B001D2821 /* UpdatableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB89901A1D5F6AAE0097F350 /* UpdatableSet.swift */; };\n\t\tBB69A82C1D6B7CAE001D2821 /* SetVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB89901F1D5F6F980097F350 /* SetVariable.swift */; };\n\t\tBB69A82D1D6B7CAF001D2821 /* SetVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB89901F1D5F6F980097F350 /* SetVariable.swift */; };\n\t\tBB69A8301D6B7E36001D2821 /* SetSortingByMappingToComparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1E4D691D61EA5200F1831F /* SetSortingByMappingToComparable.swift */; };\n\t\tBB69A8311D6B7E37001D2821 /* SetSortingByMappingToComparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1E4D691D61EA5200F1831F /* SetSortingByMappingToComparable.swift */; };\n\t\tBB69A8341D6B7F12001D2821 /* SetReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D92951D647E83003BEDBF /* SetReference.swift */; };\n\t\tBB69A8351D6B7F12001D2821 /* SetReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D92951D647E83003BEDBF /* SetReference.swift */; };\n\t\tBB69A8381D6B7F9D001D2821 /* SetFilteringOnPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B231C8FCC810050DDA9 /* SetFilteringOnPredicate.swift */; };\n\t\tBB69A8391D6B7F9E001D2821 /* SetFilteringOnPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B231C8FCC810050DDA9 /* SetFilteringOnPredicate.swift */; };\n\t\tBB69A83B1D6B90F5001D2821 /* ArrayConcatenation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A83A1D6B90F5001D2821 /* ArrayConcatenation.swift */; };\n\t\tBB69A83D1D6B90F5001D2821 /* ArrayConcatenation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A83A1D6B90F5001D2821 /* ArrayConcatenation.swift */; };\n\t\tBB69A83E1D6B90F5001D2821 /* ArrayConcatenation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A83A1D6B90F5001D2821 /* ArrayConcatenation.swift */; };\n\t\tBB69A8401D6B9A7E001D2821 /* ArrayMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A83F1D6B9A7E001D2821 /* ArrayMappingForValue.swift */; };\n\t\tBB69A8421D6B9A7E001D2821 /* ArrayMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A83F1D6B9A7E001D2821 /* ArrayMappingForValue.swift */; };\n\t\tBB69A8431D6B9A7E001D2821 /* ArrayMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB69A83F1D6B9A7E001D2821 /* ArrayMappingForValue.swift */; };\n\t\tBB6CE3B41DC4C21C00295C55 /* TransformedSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6CE3B31DC4C21C00295C55 /* TransformedSink.swift */; };\n\t\tBB6CE3B51DC4C21C00295C55 /* TransformedSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6CE3B31DC4C21C00295C55 /* TransformedSink.swift */; };\n\t\tBB6CE3B61DC4C21C00295C55 /* TransformedSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6CE3B31DC4C21C00295C55 /* TransformedSink.swift */; };\n\t\tBB6CE3B71DC4C21C00295C55 /* TransformedSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB6CE3B31DC4C21C00295C55 /* TransformedSink.swift */; };\n\t\tBB6CE3B81DC4CD3900295C55 /* Change.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990041D5DF8630097F350 /* Change.swift */; };\n\t\tBB6CE3B91DC4CD3B00295C55 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAC91DC0F0A5000B3DD0 /* Update.swift */; };\n\t\tBB6CE3BA1DC4CD3F00295C55 /* ObservableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF3F1DA3A88C005EC162 /* ObservableType.swift */; };\n\t\tBB6CE3BB1DC4CD4800295C55 /* ChangesSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73E51DBB727300E20D67 /* ChangesSource.swift */; };\n\t\tBB6CE3BC1DC4CD6500295C55 /* TransactionalThing.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73DF1DBB61C100E20D67 /* TransactionalThing.swift */; };\n\t\tBB6CE3BD1DC4CD6900295C55 /* ValueChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF441DA3A908005EC162 /* ValueChange.swift */; };\n\t\tBB6CE3BE1DC4CD6B00295C55 /* ObservableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B291C8FCC810050DDA9 /* ObservableValue.swift */; };\n\t\tBB6CE3BF1DC4CD6F00295C55 /* UpdatableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B331C8FCC820050DDA9 /* UpdatableValue.swift */; };\n\t\tBB6CE3C01DC4CD7200295C55 /* TwoWayBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73EE1DBDFEE400E20D67 /* TwoWayBinding.swift */; };\n\t\tBB6CE3C11DC4CD7600295C55 /* Variable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B351C8FCC820050DDA9 /* Variable.swift */; };\n\t\tBB6CE3C21DC4CD7A00295C55 /* BufferedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B281C8FCC810050DDA9 /* BufferedValue.swift */; };\n\t\tBB6CE3C31DC4CD7E00295C55 /* DistinctValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E271DAAD2B900E85FB9 /* DistinctValue.swift */; };\n\t\tBB6CE3C41DC4CD8300295C55 /* CompositeObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E221DAAD26200E85FB9 /* CompositeObservable.swift */; };\n\t\tBB6CE3C51DC4CD8700295C55 /* CompositeUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E2C1DAAD4BC00E85FB9 /* CompositeUpdatable.swift */; };\n\t\tBB6CE3C61DC4CD8D00295C55 /* ValueMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E0E1DAAC33700E85FB9 /* ValueMappingForValue.swift */; };\n\t\tBB6CE3C71DC4D09500295C55 /* ValueMappingForSourceField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E181DAAC50900E85FB9 /* ValueMappingForSourceField.swift */; };\n\t\tBB6CE3C81DC4D2D400295C55 /* ValueMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2C1C8FCC810050DDA9 /* ValueMappingForValueField.swift */; };\n\t\tBB6CE3CA1DC4DF4400295C55 /* CombinedObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E311DAAD66500E85FB9 /* CombinedObservableTests.swift */; };\n\t\tBB6CE3CB1DC4DF4800295C55 /* CombinedUpdatableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E351DAAD74600E85FB9 /* CombinedUpdatableTests.swift */; };\n\t\tBB6CE3CC1DC4E48200295C55 /* TypeHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E391DABC45000E85FB9 /* TypeHelperTests.swift */; };\n\t\tBB6CE3CE1DC4E4B100295C55 /* Type Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBAA827C1C91D43700586903 /* Type Helpers.swift */; };\n\t\tBB6CE3D01DC4E67700295C55 /* TimerSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA51C8FCE2C0050DDA9 /* TimerSourceTests.swift */; };\n\t\tBB6CE3D11DC4E72100295C55 /* KVOSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9A1C8FCE2C0050DDA9 /* KVOSupportTests.swift */; };\n\t\tBB6CE3D21DC4E73600295C55 /* NotificationCenterSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9C1C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift */; };\n\t\tBB6CE3D31DC4E79400295C55 /* ValueMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA01C8FCE2C0050DDA9 /* ValueMappingTests.swift */; };\n\t\tBB6CE3D41DC4F17700295C55 /* ArrayChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B1F1C8FCC810050DDA9 /* ArrayChange.swift */; };\n\t\tBB6CE3D51DC4F17A00295C55 /* ArrayChangeSeparation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1657E61D71D65900094BAC /* ArrayChangeSeparation.swift */; };\n\t\tBB6CE3D61DC4F18B00295C55 /* ArrayModificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033651DA7CFFE00E83AC1 /* ArrayModificationTests.swift */; };\n\t\tBB6CE3D71DC4F18B00295C55 /* ArrayChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033691DA7D03300E83AC1 /* ArrayChangeTests.swift */; };\n\t\tBB6CE3D81DC4F18B00295C55 /* ArrayChangeSeparationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC36AE61DA83E0E00AB3E9D /* ArrayChangeSeparationTests.swift */; };\n\t\tBB6CE3D91DC4F19D00295C55 /* ObservableArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2A1C8FCC810050DDA9 /* ObservableArray.swift */; };\n\t\tBB6CE3DA1DC4F2FB00295C55 /* SetChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990021D5DF2D20097F350 /* SetChange.swift */; };\n\t\tBB6CE3DB1DC4F2FB00295C55 /* ObservableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990091D5DF88C0097F350 /* ObservableSet.swift */; };\n\t\tBB7E04C81DA7233B00BE3051 /* ArrayMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04C71DA7233B00BE3051 /* ArrayMappingForArrayField.swift */; };\n\t\tBB7E04CA1DA7233B00BE3051 /* ArrayMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04C71DA7233B00BE3051 /* ArrayMappingForArrayField.swift */; };\n\t\tBB7E04CB1DA7233B00BE3051 /* ArrayMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04C71DA7233B00BE3051 /* ArrayMappingForArrayField.swift */; };\n\t\tBB7E04CF1DA723F300BE3051 /* SetMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04CC1DA723F300BE3051 /* SetMappingForValueField.swift */; };\n\t\tBB7E04D01DA723F300BE3051 /* SetMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04CC1DA723F300BE3051 /* SetMappingForValueField.swift */; };\n\t\tBB7E04D41DA7240C00BE3051 /* SetMappingForSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04D11DA7240C00BE3051 /* SetMappingForSequence.swift */; };\n\t\tBB7E04D51DA7240C00BE3051 /* SetMappingForSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04D11DA7240C00BE3051 /* SetMappingForSequence.swift */; };\n\t\tBB7E04D91DA7242F00BE3051 /* SetMappingForSetField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04D61DA7242F00BE3051 /* SetMappingForSetField.swift */; };\n\t\tBB7E04DA1DA7242F00BE3051 /* SetMappingForSetField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04D61DA7242F00BE3051 /* SetMappingForSetField.swift */; };\n\t\tBB7E04DE1DA7244A00BE3051 /* SetMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04DB1DA7244A00BE3051 /* SetMappingForArrayField.swift */; };\n\t\tBB7E04DF1DA7244A00BE3051 /* SetMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04DB1DA7244A00BE3051 /* SetMappingForArrayField.swift */; };\n\t\tBB7E04E11DA7255D00BE3051 /* ArrayFilteringIndexmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04E01DA7255D00BE3051 /* ArrayFilteringIndexmap.swift */; };\n\t\tBB7E04E31DA7255D00BE3051 /* ArrayFilteringIndexmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04E01DA7255D00BE3051 /* ArrayFilteringIndexmap.swift */; };\n\t\tBB7E04E41DA7255D00BE3051 /* ArrayFilteringIndexmap.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04E01DA7255D00BE3051 /* ArrayFilteringIndexmap.swift */; };\n\t\tBB7E04E61DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04E51DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift */; };\n\t\tBB7E04E81DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04E51DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift */; };\n\t\tBB7E04E91DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04E51DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift */; };\n\t\tBB8195B21DD256B700644668 /* UIControl Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC3C84D1C93164200E10D59 /* UIControl Glue.swift */; };\n\t\tBB8195B31DD256B700644668 /* UIBarButtonItem Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB318F6A1CB9922F0086EE83 /* UIBarButtonItem Extensions.swift */; };\n\t\tBB8195B41DD256B700644668 /* UIDevice Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB4F2511C9594A9002532CC /* UIDevice Glue.swift */; };\n\t\tBB8195B51DD256B700644668 /* UIGestureRecognizer Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB4F26E1C99E6CB002532CC /* UIGestureRecognizer Glue.swift */; };\n\t\tBB8195B61DD256B700644668 /* CADisplayLink Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB67E5511C9B6A63002B0AB5 /* CADisplayLink Extensions.swift */; };\n\t\tBB8195B71DD256B800644668 /* UIControl Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC3C84D1C93164200E10D59 /* UIControl Glue.swift */; };\n\t\tBB8195B81DD256B800644668 /* UIBarButtonItem Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB318F6A1CB9922F0086EE83 /* UIBarButtonItem Extensions.swift */; };\n\t\tBB8195B91DD256B800644668 /* UIDevice Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB4F2511C9594A9002532CC /* UIDevice Glue.swift */; };\n\t\tBB8195BA1DD256B800644668 /* UIGestureRecognizer Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB4F26E1C99E6CB002532CC /* UIGestureRecognizer Glue.swift */; };\n\t\tBB8195BB1DD256B800644668 /* CADisplayLink Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB67E5511C9B6A63002B0AB5 /* CADisplayLink Extensions.swift */; };\n\t\tBB8195BC1DD256B900644668 /* UIControl Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC3C84D1C93164200E10D59 /* UIControl Glue.swift */; };\n\t\tBB8195BD1DD256B900644668 /* UIBarButtonItem Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB318F6A1CB9922F0086EE83 /* UIBarButtonItem Extensions.swift */; };\n\t\tBB8195BE1DD256B900644668 /* UIDevice Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB4F2511C9594A9002532CC /* UIDevice Glue.swift */; };\n\t\tBB8195BF1DD256B900644668 /* UIGestureRecognizer Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB4F26E1C99E6CB002532CC /* UIGestureRecognizer Glue.swift */; };\n\t\tBB8195C01DD257A300644668 /* ConnectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E511DAC1B1300E85FB9 /* ConnectorTests.swift */; };\n\t\tBB82E3E11D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB82E3E01D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift */; };\n\t\tBB82E3E31D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB82E3E01D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift */; };\n\t\tBB82E3E41D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB82E3E01D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift */; };\n\t\tBB88C40E1DC3A08B00C7EC3C /* ObservableTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB88C40D1DC3A08B00C7EC3C /* ObservableTypeTests.swift */; };\n\t\tBB88C40F1DC3A08B00C7EC3C /* ObservableTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB88C40D1DC3A08B00C7EC3C /* ObservableTypeTests.swift */; };\n\t\tBB88C4101DC3A08B00C7EC3C /* ObservableTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB88C40D1DC3A08B00C7EC3C /* ObservableTypeTests.swift */; };\n\t\tBB88C4111DC3A84C00C7EC3C /* VariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA71C8FCE2C0050DDA9 /* VariableTests.swift */; };\n\t\tBB88C4131DC3B65F00C7EC3C /* ValueBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB88C4121DC3B65F00C7EC3C /* ValueBufferingTests.swift */; };\n\t\tBB88C4141DC3B65F00C7EC3C /* ValueBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB88C4121DC3B65F00C7EC3C /* ValueBufferingTests.swift */; };\n\t\tBB88C4151DC3B65F00C7EC3C /* ValueBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB88C4121DC3B65F00C7EC3C /* ValueBufferingTests.swift */; };\n\t\tBB8990271D5F84150097F350 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB8990251D5F84050097F350 /* Foundation.framework */; };\n\t\tBB8990291D5F84210097F350 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB8990281D5F84210097F350 /* Foundation.framework */; };\n\t\tBB89902B1D5F842C0097F350 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB89902A1D5F842C0097F350 /* Foundation.framework */; };\n\t\tBB89902D1D5F84340097F350 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB89902C1D5F84340097F350 /* Foundation.framework */; };\n\t\tBB8D366E1DA116CB000D44C5 /* Bookshelf.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8D366D1DA116CB000D44C5 /* Bookshelf.swift */; };\n\t\tBB8D36701DA116CB000D44C5 /* Bookshelf.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8D366D1DA116CB000D44C5 /* Bookshelf.swift */; };\n\t\tBB948BBC1DD5EFC900B0734C /* ComputedUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB948BBB1DD5EFC900B0734C /* ComputedUpdatable.swift */; };\n\t\tBB948BBD1DD5EFC900B0734C /* ComputedUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB948BBB1DD5EFC900B0734C /* ComputedUpdatable.swift */; };\n\t\tBB948BBE1DD5EFC900B0734C /* ComputedUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB948BBB1DD5EFC900B0734C /* ComputedUpdatable.swift */; };\n\t\tBB948BBF1DD5EFC900B0734C /* ComputedUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB948BBB1DD5EFC900B0734C /* ComputedUpdatable.swift */; };\n\t\tBB948BC11DD720FE00B0734C /* UISwitch Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB948BC01DD720FE00B0734C /* UISwitch Glue.swift */; };\n\t\tBB948BC21DD7213200B0734C /* UISwitch Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB948BC01DD720FE00B0734C /* UISwitch Glue.swift */; };\n\t\tBB948BC31DD7213200B0734C /* UISwitch Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB948BC01DD720FE00B0734C /* UISwitch Glue.swift */; };\n\t\tBB948BC41DD7213300B0734C /* UISwitch Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB948BC01DD720FE00B0734C /* UISwitch Glue.swift */; };\n\t\tBB9D73C91DBB2EB400E20D67 /* Connect.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73C81DBB2EB400E20D67 /* Connect.swift */; };\n\t\tBB9D73CA1DBB2EB400E20D67 /* Connect.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73C81DBB2EB400E20D67 /* Connect.swift */; };\n\t\tBB9D73CB1DBB2EB400E20D67 /* Connect.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73C81DBB2EB400E20D67 /* Connect.swift */; };\n\t\tBB9D73CC1DBB2EB400E20D67 /* Connect.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73C81DBB2EB400E20D67 /* Connect.swift */; };\n\t\tBB9D73CF1DBB38F900E20D67 /* Sink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73CE1DBB38F900E20D67 /* Sink.swift */; };\n\t\tBB9D73D01DBB38F900E20D67 /* Sink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73CE1DBB38F900E20D67 /* Sink.swift */; };\n\t\tBB9D73D11DBB38F900E20D67 /* Sink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73CE1DBB38F900E20D67 /* Sink.swift */; };\n\t\tBB9D73D21DBB38F900E20D67 /* Sink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73CE1DBB38F900E20D67 /* Sink.swift */; };\n\t\tBB9D73D31DBB3DEA00E20D67 /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2E1C8FCC810050DDA9 /* Signal.swift */; };\n\t\tBB9D73D41DBB4A3700E20D67 /* SimpleSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2F1C8FCC810050DDA9 /* SimpleSources.swift */; };\n\t\tBB9D73D51DBB4BB300E20D67 /* MergedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B261C8FCC810050DDA9 /* MergedSource.swift */; };\n\t\tBB9D73D61DBB519500E20D67 /* TransformedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B311C8FCC810050DDA9 /* TransformedSource.swift */; };\n\t\tBB9D73DC1DBB612600E20D67 /* Connector.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B221C8FCC810050DDA9 /* Connector.swift */; };\n\t\tBB9D73E01DBB61C100E20D67 /* TransactionalThing.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73DF1DBB61C100E20D67 /* TransactionalThing.swift */; };\n\t\tBB9D73E21DBB61C100E20D67 /* TransactionalThing.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73DF1DBB61C100E20D67 /* TransactionalThing.swift */; };\n\t\tBB9D73E31DBB61C100E20D67 /* TransactionalThing.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73DF1DBB61C100E20D67 /* TransactionalThing.swift */; };\n\t\tBB9D73E61DBB727300E20D67 /* ChangesSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73E51DBB727300E20D67 /* ChangesSource.swift */; };\n\t\tBB9D73E81DBB727300E20D67 /* ChangesSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73E51DBB727300E20D67 /* ChangesSource.swift */; };\n\t\tBB9D73E91DBB727300E20D67 /* ChangesSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73E51DBB727300E20D67 /* ChangesSource.swift */; };\n\t\tBB9D73EF1DBDFEE400E20D67 /* TwoWayBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73EE1DBDFEE400E20D67 /* TwoWayBinding.swift */; };\n\t\tBB9D73F11DBDFEE400E20D67 /* TwoWayBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73EE1DBDFEE400E20D67 /* TwoWayBinding.swift */; };\n\t\tBB9D73F21DBDFEE400E20D67 /* TwoWayBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73EE1DBDFEE400E20D67 /* TwoWayBinding.swift */; };\n\t\tBB9D73F41DBE03EB00E20D67 /* DispatchSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73F31DBE03EB00E20D67 /* DispatchSource.swift */; };\n\t\tBB9D73F51DBE03EB00E20D67 /* DispatchSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73F31DBE03EB00E20D67 /* DispatchSource.swift */; };\n\t\tBB9D73F61DBE03EB00E20D67 /* DispatchSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73F31DBE03EB00E20D67 /* DispatchSource.swift */; };\n\t\tBB9D73F71DBE03EB00E20D67 /* DispatchSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73F31DBE03EB00E20D67 /* DispatchSource.swift */; };\n\t\tBB9D73F81DBE041A00E20D67 /* TimerSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B321C8FCC820050DDA9 /* TimerSource.swift */; };\n\t\tBB9D73FE1DBE061D00E20D67 /* OwnedSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73FD1DBE061D00E20D67 /* OwnedSink.swift */; };\n\t\tBB9D73FF1DBE061D00E20D67 /* OwnedSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73FD1DBE061D00E20D67 /* OwnedSink.swift */; };\n\t\tBB9D74001DBE061D00E20D67 /* OwnedSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73FD1DBE061D00E20D67 /* OwnedSink.swift */; };\n\t\tBB9D74011DBE061D00E20D67 /* OwnedSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9D73FD1DBE061D00E20D67 /* OwnedSink.swift */; };\n\t\tBB9D741E1DBE644200E20D67 /* NSNotificationCenter Support.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B271C8FCC810050DDA9 /* NSNotificationCenter Support.swift */; };\n\t\tBB9D74201DBE654600E20D67 /* NSObject Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC2A8281CBC14C600394D24 /* NSObject Glue.swift */; };\n\t\tBB9D74241DBE7B3700E20D67 /* ObservableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB8990091D5DF88C0097F350 /* ObservableSet.swift */; };\n\t\tBB9D74261DBE7B3B00E20D67 /* UpdatableSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB89901A1D5F6AAE0097F350 /* UpdatableSet.swift */; };\n\t\tBB9D74271DBE7B3B00E20D67 /* SetVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB89901F1D5F6F980097F350 /* SetVariable.swift */; };\n\t\tBB9D74281DBE7B3B00E20D67 /* ObservableContains.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF400631DA108E900DA0B2C /* ObservableContains.swift */; };\n\t\tBB9D74291DBE7B3B00E20D67 /* SetMappingBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF5B1DA55DA3005EC162 /* SetMappingBase.swift */; };\n\t\tBB9D742A1DBE7B3B00E20D67 /* SetMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF561DA55384005EC162 /* SetMappingForValue.swift */; };\n\t\tBB9D742B1DBE7B3B00E20D67 /* SetMappingForSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04D11DA7240C00BE3051 /* SetMappingForSequence.swift */; };\n\t\tBB9D742C1DBE7B3B00E20D67 /* SetMappingForValueField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04CC1DA723F300BE3051 /* SetMappingForValueField.swift */; };\n\t\tBB9D742D1DBE7B3B00E20D67 /* SetMappingForSetField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04D61DA7242F00BE3051 /* SetMappingForSetField.swift */; };\n\t\tBB9D742E1DBE7B3B00E20D67 /* SetMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB7E04DB1DA7244A00BE3051 /* SetMappingForArrayField.swift */; };\n\t\tBB9D742F1DBE7B3B00E20D67 /* SetFilteringOnPredicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B231C8FCC810050DDA9 /* SetFilteringOnPredicate.swift */; };\n\t\tBB9D74301DBE7B3B00E20D67 /* SetFilteringOnObservableBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033561DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift */; };\n\t\tBB9D74311DBE7B3B00E20D67 /* SetSortingByComparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA0335B1DA7276200E83AC1 /* SetSortingByComparator.swift */; };\n\t\tBB9D74321DBE7B3B00E20D67 /* SetSortingByMappingToComparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1E4D691D61EA5200F1831F /* SetSortingByMappingToComparable.swift */; };\n\t\tBB9D74331DBE7B3B00E20D67 /* SetSortingByMappingToObservableComparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033601DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift */; };\n\t\tBB9D74341DBE7B3B00E20D67 /* SetFolding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E011DAA910500E85FB9 /* SetFolding.swift */; };\n\t\tBB9D74351DBE7B3B00E20D67 /* SetReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB3D92951D647E83003BEDBF /* SetReference.swift */; };\n\t\tBB9D74451DBEB5F300E20D67 /* DistinctUnion.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF491DA409EE005EC162 /* DistinctUnion.swift */; };\n\t\tBB9D744A1DBEC82C00E20D67 /* ValueMappingForSetField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E1D1DAAC7E600E85FB9 /* ValueMappingForSetField.swift */; };\n\t\tBB9FCDCC1F5E54BF001B8781 /* NSButton Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9FCDCB1F5E54BF001B8781 /* NSButton Glue.swift */; };\n\t\tBB9FCDCE1F5EB646001B8781 /* NSControl Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9FCDCD1F5EB646001B8781 /* NSControl Glue.swift */; };\n\t\tBB9FCDD01F5ECFF3001B8781 /* NSPopUpButton Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB9FCDCF1F5ECFF3001B8781 /* NSPopUpButton Glue.swift */; };\n\t\tBBA033591DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033561DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift */; };\n\t\tBBA0335A1DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033561DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift */; };\n\t\tBBA0335E1DA7276200E83AC1 /* SetSortingByComparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA0335B1DA7276200E83AC1 /* SetSortingByComparator.swift */; };\n\t\tBBA0335F1DA7276200E83AC1 /* SetSortingByComparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA0335B1DA7276200E83AC1 /* SetSortingByComparator.swift */; };\n\t\tBBA033631DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033601DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift */; };\n\t\tBBA033641DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033601DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift */; };\n\t\tBBA033681DA7CFFE00E83AC1 /* ArrayModificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033651DA7CFFE00E83AC1 /* ArrayModificationTests.swift */; };\n\t\tBBA0336C1DA7D03300E83AC1 /* ArrayChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033691DA7D03300E83AC1 /* ArrayChangeTests.swift */; };\n\t\tBBAA827D1C91D43700586903 /* Type Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBAA827C1C91D43700586903 /* Type Helpers.swift */; };\n\t\tBBAA827F1C91D43700586903 /* Type Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBAA827C1C91D43700586903 /* Type Helpers.swift */; };\n\t\tBBAA82801C91D43700586903 /* Type Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBAA827C1C91D43700586903 /* Type Helpers.swift */; };\n\t\tBBB4F2521C9594A9002532CC /* UIDevice Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB4F2511C9594A9002532CC /* UIDevice Glue.swift */; };\n\t\tBBB4F26F1C99E6CC002532CC /* UIGestureRecognizer Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB4F26E1C99E6CB002532CC /* UIGestureRecognizer Glue.swift */; };\n\t\tBBB55B081C8F8CBC0050DDA9 /* GlueKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBB55AFE1C8F8CBB0050DDA9 /* GlueKit.framework */; };\n\t\tBBB55B421C8FCC820050DDA9 /* Connector.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B221C8FCC810050DDA9 /* Connector.swift */; };\n\t\tBBB55B441C8FCC820050DDA9 /* Connector.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B221C8FCC810050DDA9 /* Connector.swift */; };\n\t\tBBB55B451C8FCC820050DDA9 /* Connector.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B221C8FCC810050DDA9 /* Connector.swift */; };\n\t\tBBB55B4E1C8FCC820050DDA9 /* Locks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B251C8FCC810050DDA9 /* Locks.swift */; };\n\t\tBBB55B4F1C8FCC820050DDA9 /* Locks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B251C8FCC810050DDA9 /* Locks.swift */; };\n\t\tBBB55B501C8FCC820050DDA9 /* Locks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B251C8FCC810050DDA9 /* Locks.swift */; };\n\t\tBBB55B511C8FCC820050DDA9 /* Locks.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B251C8FCC810050DDA9 /* Locks.swift */; };\n\t\tBBB55B521C8FCC820050DDA9 /* MergedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B261C8FCC810050DDA9 /* MergedSource.swift */; };\n\t\tBBB55B541C8FCC820050DDA9 /* MergedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B261C8FCC810050DDA9 /* MergedSource.swift */; };\n\t\tBBB55B551C8FCC820050DDA9 /* MergedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B261C8FCC810050DDA9 /* MergedSource.swift */; };\n\t\tBBB55B561C8FCC820050DDA9 /* NSNotificationCenter Support.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B271C8FCC810050DDA9 /* NSNotificationCenter Support.swift */; };\n\t\tBBB55B581C8FCC820050DDA9 /* NSNotificationCenter Support.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B271C8FCC810050DDA9 /* NSNotificationCenter Support.swift */; };\n\t\tBBB55B591C8FCC820050DDA9 /* NSNotificationCenter Support.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B271C8FCC810050DDA9 /* NSNotificationCenter Support.swift */; };\n\t\tBBB55B5A1C8FCC820050DDA9 /* BufferedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B281C8FCC810050DDA9 /* BufferedValue.swift */; };\n\t\tBBB55B5C1C8FCC820050DDA9 /* BufferedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B281C8FCC810050DDA9 /* BufferedValue.swift */; };\n\t\tBBB55B5D1C8FCC820050DDA9 /* BufferedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B281C8FCC810050DDA9 /* BufferedValue.swift */; };\n\t\tBBB55B5E1C8FCC820050DDA9 /* ObservableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B291C8FCC810050DDA9 /* ObservableValue.swift */; };\n\t\tBBB55B601C8FCC820050DDA9 /* ObservableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B291C8FCC810050DDA9 /* ObservableValue.swift */; };\n\t\tBBB55B611C8FCC820050DDA9 /* ObservableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B291C8FCC810050DDA9 /* ObservableValue.swift */; };\n\t\tBBB55B661C8FCC820050DDA9 /* Reference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2B1C8FCC810050DDA9 /* Reference.swift */; };\n\t\tBBB55B671C8FCC820050DDA9 /* Reference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2B1C8FCC810050DDA9 /* Reference.swift */; };\n\t\tBBB55B681C8FCC820050DDA9 /* Reference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2B1C8FCC810050DDA9 /* Reference.swift */; };\n\t\tBBB55B691C8FCC820050DDA9 /* Reference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2B1C8FCC810050DDA9 /* Reference.swift */; };\n\t\tBBB55B721C8FCC820050DDA9 /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2E1C8FCC810050DDA9 /* Signal.swift */; };\n\t\tBBB55B741C8FCC820050DDA9 /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2E1C8FCC810050DDA9 /* Signal.swift */; };\n\t\tBBB55B751C8FCC820050DDA9 /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2E1C8FCC810050DDA9 /* Signal.swift */; };\n\t\tBBB55B761C8FCC820050DDA9 /* SimpleSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2F1C8FCC810050DDA9 /* SimpleSources.swift */; };\n\t\tBBB55B781C8FCC820050DDA9 /* SimpleSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2F1C8FCC810050DDA9 /* SimpleSources.swift */; };\n\t\tBBB55B791C8FCC820050DDA9 /* SimpleSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B2F1C8FCC810050DDA9 /* SimpleSources.swift */; };\n\t\tBBB55B7A1C8FCC820050DDA9 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B301C8FCC810050DDA9 /* Source.swift */; };\n\t\tBBB55B7B1C8FCC820050DDA9 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B301C8FCC810050DDA9 /* Source.swift */; };\n\t\tBBB55B7C1C8FCC820050DDA9 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B301C8FCC810050DDA9 /* Source.swift */; };\n\t\tBBB55B7D1C8FCC820050DDA9 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B301C8FCC810050DDA9 /* Source.swift */; };\n\t\tBBB55B7E1C8FCC820050DDA9 /* TransformedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B311C8FCC810050DDA9 /* TransformedSource.swift */; };\n\t\tBBB55B801C8FCC820050DDA9 /* TransformedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B311C8FCC810050DDA9 /* TransformedSource.swift */; };\n\t\tBBB55B811C8FCC820050DDA9 /* TransformedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B311C8FCC810050DDA9 /* TransformedSource.swift */; };\n\t\tBBB55B821C8FCC820050DDA9 /* TimerSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B321C8FCC820050DDA9 /* TimerSource.swift */; };\n\t\tBBB55B841C8FCC820050DDA9 /* TimerSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B321C8FCC820050DDA9 /* TimerSource.swift */; };\n\t\tBBB55B851C8FCC820050DDA9 /* TimerSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B321C8FCC820050DDA9 /* TimerSource.swift */; };\n\t\tBBB55B861C8FCC820050DDA9 /* UpdatableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B331C8FCC820050DDA9 /* UpdatableValue.swift */; };\n\t\tBBB55B881C8FCC820050DDA9 /* UpdatableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B331C8FCC820050DDA9 /* UpdatableValue.swift */; };\n\t\tBBB55B891C8FCC820050DDA9 /* UpdatableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B331C8FCC820050DDA9 /* UpdatableValue.swift */; };\n\t\tBBB55B8E1C8FCC820050DDA9 /* Variable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B351C8FCC820050DDA9 /* Variable.swift */; };\n\t\tBBB55B901C8FCC820050DDA9 /* Variable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B351C8FCC820050DDA9 /* Variable.swift */; };\n\t\tBBB55B911C8FCC820050DDA9 /* Variable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B351C8FCC820050DDA9 /* Variable.swift */; };\n\t\tBBB55BAA1C8FCE2C0050DDA9 /* ArrayVariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B981C8FCE2C0050DDA9 /* ArrayVariableTests.swift */; };\n\t\tBBB55BAE1C8FCE2C0050DDA9 /* KVOSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9A1C8FCE2C0050DDA9 /* KVOSupportTests.swift */; };\n\t\tBBB55BB01C8FCE2C0050DDA9 /* KVOSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9A1C8FCE2C0050DDA9 /* KVOSupportTests.swift */; };\n\t\tBBB55BB11C8FCE2C0050DDA9 /* MergedSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9B1C8FCE2C0050DDA9 /* MergedSourceTests.swift */; };\n\t\tBBB55BB31C8FCE2C0050DDA9 /* MergedSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9B1C8FCE2C0050DDA9 /* MergedSourceTests.swift */; };\n\t\tBBB55BB41C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9C1C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift */; };\n\t\tBBB55BB61C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9C1C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift */; };\n\t\tBBB55BB71C8FCE2C0050DDA9 /* ObservableValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9D1C8FCE2C0050DDA9 /* ObservableValueTests.swift */; };\n\t\tBBB55BB91C8FCE2C0050DDA9 /* ObservableValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9D1C8FCE2C0050DDA9 /* ObservableValueTests.swift */; };\n\t\tBBB55BBA1C8FCE2C0050DDA9 /* DistinctTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9E1C8FCE2C0050DDA9 /* DistinctTests.swift */; };\n\t\tBBB55BBC1C8FCE2C0050DDA9 /* DistinctTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9E1C8FCE2C0050DDA9 /* DistinctTests.swift */; };\n\t\tBBB55BBF1C8FCE2C0050DDA9 /* ArrayMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9F1C8FCE2C0050DDA9 /* ArrayMappingTests.swift */; };\n\t\tBBB55BC01C8FCE2C0050DDA9 /* ValueMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA01C8FCE2C0050DDA9 /* ValueMappingTests.swift */; };\n\t\tBBB55BC21C8FCE2C0050DDA9 /* ValueMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA01C8FCE2C0050DDA9 /* ValueMappingTests.swift */; };\n\t\tBBB55BC31C8FCE2C0050DDA9 /* SignalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA11C8FCE2C0050DDA9 /* SignalTests.swift */; };\n\t\tBBB55BC51C8FCE2C0050DDA9 /* SignalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA11C8FCE2C0050DDA9 /* SignalTests.swift */; };\n\t\tBBB55BC61C8FCE2C0050DDA9 /* SimpleSourcesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA21C8FCE2C0050DDA9 /* SimpleSourcesTests.swift */; };\n\t\tBBB55BC81C8FCE2C0050DDA9 /* SimpleSourcesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA21C8FCE2C0050DDA9 /* SimpleSourcesTests.swift */; };\n\t\tBBB55BC91C8FCE2C0050DDA9 /* SourceOperatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA31C8FCE2C0050DDA9 /* SourceOperatorTests.swift */; };\n\t\tBBB55BCB1C8FCE2C0050DDA9 /* SourceOperatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA31C8FCE2C0050DDA9 /* SourceOperatorTests.swift */; };\n\t\tBBB55BCC1C8FCE2C0050DDA9 /* TestUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA41C8FCE2C0050DDA9 /* TestUtilities.swift */; };\n\t\tBBB55BCD1C8FCE2C0050DDA9 /* TestUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA41C8FCE2C0050DDA9 /* TestUtilities.swift */; };\n\t\tBBB55BCE1C8FCE2C0050DDA9 /* TestUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA41C8FCE2C0050DDA9 /* TestUtilities.swift */; };\n\t\tBBB55BCF1C8FCE2C0050DDA9 /* TimerSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA51C8FCE2C0050DDA9 /* TimerSourceTests.swift */; };\n\t\tBBB55BD11C8FCE2C0050DDA9 /* TimerSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA51C8FCE2C0050DDA9 /* TimerSourceTests.swift */; };\n\t\tBBB55BD21C8FCE2C0050DDA9 /* TwoWayBindingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA61C8FCE2C0050DDA9 /* TwoWayBindingTests.swift */; };\n\t\tBBB55BD41C8FCE2C0050DDA9 /* TwoWayBindingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA61C8FCE2C0050DDA9 /* TwoWayBindingTests.swift */; };\n\t\tBBB55BD51C8FCE2C0050DDA9 /* VariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA71C8FCE2C0050DDA9 /* VariableTests.swift */; };\n\t\tBBB55BD71C8FCE2C0050DDA9 /* VariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA71C8FCE2C0050DDA9 /* VariableTests.swift */; };\n\t\tBBBBEC8D1DCA1AEB000B646D /* ValueReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC8C1DCA1AEB000B646D /* ValueReference.swift */; };\n\t\tBBBBEC8E1DCA1AEB000B646D /* ValueReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC8C1DCA1AEB000B646D /* ValueReference.swift */; };\n\t\tBBBBEC8F1DCA1AEB000B646D /* ValueReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC8C1DCA1AEB000B646D /* ValueReference.swift */; };\n\t\tBBBBEC901DCA1AEB000B646D /* ValueReference.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC8C1DCA1AEB000B646D /* ValueReference.swift */; };\n\t\tBBBBEC921DCA1D43000B646D /* ValueReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC911DCA1D43000B646D /* ValueReferenceTests.swift */; };\n\t\tBBBBEC931DCA1D43000B646D /* ValueReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC911DCA1D43000B646D /* ValueReferenceTests.swift */; };\n\t\tBBBBEC941DCA1D43000B646D /* ValueReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC911DCA1D43000B646D /* ValueReferenceTests.swift */; };\n\t\tBBBBEC961DCA1FEB000B646D /* ArrayReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC951DCA1FEB000B646D /* ArrayReferenceTests.swift */; };\n\t\tBBBBEC971DCA1FEB000B646D /* ArrayReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC951DCA1FEB000B646D /* ArrayReferenceTests.swift */; };\n\t\tBBBBEC981DCA1FEB000B646D /* ArrayReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC951DCA1FEB000B646D /* ArrayReferenceTests.swift */; };\n\t\tBBBBEC9A1DCA223A000B646D /* SetReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC991DCA223A000B646D /* SetReferenceTests.swift */; };\n\t\tBBBBEC9B1DCA223A000B646D /* SetReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC991DCA223A000B646D /* SetReferenceTests.swift */; };\n\t\tBBBBEC9C1DCA223A000B646D /* SetReferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC991DCA223A000B646D /* SetReferenceTests.swift */; };\n\t\tBBBBEC9E1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC9D1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift */; };\n\t\tBBBBEC9F1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC9D1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift */; };\n\t\tBBBBECA01DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBEC9D1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift */; };\n\t\tBBBBECA21DCA3AA8000B646D /* DispatchSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECA11DCA3AA8000B646D /* DispatchSourceTests.swift */; };\n\t\tBBBBECA31DCA3AA8000B646D /* DispatchSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECA11DCA3AA8000B646D /* DispatchSourceTests.swift */; };\n\t\tBBBBECA41DCA3AA8000B646D /* DispatchSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECA11DCA3AA8000B646D /* DispatchSourceTests.swift */; };\n\t\tBBBBECA61DCA3FF0000B646D /* BufferedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECA51DCA3FF0000B646D /* BufferedSet.swift */; };\n\t\tBBBBECA71DCA3FF0000B646D /* BufferedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECA51DCA3FF0000B646D /* BufferedSet.swift */; };\n\t\tBBBBECA81DCA3FF0000B646D /* BufferedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECA51DCA3FF0000B646D /* BufferedSet.swift */; };\n\t\tBBBBECA91DCA3FF0000B646D /* BufferedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECA51DCA3FF0000B646D /* BufferedSet.swift */; };\n\t\tBBBBECAB1DCA4168000B646D /* ArrayBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECAA1DCA4168000B646D /* ArrayBufferingTests.swift */; };\n\t\tBBBBECAC1DCA4168000B646D /* ArrayBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECAA1DCA4168000B646D /* ArrayBufferingTests.swift */; };\n\t\tBBBBECAD1DCA4168000B646D /* ArrayBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECAA1DCA4168000B646D /* ArrayBufferingTests.swift */; };\n\t\tBBBBECAF1DCA446A000B646D /* SetBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECAE1DCA446A000B646D /* SetBufferingTests.swift */; };\n\t\tBBBBECB01DCA446A000B646D /* SetBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECAE1DCA446A000B646D /* SetBufferingTests.swift */; };\n\t\tBBBBECB11DCA446A000B646D /* SetBufferingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBECAE1DCA446A000B646D /* SetBufferingTests.swift */; };\n\t\tBBBFD14B1EBE673200EC9814 /* SetSortingByComparableField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBFD14A1EBE673200EC9814 /* SetSortingByComparableField.swift */; };\n\t\tBBBFD14C1EBE673200EC9814 /* SetSortingByComparableField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBFD14A1EBE673200EC9814 /* SetSortingByComparableField.swift */; };\n\t\tBBBFD14D1EBE673200EC9814 /* SetSortingByComparableField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBFD14A1EBE673200EC9814 /* SetSortingByComparableField.swift */; };\n\t\tBBBFD14E1EBE673200EC9814 /* SetSortingByComparableField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBFD14A1EBE673200EC9814 /* SetSortingByComparableField.swift */; };\n\t\tBBC2A8291CBC14C600394D24 /* NSObject Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC2A8281CBC14C600394D24 /* NSObject Glue.swift */; };\n\t\tBBC2A82B1CBC14C600394D24 /* NSObject Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC2A8281CBC14C600394D24 /* NSObject Glue.swift */; };\n\t\tBBC2A82C1CBC14C600394D24 /* NSObject Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC2A8281CBC14C600394D24 /* NSObject Glue.swift */; };\n\t\tBBC36AED1DA8453000AB3E9D /* ArrayChangeSeparationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC36AE61DA83E0E00AB3E9D /* ArrayChangeSeparationTests.swift */; };\n\t\tBBC3C84E1C93164200E10D59 /* UIControl Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC3C84D1C93164200E10D59 /* UIControl Glue.swift */; };\n\t\tBBC4AE501D9A829500FF7DE0 /* ArrayFilteringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC4AE4D1D9A829500FF7DE0 /* ArrayFilteringTests.swift */; };\n\t\tBBCD9DF51DA9104A00E85FB9 /* RefListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DF41DA9104A00E85FB9 /* RefListTests.swift */; };\n\t\tBBCD9DF61DA9104A00E85FB9 /* RefListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DF41DA9104A00E85FB9 /* RefListTests.swift */; };\n\t\tBBCD9DF71DA9104A00E85FB9 /* RefListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DF41DA9104A00E85FB9 /* RefListTests.swift */; };\n\t\tBBCD9DF91DAA885E00E85FB9 /* ArrayFolding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DF81DAA885E00E85FB9 /* ArrayFolding.swift */; };\n\t\tBBCD9DFB1DAA885E00E85FB9 /* ArrayFolding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DF81DAA885E00E85FB9 /* ArrayFolding.swift */; };\n\t\tBBCD9DFC1DAA885E00E85FB9 /* ArrayFolding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DF81DAA885E00E85FB9 /* ArrayFolding.swift */; };\n\t\tBBCD9E001DAA8F7800E85FB9 /* ArrayFoldingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DFD1DAA8F7800E85FB9 /* ArrayFoldingTests.swift */; };\n\t\tBBCD9E041DAA910500E85FB9 /* SetFolding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E011DAA910500E85FB9 /* SetFolding.swift */; };\n\t\tBBCD9E051DAA910500E85FB9 /* SetFolding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E011DAA910500E85FB9 /* SetFolding.swift */; };\n\t\tBBCD9E071DAA918400E85FB9 /* SetFoldingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E061DAA918400E85FB9 /* SetFoldingTests.swift */; };\n\t\tBBCD9E091DAA918400E85FB9 /* SetFoldingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E061DAA918400E85FB9 /* SetFoldingTests.swift */; };\n\t\tBBCD9E0B1DAAB6E700E85FB9 /* MockUpdateSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E0A1DAAB6E700E85FB9 /* MockUpdateSink.swift */; };\n\t\tBBCD9E0D1DAAB6E700E85FB9 /* MockUpdateSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E0A1DAAB6E700E85FB9 /* MockUpdateSink.swift */; };\n\t\tBBCD9E0F1DAAC33700E85FB9 /* ValueMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E0E1DAAC33700E85FB9 /* ValueMappingForValue.swift */; };\n\t\tBBCD9E111DAAC33700E85FB9 /* ValueMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E0E1DAAC33700E85FB9 /* ValueMappingForValue.swift */; };\n\t\tBBCD9E121DAAC33700E85FB9 /* ValueMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E0E1DAAC33700E85FB9 /* ValueMappingForValue.swift */; };\n\t\tBBCD9E141DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E131DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift */; };\n\t\tBBCD9E161DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E131DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift */; };\n\t\tBBCD9E171DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E131DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift */; };\n\t\tBBCD9E191DAAC50900E85FB9 /* ValueMappingForSourceField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E181DAAC50900E85FB9 /* ValueMappingForSourceField.swift */; };\n\t\tBBCD9E1B1DAAC50900E85FB9 /* ValueMappingForSourceField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E181DAAC50900E85FB9 /* ValueMappingForSourceField.swift */; };\n\t\tBBCD9E1C1DAAC50900E85FB9 /* ValueMappingForSourceField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E181DAAC50900E85FB9 /* ValueMappingForSourceField.swift */; };\n\t\tBBCD9E201DAAC7E600E85FB9 /* ValueMappingForSetField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E1D1DAAC7E600E85FB9 /* ValueMappingForSetField.swift */; };\n\t\tBBCD9E211DAAC7E600E85FB9 /* ValueMappingForSetField.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E1D1DAAC7E600E85FB9 /* ValueMappingForSetField.swift */; };\n\t\tBBCD9E231DAAD26200E85FB9 /* CompositeObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E221DAAD26200E85FB9 /* CompositeObservable.swift */; };\n\t\tBBCD9E251DAAD26200E85FB9 /* CompositeObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E221DAAD26200E85FB9 /* CompositeObservable.swift */; };\n\t\tBBCD9E261DAAD26200E85FB9 /* CompositeObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E221DAAD26200E85FB9 /* CompositeObservable.swift */; };\n\t\tBBCD9E281DAAD2B900E85FB9 /* DistinctValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E271DAAD2B900E85FB9 /* DistinctValue.swift */; };\n\t\tBBCD9E2A1DAAD2B900E85FB9 /* DistinctValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E271DAAD2B900E85FB9 /* DistinctValue.swift */; };\n\t\tBBCD9E2B1DAAD2B900E85FB9 /* DistinctValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E271DAAD2B900E85FB9 /* DistinctValue.swift */; };\n\t\tBBCD9E2D1DAAD4BC00E85FB9 /* CompositeUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E2C1DAAD4BC00E85FB9 /* CompositeUpdatable.swift */; };\n\t\tBBCD9E2F1DAAD4BC00E85FB9 /* CompositeUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E2C1DAAD4BC00E85FB9 /* CompositeUpdatable.swift */; };\n\t\tBBCD9E301DAAD4BC00E85FB9 /* CompositeUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E2C1DAAD4BC00E85FB9 /* CompositeUpdatable.swift */; };\n\t\tBBCD9E321DAAD66500E85FB9 /* CombinedObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E311DAAD66500E85FB9 /* CombinedObservableTests.swift */; };\n\t\tBBCD9E341DAAD66500E85FB9 /* CombinedObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E311DAAD66500E85FB9 /* CombinedObservableTests.swift */; };\n\t\tBBCD9E361DAAD74600E85FB9 /* CombinedUpdatableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E351DAAD74600E85FB9 /* CombinedUpdatableTests.swift */; };\n\t\tBBCD9E381DAAD74600E85FB9 /* CombinedUpdatableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E351DAAD74600E85FB9 /* CombinedUpdatableTests.swift */; };\n\t\tBBCD9E3A1DABC45000E85FB9 /* TypeHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E391DABC45000E85FB9 /* TypeHelperTests.swift */; };\n\t\tBBCD9E3C1DABC45000E85FB9 /* TypeHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E391DABC45000E85FB9 /* TypeHelperTests.swift */; };\n\t\tBBCD9E3E1DABC81A00E85FB9 /* MockSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E3D1DABC81A00E85FB9 /* MockSink.swift */; };\n\t\tBBCD9E401DABC81A00E85FB9 /* MockSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E3D1DABC81A00E85FB9 /* MockSink.swift */; };\n\t\tBBCD9E421DABD4BE00E85FB9 /* ObservableSetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E411DABD4BE00E85FB9 /* ObservableSetTests.swift */; };\n\t\tBBCD9E441DABD4BE00E85FB9 /* ObservableSetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E411DABD4BE00E85FB9 /* ObservableSetTests.swift */; };\n\t\tBBCD9E481DABEA5500E85FB9 /* ObservableArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E451DABEA5500E85FB9 /* ObservableArrayTests.swift */; };\n\t\tBBCD9E4C1DABFA2900E85FB9 /* ArrayConcatenationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E491DABFA2900E85FB9 /* ArrayConcatenationTests.swift */; };\n\t\tBBCD9E4E1DABFE8800E85FB9 /* SetVariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E4D1DABFE8800E85FB9 /* SetVariableTests.swift */; };\n\t\tBBCD9E501DABFE8800E85FB9 /* SetVariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E4D1DABFE8800E85FB9 /* SetVariableTests.swift */; };\n\t\tBBCD9E521DAC1B1300E85FB9 /* ConnectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E511DAC1B1300E85FB9 /* ConnectorTests.swift */; };\n\t\tBBCD9E541DAC1B1300E85FB9 /* ConnectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E511DAC1B1300E85FB9 /* ConnectorTests.swift */; };\n\t\tBBE4DF401DA3A88C005EC162 /* ObservableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF3F1DA3A88C005EC162 /* ObservableType.swift */; };\n\t\tBBE4DF421DA3A88C005EC162 /* ObservableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF3F1DA3A88C005EC162 /* ObservableType.swift */; };\n\t\tBBE4DF431DA3A88C005EC162 /* ObservableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF3F1DA3A88C005EC162 /* ObservableType.swift */; };\n\t\tBBE4DF451DA3A908005EC162 /* ValueChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF441DA3A908005EC162 /* ValueChange.swift */; };\n\t\tBBE4DF471DA3A908005EC162 /* ValueChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF441DA3A908005EC162 /* ValueChange.swift */; };\n\t\tBBE4DF481DA3A908005EC162 /* ValueChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF441DA3A908005EC162 /* ValueChange.swift */; };\n\t\tBBE4DF4C1DA409EE005EC162 /* DistinctUnion.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF491DA409EE005EC162 /* DistinctUnion.swift */; };\n\t\tBBE4DF4D1DA409EE005EC162 /* DistinctUnion.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF491DA409EE005EC162 /* DistinctUnion.swift */; };\n\t\tBBE4DF551DA41373005EC162 /* DistinctUnionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF4E1DA412A0005EC162 /* DistinctUnionTests.swift */; };\n\t\tBBE4DF591DA55384005EC162 /* SetMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF561DA55384005EC162 /* SetMappingForValue.swift */; };\n\t\tBBE4DF5A1DA55384005EC162 /* SetMappingForValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF561DA55384005EC162 /* SetMappingForValue.swift */; };\n\t\tBBE4DF5E1DA55DA3005EC162 /* SetMappingBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF5B1DA55DA3005EC162 /* SetMappingBase.swift */; };\n\t\tBBE4DF5F1DA55DA3005EC162 /* SetMappingBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF5B1DA55DA3005EC162 /* SetMappingBase.swift */; };\n\t\tBBE4DF661DA5656B005EC162 /* SetMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF611DA5654F005EC162 /* SetMappingTests.swift */; };\n\t\tBBE4DF681DA5656D005EC162 /* SetMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF611DA5654F005EC162 /* SetMappingTests.swift */; };\n\t\tBBE9AACA1DC0F0A5000B3DD0 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAC91DC0F0A5000B3DD0 /* Update.swift */; };\n\t\tBBE9AACC1DC0F0A5000B3DD0 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAC91DC0F0A5000B3DD0 /* Update.swift */; };\n\t\tBBE9AACD1DC0F0A5000B3DD0 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAC91DC0F0A5000B3DD0 /* Update.swift */; };\n\t\tBBE9AACF1DC0F1F6000B3DD0 /* ChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AACE1DC0F1F6000B3DD0 /* ChangeTests.swift */; };\n\t\tBBE9AAD01DC0F1F6000B3DD0 /* ChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AACE1DC0F1F6000B3DD0 /* ChangeTests.swift */; };\n\t\tBBE9AAD11DC0F1F6000B3DD0 /* ChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AACE1DC0F1F6000B3DD0 /* ChangeTests.swift */; };\n\t\tBBE9AAD41DC0F474000B3DD0 /* BufferedSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAD31DC0F474000B3DD0 /* BufferedSourceTests.swift */; };\n\t\tBBE9AAD51DC0F474000B3DD0 /* BufferedSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAD31DC0F474000B3DD0 /* BufferedSourceTests.swift */; };\n\t\tBBE9AAD61DC0F474000B3DD0 /* BufferedSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAD31DC0F474000B3DD0 /* BufferedSourceTests.swift */; };\n\t\tBBE9AAD81DC0FC17000B3DD0 /* BracketingSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAD71DC0FC17000B3DD0 /* BracketingSourceTests.swift */; };\n\t\tBBE9AAD91DC0FC17000B3DD0 /* BracketingSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAD71DC0FC17000B3DD0 /* BracketingSourceTests.swift */; };\n\t\tBBE9AADA1DC0FC17000B3DD0 /* BracketingSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE9AAD71DC0FC17000B3DD0 /* BracketingSourceTests.swift */; };\n\t\tBBEA2A291DBF9ADA00CCCB08 /* MockSink.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E3D1DABC81A00E85FB9 /* MockSink.swift */; };\n\t\tBBEA2A2B1DBF9E9C00CCCB08 /* AnySinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A2A1DBF9E9C00CCCB08 /* AnySinkTests.swift */; };\n\t\tBBEA2A2C1DBF9E9C00CCCB08 /* AnySinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A2A1DBF9E9C00CCCB08 /* AnySinkTests.swift */; };\n\t\tBBEA2A2D1DBF9E9C00CCCB08 /* AnySinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A2A1DBF9E9C00CCCB08 /* AnySinkTests.swift */; };\n\t\tBBEA2A321DBFC3BB00CCCB08 /* SignalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA11C8FCE2C0050DDA9 /* SignalTests.swift */; };\n\t\tBBEA2A341DBFC4C300CCCB08 /* AnySourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A331DBFC4C300CCCB08 /* AnySourceTests.swift */; };\n\t\tBBEA2A351DBFC4C300CCCB08 /* AnySourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A331DBFC4C300CCCB08 /* AnySourceTests.swift */; };\n\t\tBBEA2A361DBFC4C300CCCB08 /* AnySourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A331DBFC4C300CCCB08 /* AnySourceTests.swift */; };\n\t\tBBEA2A371DBFC71000CCCB08 /* SimpleSourcesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA21C8FCE2C0050DDA9 /* SimpleSourcesTests.swift */; };\n\t\tBBEA2A381DBFC7B800CCCB08 /* MergedSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9B1C8FCE2C0050DDA9 /* MergedSourceTests.swift */; };\n\t\tBBEA2A3A1DBFE37A00CCCB08 /* BracketingSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A391DBFE37A00CCCB08 /* BracketingSource.swift */; };\n\t\tBBEA2A3B1DBFE37B00CCCB08 /* BracketingSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A391DBFE37A00CCCB08 /* BracketingSource.swift */; };\n\t\tBBEA2A3C1DBFE37B00CCCB08 /* BracketingSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A391DBFE37A00CCCB08 /* BracketingSource.swift */; };\n\t\tBBEA2A3D1DBFE37B00CCCB08 /* BracketingSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A391DBFE37A00CCCB08 /* BracketingSource.swift */; };\n\t\tBBEA2A3F1DBFE38F00CCCB08 /* BufferedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A3E1DBFE38F00CCCB08 /* BufferedSource.swift */; };\n\t\tBBEA2A401DBFE38F00CCCB08 /* BufferedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A3E1DBFE38F00CCCB08 /* BufferedSource.swift */; };\n\t\tBBEA2A411DBFE38F00CCCB08 /* BufferedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A3E1DBFE38F00CCCB08 /* BufferedSource.swift */; };\n\t\tBBEA2A421DBFE38F00CCCB08 /* BufferedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBEA2A3E1DBFE38F00CCCB08 /* BufferedSource.swift */; };\n\t\tBBEA2A4D1DC0BB4D00CCCB08 /* SourceOperatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55BA31C8FCE2C0050DDA9 /* SourceOperatorTests.swift */; };\n\t\tBBEBFF721DB77D77008AC632 /* MockArrayObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB568AF61DA6A9EE00BC4B58 /* MockArrayObserver.swift */; };\n\t\tBBEBFF731DB77D77008AC632 /* ArrayModificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033651DA7CFFE00E83AC1 /* ArrayModificationTests.swift */; };\n\t\tBBEBFF741DB77D77008AC632 /* ArrayChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBA033691DA7D03300E83AC1 /* ArrayChangeTests.swift */; };\n\t\tBBEBFF751DB77D77008AC632 /* ArrayChangeSeparationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC36AE61DA83E0E00AB3E9D /* ArrayChangeSeparationTests.swift */; };\n\t\tBBEBFF761DB77D77008AC632 /* ObservableArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E451DABEA5500E85FB9 /* ObservableArrayTests.swift */; };\n\t\tBBEBFF771DB77D77008AC632 /* ArrayVariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B981C8FCE2C0050DDA9 /* ArrayVariableTests.swift */; };\n\t\tBBEBFF781DB77D77008AC632 /* ArrayMappingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB55B9F1C8FCE2C0050DDA9 /* ArrayMappingTests.swift */; };\n\t\tBBEBFF791DB77D77008AC632 /* ArrayFilteringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBC4AE4D1D9A829500FF7DE0 /* ArrayFilteringTests.swift */; };\n\t\tBBEBFF7A1DB77D77008AC632 /* ArrayFoldingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9DFD1DAA8F7800E85FB9 /* ArrayFoldingTests.swift */; };\n\t\tBBEBFF7B1DB77D77008AC632 /* DistinctUnionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE4DF4E1DA412A0005EC162 /* DistinctUnionTests.swift */; };\n\t\tBBEBFF7C1DB77D77008AC632 /* ArrayConcatenationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBCD9E491DABFA2900E85FB9 /* ArrayConcatenationTests.swift */; };\n\t\tBBF3EB0E1D99ACDE006AC7CD /* RefList.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF3EB0D1D99ACDE006AC7CD /* RefList.swift */; };\n\t\tBBF3EB0F1D99ACDE006AC7CD /* RefList.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF3EB0D1D99ACDE006AC7CD /* RefList.swift */; };\n\t\tBBF3EB101D99ACDE006AC7CD /* RefList.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF3EB0D1D99ACDE006AC7CD /* RefList.swift */; };\n\t\tBBF3EB111D99ACDE006AC7CD /* RefList.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF3EB0D1D99ACDE006AC7CD /* RefList.swift */; };\n\t\tBBF400661DA108E900DA0B2C /* ObservableContains.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF400631DA108E900DA0B2C /* ObservableContains.swift */; };\n\t\tBBF400671DA108E900DA0B2C /* ObservableContains.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF400631DA108E900DA0B2C /* ObservableContains.swift */; };\n\t\tBBF7B9521EACE69B00073DF8 /* UILabel Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9511EACE69B00073DF8 /* UILabel Glue.swift */; };\n\t\tBBF7B9541EACEB0100073DF8 /* AccumulatedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9531EACEB0100073DF8 /* AccumulatedSource.swift */; };\n\t\tBBF7B9551EACEB0100073DF8 /* AccumulatedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9531EACEB0100073DF8 /* AccumulatedSource.swift */; };\n\t\tBBF7B9561EACEB0100073DF8 /* AccumulatedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9531EACEB0100073DF8 /* AccumulatedSource.swift */; };\n\t\tBBF7B9571EACEB0100073DF8 /* AccumulatedSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9531EACEB0100073DF8 /* AccumulatedSource.swift */; };\n\t\tBBF7B9591EACFC3B00073DF8 /* DependentValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9581EACFC3B00073DF8 /* DependentValue.swift */; };\n\t\tBBF7B95A1EACFC3B00073DF8 /* DependentValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9581EACFC3B00073DF8 /* DependentValue.swift */; };\n\t\tBBF7B95B1EACFC3B00073DF8 /* DependentValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9581EACFC3B00073DF8 /* DependentValue.swift */; };\n\t\tBBF7B95C1EACFC3B00073DF8 /* DependentValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B9581EACFC3B00073DF8 /* DependentValue.swift */; };\n\t\tBBF7B9601EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B95F1EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift */; };\n\t\tBBF7B9611EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B95F1EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift */; };\n\t\tBBF7B9621EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B95F1EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift */; };\n\t\tBBF7B9631EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBF7B95F1EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\tBB351B021DB81E67005F083F /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = BBB55AA91C8F80020050DDA9 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = BBB55AD31C8F88F20050DDA9;\n\t\t\tremoteInfo = macOS;\n\t\t};\n\t\tBBB55ABE1C8F80020050DDA9 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = BBB55AA91C8F80020050DDA9 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = BBB55AB11C8F80020050DDA9;\n\t\t\tremoteInfo = GlueKit;\n\t\t};\n\t\tBBB55ADF1C8F88F20050DDA9 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = BBB55AA91C8F80020050DDA9 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = BBB55AD31C8F88F20050DDA9;\n\t\t\tremoteInfo = GlueKit;\n\t\t};\n\t\tBBB55B091C8F8CBC0050DDA9 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = BBB55AA91C8F80020050DDA9 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = BBB55AFD1C8F8CBB0050DDA9;\n\t\t\tremoteInfo = GlueKit;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\tBB015F4E1DC624FB00C8C05A /* Language Enhancements.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; lineEnding = 0; path = \"Language Enhancements.md\"; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.markdown; };\n\t\tBB1657E61D71D65900094BAC /* ArrayChangeSeparation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayChangeSeparation.swift; sourceTree = \"<group>\"; };\n\t\tBB170F231DC1066D0000443E /* UpdateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateTests.swift; sourceTree = \"<group>\"; };\n\t\tBB170F271DC106DE0000443E /* TestChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestChange.swift; sourceTree = \"<group>\"; };\n\t\tBB170F2B1DC10D350000443E /* TestObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestObservable.swift; sourceTree = \"<group>\"; };\n\t\tBB170F2F1DC10DDB0000443E /* ChangesSourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangesSourceTests.swift; sourceTree = \"<group>\"; };\n\t\tBB170F331DC110BD0000443E /* TestUpdatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUpdatable.swift; sourceTree = \"<group>\"; };\n\t\tBB170F371DC1545E0000443E /* TransactionStateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionStateTests.swift; sourceTree = \"<group>\"; };\n\t\tBB170F3D1DC221180000443E /* ValueChangeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueChangeTests.swift; sourceTree = \"<group>\"; };\n\t\tBB170F411DC22A300000443E /* UpdatableValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = UpdatableValueTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBB1E4D691D61EA5200F1831F /* SetSortingByMappingToComparable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetSortingByMappingToComparable.swift; sourceTree = \"<group>\"; };\n\t\tBB318F6A1CB9922F0086EE83 /* UIBarButtonItem Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = \"UIBarButtonItem Extensions.swift\"; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBB351AFC1DB81E67005F083F /* PerformanceTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PerformanceTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBB3982EC1EC109C4000CDCB5 /* UISearchBar Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"UISearchBar Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBB3D12AF1E49FBF500097510 /* SipHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SipHash.framework; path = \"../../Library/Developer/Xcode/DerivedData/GlueKit-gstdcmlxjxkcnggtlmasijktewlg/Build/Products/Debug/SipHash.framework\"; sourceTree = \"<group>\"; };\n\t\tBB3D12B11E49FC5A00097510 /* BTree.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BTree.framework; path = Carthage/Build/iOS/BTree.framework; sourceTree = \"<group>\"; };\n\t\tBB3D12B31E49FC5E00097510 /* SipHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SipHash.framework; path = Carthage/Build/iOS/SipHash.framework; sourceTree = \"<group>\"; };\n\t\tBB3D12B51E49FC7600097510 /* BTree.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BTree.framework; path = Carthage/Build/Mac/BTree.framework; sourceTree = \"<group>\"; };\n\t\tBB3D12B61E49FC7600097510 /* SipHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SipHash.framework; path = Carthage/Build/Mac/SipHash.framework; sourceTree = \"<group>\"; };\n\t\tBB3D12B91E49FC8000097510 /* BTree.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BTree.framework; path = Carthage/Build/watchOS/BTree.framework; sourceTree = \"<group>\"; };\n\t\tBB3D12BA1E49FC8000097510 /* SipHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SipHash.framework; path = Carthage/Build/watchOS/SipHash.framework; sourceTree = \"<group>\"; };\n\t\tBB3D12BD1E49FC8700097510 /* BTree.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BTree.framework; path = Carthage/Build/tvOS/BTree.framework; sourceTree = \"<group>\"; };\n\t\tBB3D12BE1E49FC8700097510 /* SipHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SipHash.framework; path = Carthage/Build/tvOS/SipHash.framework; sourceTree = \"<group>\"; };\n\t\tBB3D92951D647E83003BEDBF /* SetReference.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetReference.swift; sourceTree = \"<group>\"; };\n\t\tBB3D929A1D64862D003BEDBF /* ArrayReference.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayReference.swift; sourceTree = \"<group>\"; };\n\t\tBB4052011C958712003D8F5B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };\n\t\tBB471D991DA57FF8002550B0 /* SetSortingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SetSortingTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBB471D9E1DA58EA3002550B0 /* .codecov.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .codecov.yml; sourceTree = \"<group>\"; };\n\t\tBB568AE81DA66E6200BC4B58 /* Cartfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Cartfile; sourceTree = \"<group>\"; };\n\t\tBB568AEE1DA693F700BC4B58 /* SetFilteringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetFilteringTests.swift; sourceTree = \"<group>\"; };\n\t\tBB568AF21DA6942700BC4B58 /* MockSetObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockSetObserver.swift; sourceTree = \"<group>\"; };\n\t\tBB568AF61DA6A9EE00BC4B58 /* MockArrayObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockArrayObserver.swift; sourceTree = \"<group>\"; };\n\t\tBB5B02DA1F5E3FC50084D86B /* ArrayGatheringSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayGatheringSource.swift; sourceTree = \"<group>\"; };\n\t\tBB5B02DF1F5E3FDE0084D86B /* SetGatheringSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetGatheringSource.swift; sourceTree = \"<group>\"; };\n\t\tBB6139821F5E1B3F005455D5 /* NSTextField Glue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"NSTextField Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBB67E5511C9B6A63002B0AB5 /* CADisplayLink Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"CADisplayLink Extensions.swift\"; sourceTree = \"<group>\"; };\n\t\tBB69A7EE1D6AFF1A001D2821 /* Abstract.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Abstract.swift; sourceTree = \"<group>\"; };\n\t\tBB69A7FF1D6B2377001D2821 /* BufferedArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferedArray.swift; sourceTree = \"<group>\"; };\n\t\tBB69A83A1D6B90F5001D2821 /* ArrayConcatenation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayConcatenation.swift; sourceTree = \"<group>\"; };\n\t\tBB69A83F1D6B9A7E001D2821 /* ArrayMappingForValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayMappingForValue.swift; sourceTree = \"<group>\"; };\n\t\tBB6CE3B31DC4C21C00295C55 /* TransformedSink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformedSink.swift; sourceTree = \"<group>\"; };\n\t\tBB7E04C71DA7233B00BE3051 /* ArrayMappingForArrayField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayMappingForArrayField.swift; sourceTree = \"<group>\"; };\n\t\tBB7E04CC1DA723F300BE3051 /* SetMappingForValueField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetMappingForValueField.swift; sourceTree = \"<group>\"; };\n\t\tBB7E04D11DA7240C00BE3051 /* SetMappingForSequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetMappingForSequence.swift; sourceTree = \"<group>\"; };\n\t\tBB7E04D61DA7242F00BE3051 /* SetMappingForSetField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetMappingForSetField.swift; sourceTree = \"<group>\"; };\n\t\tBB7E04DB1DA7244A00BE3051 /* SetMappingForArrayField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetMappingForArrayField.swift; sourceTree = \"<group>\"; };\n\t\tBB7E04E01DA7255D00BE3051 /* ArrayFilteringIndexmap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayFilteringIndexmap.swift; sourceTree = \"<group>\"; };\n\t\tBB7E04E51DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayFilteringOnObservableBool.swift; sourceTree = \"<group>\"; };\n\t\tBB82E3E01D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayFilteringOnPredicate.swift; sourceTree = \"<group>\"; };\n\t\tBB88C40D1DC3A08B00C7EC3C /* ObservableTypeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObservableTypeTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBB88C4121DC3B65F00C7EC3C /* ValueBufferingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ValueBufferingTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBB8990021D5DF2D20097F350 /* SetChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetChange.swift; sourceTree = \"<group>\"; };\n\t\tBB8990041D5DF8630097F350 /* Change.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Change.swift; sourceTree = \"<group>\"; };\n\t\tBB8990091D5DF88C0097F350 /* ObservableSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObservableSet.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBB89901A1D5F6AAE0097F350 /* UpdatableSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatableSet.swift; sourceTree = \"<group>\"; };\n\t\tBB89901F1D5F6F980097F350 /* SetVariable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetVariable.swift; sourceTree = \"<group>\"; };\n\t\tBB8990251D5F84050097F350 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };\n\t\tBB8990281D5F84210097F350 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS3.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };\n\t\tBB89902A1D5F842C0097F350 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };\n\t\tBB89902C1D5F84340097F350 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS10.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };\n\t\tBB8D366D1DA116CB000D44C5 /* Bookshelf.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bookshelf.swift; sourceTree = \"<group>\"; };\n\t\tBB8D36711DA14800000D44C5 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = \"<group>\"; };\n\t\tBB948BBB1DD5EFC900B0734C /* ComputedUpdatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComputedUpdatable.swift; sourceTree = \"<group>\"; };\n\t\tBB948BC01DD720FE00B0734C /* UISwitch Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"UISwitch Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBB9D73C81DBB2EB400E20D67 /* Connect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Connect.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBB9D73CE1DBB38F900E20D67 /* Sink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sink.swift; sourceTree = \"<group>\"; };\n\t\tBB9D73DF1DBB61C100E20D67 /* TransactionalThing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionalThing.swift; sourceTree = \"<group>\"; };\n\t\tBB9D73E51DBB727300E20D67 /* ChangesSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ChangesSource.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBB9D73EE1DBDFEE400E20D67 /* TwoWayBinding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwoWayBinding.swift; sourceTree = \"<group>\"; };\n\t\tBB9D73F31DBE03EB00E20D67 /* DispatchSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatchSource.swift; sourceTree = \"<group>\"; };\n\t\tBB9D73FD1DBE061D00E20D67 /* OwnedSink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OwnedSink.swift; sourceTree = \"<group>\"; };\n\t\tBB9FCDCB1F5E54BF001B8781 /* NSButton Glue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"NSButton Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBB9FCDCD1F5EB646001B8781 /* NSControl Glue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"NSControl Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBB9FCDCF1F5ECFF3001B8781 /* NSPopUpButton Glue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = \"NSPopUpButton Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBBA033561DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetFilteringOnObservableBool.swift; sourceTree = \"<group>\"; };\n\t\tBBA0335B1DA7276200E83AC1 /* SetSortingByComparator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetSortingByComparator.swift; sourceTree = \"<group>\"; };\n\t\tBBA033601DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetSortingByMappingToObservableComparable.swift; sourceTree = \"<group>\"; };\n\t\tBBA033651DA7CFFE00E83AC1 /* ArrayModificationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayModificationTests.swift; sourceTree = \"<group>\"; };\n\t\tBBA033691DA7D03300E83AC1 /* ArrayChangeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayChangeTests.swift; sourceTree = \"<group>\"; };\n\t\tBBAA827C1C91D43700586903 /* Type Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"Type Helpers.swift\"; sourceTree = \"<group>\"; };\n\t\tBBB4F2511C9594A9002532CC /* UIDevice Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"UIDevice Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBBB4F26E1C99E6CB002532CC /* UIGestureRecognizer Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"UIGestureRecognizer Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBBB55AB21C8F80020050DDA9 /* GlueKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GlueKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBB55AB71C8F80020050DDA9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tBBB55ABC1C8F80020050DDA9 /* GlueKit-Test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = \"GlueKit-Test.xctest\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBB55AC31C8F80020050DDA9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tBBB55ACC1C8F80660050DDA9 /* version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = version.xcconfig; sourceTree = \"<group>\"; };\n\t\tBBB55AD41C8F88F20050DDA9 /* GlueKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GlueKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBB55ADD1C8F88F20050DDA9 /* GlueKit-Test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = \"GlueKit-Test.xctest\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBB55AF11C8F8BE00050DDA9 /* GlueKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GlueKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBB55AFE1C8F8CBB0050DDA9 /* GlueKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GlueKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBB55B071C8F8CBB0050DDA9 /* GlueKit-Test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = \"GlueKit-Test.xctest\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tBBB55B1C1C8F90F60050DDA9 /* .travis.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .travis.yml; sourceTree = \"<group>\"; };\n\t\tBBB55B1D1C8F9E850050DDA9 /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = \"<group>\"; };\n\t\tBBB55B1E1C8F9E920050DDA9 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; lineEnding = 0; path = README.md; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.markdown; };\n\t\tBBB55B1F1C8FCC810050DDA9 /* ArrayChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayChange.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B201C8FCC810050DDA9 /* ArrayVariable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayVariable.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B221C8FCC810050DDA9 /* Connector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Connector.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B231C8FCC810050DDA9 /* SetFilteringOnPredicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetFilteringOnPredicate.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B251C8FCC810050DDA9 /* Locks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Locks.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B261C8FCC810050DDA9 /* MergedSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MergedSource.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B271C8FCC810050DDA9 /* NSNotificationCenter Support.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"NSNotificationCenter Support.swift\"; sourceTree = \"<group>\"; };\n\t\tBBB55B281C8FCC810050DDA9 /* BufferedValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BufferedValue.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55B291C8FCC810050DDA9 /* ObservableValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObservableValue.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55B2A1C8FCC810050DDA9 /* ObservableArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObservableArray.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B2B1C8FCC810050DDA9 /* Reference.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reference.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B2C1C8FCC810050DDA9 /* ValueMappingForValueField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ValueMappingForValueField.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55B2D1C8FCC810050DDA9 /* ArrayMappingForValueField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayMappingForValueField.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B2E1C8FCC810050DDA9 /* Signal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Signal.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B2F1C8FCC810050DDA9 /* SimpleSources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleSources.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B301C8FCC810050DDA9 /* Source.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Source.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55B311C8FCC810050DDA9 /* TransformedSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformedSource.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B321C8FCC820050DDA9 /* TimerSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimerSource.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B331C8FCC820050DDA9 /* UpdatableValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatableValue.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B341C8FCC820050DDA9 /* UpdatableArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatableArray.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B351C8FCC820050DDA9 /* Variable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Variable.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B981C8FCE2C0050DDA9 /* ArrayVariableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ArrayVariableTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55B9A1C8FCE2C0050DDA9 /* KVOSupportTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = KVOSupportTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55B9B1C8FCE2C0050DDA9 /* MergedSourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MergedSourceTests.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B9C1C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = NotificationCenterSupportTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55B9D1C8FCE2C0050DDA9 /* ObservableValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObservableValueTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55B9E1C8FCE2C0050DDA9 /* DistinctTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DistinctTests.swift; sourceTree = \"<group>\"; };\n\t\tBBB55B9F1C8FCE2C0050DDA9 /* ArrayMappingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayMappingTests.swift; sourceTree = \"<group>\"; };\n\t\tBBB55BA01C8FCE2C0050DDA9 /* ValueMappingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ValueMappingTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55BA11C8FCE2C0050DDA9 /* SignalTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SignalTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55BA21C8FCE2C0050DDA9 /* SimpleSourcesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleSourcesTests.swift; sourceTree = \"<group>\"; };\n\t\tBBB55BA31C8FCE2C0050DDA9 /* SourceOperatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SourceOperatorTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55BA41C8FCE2C0050DDA9 /* TestUtilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUtilities.swift; sourceTree = \"<group>\"; };\n\t\tBBB55BA51C8FCE2C0050DDA9 /* TimerSourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = TimerSourceTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55BA61C8FCE2C0050DDA9 /* TwoWayBindingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = TwoWayBindingTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55BA71C8FCE2C0050DDA9 /* VariableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = VariableTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBB55BDC1C8FCFAD0050DDA9 /* Overview.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; lineEnding = 0; path = Overview.md; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.markdown; };\n\t\tBBB55BDD1C8FD0160050DDA9 /* Demo.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = Demo.playground; path = ../GlueKit/Demo.playground; sourceTree = \"<group>\"; };\n\t\tBBB55BE61C8FD1C60050DDA9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tBBB55BEA1C8FD25F0050DDA9 /* GlueKitPerformanceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = GlueKitPerformanceTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBBBEC8C1DCA1AEB000B646D /* ValueReference.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueReference.swift; sourceTree = \"<group>\"; };\n\t\tBBBBEC911DCA1D43000B646D /* ValueReferenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueReferenceTests.swift; sourceTree = \"<group>\"; };\n\t\tBBBBEC951DCA1FEB000B646D /* ArrayReferenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayReferenceTests.swift; sourceTree = \"<group>\"; };\n\t\tBBBBEC991DCA223A000B646D /* SetReferenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetReferenceTests.swift; sourceTree = \"<group>\"; };\n\t\tBBBBEC9D1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSUserDefaultsSupportTests.swift; sourceTree = \"<group>\"; };\n\t\tBBBBECA11DCA3AA8000B646D /* DispatchSourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = DispatchSourceTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBBBECA51DCA3FF0000B646D /* BufferedSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferedSet.swift; sourceTree = \"<group>\"; };\n\t\tBBBBECAA1DCA4168000B646D /* ArrayBufferingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayBufferingTests.swift; sourceTree = \"<group>\"; };\n\t\tBBBBECAE1DCA446A000B646D /* SetBufferingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetBufferingTests.swift; sourceTree = \"<group>\"; };\n\t\tBBBFD14A1EBE673200EC9814 /* SetSortingByComparableField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetSortingByComparableField.swift; sourceTree = \"<group>\"; };\n\t\tBBC1F1D01D7EDF4A00A320F5 /* GlueKit.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = GlueKit.podspec; sourceTree = \"<group>\"; };\n\t\tBBC2A8281CBC14C600394D24 /* NSObject Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"NSObject Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBBC36AE61DA83E0E00AB3E9D /* ArrayChangeSeparationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayChangeSeparationTests.swift; sourceTree = \"<group>\"; };\n\t\tBBC3C84D1C93164200E10D59 /* UIControl Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"UIControl Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBBC4AE4D1D9A829500FF7DE0 /* ArrayFilteringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayFilteringTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9DF41DA9104A00E85FB9 /* RefListTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefListTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9DF81DAA885E00E85FB9 /* ArrayFolding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ArrayFolding.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBCD9DFD1DAA8F7800E85FB9 /* ArrayFoldingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayFoldingTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E011DAA910500E85FB9 /* SetFolding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetFolding.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E061DAA918400E85FB9 /* SetFoldingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetFoldingTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E0A1DAAB6E700E85FB9 /* MockUpdateSink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockUpdateSink.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E0E1DAAC33700E85FB9 /* ValueMappingForValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueMappingForValue.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E131DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueMappingForArrayField.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E181DAAC50900E85FB9 /* ValueMappingForSourceField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ValueMappingForSourceField.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBCD9E1D1DAAC7E600E85FB9 /* ValueMappingForSetField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ValueMappingForSetField.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBCD9E221DAAD26200E85FB9 /* CompositeObservable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompositeObservable.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E271DAAD2B900E85FB9 /* DistinctValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DistinctValue.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E2C1DAAD4BC00E85FB9 /* CompositeUpdatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompositeUpdatable.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E311DAAD66500E85FB9 /* CombinedObservableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CombinedObservableTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBCD9E351DAAD74600E85FB9 /* CombinedUpdatableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CombinedUpdatableTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBCD9E391DABC45000E85FB9 /* TypeHelperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeHelperTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E3D1DABC81A00E85FB9 /* MockSink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockSink.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E411DABD4BE00E85FB9 /* ObservableSetTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObservableSetTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E451DABEA5500E85FB9 /* ObservableArrayTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObservableArrayTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E491DABFA2900E85FB9 /* ArrayConcatenationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayConcatenationTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E4D1DABFE8800E85FB9 /* SetVariableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetVariableTests.swift; sourceTree = \"<group>\"; };\n\t\tBBCD9E511DAC1B1300E85FB9 /* ConnectorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ConnectorTests.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBE4DF3F1DA3A88C005EC162 /* ObservableType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObservableType.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBE4DF441DA3A908005EC162 /* ValueChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValueChange.swift; sourceTree = \"<group>\"; };\n\t\tBBE4DF491DA409EE005EC162 /* DistinctUnion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DistinctUnion.swift; sourceTree = \"<group>\"; };\n\t\tBBE4DF4E1DA412A0005EC162 /* DistinctUnionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DistinctUnionTests.swift; sourceTree = \"<group>\"; };\n\t\tBBE4DF561DA55384005EC162 /* SetMappingForValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetMappingForValue.swift; sourceTree = \"<group>\"; };\n\t\tBBE4DF5B1DA55DA3005EC162 /* SetMappingBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetMappingBase.swift; sourceTree = \"<group>\"; };\n\t\tBBE4DF611DA5654F005EC162 /* SetMappingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SetMappingTests.swift; sourceTree = \"<group>\"; };\n\t\tBBE9AAC91DC0F0A5000B3DD0 /* Update.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Update.swift; sourceTree = \"<group>\"; };\n\t\tBBE9AACE1DC0F1F6000B3DD0 /* ChangeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChangeTests.swift; sourceTree = \"<group>\"; };\n\t\tBBE9AAD31DC0F474000B3DD0 /* BufferedSourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferedSourceTests.swift; sourceTree = \"<group>\"; };\n\t\tBBE9AAD71DC0FC17000B3DD0 /* BracketingSourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BracketingSourceTests.swift; sourceTree = \"<group>\"; };\n\t\tBBEA2A2A1DBF9E9C00CCCB08 /* AnySinkTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnySinkTests.swift; sourceTree = \"<group>\"; };\n\t\tBBEA2A331DBFC4C300CCCB08 /* AnySourceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnySourceTests.swift; sourceTree = \"<group>\"; };\n\t\tBBEA2A391DBFE37A00CCCB08 /* BracketingSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BracketingSource.swift; sourceTree = \"<group>\"; };\n\t\tBBEA2A3E1DBFE38F00CCCB08 /* BufferedSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferedSource.swift; sourceTree = \"<group>\"; };\n\t\tBBF3EB0D1D99ACDE006AC7CD /* RefList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefList.swift; sourceTree = \"<group>\"; };\n\t\tBBF400631DA108E900DA0B2C /* ObservableContains.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ObservableContains.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\tBBF7B9511EACE69B00073DF8 /* UILabel Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = \"UILabel Glue.swift\"; sourceTree = \"<group>\"; };\n\t\tBBF7B9531EACEB0100073DF8 /* AccumulatedSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccumulatedSource.swift; sourceTree = \"<group>\"; };\n\t\tBBF7B9581EACFC3B00073DF8 /* DependentValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DependentValue.swift; sourceTree = \"<group>\"; };\n\t\tBBF7B95F1EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayBasedTableViewDataSource.swift; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tBB351AF91DB81E67005F083F /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB351B011DB81E67005F083F /* GlueKit.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AAE1C8F80020050DDA9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB89902B1D5F842C0097F350 /* Foundation.framework in Frameworks */,\n\t\t\t\tBB4052021C958712003D8F5B /* UIKit.framework in Frameworks */,\n\t\t\t\tBB3D12B21E49FC5A00097510 /* BTree.framework in Frameworks */,\n\t\t\t\tBB3D12B41E49FC5E00097510 /* SipHash.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AB91C8F80020050DDA9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB23E63D1C90DEB6005EFD0A /* GlueKit.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AD01C8F88F20050DDA9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB8990271D5F84150097F350 /* Foundation.framework in Frameworks */,\n\t\t\t\tBB3D12B71E49FC7600097510 /* BTree.framework in Frameworks */,\n\t\t\t\tBB3D12B81E49FC7600097510 /* SipHash.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55ADA1C8F88F20050DDA9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB3D12C11E49FD1700097510 /* GlueKit.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AED1C8F8BE00050DDA9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB8990291D5F84210097F350 /* Foundation.framework in Frameworks */,\n\t\t\t\tBB3D12BB1E49FC8000097510 /* BTree.framework in Frameworks */,\n\t\t\t\tBB3D12BC1E49FC8000097510 /* SipHash.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AFA1C8F8CBB0050DDA9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB89902D1D5F84340097F350 /* Foundation.framework in Frameworks */,\n\t\t\t\tBB3D12BF1E49FC8700097510 /* BTree.framework in Frameworks */,\n\t\t\t\tBB3D12C01E49FC8700097510 /* SipHash.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55B041C8F8CBB0050DDA9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBBB55B081C8F8CBC0050DDA9 /* GlueKit.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\tBB3D12AE1E49FBF500097510 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB3D12BD1E49FC8700097510 /* BTree.framework */,\n\t\t\t\tBB3D12BE1E49FC8700097510 /* SipHash.framework */,\n\t\t\t\tBB3D12B91E49FC8000097510 /* BTree.framework */,\n\t\t\t\tBB3D12BA1E49FC8000097510 /* SipHash.framework */,\n\t\t\t\tBB3D12B51E49FC7600097510 /* BTree.framework */,\n\t\t\t\tBB3D12B61E49FC7600097510 /* SipHash.framework */,\n\t\t\t\tBB3D12B31E49FC5E00097510 /* SipHash.framework */,\n\t\t\t\tBB3D12B11E49FC5A00097510 /* BTree.framework */,\n\t\t\t\tBB4052011C958712003D8F5B /* UIKit.framework */,\n\t\t\t\tBB89902C1D5F84340097F350 /* Foundation.framework */,\n\t\t\t\tBB89902A1D5F842C0097F350 /* Foundation.framework */,\n\t\t\t\tBB8990281D5F84210097F350 /* Foundation.framework */,\n\t\t\t\tBB8990251D5F84050097F350 /* Foundation.framework */,\n\t\t\t\tBB3D12AF1E49FBF500097510 /* SipHash.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBB5B02D71F5E1B880084D86B /* AppKit Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB9FCDCD1F5EB646001B8781 /* NSControl Glue.swift */,\n\t\t\t\tBB9FCDCB1F5E54BF001B8781 /* NSButton Glue.swift */,\n\t\t\t\tBB9FCDCF1F5ECFF3001B8781 /* NSPopUpButton Glue.swift */,\n\t\t\t\tBB6139821F5E1B3F005455D5 /* NSTextField Glue.swift */,\n\t\t\t);\n\t\t\tname = \"AppKit Extensions\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBB8990011D5DF2BD0097F350 /* Observable Sets */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB8990021D5DF2D20097F350 /* SetChange.swift */,\n\t\t\t\tBB8990091D5DF88C0097F350 /* ObservableSet.swift */,\n\t\t\t\tBB89901A1D5F6AAE0097F350 /* UpdatableSet.swift */,\n\t\t\t\tBB89901F1D5F6F980097F350 /* SetVariable.swift */,\n\t\t\t\tBBBBECA51DCA3FF0000B646D /* BufferedSet.swift */,\n\t\t\t\tBBF400631DA108E900DA0B2C /* ObservableContains.swift */,\n\t\t\t\tBBE4DF5B1DA55DA3005EC162 /* SetMappingBase.swift */,\n\t\t\t\tBBE4DF561DA55384005EC162 /* SetMappingForValue.swift */,\n\t\t\t\tBB7E04D11DA7240C00BE3051 /* SetMappingForSequence.swift */,\n\t\t\t\tBB7E04CC1DA723F300BE3051 /* SetMappingForValueField.swift */,\n\t\t\t\tBB7E04D61DA7242F00BE3051 /* SetMappingForSetField.swift */,\n\t\t\t\tBB7E04DB1DA7244A00BE3051 /* SetMappingForArrayField.swift */,\n\t\t\t\tBBB55B231C8FCC810050DDA9 /* SetFilteringOnPredicate.swift */,\n\t\t\t\tBBA033561DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift */,\n\t\t\t\tBBA0335B1DA7276200E83AC1 /* SetSortingByComparator.swift */,\n\t\t\t\tBB1E4D691D61EA5200F1831F /* SetSortingByMappingToComparable.swift */,\n\t\t\t\tBBA033601DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift */,\n\t\t\t\tBBBFD14A1EBE673200EC9814 /* SetSortingByComparableField.swift */,\n\t\t\t\tBBCD9E011DAA910500E85FB9 /* SetFolding.swift */,\n\t\t\t\tBB3D92951D647E83003BEDBF /* SetReference.swift */,\n\t\t\t);\n\t\t\tname = \"Observable Sets\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBB8D366C1DA116AA000D44C5 /* Examples */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB8D366D1DA116CB000D44C5 /* Bookshelf.swift */,\n\t\t\t);\n\t\t\tname = Examples;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB4F2531C9594E0002532CC /* Foundation Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB9D73F31DBE03EB00E20D67 /* DispatchSource.swift */,\n\t\t\t\tBBB55B321C8FCC820050DDA9 /* TimerSource.swift */,\n\t\t\t\tBBC2A8281CBC14C600394D24 /* NSObject Glue.swift */,\n\t\t\t\tBBAA827C1C91D43700586903 /* Type Helpers.swift */,\n\t\t\t\tBBB55B271C8FCC810050DDA9 /* NSNotificationCenter Support.swift */,\n\t\t\t\tBBF7B9581EACFC3B00073DF8 /* DependentValue.swift */,\n\t\t\t);\n\t\t\tname = \"Foundation Extensions\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55AA81C8F80020050DDA9 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55B1E1C8F9E920050DDA9 /* README.md */,\n\t\t\t\tBBB55B1D1C8F9E850050DDA9 /* LICENSE.md */,\n\t\t\t\tBBB55B1C1C8F90F60050DDA9 /* .travis.yml */,\n\t\t\t\tBB471D9E1DA58EA3002550B0 /* .codecov.yml */,\n\t\t\t\tBBC1F1D01D7EDF4A00A320F5 /* GlueKit.podspec */,\n\t\t\t\tBB568AE81DA66E6200BC4B58 /* Cartfile */,\n\t\t\t\tBB8D36711DA14800000D44C5 /* Package.swift */,\n\t\t\t\tBBB55ACC1C8F80660050DDA9 /* version.xcconfig */,\n\t\t\t\tBBB55BDD1C8FD0160050DDA9 /* Demo.playground */,\n\t\t\t\tBBB55BDB1C8FCFAD0050DDA9 /* Documentation */,\n\t\t\t\tBBB55AB41C8F80020050DDA9 /* Sources */,\n\t\t\t\tBBB55AC01C8F80020050DDA9 /* Tests */,\n\t\t\t\tBBB55BE31C8FD1C60050DDA9 /* PerformanceTests */,\n\t\t\t\tBBB55AB31C8F80020050DDA9 /* Products */,\n\t\t\t\tBB3D12AE1E49FBF500097510 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55AB31C8F80020050DDA9 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55AB21C8F80020050DDA9 /* GlueKit.framework */,\n\t\t\t\tBBB55ABC1C8F80020050DDA9 /* GlueKit-Test.xctest */,\n\t\t\t\tBBB55AD41C8F88F20050DDA9 /* GlueKit.framework */,\n\t\t\t\tBBB55ADD1C8F88F20050DDA9 /* GlueKit-Test.xctest */,\n\t\t\t\tBBB55AF11C8F8BE00050DDA9 /* GlueKit.framework */,\n\t\t\t\tBBB55AFE1C8F8CBB0050DDA9 /* GlueKit.framework */,\n\t\t\t\tBBB55B071C8F8CBB0050DDA9 /* GlueKit-Test.xctest */,\n\t\t\t\tBB351AFC1DB81E67005F083F /* PerformanceTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55AB41C8F80020050DDA9 /* Sources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55AB71C8F80020050DDA9 /* Info.plist */,\n\t\t\t\tBBB55B921C8FCCD40050DDA9 /* Tools */,\n\t\t\t\tBBB55B931C8FCD010050DDA9 /* Sources and Signals */,\n\t\t\t\tBBB55B941C8FCD320050DDA9 /* Abstract Observable */,\n\t\t\t\tBBE4DF3E1DA3A869005EC162 /* Observable Values */,\n\t\t\t\tBBB55B951C8FCD4E0050DDA9 /* Observable Arrays */,\n\t\t\t\tBB8990011D5DF2BD0097F350 /* Observable Sets */,\n\t\t\t\tBBB4F2531C9594E0002532CC /* Foundation Extensions */,\n\t\t\t\tBB5B02D71F5E1B880084D86B /* AppKit Extensions */,\n\t\t\t\tBBC3C84F1C93164700E10D59 /* UIKit Extensions */,\n\t\t\t);\n\t\t\tpath = Sources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55AC01C8F80020050DDA9 /* Tests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55AC31C8F80020050DDA9 /* Info.plist */,\n\t\t\t\tBBB55BA41C8FCE2C0050DDA9 /* TestUtilities.swift */,\n\t\t\t\tBBCD9DF41DA9104A00E85FB9 /* RefListTests.swift */,\n\t\t\t\tBBB55BD81C8FCE740050DDA9 /* Sources and Signals */,\n\t\t\t\tBBE9AAD21DC0F204000B3DD0 /* Abstract Observables */,\n\t\t\t\tBBB55BD91C8FCE9D0050DDA9 /* Observable Values */,\n\t\t\t\tBBB55BDA1C8FCEAE0050DDA9 /* Observable Arrays */,\n\t\t\t\tBBE4DF601DA56530005EC162 /* Observable Sets */,\n\t\t\t\tBBEA2A4C1DBFE60500CCCB08 /* Foundation Extensions */,\n\t\t\t\tBB8D366C1DA116AA000D44C5 /* Examples */,\n\t\t\t);\n\t\t\tname = Tests;\n\t\t\tpath = Tests/GlueKitTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55B921C8FCCD40050DDA9 /* Tools */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55B251C8FCC810050DDA9 /* Locks.swift */,\n\t\t\t\tBBB55B2B1C8FCC810050DDA9 /* Reference.swift */,\n\t\t\t\tBB69A7EE1D6AFF1A001D2821 /* Abstract.swift */,\n\t\t\t\tBBF3EB0D1D99ACDE006AC7CD /* RefList.swift */,\n\t\t\t);\n\t\t\tname = Tools;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55B931C8FCD010050DDA9 /* Sources and Signals */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB9D73CE1DBB38F900E20D67 /* Sink.swift */,\n\t\t\t\tBB6CE3B31DC4C21C00295C55 /* TransformedSink.swift */,\n\t\t\t\tBB9D73FD1DBE061D00E20D67 /* OwnedSink.swift */,\n\t\t\t\tBBB55B301C8FCC810050DDA9 /* Source.swift */,\n\t\t\t\tBBB55B221C8FCC810050DDA9 /* Connector.swift */,\n\t\t\t\tBB9D73C81DBB2EB400E20D67 /* Connect.swift */,\n\t\t\t\tBBB55B2E1C8FCC810050DDA9 /* Signal.swift */,\n\t\t\t\tBBB55B2F1C8FCC810050DDA9 /* SimpleSources.swift */,\n\t\t\t\tBBB55B261C8FCC810050DDA9 /* MergedSource.swift */,\n\t\t\t\tBB5B02DA1F5E3FC50084D86B /* ArrayGatheringSource.swift */,\n\t\t\t\tBB5B02DF1F5E3FDE0084D86B /* SetGatheringSource.swift */,\n\t\t\t\tBBB55B311C8FCC810050DDA9 /* TransformedSource.swift */,\n\t\t\t\tBBEA2A3E1DBFE38F00CCCB08 /* BufferedSource.swift */,\n\t\t\t\tBBEA2A391DBFE37A00CCCB08 /* BracketingSource.swift */,\n\t\t\t\tBBF7B9531EACEB0100073DF8 /* AccumulatedSource.swift */,\n\t\t\t);\n\t\t\tname = \"Sources and Signals\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55B941C8FCD320050DDA9 /* Abstract Observable */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB8990041D5DF8630097F350 /* Change.swift */,\n\t\t\t\tBBE9AAC91DC0F0A5000B3DD0 /* Update.swift */,\n\t\t\t\tBBE4DF3F1DA3A88C005EC162 /* ObservableType.swift */,\n\t\t\t\tBB9D73E51DBB727300E20D67 /* ChangesSource.swift */,\n\t\t\t\tBB9D73DF1DBB61C100E20D67 /* TransactionalThing.swift */,\n\t\t\t);\n\t\t\tname = \"Abstract Observable\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55B951C8FCD4E0050DDA9 /* Observable Arrays */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55B1F1C8FCC810050DDA9 /* ArrayChange.swift */,\n\t\t\t\tBB1657E61D71D65900094BAC /* ArrayChangeSeparation.swift */,\n\t\t\t\tBBB55B2A1C8FCC810050DDA9 /* ObservableArray.swift */,\n\t\t\t\tBBB55B341C8FCC820050DDA9 /* UpdatableArray.swift */,\n\t\t\t\tBBB55B201C8FCC810050DDA9 /* ArrayVariable.swift */,\n\t\t\t\tBB69A7FF1D6B2377001D2821 /* BufferedArray.swift */,\n\t\t\t\tBB69A83F1D6B9A7E001D2821 /* ArrayMappingForValue.swift */,\n\t\t\t\tBBB55B2D1C8FCC810050DDA9 /* ArrayMappingForValueField.swift */,\n\t\t\t\tBB7E04C71DA7233B00BE3051 /* ArrayMappingForArrayField.swift */,\n\t\t\t\tBB7E04E01DA7255D00BE3051 /* ArrayFilteringIndexmap.swift */,\n\t\t\t\tBB82E3E01D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift */,\n\t\t\t\tBB7E04E51DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift */,\n\t\t\t\tBBCD9DF81DAA885E00E85FB9 /* ArrayFolding.swift */,\n\t\t\t\tBB3D929A1D64862D003BEDBF /* ArrayReference.swift */,\n\t\t\t\tBB69A83A1D6B90F5001D2821 /* ArrayConcatenation.swift */,\n\t\t\t\tBBE4DF491DA409EE005EC162 /* DistinctUnion.swift */,\n\t\t\t);\n\t\t\tname = \"Observable Arrays\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55BD81C8FCE740050DDA9 /* Sources and Signals */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBCD9E3D1DABC81A00E85FB9 /* MockSink.swift */,\n\t\t\t\tBBEA2A2A1DBF9E9C00CCCB08 /* AnySinkTests.swift */,\n\t\t\t\tBBEA2A331DBFC4C300CCCB08 /* AnySourceTests.swift */,\n\t\t\t\tBBB55BA11C8FCE2C0050DDA9 /* SignalTests.swift */,\n\t\t\t\tBBB55BA21C8FCE2C0050DDA9 /* SimpleSourcesTests.swift */,\n\t\t\t\tBBB55B9B1C8FCE2C0050DDA9 /* MergedSourceTests.swift */,\n\t\t\t\tBBB55BA31C8FCE2C0050DDA9 /* SourceOperatorTests.swift */,\n\t\t\t\tBBE9AAD31DC0F474000B3DD0 /* BufferedSourceTests.swift */,\n\t\t\t\tBBE9AAD71DC0FC17000B3DD0 /* BracketingSourceTests.swift */,\n\t\t\t\tBBCD9E511DAC1B1300E85FB9 /* ConnectorTests.swift */,\n\t\t\t);\n\t\t\tname = \"Sources and Signals\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55BD91C8FCE9D0050DDA9 /* Observable Values */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB170F3D1DC221180000443E /* ValueChangeTests.swift */,\n\t\t\t\tBBB55B9D1C8FCE2C0050DDA9 /* ObservableValueTests.swift */,\n\t\t\t\tBB170F411DC22A300000443E /* UpdatableValueTests.swift */,\n\t\t\t\tBBB55BA61C8FCE2C0050DDA9 /* TwoWayBindingTests.swift */,\n\t\t\t\tBBB55BA71C8FCE2C0050DDA9 /* VariableTests.swift */,\n\t\t\t\tBBB55B9E1C8FCE2C0050DDA9 /* DistinctTests.swift */,\n\t\t\t\tBB88C4121DC3B65F00C7EC3C /* ValueBufferingTests.swift */,\n\t\t\t\tBBB55BA01C8FCE2C0050DDA9 /* ValueMappingTests.swift */,\n\t\t\t\tBBCD9E311DAAD66500E85FB9 /* CombinedObservableTests.swift */,\n\t\t\t\tBBCD9E351DAAD74600E85FB9 /* CombinedUpdatableTests.swift */,\n\t\t\t\tBBCD9E391DABC45000E85FB9 /* TypeHelperTests.swift */,\n\t\t\t\tBBBBEC911DCA1D43000B646D /* ValueReferenceTests.swift */,\n\t\t\t);\n\t\t\tname = \"Observable Values\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55BDA1C8FCEAE0050DDA9 /* Observable Arrays */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB568AF61DA6A9EE00BC4B58 /* MockArrayObserver.swift */,\n\t\t\t\tBBA033651DA7CFFE00E83AC1 /* ArrayModificationTests.swift */,\n\t\t\t\tBBA033691DA7D03300E83AC1 /* ArrayChangeTests.swift */,\n\t\t\t\tBBC36AE61DA83E0E00AB3E9D /* ArrayChangeSeparationTests.swift */,\n\t\t\t\tBBCD9E451DABEA5500E85FB9 /* ObservableArrayTests.swift */,\n\t\t\t\tBBB55B981C8FCE2C0050DDA9 /* ArrayVariableTests.swift */,\n\t\t\t\tBBBBECAA1DCA4168000B646D /* ArrayBufferingTests.swift */,\n\t\t\t\tBBB55B9F1C8FCE2C0050DDA9 /* ArrayMappingTests.swift */,\n\t\t\t\tBBC4AE4D1D9A829500FF7DE0 /* ArrayFilteringTests.swift */,\n\t\t\t\tBBCD9DFD1DAA8F7800E85FB9 /* ArrayFoldingTests.swift */,\n\t\t\t\tBBE4DF4E1DA412A0005EC162 /* DistinctUnionTests.swift */,\n\t\t\t\tBBCD9E491DABFA2900E85FB9 /* ArrayConcatenationTests.swift */,\n\t\t\t\tBBBBEC951DCA1FEB000B646D /* ArrayReferenceTests.swift */,\n\t\t\t);\n\t\t\tname = \"Observable Arrays\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55BDB1C8FCFAD0050DDA9 /* Documentation */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55BDC1C8FCFAD0050DDA9 /* Overview.md */,\n\t\t\t\tBB015F4E1DC624FB00C8C05A /* Language Enhancements.md */,\n\t\t\t);\n\t\t\tpath = Documentation;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBB55BE31C8FD1C60050DDA9 /* PerformanceTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55BEA1C8FD25F0050DDA9 /* GlueKitPerformanceTests.swift */,\n\t\t\t\tBBB55BE61C8FD1C60050DDA9 /* Info.plist */,\n\t\t\t);\n\t\t\tname = PerformanceTests;\n\t\t\tpath = Tests/PerformanceTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBC3C84F1C93164700E10D59 /* UIKit Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBC3C84D1C93164200E10D59 /* UIControl Glue.swift */,\n\t\t\t\tBB948BC01DD720FE00B0734C /* UISwitch Glue.swift */,\n\t\t\t\tBBF7B9511EACE69B00073DF8 /* UILabel Glue.swift */,\n\t\t\t\tBBB4F2511C9594A9002532CC /* UIDevice Glue.swift */,\n\t\t\t\tBB3982EC1EC109C4000CDCB5 /* UISearchBar Glue.swift */,\n\t\t\t\tBBF7B95F1EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift */,\n\t\t\t\tBBB4F26E1C99E6CB002532CC /* UIGestureRecognizer Glue.swift */,\n\t\t\t\tBB318F6A1CB9922F0086EE83 /* UIBarButtonItem Extensions.swift */,\n\t\t\t\tBB67E5511C9B6A63002B0AB5 /* CADisplayLink Extensions.swift */,\n\t\t\t);\n\t\t\tname = \"UIKit Extensions\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBE4DF3E1DA3A869005EC162 /* Observable Values */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBE4DF441DA3A908005EC162 /* ValueChange.swift */,\n\t\t\t\tBBB55B291C8FCC810050DDA9 /* ObservableValue.swift */,\n\t\t\t\tBBB55B331C8FCC820050DDA9 /* UpdatableValue.swift */,\n\t\t\t\tBB948BBB1DD5EFC900B0734C /* ComputedUpdatable.swift */,\n\t\t\t\tBB9D73EE1DBDFEE400E20D67 /* TwoWayBinding.swift */,\n\t\t\t\tBBB55B351C8FCC820050DDA9 /* Variable.swift */,\n\t\t\t\tBBB55B281C8FCC810050DDA9 /* BufferedValue.swift */,\n\t\t\t\tBBCD9E271DAAD2B900E85FB9 /* DistinctValue.swift */,\n\t\t\t\tBBCD9E221DAAD26200E85FB9 /* CompositeObservable.swift */,\n\t\t\t\tBBCD9E2C1DAAD4BC00E85FB9 /* CompositeUpdatable.swift */,\n\t\t\t\tBBCD9E0E1DAAC33700E85FB9 /* ValueMappingForValue.swift */,\n\t\t\t\tBBCD9E181DAAC50900E85FB9 /* ValueMappingForSourceField.swift */,\n\t\t\t\tBBB55B2C1C8FCC810050DDA9 /* ValueMappingForValueField.swift */,\n\t\t\t\tBBCD9E131DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift */,\n\t\t\t\tBBCD9E1D1DAAC7E600E85FB9 /* ValueMappingForSetField.swift */,\n\t\t\t\tBBBBEC8C1DCA1AEB000B646D /* ValueReference.swift */,\n\t\t\t);\n\t\t\tname = \"Observable Values\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBE4DF601DA56530005EC162 /* Observable Sets */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBB568AF21DA6942700BC4B58 /* MockSetObserver.swift */,\n\t\t\t\tBBCD9E411DABD4BE00E85FB9 /* ObservableSetTests.swift */,\n\t\t\t\tBBCD9E4D1DABFE8800E85FB9 /* SetVariableTests.swift */,\n\t\t\t\tBBBBECAE1DCA446A000B646D /* SetBufferingTests.swift */,\n\t\t\t\tBBE4DF611DA5654F005EC162 /* SetMappingTests.swift */,\n\t\t\t\tBB568AEE1DA693F700BC4B58 /* SetFilteringTests.swift */,\n\t\t\t\tBB471D991DA57FF8002550B0 /* SetSortingTests.swift */,\n\t\t\t\tBBCD9E061DAA918400E85FB9 /* SetFoldingTests.swift */,\n\t\t\t\tBBBBEC991DCA223A000B646D /* SetReferenceTests.swift */,\n\t\t\t);\n\t\t\tname = \"Observable Sets\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBE9AAD21DC0F204000B3DD0 /* Abstract Observables */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBCD9E0A1DAAB6E700E85FB9 /* MockUpdateSink.swift */,\n\t\t\t\tBB170F271DC106DE0000443E /* TestChange.swift */,\n\t\t\t\tBB170F2B1DC10D350000443E /* TestObservable.swift */,\n\t\t\t\tBB170F331DC110BD0000443E /* TestUpdatable.swift */,\n\t\t\t\tBBE9AACE1DC0F1F6000B3DD0 /* ChangeTests.swift */,\n\t\t\t\tBB170F231DC1066D0000443E /* UpdateTests.swift */,\n\t\t\t\tBB88C40D1DC3A08B00C7EC3C /* ObservableTypeTests.swift */,\n\t\t\t\tBB170F2F1DC10DDB0000443E /* ChangesSourceTests.swift */,\n\t\t\t\tBB170F371DC1545E0000443E /* TransactionStateTests.swift */,\n\t\t\t);\n\t\t\tname = \"Abstract Observables\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tBBEA2A4C1DBFE60500CCCB08 /* Foundation Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tBBB55BA51C8FCE2C0050DDA9 /* TimerSourceTests.swift */,\n\t\t\t\tBBB55B9A1C8FCE2C0050DDA9 /* KVOSupportTests.swift */,\n\t\t\t\tBBB55B9C1C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift */,\n\t\t\t\tBBBBEC9D1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift */,\n\t\t\t\tBBBBECA11DCA3AA8000B646D /* DispatchSourceTests.swift */,\n\t\t\t);\n\t\t\tname = \"Foundation Extensions\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\tBBB55AAF1C8F80020050DDA9 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AD11C8F88F20050DDA9 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AEE1C8F8BE00050DDA9 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AFB1C8F8CBB0050DDA9 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\tBB351AFB1DB81E67005F083F /* PerformanceTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BB351B041DB81E67005F083F /* Build configuration list for PBXNativeTarget \"PerformanceTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBB351AF81DB81E67005F083F /* Sources */,\n\t\t\t\tBB351AF91DB81E67005F083F /* Frameworks */,\n\t\t\t\tBB351AFA1DB81E67005F083F /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tBB351B031DB81E67005F083F /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = PerformanceTests;\n\t\t\tproductName = PerformanceTests;\n\t\t\tproductReference = BB351AFC1DB81E67005F083F /* PerformanceTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\tBBB55AB11C8F80020050DDA9 /* iOS */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBB55AC61C8F80020050DDA9 /* Build configuration list for PBXNativeTarget \"iOS\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBB55AAD1C8F80020050DDA9 /* Sources */,\n\t\t\t\tBBB55AAE1C8F80020050DDA9 /* Frameworks */,\n\t\t\t\tBBB55AAF1C8F80020050DDA9 /* Headers */,\n\t\t\t\tBBB55AB01C8F80020050DDA9 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = iOS;\n\t\t\tproductName = GlueKit;\n\t\t\tproductReference = BBB55AB21C8F80020050DDA9 /* GlueKit.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\tBBB55ABB1C8F80020050DDA9 /* iOS Tests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBB55AC91C8F80020050DDA9 /* Build configuration list for PBXNativeTarget \"iOS Tests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBB55AB81C8F80020050DDA9 /* Sources */,\n\t\t\t\tBBB55AB91C8F80020050DDA9 /* Frameworks */,\n\t\t\t\tBBB55ABA1C8F80020050DDA9 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tBBB55ABF1C8F80020050DDA9 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"iOS Tests\";\n\t\t\tproductName = GlueKitTests;\n\t\t\tproductReference = BBB55ABC1C8F80020050DDA9 /* GlueKit-Test.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\tBBB55AD31C8F88F20050DDA9 /* macOS */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBB55AE51C8F88F20050DDA9 /* Build configuration list for PBXNativeTarget \"macOS\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBB55ACF1C8F88F20050DDA9 /* Sources */,\n\t\t\t\tBBB55AD01C8F88F20050DDA9 /* Frameworks */,\n\t\t\t\tBBB55AD11C8F88F20050DDA9 /* Headers */,\n\t\t\t\tBBB55AD21C8F88F20050DDA9 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = macOS;\n\t\t\tproductName = GlueKit;\n\t\t\tproductReference = BBB55AD41C8F88F20050DDA9 /* GlueKit.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\tBBB55ADC1C8F88F20050DDA9 /* macOS Tests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBB55AE81C8F88F20050DDA9 /* Build configuration list for PBXNativeTarget \"macOS Tests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBB55AD91C8F88F20050DDA9 /* Sources */,\n\t\t\t\tBBB55ADA1C8F88F20050DDA9 /* Frameworks */,\n\t\t\t\tBBB55ADB1C8F88F20050DDA9 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tBBB55AE01C8F88F20050DDA9 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"macOS Tests\";\n\t\t\tproductName = GlueKitTests;\n\t\t\tproductReference = BBB55ADD1C8F88F20050DDA9 /* GlueKit-Test.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\tBBB55AF01C8F8BE00050DDA9 /* watchOS */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBB55AF61C8F8BE00050DDA9 /* Build configuration list for PBXNativeTarget \"watchOS\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBB55AEC1C8F8BE00050DDA9 /* Sources */,\n\t\t\t\tBBB55AED1C8F8BE00050DDA9 /* Frameworks */,\n\t\t\t\tBBB55AEE1C8F8BE00050DDA9 /* Headers */,\n\t\t\t\tBBB55AEF1C8F8BE00050DDA9 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = watchOS;\n\t\t\tproductName = GlueKit;\n\t\t\tproductReference = BBB55AF11C8F8BE00050DDA9 /* GlueKit.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\tBBB55AFD1C8F8CBB0050DDA9 /* tvOS */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBB55B0F1C8F8CBC0050DDA9 /* Build configuration list for PBXNativeTarget \"tvOS\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBB55AF91C8F8CBB0050DDA9 /* Sources */,\n\t\t\t\tBBB55AFA1C8F8CBB0050DDA9 /* Frameworks */,\n\t\t\t\tBBB55AFB1C8F8CBB0050DDA9 /* Headers */,\n\t\t\t\tBBB55AFC1C8F8CBB0050DDA9 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = tvOS;\n\t\t\tproductName = GlueKit;\n\t\t\tproductReference = BBB55AFE1C8F8CBB0050DDA9 /* GlueKit.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\tBBB55B061C8F8CBB0050DDA9 /* tvOS Tests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = BBB55B121C8F8CBC0050DDA9 /* Build configuration list for PBXNativeTarget \"tvOS Tests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tBBB55B031C8F8CBB0050DDA9 /* Sources */,\n\t\t\t\tBBB55B041C8F8CBB0050DDA9 /* Frameworks */,\n\t\t\t\tBBB55B051C8F8CBB0050DDA9 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tBBB55B0A1C8F8CBC0050DDA9 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = \"tvOS Tests\";\n\t\t\tproductName = GlueKitTests;\n\t\t\tproductReference = BBB55B071C8F8CBB0050DDA9 /* GlueKit-Test.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tBBB55AA91C8F80020050DDA9 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0800;\n\t\t\t\tLastUpgradeCheck = 0900;\n\t\t\t\tORGANIZATIONNAME = \"Károly Lőrentey\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\tBB351AFB1DB81E67005F083F = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.0;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\tBBB55AB11C8F80020050DDA9 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t\tLastSwiftMigration = 0800;\n\t\t\t\t\t};\n\t\t\t\t\tBBB55ABB1C8F80020050DDA9 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t\tLastSwiftMigration = 0800;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\tBBB55AD31C8F88F20050DDA9 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t\tLastSwiftMigration = 0800;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\tBBB55ADC1C8F88F20050DDA9 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t\tLastSwiftMigration = 0800;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\tBBB55AF01C8F8BE00050DDA9 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t\tLastSwiftMigration = 0800;\n\t\t\t\t\t};\n\t\t\t\t\tBBB55AFD1C8F8CBB0050DDA9 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t\tLastSwiftMigration = 0800;\n\t\t\t\t\t};\n\t\t\t\t\tBBB55B061C8F8CBB0050DDA9 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3;\n\t\t\t\t\t\tLastSwiftMigration = 0800;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = BBB55AAC1C8F80020050DDA9 /* Build configuration list for PBXProject \"GlueKit\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = BBB55AA81C8F80020050DDA9;\n\t\t\tproductRefGroup = BBB55AB31C8F80020050DDA9 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tBBB55AB11C8F80020050DDA9 /* iOS */,\n\t\t\t\tBBB55AD31C8F88F20050DDA9 /* macOS */,\n\t\t\t\tBBB55AF01C8F8BE00050DDA9 /* watchOS */,\n\t\t\t\tBBB55AFD1C8F8CBB0050DDA9 /* tvOS */,\n\t\t\t\tBBB55ABB1C8F80020050DDA9 /* iOS Tests */,\n\t\t\t\tBBB55ADC1C8F88F20050DDA9 /* macOS Tests */,\n\t\t\t\tBBB55B061C8F8CBB0050DDA9 /* tvOS Tests */,\n\t\t\t\tBB351AFB1DB81E67005F083F /* PerformanceTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tBB351AFA1DB81E67005F083F /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AB01C8F80020050DDA9 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55ABA1C8F80020050DDA9 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AD21C8F88F20050DDA9 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55ADB1C8F88F20050DDA9 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AEF1C8F8BE00050DDA9 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AFC1C8F8CBB0050DDA9 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55B051C8F8CBB0050DDA9 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tBB351AF81DB81E67005F083F /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB351B071DB81EE1005F083F /* GlueKitPerformanceTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AAD1C8F80020050DDA9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB9D742F1DBE7B3B00E20D67 /* SetFilteringOnPredicate.swift in Sources */,\n\t\t\t\tBBB55B5E1C8FCC820050DDA9 /* ObservableValue.swift in Sources */,\n\t\t\t\tBB7E04E61DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift in Sources */,\n\t\t\t\tBB948BBC1DD5EFC900B0734C /* ComputedUpdatable.swift in Sources */,\n\t\t\t\tBB9D74451DBEB5F300E20D67 /* DistinctUnion.swift in Sources */,\n\t\t\t\tBB9D744A1DBEC82C00E20D67 /* ValueMappingForSetField.swift in Sources */,\n\t\t\t\tBBB55B821C8FCC820050DDA9 /* TimerSource.swift in Sources */,\n\t\t\t\tBB1657E71D71D65900094BAC /* ArrayChangeSeparation.swift in Sources */,\n\t\t\t\tBBBBECA61DCA3FF0000B646D /* BufferedSet.swift in Sources */,\n\t\t\t\tBB69A83B1D6B90F5001D2821 /* ArrayConcatenation.swift in Sources */,\n\t\t\t\tBB6CE3B41DC4C21C00295C55 /* TransformedSink.swift in Sources */,\n\t\t\t\tBB82E3E11D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift in Sources */,\n\t\t\t\tBBF7B9601EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift in Sources */,\n\t\t\t\tBB9D742E1DBE7B3B00E20D67 /* SetMappingForArrayField.swift in Sources */,\n\t\t\t\tBB9D74301DBE7B3B00E20D67 /* SetFilteringOnObservableBool.swift in Sources */,\n\t\t\t\tBBB55B761C8FCC820050DDA9 /* SimpleSources.swift in Sources */,\n\t\t\t\tBBC2A8291CBC14C600394D24 /* NSObject Glue.swift in Sources */,\n\t\t\t\tBB5B02E01F5E3FDE0084D86B /* SetGatheringSource.swift in Sources */,\n\t\t\t\tBB69A7FB1D6B1D94001D2821 /* ObservableArray.swift in Sources */,\n\t\t\t\tBBF3EB0E1D99ACDE006AC7CD /* RefList.swift in Sources */,\n\t\t\t\tBBB55B7E1C8FCC820050DDA9 /* TransformedSource.swift in Sources */,\n\t\t\t\tBB9D73E61DBB727300E20D67 /* ChangesSource.swift in Sources */,\n\t\t\t\tBBE4DF451DA3A908005EC162 /* ValueChange.swift in Sources */,\n\t\t\t\tBBB55B661C8FCC820050DDA9 /* Reference.swift in Sources */,\n\t\t\t\tBBCD9E281DAAD2B900E85FB9 /* DistinctValue.swift in Sources */,\n\t\t\t\tBBB55B721C8FCC820050DDA9 /* Signal.swift in Sources */,\n\t\t\t\tBB9D74331DBE7B3B00E20D67 /* SetSortingByMappingToObservableComparable.swift in Sources */,\n\t\t\t\tBB69A8081D6B442B001D2821 /* ArrayVariable.swift in Sources */,\n\t\t\t\tBB9D74311DBE7B3B00E20D67 /* SetSortingByComparator.swift in Sources */,\n\t\t\t\tBBB55B5A1C8FCC820050DDA9 /* BufferedValue.swift in Sources */,\n\t\t\t\tBBCD9E231DAAD26200E85FB9 /* CompositeObservable.swift in Sources */,\n\t\t\t\tBB9D74271DBE7B3B00E20D67 /* SetVariable.swift in Sources */,\n\t\t\t\tBB9D742D1DBE7B3B00E20D67 /* SetMappingForSetField.swift in Sources */,\n\t\t\t\tBBB55B521C8FCC820050DDA9 /* MergedSource.swift in Sources */,\n\t\t\t\tBB69A7F31D6B1D7B001D2821 /* Change.swift in Sources */,\n\t\t\t\tBB69A7F71D6B1D82001D2821 /* ArrayChange.swift in Sources */,\n\t\t\t\tBB7E04E11DA7255D00BE3051 /* ArrayFilteringIndexmap.swift in Sources */,\n\t\t\t\tBB9D73E01DBB61C100E20D67 /* TransactionalThing.swift in Sources */,\n\t\t\t\tBB9D73CF1DBB38F900E20D67 /* Sink.swift in Sources */,\n\t\t\t\tBB69A81D1D6B71F9001D2821 /* SetChange.swift in Sources */,\n\t\t\t\tBB69A8101D6B5397001D2821 /* ValueMappingForValueField.swift in Sources */,\n\t\t\t\tBBB55B4E1C8FCC820050DDA9 /* Locks.swift in Sources */,\n\t\t\t\tBBB55B8E1C8FCC820050DDA9 /* Variable.swift in Sources */,\n\t\t\t\tBBF7B9591EACFC3B00073DF8 /* DependentValue.swift in Sources */,\n\t\t\t\tBB9D74261DBE7B3B00E20D67 /* UpdatableSet.swift in Sources */,\n\t\t\t\tBB9D73C91DBB2EB400E20D67 /* Connect.swift in Sources */,\n\t\t\t\tBBBBEC8D1DCA1AEB000B646D /* ValueReference.swift in Sources */,\n\t\t\t\tBB318F6B1CB992300086EE83 /* UIBarButtonItem Extensions.swift in Sources */,\n\t\t\t\tBB9D742B1DBE7B3B00E20D67 /* SetMappingForSequence.swift in Sources */,\n\t\t\t\tBB9D74291DBE7B3B00E20D67 /* SetMappingBase.swift in Sources */,\n\t\t\t\tBBBFD14B1EBE673200EC9814 /* SetSortingByComparableField.swift in Sources */,\n\t\t\t\tBBB55B561C8FCC820050DDA9 /* NSNotificationCenter Support.swift in Sources */,\n\t\t\t\tBBAA827D1C91D43700586903 /* Type Helpers.swift in Sources */,\n\t\t\t\tBB5B02DB1F5E3FC50084D86B /* ArrayGatheringSource.swift in Sources */,\n\t\t\t\tBB9D742A1DBE7B3B00E20D67 /* SetMappingForValue.swift in Sources */,\n\t\t\t\tBBCD9E141DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift in Sources */,\n\t\t\t\tBBEA2A3A1DBFE37A00CCCB08 /* BracketingSource.swift in Sources */,\n\t\t\t\tBBB55B421C8FCC820050DDA9 /* Connector.swift in Sources */,\n\t\t\t\tBB9D73EF1DBDFEE400E20D67 /* TwoWayBinding.swift in Sources */,\n\t\t\t\tBBEA2A3F1DBFE38F00CCCB08 /* BufferedSource.swift in Sources */,\n\t\t\t\tBB948BC11DD720FE00B0734C /* UISwitch Glue.swift in Sources */,\n\t\t\t\tBB9D742C1DBE7B3B00E20D67 /* SetMappingForValueField.swift in Sources */,\n\t\t\t\tBBB55B861C8FCC820050DDA9 /* UpdatableValue.swift in Sources */,\n\t\t\t\tBB69A8001D6B2377001D2821 /* BufferedArray.swift in Sources */,\n\t\t\t\tBBB55B7A1C8FCC820050DDA9 /* Source.swift in Sources */,\n\t\t\t\tBB9D74351DBE7B3B00E20D67 /* SetReference.swift in Sources */,\n\t\t\t\tBBC3C84E1C93164200E10D59 /* UIControl Glue.swift in Sources */,\n\t\t\t\tBB69A8401D6B9A7E001D2821 /* ArrayMappingForValue.swift in Sources */,\n\t\t\t\tBBCD9E0F1DAAC33700E85FB9 /* ValueMappingForValue.swift in Sources */,\n\t\t\t\tBB69A8191D6B6A99001D2821 /* ArrayReference.swift in Sources */,\n\t\t\t\tBB7E04C81DA7233B00BE3051 /* ArrayMappingForArrayField.swift in Sources */,\n\t\t\t\tBBCD9E2D1DAAD4BC00E85FB9 /* CompositeUpdatable.swift in Sources */,\n\t\t\t\tBBCD9DF91DAA885E00E85FB9 /* ArrayFolding.swift in Sources */,\n\t\t\t\tBB9D74341DBE7B3B00E20D67 /* SetFolding.swift in Sources */,\n\t\t\t\tBBB4F26F1C99E6CC002532CC /* UIGestureRecognizer Glue.swift in Sources */,\n\t\t\t\tBBE9AACA1DC0F0A5000B3DD0 /* Update.swift in Sources */,\n\t\t\t\tBBF7B9541EACEB0100073DF8 /* AccumulatedSource.swift in Sources */,\n\t\t\t\tBB9D74281DBE7B3B00E20D67 /* ObservableContains.swift in Sources */,\n\t\t\t\tBBE4DF401DA3A88C005EC162 /* ObservableType.swift in Sources */,\n\t\t\t\tBB9D74241DBE7B3700E20D67 /* ObservableSet.swift in Sources */,\n\t\t\t\tBB9D73F41DBE03EB00E20D67 /* DispatchSource.swift in Sources */,\n\t\t\t\tBB69A7EF1D6AFF1A001D2821 /* Abstract.swift in Sources */,\n\t\t\t\tBB69A80C1D6B472D001D2821 /* ArrayMappingForValueField.swift in Sources */,\n\t\t\t\tBB67E5521C9B6A63002B0AB5 /* CADisplayLink Extensions.swift in Sources */,\n\t\t\t\tBB69A8041D6B344C001D2821 /* UpdatableArray.swift in Sources */,\n\t\t\t\tBBB4F2521C9594A9002532CC /* UIDevice Glue.swift in Sources */,\n\t\t\t\tBBF7B9521EACE69B00073DF8 /* UILabel Glue.swift in Sources */,\n\t\t\t\tBB3982ED1EC109C4000CDCB5 /* UISearchBar Glue.swift in Sources */,\n\t\t\t\tBB9D73FE1DBE061D00E20D67 /* OwnedSink.swift in Sources */,\n\t\t\t\tBBCD9E191DAAC50900E85FB9 /* ValueMappingForSourceField.swift in Sources */,\n\t\t\t\tBB9D74321DBE7B3B00E20D67 /* SetSortingByMappingToComparable.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AB81C8F80020050DDA9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBBEBFF791DB77D77008AC632 /* ArrayFilteringTests.swift in Sources */,\n\t\t\t\tBBB55BCC1C8FCE2C0050DDA9 /* TestUtilities.swift in Sources */,\n\t\t\t\tBBB55BB41C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift in Sources */,\n\t\t\t\tBBE9AAD41DC0F474000B3DD0 /* BufferedSourceTests.swift in Sources */,\n\t\t\t\tBBE9AACF1DC0F1F6000B3DD0 /* ChangeTests.swift in Sources */,\n\t\t\t\tBBB55BBA1C8FCE2C0050DDA9 /* DistinctTests.swift in Sources */,\n\t\t\t\tBBB55BAE1C8FCE2C0050DDA9 /* KVOSupportTests.swift in Sources */,\n\t\t\t\tBB88C4131DC3B65F00C7EC3C /* ValueBufferingTests.swift in Sources */,\n\t\t\t\tBBCD9E3A1DABC45000E85FB9 /* TypeHelperTests.swift in Sources */,\n\t\t\t\tBBB55BC31C8FCE2C0050DDA9 /* SignalTests.swift in Sources */,\n\t\t\t\tBBCD9E0B1DAAB6E700E85FB9 /* MockUpdateSink.swift in Sources */,\n\t\t\t\tBBE4DF661DA5656B005EC162 /* SetMappingTests.swift in Sources */,\n\t\t\t\tBBBBECA21DCA3AA8000B646D /* DispatchSourceTests.swift in Sources */,\n\t\t\t\tBBEBFF771DB77D77008AC632 /* ArrayVariableTests.swift in Sources */,\n\t\t\t\tBBCD9E361DAAD74600E85FB9 /* CombinedUpdatableTests.swift in Sources */,\n\t\t\t\tBBEBFF741DB77D77008AC632 /* ArrayChangeTests.swift in Sources */,\n\t\t\t\tBB170F241DC1066D0000443E /* UpdateTests.swift in Sources */,\n\t\t\t\tBB471D9A1DA57FF8002550B0 /* SetSortingTests.swift in Sources */,\n\t\t\t\tBBEBFF781DB77D77008AC632 /* ArrayMappingTests.swift in Sources */,\n\t\t\t\tBBCD9E4E1DABFE8800E85FB9 /* SetVariableTests.swift in Sources */,\n\t\t\t\tBB88C40E1DC3A08B00C7EC3C /* ObservableTypeTests.swift in Sources */,\n\t\t\t\tBBEBFF7A1DB77D77008AC632 /* ArrayFoldingTests.swift in Sources */,\n\t\t\t\tBBCD9DF51DA9104A00E85FB9 /* RefListTests.swift in Sources */,\n\t\t\t\tBB170F341DC110BD0000443E /* TestUpdatable.swift in Sources */,\n\t\t\t\tBB170F2C1DC10D350000443E /* TestObservable.swift in Sources */,\n\t\t\t\tBBCD9E071DAA918400E85FB9 /* SetFoldingTests.swift in Sources */,\n\t\t\t\tBBEBFF761DB77D77008AC632 /* ObservableArrayTests.swift in Sources */,\n\t\t\t\tBBBBEC9A1DCA223A000B646D /* SetReferenceTests.swift in Sources */,\n\t\t\t\tBBEBFF721DB77D77008AC632 /* MockArrayObserver.swift in Sources */,\n\t\t\t\tBBBBEC921DCA1D43000B646D /* ValueReferenceTests.swift in Sources */,\n\t\t\t\tBB170F281DC106DE0000443E /* TestChange.swift in Sources */,\n\t\t\t\tBBBBECAF1DCA446A000B646D /* SetBufferingTests.swift in Sources */,\n\t\t\t\tBB170F301DC10DDB0000443E /* ChangesSourceTests.swift in Sources */,\n\t\t\t\tBBBBEC961DCA1FEB000B646D /* ArrayReferenceTests.swift in Sources */,\n\t\t\t\tBBCD9E3E1DABC81A00E85FB9 /* MockSink.swift in Sources */,\n\t\t\t\tBBB55BD51C8FCE2C0050DDA9 /* VariableTests.swift in Sources */,\n\t\t\t\tBBCD9E521DAC1B1300E85FB9 /* ConnectorTests.swift in Sources */,\n\t\t\t\tBBCD9E321DAAD66500E85FB9 /* CombinedObservableTests.swift in Sources */,\n\t\t\t\tBBB55BC61C8FCE2C0050DDA9 /* SimpleSourcesTests.swift in Sources */,\n\t\t\t\tBBBBECAB1DCA4168000B646D /* ArrayBufferingTests.swift in Sources */,\n\t\t\t\tBBEA2A341DBFC4C300CCCB08 /* AnySourceTests.swift in Sources */,\n\t\t\t\tBBEBFF751DB77D77008AC632 /* ArrayChangeSeparationTests.swift in Sources */,\n\t\t\t\tBBB55BD21C8FCE2C0050DDA9 /* TwoWayBindingTests.swift in Sources */,\n\t\t\t\tBBCD9E421DABD4BE00E85FB9 /* ObservableSetTests.swift in Sources */,\n\t\t\t\tBB568AEF1DA693F700BC4B58 /* SetFilteringTests.swift in Sources */,\n\t\t\t\tBBBBEC9E1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift in Sources */,\n\t\t\t\tBB170F381DC1545E0000443E /* TransactionStateTests.swift in Sources */,\n\t\t\t\tBBB55BCF1C8FCE2C0050DDA9 /* TimerSourceTests.swift in Sources */,\n\t\t\t\tBB170F421DC22A300000443E /* UpdatableValueTests.swift in Sources */,\n\t\t\t\tBBB55BC01C8FCE2C0050DDA9 /* ValueMappingTests.swift in Sources */,\n\t\t\t\tBBB55BC91C8FCE2C0050DDA9 /* SourceOperatorTests.swift in Sources */,\n\t\t\t\tBBEBFF7C1DB77D77008AC632 /* ArrayConcatenationTests.swift in Sources */,\n\t\t\t\tBB170F3E1DC221180000443E /* ValueChangeTests.swift in Sources */,\n\t\t\t\tBBEBFF7B1DB77D77008AC632 /* DistinctUnionTests.swift in Sources */,\n\t\t\t\tBBEA2A2B1DBF9E9C00CCCB08 /* AnySinkTests.swift in Sources */,\n\t\t\t\tBBB55BB11C8FCE2C0050DDA9 /* MergedSourceTests.swift in Sources */,\n\t\t\t\tBB568AF31DA6942700BC4B58 /* MockSetObserver.swift in Sources */,\n\t\t\t\tBBEBFF731DB77D77008AC632 /* ArrayModificationTests.swift in Sources */,\n\t\t\t\tBB8D366E1DA116CB000D44C5 /* Bookshelf.swift in Sources */,\n\t\t\t\tBBB55BB71C8FCE2C0050DDA9 /* ObservableValueTests.swift in Sources */,\n\t\t\t\tBBE9AAD81DC0FC17000B3DD0 /* BracketingSourceTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55ACF1C8F88F20050DDA9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB6CE3C01DC4CD7200295C55 /* TwoWayBinding.swift in Sources */,\n\t\t\t\tBB8195B31DD256B700644668 /* UIBarButtonItem Extensions.swift in Sources */,\n\t\t\t\tBBF3EB0F1D99ACDE006AC7CD /* RefList.swift in Sources */,\n\t\t\t\tBB948BBD1DD5EFC900B0734C /* ComputedUpdatable.swift in Sources */,\n\t\t\t\tBB015F421DC526BF00C8C05A /* ArrayFilteringOnObservableBool.swift in Sources */,\n\t\t\t\tBB015F491DC52D3500C8C05A /* DistinctUnion.swift in Sources */,\n\t\t\t\tBB015F2F1DC4F5C200C8C05A /* UpdatableArray.swift in Sources */,\n\t\t\t\tBBBBECA71DCA3FF0000B646D /* BufferedSet.swift in Sources */,\n\t\t\t\tBB015F401DC5261900C8C05A /* ArrayFilteringIndexmap.swift in Sources */,\n\t\t\t\tBB9D73D01DBB38F900E20D67 /* Sink.swift in Sources */,\n\t\t\t\tBB6CE3DA1DC4F2FB00295C55 /* SetChange.swift in Sources */,\n\t\t\t\tBB6CE3DB1DC4F2FB00295C55 /* ObservableSet.swift in Sources */,\n\t\t\t\tBBF7B9611EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift in Sources */,\n\t\t\t\tBB015F391DC509D000C8C05A /* SetMappingForValue.swift in Sources */,\n\t\t\t\tBB015F361DC5004F00C8C05A /* ValueMappingForSetField.swift in Sources */,\n\t\t\t\tBB6CE3C11DC4CD7600295C55 /* Variable.swift in Sources */,\n\t\t\t\tBB9D741E1DBE644200E20D67 /* NSNotificationCenter Support.swift in Sources */,\n\t\t\t\tBB5B02E11F5E3FDE0084D86B /* SetGatheringSource.swift in Sources */,\n\t\t\t\tBB6CE3C61DC4CD8D00295C55 /* ValueMappingForValue.swift in Sources */,\n\t\t\t\tBB015F301DC4F64200C8C05A /* UpdatableSet.swift in Sources */,\n\t\t\t\tBB9FCDCC1F5E54BF001B8781 /* NSButton Glue.swift in Sources */,\n\t\t\t\tBB9FCDD01F5ECFF3001B8781 /* NSPopUpButton Glue.swift in Sources */,\n\t\t\t\tBB6CE3D91DC4F19D00295C55 /* ObservableArray.swift in Sources */,\n\t\t\t\tBB6CE3BC1DC4CD6500295C55 /* TransactionalThing.swift in Sources */,\n\t\t\t\tBBEA2A401DBFE38F00CCCB08 /* BufferedSource.swift in Sources */,\n\t\t\t\tBB69A7F01D6AFF1A001D2821 /* Abstract.swift in Sources */,\n\t\t\t\tBB015F471DC52B6200C8C05A /* ArrayConcatenation.swift in Sources */,\n\t\t\t\tBB6CE3D51DC4F17A00295C55 /* ArrayChangeSeparation.swift in Sources */,\n\t\t\t\tBB6CE3D41DC4F17700295C55 /* ArrayChange.swift in Sources */,\n\t\t\t\tBB015F571DC67DA900C8C05A /* SetFilteringOnObservableBool.swift in Sources */,\n\t\t\t\tBB6CE3C51DC4CD8700295C55 /* CompositeUpdatable.swift in Sources */,\n\t\t\t\tBB015F4C1DC6233E00C8C05A /* SetMappingForSequence.swift in Sources */,\n\t\t\t\tBB6CE3BA1DC4CD3F00295C55 /* ObservableType.swift in Sources */,\n\t\t\t\tBB015F551DC67C1000C8C05A /* SetFilteringOnPredicate.swift in Sources */,\n\t\t\t\tBB015F501DC678C200C8C05A /* SetMappingForSetField.swift in Sources */,\n\t\t\t\tBB6CE3BF1DC4CD6F00295C55 /* UpdatableValue.swift in Sources */,\n\t\t\t\tBB9D73CA1DBB2EB400E20D67 /* Connect.swift in Sources */,\n\t\t\t\tBB015F3C1DC5106B00C8C05A /* ArrayMappingForValueField.swift in Sources */,\n\t\t\t\tBB015F331DC4FC3700C8C05A /* ArrayVariable.swift in Sources */,\n\t\t\t\tBB8195B61DD256B700644668 /* CADisplayLink Extensions.swift in Sources */,\n\t\t\t\tBB9D73DC1DBB612600E20D67 /* Connector.swift in Sources */,\n\t\t\t\tBBBFD14C1EBE673200EC9814 /* SetSortingByComparableField.swift in Sources */,\n\t\t\t\tBB6CE3B91DC4CD3B00295C55 /* Update.swift in Sources */,\n\t\t\t\tBB6CE3C21DC4CD7A00295C55 /* BufferedValue.swift in Sources */,\n\t\t\t\tBB015F511DC679F000C8C05A /* SetMappingForArrayField.swift in Sources */,\n\t\t\t\tBB6CE3CE1DC4E4B100295C55 /* Type Helpers.swift in Sources */,\n\t\t\t\tBB015F3D1DC512D600C8C05A /* ArrayMappingForArrayField.swift in Sources */,\n\t\t\t\tBBF7B95A1EACFC3B00073DF8 /* DependentValue.swift in Sources */,\n\t\t\t\tBB015F561DC67C3F00C8C05A /* SetReference.swift in Sources */,\n\t\t\t\tBB6CE3BD1DC4CD6900295C55 /* ValueChange.swift in Sources */,\n\t\t\t\tBB9D73D51DBB4BB300E20D67 /* MergedSource.swift in Sources */,\n\t\t\t\tBBB55B671C8FCC820050DDA9 /* Reference.swift in Sources */,\n\t\t\t\tBB6CE3B51DC4C21C00295C55 /* TransformedSink.swift in Sources */,\n\t\t\t\tBB9FCDCE1F5EB646001B8781 /* NSControl Glue.swift in Sources */,\n\t\t\t\tBB015F371DC506B400C8C05A /* ValueMappingForArrayField.swift in Sources */,\n\t\t\t\tBB015F5F1DC687EE00C8C05A /* SetSortingByComparator.swift in Sources */,\n\t\t\t\tBB5B02DC1F5E3FC50084D86B /* ArrayGatheringSource.swift in Sources */,\n\t\t\t\tBB015F3A1DC50B1200C8C05A /* ArrayMappingForValue.swift in Sources */,\n\t\t\t\tBB015F411DC5262400C8C05A /* ArrayFilteringOnPredicate.swift in Sources */,\n\t\t\t\tBB015F5D1DC686CD00C8C05A /* SetSortingByMappingToObservableComparable.swift in Sources */,\n\t\t\t\tBB8195B21DD256B700644668 /* UIControl Glue.swift in Sources */,\n\t\t\t\tBB948BC21DD7213200B0734C /* UISwitch Glue.swift in Sources */,\n\t\t\t\tBB015F321DC4FC3100C8C05A /* SetVariable.swift in Sources */,\n\t\t\t\tBB6CE3BB1DC4CD4800295C55 /* ChangesSource.swift in Sources */,\n\t\t\t\tBB6CE3C41DC4CD8300295C55 /* CompositeObservable.swift in Sources */,\n\t\t\t\tBB6CE3C81DC4D2D400295C55 /* ValueMappingForValueField.swift in Sources */,\n\t\t\t\tBB6139831F5E1B3F005455D5 /* NSTextField Glue.swift in Sources */,\n\t\t\t\tBB9D73F51DBE03EB00E20D67 /* DispatchSource.swift in Sources */,\n\t\t\t\tBB9D73FF1DBE061D00E20D67 /* OwnedSink.swift in Sources */,\n\t\t\t\tBB015F451DC52ADD00C8C05A /* ArrayFolding.swift in Sources */,\n\t\t\t\tBB9D73F81DBE041A00E20D67 /* TimerSource.swift in Sources */,\n\t\t\t\tBB9D73D61DBB519500E20D67 /* TransformedSource.swift in Sources */,\n\t\t\t\tBB6CE3C31DC4CD7E00295C55 /* DistinctValue.swift in Sources */,\n\t\t\t\tBB9D74201DBE654600E20D67 /* NSObject Glue.swift in Sources */,\n\t\t\t\tBB9D73D31DBB3DEA00E20D67 /* Signal.swift in Sources */,\n\t\t\t\tBBBBEC8E1DCA1AEB000B646D /* ValueReference.swift in Sources */,\n\t\t\t\tBBF7B9551EACEB0100073DF8 /* AccumulatedSource.swift in Sources */,\n\t\t\t\tBB3982EE1EC109C7000CDCB5 /* UISearchBar Glue.swift in Sources */,\n\t\t\t\tBB015F4F1DC677A900C8C05A /* SetMappingForValueField.swift in Sources */,\n\t\t\t\tBB8195B41DD256B700644668 /* UIDevice Glue.swift in Sources */,\n\t\t\t\tBB6CE3BE1DC4CD6B00295C55 /* ObservableValue.swift in Sources */,\n\t\t\t\tBB015F5C1DC6868F00C8C05A /* SetSortingByMappingToComparable.swift in Sources */,\n\t\t\t\tBB015F341DC4FDCE00C8C05A /* SetMappingBase.swift in Sources */,\n\t\t\t\tBB8195B51DD256B700644668 /* UIGestureRecognizer Glue.swift in Sources */,\n\t\t\t\tBB015F5A1DC684E200C8C05A /* SetFolding.swift in Sources */,\n\t\t\t\tBBEA2A3B1DBFE37B00CCCB08 /* BracketingSource.swift in Sources */,\n\t\t\t\tBBB55B4F1C8FCC820050DDA9 /* Locks.swift in Sources */,\n\t\t\t\tBBB55B7B1C8FCC820050DDA9 /* Source.swift in Sources */,\n\t\t\t\tBB9D73D41DBB4A3700E20D67 /* SimpleSources.swift in Sources */,\n\t\t\t\tBB6CE3B81DC4CD3900295C55 /* Change.swift in Sources */,\n\t\t\t\tBB6CE3C71DC4D09500295C55 /* ValueMappingForSourceField.swift in Sources */,\n\t\t\t\tBB015F381DC508AC00C8C05A /* BufferedArray.swift in Sources */,\n\t\t\t\tBB015F431DC5281F00C8C05A /* ArrayReference.swift in Sources */,\n\t\t\t\tBB015F351DC4FDD300C8C05A /* ObservableContains.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AD91C8F88F20050DDA9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBBBBEC931DCA1D43000B646D /* ValueReferenceTests.swift in Sources */,\n\t\t\t\tBB170F3C1DC220B20000443E /* ObservableValueTests.swift in Sources */,\n\t\t\t\tBB170F3B1DC220A80000443E /* MockUpdateSink.swift in Sources */,\n\t\t\t\tBB6CE3D21DC4E73600295C55 /* NotificationCenterSupportTests.swift in Sources */,\n\t\t\t\tBBBBEC971DCA1FEB000B646D /* ArrayReferenceTests.swift in Sources */,\n\t\t\t\tBBEA2A291DBF9ADA00CCCB08 /* MockSink.swift in Sources */,\n\t\t\t\tBB6CE3D31DC4E79400295C55 /* ValueMappingTests.swift in Sources */,\n\t\t\t\tBB170F431DC22A300000443E /* UpdatableValueTests.swift in Sources */,\n\t\t\t\tBB170F461DC255200000443E /* TwoWayBindingTests.swift in Sources */,\n\t\t\t\tBB170F251DC1066D0000443E /* UpdateTests.swift in Sources */,\n\t\t\t\tBB015F541DC67ACA00C8C05A /* SetMappingTests.swift in Sources */,\n\t\t\t\tBBB55BCD1C8FCE2C0050DDA9 /* TestUtilities.swift in Sources */,\n\t\t\t\tBB6CE3CA1DC4DF4400295C55 /* CombinedObservableTests.swift in Sources */,\n\t\t\t\tBB170F2D1DC10D350000443E /* TestObservable.swift in Sources */,\n\t\t\t\tBBE9AAD51DC0F474000B3DD0 /* BufferedSourceTests.swift in Sources */,\n\t\t\t\tBBE9AAD01DC0F1F6000B3DD0 /* ChangeTests.swift in Sources */,\n\t\t\t\tBBCD9DF61DA9104A00E85FB9 /* RefListTests.swift in Sources */,\n\t\t\t\tBBBBEC9B1DCA223A000B646D /* SetReferenceTests.swift in Sources */,\n\t\t\t\tBB8195C01DD257A300644668 /* ConnectorTests.swift in Sources */,\n\t\t\t\tBB015F531DC67A6400C8C05A /* SetVariableTests.swift in Sources */,\n\t\t\t\tBB015F3B1DC50C6700C8C05A /* MockArrayObserver.swift in Sources */,\n\t\t\t\tBB170F391DC1545E0000443E /* TransactionStateTests.swift in Sources */,\n\t\t\t\tBB170F311DC10DDB0000443E /* ChangesSourceTests.swift in Sources */,\n\t\t\t\tBB015F5E1DC687B100C8C05A /* SetSortingTests.swift in Sources */,\n\t\t\t\tBB88C40F1DC3A08B00C7EC3C /* ObservableTypeTests.swift in Sources */,\n\t\t\t\tBBEA2A371DBFC71000CCCB08 /* SimpleSourcesTests.swift in Sources */,\n\t\t\t\tBBEA2A351DBFC4C300CCCB08 /* AnySourceTests.swift in Sources */,\n\t\t\t\tBBEA2A381DBFC7B800CCCB08 /* MergedSourceTests.swift in Sources */,\n\t\t\t\tBB170F291DC106DE0000443E /* TestChange.swift in Sources */,\n\t\t\t\tBB6CE3D81DC4F18B00295C55 /* ArrayChangeSeparationTests.swift in Sources */,\n\t\t\t\tBB015F591DC684DC00C8C05A /* SetFoldingTests.swift in Sources */,\n\t\t\t\tBB015F3F1DC51D8300C8C05A /* ArrayVariableTests.swift in Sources */,\n\t\t\t\tBBE9AAD91DC0FC17000B3DD0 /* BracketingSourceTests.swift in Sources */,\n\t\t\t\tBB170F351DC110BD0000443E /* TestUpdatable.swift in Sources */,\n\t\t\t\tBB015F4A1DC52DC500C8C05A /* DistinctUnionTests.swift in Sources */,\n\t\t\t\tBB015F4B1DC52FA000C8C05A /* ObservableArrayTests.swift in Sources */,\n\t\t\t\tBB015F601DC689F600C8C05A /* Bookshelf.swift in Sources */,\n\t\t\t\tBB6CE3D01DC4E67700295C55 /* TimerSourceTests.swift in Sources */,\n\t\t\t\tBB015F461DC52B4500C8C05A /* ArrayFoldingTests.swift in Sources */,\n\t\t\t\tBB015F311DC4F90200C8C05A /* MockSetObserver.swift in Sources */,\n\t\t\t\tBB170F451DC239BC0000443E /* DistinctTests.swift in Sources */,\n\t\t\t\tBB6CE3D11DC4E72100295C55 /* KVOSupportTests.swift in Sources */,\n\t\t\t\tBBBBECA31DCA3AA8000B646D /* DispatchSourceTests.swift in Sources */,\n\t\t\t\tBB015F481DC52CE200C8C05A /* ArrayConcatenationTests.swift in Sources */,\n\t\t\t\tBB015F581DC67F0500C8C05A /* SetFilteringTests.swift in Sources */,\n\t\t\t\tBB015F3E1DC5147700C8C05A /* ArrayMappingTests.swift in Sources */,\n\t\t\t\tBB88C4111DC3A84C00C7EC3C /* VariableTests.swift in Sources */,\n\t\t\t\tBBEA2A2C1DBF9E9C00CCCB08 /* AnySinkTests.swift in Sources */,\n\t\t\t\tBBBBECB01DCA446A000B646D /* SetBufferingTests.swift in Sources */,\n\t\t\t\tBB015F441DC529CF00C8C05A /* ArrayFilteringTests.swift in Sources */,\n\t\t\t\tBBBBEC9F1DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift in Sources */,\n\t\t\t\tBB015F2E1DC4F5BA00C8C05A /* ObservableSetTests.swift in Sources */,\n\t\t\t\tBBEA2A4D1DC0BB4D00CCCB08 /* SourceOperatorTests.swift in Sources */,\n\t\t\t\tBBEA2A321DBFC3BB00CCCB08 /* SignalTests.swift in Sources */,\n\t\t\t\tBB6CE3D71DC4F18B00295C55 /* ArrayChangeTests.swift in Sources */,\n\t\t\t\tBBBBECAC1DCA4168000B646D /* ArrayBufferingTests.swift in Sources */,\n\t\t\t\tBB6CE3CC1DC4E48200295C55 /* TypeHelperTests.swift in Sources */,\n\t\t\t\tBB88C4141DC3B65F00C7EC3C /* ValueBufferingTests.swift in Sources */,\n\t\t\t\tBB170F3F1DC221180000443E /* ValueChangeTests.swift in Sources */,\n\t\t\t\tBB6CE3CB1DC4DF4800295C55 /* CombinedUpdatableTests.swift in Sources */,\n\t\t\t\tBB6CE3D61DC4F18B00295C55 /* ArrayModificationTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AEC1C8F8BE00050DDA9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBBCD9E251DAAD26200E85FB9 /* CompositeObservable.swift in Sources */,\n\t\t\t\tBB8195B81DD256B800644668 /* UIBarButtonItem Extensions.swift in Sources */,\n\t\t\t\tBB69A81B1D6B6A9A001D2821 /* ArrayReference.swift in Sources */,\n\t\t\t\tBB948BBE1DD5EFC900B0734C /* ComputedUpdatable.swift in Sources */,\n\t\t\t\tBBB55B601C8FCC820050DDA9 /* ObservableValue.swift in Sources */,\n\t\t\t\tBB69A7F91D6B1D83001D2821 /* ArrayChange.swift in Sources */,\n\t\t\t\tBBB55B841C8FCC820050DDA9 /* TimerSource.swift in Sources */,\n\t\t\t\tBB7E04D41DA7240C00BE3051 /* SetMappingForSequence.swift in Sources */,\n\t\t\t\tBBBBECA81DCA3FF0000B646D /* BufferedSet.swift in Sources */,\n\t\t\t\tBB69A81F1D6B71FA001D2821 /* SetChange.swift in Sources */,\n\t\t\t\tBB9D74001DBE061D00E20D67 /* OwnedSink.swift in Sources */,\n\t\t\t\tBB69A8061D6B344D001D2821 /* UpdatableArray.swift in Sources */,\n\t\t\t\tBBF7B9621EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift in Sources */,\n\t\t\t\tBB9D73F61DBE03EB00E20D67 /* DispatchSource.swift in Sources */,\n\t\t\t\tBB9D73E81DBB727300E20D67 /* ChangesSource.swift in Sources */,\n\t\t\t\tBB5B02E21F5E3FDE0084D86B /* SetGatheringSource.swift in Sources */,\n\t\t\t\tBBEA2A411DBFE38F00CCCB08 /* BufferedSource.swift in Sources */,\n\t\t\t\tBBE4DF421DA3A88C005EC162 /* ObservableType.swift in Sources */,\n\t\t\t\tBBB55B781C8FCC820050DDA9 /* SimpleSources.swift in Sources */,\n\t\t\t\tBBE4DF471DA3A908005EC162 /* ValueChange.swift in Sources */,\n\t\t\t\tBBB55B801C8FCC820050DDA9 /* TransformedSource.swift in Sources */,\n\t\t\t\tBBF400661DA108E900DA0B2C /* ObservableContains.swift in Sources */,\n\t\t\t\tBB6CE3B61DC4C21C00295C55 /* TransformedSink.swift in Sources */,\n\t\t\t\tBB5B02DD1F5E3FC50084D86B /* ArrayGatheringSource.swift in Sources */,\n\t\t\t\tBB69A80E1D6B472F001D2821 /* ArrayMappingForValueField.swift in Sources */,\n\t\t\t\tBBF3EB101D99ACDE006AC7CD /* RefList.swift in Sources */,\n\t\t\t\tBB69A7F11D6AFF1A001D2821 /* Abstract.swift in Sources */,\n\t\t\t\tBBA033631DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift in Sources */,\n\t\t\t\tBB7E04CA1DA7233B00BE3051 /* ArrayMappingForArrayField.swift in Sources */,\n\t\t\t\tBBE9AACC1DC0F0A5000B3DD0 /* Update.swift in Sources */,\n\t\t\t\tBB69A80A1D6B442C001D2821 /* ArrayVariable.swift in Sources */,\n\t\t\t\tBBCD9DFB1DAA885E00E85FB9 /* ArrayFolding.swift in Sources */,\n\t\t\t\tBBCD9E201DAAC7E600E85FB9 /* ValueMappingForSetField.swift in Sources */,\n\t\t\t\tBBE4DF4C1DA409EE005EC162 /* DistinctUnion.swift in Sources */,\n\t\t\t\tBB9D73D11DBB38F900E20D67 /* Sink.swift in Sources */,\n\t\t\t\tBB69A83D1D6B90F5001D2821 /* ArrayConcatenation.swift in Sources */,\n\t\t\t\tBB69A8281D6B779A001D2821 /* UpdatableSet.swift in Sources */,\n\t\t\t\tBB69A8341D6B7F12001D2821 /* SetReference.swift in Sources */,\n\t\t\t\tBB7E04CF1DA723F300BE3051 /* SetMappingForValueField.swift in Sources */,\n\t\t\t\tBBB55B681C8FCC820050DDA9 /* Reference.swift in Sources */,\n\t\t\t\tBBBFD14D1EBE673200EC9814 /* SetSortingByComparableField.swift in Sources */,\n\t\t\t\tBB8195BB1DD256B800644668 /* CADisplayLink Extensions.swift in Sources */,\n\t\t\t\tBB69A7FD1D6B1D95001D2821 /* ObservableArray.swift in Sources */,\n\t\t\t\tBBA0335E1DA7276200E83AC1 /* SetSortingByComparator.swift in Sources */,\n\t\t\t\tBB7E04E81DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift in Sources */,\n\t\t\t\tBB9D73E21DBB61C100E20D67 /* TransactionalThing.swift in Sources */,\n\t\t\t\tBBF7B95B1EACFC3B00073DF8 /* DependentValue.swift in Sources */,\n\t\t\t\tBBB55B741C8FCC820050DDA9 /* Signal.swift in Sources */,\n\t\t\t\tBBB55B5C1C8FCC820050DDA9 /* BufferedValue.swift in Sources */,\n\t\t\t\tBB69A82C1D6B7CAE001D2821 /* SetVariable.swift in Sources */,\n\t\t\t\tBBCD9E111DAAC33700E85FB9 /* ValueMappingForValue.swift in Sources */,\n\t\t\t\tBBB55B541C8FCC820050DDA9 /* MergedSource.swift in Sources */,\n\t\t\t\tBB69A8301D6B7E36001D2821 /* SetSortingByMappingToComparable.swift in Sources */,\n\t\t\t\tBB69A8231D6B7203001D2821 /* ObservableSet.swift in Sources */,\n\t\t\t\tBBB55B501C8FCC820050DDA9 /* Locks.swift in Sources */,\n\t\t\t\tBBB55B901C8FCC820050DDA9 /* Variable.swift in Sources */,\n\t\t\t\tBB7E04D91DA7242F00BE3051 /* SetMappingForSetField.swift in Sources */,\n\t\t\t\tBBCD9E2F1DAAD4BC00E85FB9 /* CompositeUpdatable.swift in Sources */,\n\t\t\t\tBB8195B71DD256B800644668 /* UIControl Glue.swift in Sources */,\n\t\t\t\tBB948BC31DD7213200B0734C /* UISwitch Glue.swift in Sources */,\n\t\t\t\tBBB55B581C8FCC820050DDA9 /* NSNotificationCenter Support.swift in Sources */,\n\t\t\t\tBB1657E91D71D65900094BAC /* ArrayChangeSeparation.swift in Sources */,\n\t\t\t\tBB69A8381D6B7F9D001D2821 /* SetFilteringOnPredicate.swift in Sources */,\n\t\t\t\tBB9D73F11DBDFEE400E20D67 /* TwoWayBinding.swift in Sources */,\n\t\t\t\tBBEA2A3C1DBFE37B00CCCB08 /* BracketingSource.swift in Sources */,\n\t\t\t\tBB7E04E31DA7255D00BE3051 /* ArrayFilteringIndexmap.swift in Sources */,\n\t\t\t\tBBCD9E161DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift in Sources */,\n\t\t\t\tBB82E3E31D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift in Sources */,\n\t\t\t\tBBA033591DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift in Sources */,\n\t\t\t\tBBAA827F1C91D43700586903 /* Type Helpers.swift in Sources */,\n\t\t\t\tBB69A8141D6B539A001D2821 /* ValueMappingForValueField.swift in Sources */,\n\t\t\t\tBB69A8021D6B2377001D2821 /* BufferedArray.swift in Sources */,\n\t\t\t\tBBF7B9561EACEB0100073DF8 /* AccumulatedSource.swift in Sources */,\n\t\t\t\tBB3982EF1EC109C8000CDCB5 /* UISearchBar Glue.swift in Sources */,\n\t\t\t\tBBBBEC8F1DCA1AEB000B646D /* ValueReference.swift in Sources */,\n\t\t\t\tBBE4DF591DA55384005EC162 /* SetMappingForValue.swift in Sources */,\n\t\t\t\tBB8195B91DD256B800644668 /* UIDevice Glue.swift in Sources */,\n\t\t\t\tBB69A8421D6B9A7E001D2821 /* ArrayMappingForValue.swift in Sources */,\n\t\t\t\tBBB55B441C8FCC820050DDA9 /* Connector.swift in Sources */,\n\t\t\t\tBB69A7F51D6B1D7C001D2821 /* Change.swift in Sources */,\n\t\t\t\tBB8195BA1DD256B800644668 /* UIGestureRecognizer Glue.swift in Sources */,\n\t\t\t\tBBE4DF5E1DA55DA3005EC162 /* SetMappingBase.swift in Sources */,\n\t\t\t\tBBCD9E041DAA910500E85FB9 /* SetFolding.swift in Sources */,\n\t\t\t\tBB7E04DE1DA7244A00BE3051 /* SetMappingForArrayField.swift in Sources */,\n\t\t\t\tBBB55B881C8FCC820050DDA9 /* UpdatableValue.swift in Sources */,\n\t\t\t\tBBCD9E2A1DAAD2B900E85FB9 /* DistinctValue.swift in Sources */,\n\t\t\t\tBB9D73CB1DBB2EB400E20D67 /* Connect.swift in Sources */,\n\t\t\t\tBBB55B7C1C8FCC820050DDA9 /* Source.swift in Sources */,\n\t\t\t\tBBCD9E1B1DAAC50900E85FB9 /* ValueMappingForSourceField.swift in Sources */,\n\t\t\t\tBBC2A82B1CBC14C600394D24 /* NSObject Glue.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55AF91C8F8CBB0050DDA9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBB69A7F21D6AFF1A001D2821 /* Abstract.swift in Sources */,\n\t\t\t\tBB9D73F71DBE03EB00E20D67 /* DispatchSource.swift in Sources */,\n\t\t\t\tBBCD9DFC1DAA885E00E85FB9 /* ArrayFolding.swift in Sources */,\n\t\t\t\tBB948BBF1DD5EFC900B0734C /* ComputedUpdatable.swift in Sources */,\n\t\t\t\tBBCD9E171DAAC4DC00E85FB9 /* ValueMappingForArrayField.swift in Sources */,\n\t\t\t\tBB67E5531C9B6A63002B0AB5 /* CADisplayLink Extensions.swift in Sources */,\n\t\t\t\tBBE4DF4D1DA409EE005EC162 /* DistinctUnion.swift in Sources */,\n\t\t\t\tBB69A83E1D6B90F5001D2821 /* ArrayConcatenation.swift in Sources */,\n\t\t\t\tBB69A7F61D6B1D7C001D2821 /* Change.swift in Sources */,\n\t\t\t\tBBCD9E211DAAC7E600E85FB9 /* ValueMappingForSetField.swift in Sources */,\n\t\t\t\tBB69A80B1D6B442D001D2821 /* ArrayVariable.swift in Sources */,\n\t\t\t\tBB8195BE1DD256B900644668 /* UIDevice Glue.swift in Sources */,\n\t\t\t\tBBF7B9631EAEA60900073DF8 /* ArrayBasedTableViewDataSource.swift in Sources */,\n\t\t\t\tBB9D74011DBE061D00E20D67 /* OwnedSink.swift in Sources */,\n\t\t\t\tBB69A8311D6B7E37001D2821 /* SetSortingByMappingToComparable.swift in Sources */,\n\t\t\t\tBB5B02E31F5E3FDE0084D86B /* SetGatheringSource.swift in Sources */,\n\t\t\t\tBBEA2A3D1DBFE37B00CCCB08 /* BracketingSource.swift in Sources */,\n\t\t\t\tBBB55B611C8FCC820050DDA9 /* ObservableValue.swift in Sources */,\n\t\t\t\tBBCD9E1C1DAAC50900E85FB9 /* ValueMappingForSourceField.swift in Sources */,\n\t\t\t\tBB9D73E91DBB727300E20D67 /* ChangesSource.swift in Sources */,\n\t\t\t\tBBCD9E2B1DAAD2B900E85FB9 /* DistinctValue.swift in Sources */,\n\t\t\t\tBBB55B851C8FCC820050DDA9 /* TimerSource.swift in Sources */,\n\t\t\t\tBBB55B791C8FCC820050DDA9 /* SimpleSources.swift in Sources */,\n\t\t\t\tBB5B02DE1F5E3FC50084D86B /* ArrayGatheringSource.swift in Sources */,\n\t\t\t\tBB7E04D51DA7240C00BE3051 /* SetMappingForSequence.swift in Sources */,\n\t\t\t\tBBB55B811C8FCC820050DDA9 /* TransformedSource.swift in Sources */,\n\t\t\t\tBB69A8031D6B2377001D2821 /* BufferedArray.swift in Sources */,\n\t\t\t\tBB69A82D1D6B7CAF001D2821 /* SetVariable.swift in Sources */,\n\t\t\t\tBBCD9E301DAAD4BC00E85FB9 /* CompositeUpdatable.swift in Sources */,\n\t\t\t\tBBE4DF431DA3A88C005EC162 /* ObservableType.swift in Sources */,\n\t\t\t\tBBB55B691C8FCC820050DDA9 /* Reference.swift in Sources */,\n\t\t\t\tBB9D73CC1DBB2EB400E20D67 /* Connect.swift in Sources */,\n\t\t\t\tBB7E04E41DA7255D00BE3051 /* ArrayFilteringIndexmap.swift in Sources */,\n\t\t\t\tBB69A7FA1D6B1D83001D2821 /* ArrayChange.swift in Sources */,\n\t\t\t\tBBEA2A421DBFE38F00CCCB08 /* BufferedSource.swift in Sources */,\n\t\t\t\tBB8195BC1DD256B900644668 /* UIControl Glue.swift in Sources */,\n\t\t\t\tBBB55B751C8FCC820050DDA9 /* Signal.swift in Sources */,\n\t\t\t\tBBCD9E261DAAD26200E85FB9 /* CompositeObservable.swift in Sources */,\n\t\t\t\tBBCD9E121DAAC33700E85FB9 /* ValueMappingForValue.swift in Sources */,\n\t\t\t\tBB69A8431D6B9A7E001D2821 /* ArrayMappingForValue.swift in Sources */,\n\t\t\t\tBBBFD14E1EBE673200EC9814 /* SetSortingByComparableField.swift in Sources */,\n\t\t\t\tBBB55B5D1C8FCC820050DDA9 /* BufferedValue.swift in Sources */,\n\t\t\t\tBB9D73D21DBB38F900E20D67 /* Sink.swift in Sources */,\n\t\t\t\tBBCD9E051DAA910500E85FB9 /* SetFolding.swift in Sources */,\n\t\t\t\tBB69A7FE1D6B1D95001D2821 /* ObservableArray.swift in Sources */,\n\t\t\t\tBBF3EB111D99ACDE006AC7CD /* RefList.swift in Sources */,\n\t\t\t\tBBF7B95C1EACFC3B00073DF8 /* DependentValue.swift in Sources */,\n\t\t\t\tBB8195BD1DD256B900644668 /* UIBarButtonItem Extensions.swift in Sources */,\n\t\t\t\tBBF400671DA108E900DA0B2C /* ObservableContains.swift in Sources */,\n\t\t\t\tBB6CE3B71DC4C21C00295C55 /* TransformedSink.swift in Sources */,\n\t\t\t\tBB7E04E91DA725A500BE3051 /* ArrayFilteringOnObservableBool.swift in Sources */,\n\t\t\t\tBBB55B551C8FCC820050DDA9 /* MergedSource.swift in Sources */,\n\t\t\t\tBBE9AACD1DC0F0A5000B3DD0 /* Update.swift in Sources */,\n\t\t\t\tBBE4DF5F1DA55DA3005EC162 /* SetMappingBase.swift in Sources */,\n\t\t\t\tBB69A80F1D6B472F001D2821 /* ArrayMappingForValueField.swift in Sources */,\n\t\t\t\tBBA033641DA7278C00E83AC1 /* SetSortingByMappingToObservableComparable.swift in Sources */,\n\t\t\t\tBB1657EA1D71D65900094BAC /* ArrayChangeSeparation.swift in Sources */,\n\t\t\t\tBBA0335F1DA7276200E83AC1 /* SetSortingByComparator.swift in Sources */,\n\t\t\t\tBB69A8351D6B7F12001D2821 /* SetReference.swift in Sources */,\n\t\t\t\tBB948BC41DD7213300B0734C /* UISwitch Glue.swift in Sources */,\n\t\t\t\tBBE4DF481DA3A908005EC162 /* ValueChange.swift in Sources */,\n\t\t\t\tBBB55B511C8FCC820050DDA9 /* Locks.swift in Sources */,\n\t\t\t\tBB69A8071D6B344E001D2821 /* UpdatableArray.swift in Sources */,\n\t\t\t\tBBB55B911C8FCC820050DDA9 /* Variable.swift in Sources */,\n\t\t\t\tBBB55B591C8FCC820050DDA9 /* NSNotificationCenter Support.swift in Sources */,\n\t\t\t\tBBAA82801C91D43700586903 /* Type Helpers.swift in Sources */,\n\t\t\t\tBBB55B451C8FCC820050DDA9 /* Connector.swift in Sources */,\n\t\t\t\tBB7E04CB1DA7233B00BE3051 /* ArrayMappingForArrayField.swift in Sources */,\n\t\t\t\tBBB55B891C8FCC820050DDA9 /* UpdatableValue.swift in Sources */,\n\t\t\t\tBB9D73E31DBB61C100E20D67 /* TransactionalThing.swift in Sources */,\n\t\t\t\tBB69A8201D6B71FB001D2821 /* SetChange.swift in Sources */,\n\t\t\t\tBBBBEC901DCA1AEB000B646D /* ValueReference.swift in Sources */,\n\t\t\t\tBBF7B9571EACEB0100073DF8 /* AccumulatedSource.swift in Sources */,\n\t\t\t\tBB3982F01EC109C8000CDCB5 /* UISearchBar Glue.swift in Sources */,\n\t\t\t\tBB7E04DF1DA7244A00BE3051 /* SetMappingForArrayField.swift in Sources */,\n\t\t\t\tBB69A8131D6B539A001D2821 /* ValueMappingForValueField.swift in Sources */,\n\t\t\t\tBBA0335A1DA726AA00E83AC1 /* SetFilteringOnObservableBool.swift in Sources */,\n\t\t\t\tBB9D73F21DBDFEE400E20D67 /* TwoWayBinding.swift in Sources */,\n\t\t\t\tBB7E04DA1DA7242F00BE3051 /* SetMappingForSetField.swift in Sources */,\n\t\t\t\tBBB55B7D1C8FCC820050DDA9 /* Source.swift in Sources */,\n\t\t\t\tBBC2A82C1CBC14C600394D24 /* NSObject Glue.swift in Sources */,\n\t\t\t\tBBE4DF5A1DA55384005EC162 /* SetMappingForValue.swift in Sources */,\n\t\t\t\tBB69A81C1D6B6A9B001D2821 /* ArrayReference.swift in Sources */,\n\t\t\t\tBB69A8391D6B7F9E001D2821 /* SetFilteringOnPredicate.swift in Sources */,\n\t\t\t\tBBBBECA91DCA3FF0000B646D /* BufferedSet.swift in Sources */,\n\t\t\t\tBB7E04D01DA723F300BE3051 /* SetMappingForValueField.swift in Sources */,\n\t\t\t\tBB8195BF1DD256B900644668 /* UIGestureRecognizer Glue.swift in Sources */,\n\t\t\t\tBB69A8241D6B7203001D2821 /* ObservableSet.swift in Sources */,\n\t\t\t\tBB69A8291D6B779B001D2821 /* UpdatableSet.swift in Sources */,\n\t\t\t\tBB82E3E41D98F34E0035DDAD /* ArrayFilteringOnPredicate.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tBBB55B031C8F8CBB0050DDA9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tBBB55BCE1C8FCE2C0050DDA9 /* TestUtilities.swift in Sources */,\n\t\t\t\tBBB55BB61C8FCE2C0050DDA9 /* NotificationCenterSupportTests.swift in Sources */,\n\t\t\t\tBBB55BBC1C8FCE2C0050DDA9 /* DistinctTests.swift in Sources */,\n\t\t\t\tBBE9AAD61DC0F474000B3DD0 /* BufferedSourceTests.swift in Sources */,\n\t\t\t\tBBE9AAD11DC0F1F6000B3DD0 /* ChangeTests.swift in Sources */,\n\t\t\t\tBBB55BB01C8FCE2C0050DDA9 /* KVOSupportTests.swift in Sources */,\n\t\t\t\tBBCD9E3C1DABC45000E85FB9 /* TypeHelperTests.swift in Sources */,\n\t\t\t\tBB88C4151DC3B65F00C7EC3C /* ValueBufferingTests.swift in Sources */,\n\t\t\t\tBBB55BC51C8FCE2C0050DDA9 /* SignalTests.swift in Sources */,\n\t\t\t\tBBCD9E0D1DAAB6E700E85FB9 /* MockUpdateSink.swift in Sources */,\n\t\t\t\tBBC36AED1DA8453000AB3E9D /* ArrayChangeSeparationTests.swift in Sources */,\n\t\t\t\tBBE4DF681DA5656D005EC162 /* SetMappingTests.swift in Sources */,\n\t\t\t\tBBBBECA41DCA3AA8000B646D /* DispatchSourceTests.swift in Sources */,\n\t\t\t\tBBCD9E381DAAD74600E85FB9 /* CombinedUpdatableTests.swift in Sources */,\n\t\t\t\tBBCD9E001DAA8F7800E85FB9 /* ArrayFoldingTests.swift in Sources */,\n\t\t\t\tBB471D9C1DA57FF8002550B0 /* SetSortingTests.swift in Sources */,\n\t\t\t\tBB170F261DC1066D0000443E /* UpdateTests.swift in Sources */,\n\t\t\t\tBBCD9E501DABFE8800E85FB9 /* SetVariableTests.swift in Sources */,\n\t\t\t\tBBC4AE501D9A829500FF7DE0 /* ArrayFilteringTests.swift in Sources */,\n\t\t\t\tBBCD9DF71DA9104A00E85FB9 /* RefListTests.swift in Sources */,\n\t\t\t\tBB88C4101DC3A08B00C7EC3C /* ObservableTypeTests.swift in Sources */,\n\t\t\t\tBBB55BBF1C8FCE2C0050DDA9 /* ArrayMappingTests.swift in Sources */,\n\t\t\t\tBBCD9E091DAA918400E85FB9 /* SetFoldingTests.swift in Sources */,\n\t\t\t\tBB170F361DC110BD0000443E /* TestUpdatable.swift in Sources */,\n\t\t\t\tBB170F2E1DC10D350000443E /* TestObservable.swift in Sources */,\n\t\t\t\tBBA033681DA7CFFE00E83AC1 /* ArrayModificationTests.swift in Sources */,\n\t\t\t\tBBCD9E401DABC81A00E85FB9 /* MockSink.swift in Sources */,\n\t\t\t\tBBBBEC9C1DCA223A000B646D /* SetReferenceTests.swift in Sources */,\n\t\t\t\tBBB55BAA1C8FCE2C0050DDA9 /* ArrayVariableTests.swift in Sources */,\n\t\t\t\tBBBBEC941DCA1D43000B646D /* ValueReferenceTests.swift in Sources */,\n\t\t\t\tBB170F2A1DC106DE0000443E /* TestChange.swift in Sources */,\n\t\t\t\tBBBBECB11DCA446A000B646D /* SetBufferingTests.swift in Sources */,\n\t\t\t\tBB170F321DC10DDB0000443E /* ChangesSourceTests.swift in Sources */,\n\t\t\t\tBBBBEC981DCA1FEB000B646D /* ArrayReferenceTests.swift in Sources */,\n\t\t\t\tBBB55BD71C8FCE2C0050DDA9 /* VariableTests.swift in Sources */,\n\t\t\t\tBBCD9E541DAC1B1300E85FB9 /* ConnectorTests.swift in Sources */,\n\t\t\t\tBBCD9E341DAAD66500E85FB9 /* CombinedObservableTests.swift in Sources */,\n\t\t\t\tBBB55BC81C8FCE2C0050DDA9 /* SimpleSourcesTests.swift in Sources */,\n\t\t\t\tBBB55BD41C8FCE2C0050DDA9 /* TwoWayBindingTests.swift in Sources */,\n\t\t\t\tBBBBECAD1DCA4168000B646D /* ArrayBufferingTests.swift in Sources */,\n\t\t\t\tBBEA2A361DBFC4C300CCCB08 /* AnySourceTests.swift in Sources */,\n\t\t\t\tBBCD9E441DABD4BE00E85FB9 /* ObservableSetTests.swift in Sources */,\n\t\t\t\tBB568AF11DA693F700BC4B58 /* SetFilteringTests.swift in Sources */,\n\t\t\t\tBBB55BD11C8FCE2C0050DDA9 /* TimerSourceTests.swift in Sources */,\n\t\t\t\tBBCD9E4C1DABFA2900E85FB9 /* ArrayConcatenationTests.swift in Sources */,\n\t\t\t\tBBBBECA01DCA2FAB000B646D /* NSUserDefaultsSupportTests.swift in Sources */,\n\t\t\t\tBB170F3A1DC1545E0000443E /* TransactionStateTests.swift in Sources */,\n\t\t\t\tBBB55BC21C8FCE2C0050DDA9 /* ValueMappingTests.swift in Sources */,\n\t\t\t\tBB170F441DC22A300000443E /* UpdatableValueTests.swift in Sources */,\n\t\t\t\tBBB55BCB1C8FCE2C0050DDA9 /* SourceOperatorTests.swift in Sources */,\n\t\t\t\tBBB55BB31C8FCE2C0050DDA9 /* MergedSourceTests.swift in Sources */,\n\t\t\t\tBBE4DF551DA41373005EC162 /* DistinctUnionTests.swift in Sources */,\n\t\t\t\tBB170F401DC221180000443E /* ValueChangeTests.swift in Sources */,\n\t\t\t\tBB568AF91DA6A9EE00BC4B58 /* MockArrayObserver.swift in Sources */,\n\t\t\t\tBBEA2A2D1DBF9E9C00CCCB08 /* AnySinkTests.swift in Sources */,\n\t\t\t\tBB568AF51DA6942700BC4B58 /* MockSetObserver.swift in Sources */,\n\t\t\t\tBB8D36701DA116CB000D44C5 /* Bookshelf.swift in Sources */,\n\t\t\t\tBBCD9E481DABEA5500E85FB9 /* ObservableArrayTests.swift in Sources */,\n\t\t\t\tBBB55BB91C8FCE2C0050DDA9 /* ObservableValueTests.swift in Sources */,\n\t\t\t\tBBA0336C1DA7D03300E83AC1 /* ArrayChangeTests.swift in Sources */,\n\t\t\t\tBBE9AADA1DC0FC17000B3DD0 /* BracketingSourceTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\tBB351B031DB81E67005F083F /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = BBB55AD31C8F88F20050DDA9 /* macOS */;\n\t\t\ttargetProxy = BB351B021DB81E67005F083F /* PBXContainerItemProxy */;\n\t\t};\n\t\tBBB55ABF1C8F80020050DDA9 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = BBB55AB11C8F80020050DDA9 /* iOS */;\n\t\t\ttargetProxy = BBB55ABE1C8F80020050DDA9 /* PBXContainerItemProxy */;\n\t\t};\n\t\tBBB55AE01C8F88F20050DDA9 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = BBB55AD31C8F88F20050DDA9 /* macOS */;\n\t\t\ttargetProxy = BBB55ADF1C8F88F20050DDA9 /* PBXContainerItemProxy */;\n\t\t};\n\t\tBBB55B0A1C8F8CBC0050DDA9 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = BBB55AFD1C8F8CBB0050DDA9 /* tvOS */;\n\t\t\ttargetProxy = BBB55B091C8F8CBC0050DDA9 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\tBB351B051DB81E67005F083F /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = NO;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Tests/PerformanceTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).PerformanceTests\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBB351B061DB81E67005F083F /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = NO;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Tests/PerformanceTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).PerformanceTests\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBB55AC41C8F80020050DDA9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = BBB55ACC1C8F80660050DDA9 /* version.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(BUILD_NUMBER)\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = \"$(BUILD_NUMBER)\";\n\t\t\t\tDYLIB_CURRENT_VERSION = \"$(BUILD_NUMBER)\";\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 4.0;\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBB55AC51C8F80020050DDA9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = BBB55ACC1C8F80660050DDA9 /* version.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(BUILD_NUMBER)\";\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = \"$(BUILD_NUMBER)\";\n\t\t\t\tDYLIB_CURRENT_VERSION = \"$(BUILD_NUMBER)\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tSWIFT_VERSION = 4.0;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBB55AC71C8F80020050DDA9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).$(PLATFORM_DISPLAY_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBB55AC81C8F80020050DDA9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).$(PLATFORM_DISPLAY_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBB55ACA1C8F80020050DDA9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tINFOPLIST_FILE = Tests/GlueKitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).Tests\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)-Test\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBB55ACB1C8F80020050DDA9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tINFOPLIST_FILE = Tests/GlueKitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).Tests\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)-Test\";\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBB55AE61C8F88F20050DDA9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tFRAMEWORK_VERSION = A;\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).$(PLATFORM_DISPLAY_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBB55AE71C8F88F20050DDA9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tFRAMEWORK_VERSION = A;\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).$(PLATFORM_DISPLAY_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBB55AE91C8F88F20050DDA9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Tests/GlueKitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).Tests\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)-Test\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBB55AEA1C8F88F20050DDA9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = Tests/GlueKitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).Tests\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)-Test\";\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBB55AF71C8F8BE00050DDA9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=watchos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).$(PLATFORM_DISPLAY_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)\";\n\t\t\t\tSDKROOT = watchos;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = 4;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBB55AF81C8F8BE00050DDA9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=watchos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).$(PLATFORM_DISPLAY_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)\";\n\t\t\t\tSDKROOT = watchos;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tTARGETED_DEVICE_FAMILY = 4;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBB55B101C8F8CBC0050DDA9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=appletvos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).$(PLATFORM_DISPLAY_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)\";\n\t\t\t\tSDKROOT = appletvos;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = 3;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBB55B111C8F8CBC0050DDA9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=appletvos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tINFOPLIST_FILE = Sources/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).$(PLATFORM_DISPLAY_NAME:rfc1034identifier)\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)\";\n\t\t\t\tSDKROOT = appletvos;\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tTARGETED_DEVICE_FAMILY = 3;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tBBB55B131C8F8CBC0050DDA9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=appletvos*]\" = \"iPhone Developer\";\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tINFOPLIST_FILE = Tests/GlueKitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).Tests\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)-Test\";\n\t\t\t\tSDKROOT = appletvos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tBBB55B141C8F8CBC0050DDA9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = NO;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=appletvos*]\" = \"iPhone Developer\";\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tINFOPLIST_FILE = Tests/GlueKitTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"$(BUNDLE_IDENTIFIER_BASE).Tests\";\n\t\t\t\tPRODUCT_NAME = \"$(PROJECT_NAME)-Test\";\n\t\t\t\tSDKROOT = appletvos;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tBB351B041DB81E67005F083F /* Build configuration list for PBXNativeTarget \"PerformanceTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBB351B051DB81E67005F083F /* Debug */,\n\t\t\t\tBB351B061DB81E67005F083F /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBB55AAC1C8F80020050DDA9 /* Build configuration list for PBXProject \"GlueKit\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBB55AC41C8F80020050DDA9 /* Debug */,\n\t\t\t\tBBB55AC51C8F80020050DDA9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBB55AC61C8F80020050DDA9 /* Build configuration list for PBXNativeTarget \"iOS\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBB55AC71C8F80020050DDA9 /* Debug */,\n\t\t\t\tBBB55AC81C8F80020050DDA9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBB55AC91C8F80020050DDA9 /* Build configuration list for PBXNativeTarget \"iOS Tests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBB55ACA1C8F80020050DDA9 /* Debug */,\n\t\t\t\tBBB55ACB1C8F80020050DDA9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBB55AE51C8F88F20050DDA9 /* Build configuration list for PBXNativeTarget \"macOS\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBB55AE61C8F88F20050DDA9 /* Debug */,\n\t\t\t\tBBB55AE71C8F88F20050DDA9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBB55AE81C8F88F20050DDA9 /* Build configuration list for PBXNativeTarget \"macOS Tests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBB55AE91C8F88F20050DDA9 /* Debug */,\n\t\t\t\tBBB55AEA1C8F88F20050DDA9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBB55AF61C8F8BE00050DDA9 /* Build configuration list for PBXNativeTarget \"watchOS\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBB55AF71C8F8BE00050DDA9 /* Debug */,\n\t\t\t\tBBB55AF81C8F8BE00050DDA9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBB55B0F1C8F8CBC0050DDA9 /* Build configuration list for PBXNativeTarget \"tvOS\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBB55B101C8F8CBC0050DDA9 /* Debug */,\n\t\t\t\tBBB55B111C8F8CBC0050DDA9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tBBB55B121C8F8CBC0050DDA9 /* Build configuration list for PBXNativeTarget \"tvOS Tests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tBBB55B131C8F8CBC0050DDA9 /* Debug */,\n\t\t\t\tBBB55B141C8F8CBC0050DDA9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = BBB55AA91C8F80020050DDA9 /* Project object */;\n}\n"
  },
  {
    "path": "GlueKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:GlueKit.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "GlueKit.xcodeproj/project.xcworkspace/xcshareddata/GlueKit.xcscmblueprint",
    "content": "{\n  \"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey\" : \"1C1227F33F1818028D5EE61FD15F57BEC36D44F4\",\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey\" : {\n\n  },\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey\" : {\n    \"05D6826B0162543BD57EFC4EE6354EB49FD59438\" : 9223372036854775807,\n    \"1C1227F33F1818028D5EE61FD15F57BEC36D44F4\" : 9223372036854775807\n  },\n  \"DVTSourceControlWorkspaceBlueprintIdentifierKey\" : \"7F20ECAA-BD48-4077-9606-C54D512EB5F5\",\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey\" : {\n    \"05D6826B0162543BD57EFC4EE6354EB49FD59438\" : \"BTree\\/\",\n    \"1C1227F33F1818028D5EE61FD15F57BEC36D44F4\" : \"GlueKit\\/\"\n  },\n  \"DVTSourceControlWorkspaceBlueprintNameKey\" : \"GlueKit\",\n  \"DVTSourceControlWorkspaceBlueprintVersion\" : 204,\n  \"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey\" : \"GlueKit.xcodeproj\",\n  \"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey\" : [\n    {\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey\" : \"https:\\/\\/github.com\\/lorentey\\/BTree.git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey\" : \"com.apple.dt.Xcode.sourcecontrol.Git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey\" : \"05D6826B0162543BD57EFC4EE6354EB49FD59438\"\n    },\n    {\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey\" : \"https:\\/\\/github.com\\/lorentey\\/GlueKit.git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey\" : \"com.apple.dt.Xcode.sourcecontrol.Git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey\" : \"1C1227F33F1818028D5EE61FD15F57BEC36D44F4\"\n    }\n  ]\n}"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcbaselines/BB351AFB1DB81E67005F083F.xcbaseline/EBF79DD4-EE66-4D33-B51C-EE37857B70A1.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>classNames</key>\n\t<dict>\n\t\t<key>SignalPerformanceTests</key>\n\t\t<dict>\n\t\t\t<key>testChainedSendPerformance()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.52115</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-10-19 23:39:50</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>testConcurrentSendPerformance()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>1.4352</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-10-19 23:39:50</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>testSendPerformance()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.65624</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-10-19 23:39:50</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<key>SignalSendTests</key>\n\t\t<dict>\n\t\t\t<key>testChainedSendPerformance()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.27853</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:29:28</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>testConcurrentSendPerformance()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>2.2684</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:29:28</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>test_send_toClosure()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.61261</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:29:28</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>test_send_toSink()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.5974</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:29:28</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<key>SignalSubscriptionTests</key>\n\t\t<dict>\n\t\t\t<key>test_subscribe_Closures()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.3053</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:43:05</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>test_subscribe_EmptySink()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.20632</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:43:05</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>test_subscribe_HardwiredMethodSink()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.21459</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:43:05</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>test_subscribe_LocalMethodSink()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.32126</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:29:28</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>test_subscribe_MethodSink()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.31883</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:43:05</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>test_subscribe_PartiallyAppliedMethodSink()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.36757</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:43:05</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>test_subscribe_RefCountingSink()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.22047</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:43:05</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t</dict>\n\t\t<key>SignalUnsubscriptionTests</key>\n\t\t<dict>\n\t\t\t<key>test_unsubscribe_emptySinks()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.18989</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-11-01 15:29:28</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcbaselines/BB351AFB1DB81E67005F083F.xcbaseline/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>runDestinationsByUUID</key>\n\t<dict>\n\t\t<key>EBF79DD4-EE66-4D33-B51C-EE37857B70A1</key>\n\t\t<dict>\n\t\t\t<key>localComputer</key>\n\t\t\t<dict>\n\t\t\t\t<key>busSpeedInMHz</key>\n\t\t\t\t<integer>100</integer>\n\t\t\t\t<key>cpuCount</key>\n\t\t\t\t<integer>1</integer>\n\t\t\t\t<key>cpuKind</key>\n\t\t\t\t<string>Intel Core i7</string>\n\t\t\t\t<key>cpuSpeedInMHz</key>\n\t\t\t\t<integer>2600</integer>\n\t\t\t\t<key>logicalCPUCoresPerPackage</key>\n\t\t\t\t<integer>8</integer>\n\t\t\t\t<key>modelCode</key>\n\t\t\t\t<string>MacBookPro10,1</string>\n\t\t\t\t<key>physicalCPUCoresPerPackage</key>\n\t\t\t\t<integer>4</integer>\n\t\t\t\t<key>platformIdentifier</key>\n\t\t\t\t<string>com.apple.platform.macosx</string>\n\t\t\t</dict>\n\t\t\t<key>targetArchitecture</key>\n\t\t\t<string>x86_64</string>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcbaselines/BBB55BE11C8FD1C60050DDA9.xcbaseline/DD663408-0BA9-46F9-868F-F1570927CA52.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>classNames</key>\n\t<dict>\n\t\t<key>SignalPerformanceTests</key>\n\t\t<dict>\n\t\t\t<key>testChainedSendPerformance()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.53204</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-10-19 23:23:14</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>testConcurrentSendPerformance()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>1.6244</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-10-19 23:23:14</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t\t<key>testSendPerformance()</key>\n\t\t\t<dict>\n\t\t\t\t<key>com.apple.XCTPerformanceMetric_WallClockTime</key>\n\t\t\t\t<dict>\n\t\t\t\t\t<key>baselineAverage</key>\n\t\t\t\t\t<real>0.6672</real>\n\t\t\t\t\t<key>baselineIntegrationDisplayName</key>\n\t\t\t\t\t<string>2016-10-19 23:23:14</string>\n\t\t\t\t</dict>\n\t\t\t</dict>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcbaselines/BBB55BE11C8FD1C60050DDA9.xcbaseline/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>runDestinationsByUUID</key>\n\t<dict>\n\t\t<key>DD663408-0BA9-46F9-868F-F1570927CA52</key>\n\t\t<dict>\n\t\t\t<key>localComputer</key>\n\t\t\t<dict>\n\t\t\t\t<key>busSpeedInMHz</key>\n\t\t\t\t<integer>100</integer>\n\t\t\t\t<key>cpuCount</key>\n\t\t\t\t<integer>1</integer>\n\t\t\t\t<key>cpuKind</key>\n\t\t\t\t<string>Intel Core i7</string>\n\t\t\t\t<key>cpuSpeedInMHz</key>\n\t\t\t\t<integer>2600</integer>\n\t\t\t\t<key>logicalCPUCoresPerPackage</key>\n\t\t\t\t<integer>8</integer>\n\t\t\t\t<key>modelCode</key>\n\t\t\t\t<string>MacBookPro10,1</string>\n\t\t\t\t<key>physicalCPUCoresPerPackage</key>\n\t\t\t\t<integer>4</integer>\n\t\t\t\t<key>platformIdentifier</key>\n\t\t\t\t<string>com.apple.platform.macosx</string>\n\t\t\t</dict>\n\t\t\t<key>targetArchitecture</key>\n\t\t\t<string>x86_64</string>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcschemes/GlueKit-PerformanceTests.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0900\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BB9AE43A1C1FCC35002C5D63\"\n               BuildableName = \"BTree.framework\"\n               BlueprintName = \"Mac\"\n               ReferencedContainer = \"container:Carthage/Checkouts/BTree/BTree.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBB55AD31C8F88F20050DDA9\"\n               BuildableName = \"GlueKit.framework\"\n               BlueprintName = \"macOS\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Release\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BB351AFB1DB81E67005F083F\"\n               BuildableName = \"PerformanceTests.xctest\"\n               BlueprintName = \"PerformanceTests\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BB9AE43A1C1FCC35002C5D63\"\n            BuildableName = \"BTree.framework\"\n            BlueprintName = \"Mac\"\n            ReferencedContainer = \"container:Carthage/Checkouts/BTree/BTree.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Release\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BB9AE43A1C1FCC35002C5D63\"\n            BuildableName = \"BTree.framework\"\n            BlueprintName = \"Mac\"\n            ReferencedContainer = \"container:Carthage/Checkouts/BTree/BTree.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BB9AE43A1C1FCC35002C5D63\"\n            BuildableName = \"BTree.framework\"\n            BlueprintName = \"Mac\"\n            ReferencedContainer = \"container:Carthage/Checkouts/BTree/BTree.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcschemes/GlueKit-iOS.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0900\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBB55AB11C8F80020050DDA9\"\n               BuildableName = \"GlueKit.framework\"\n               BlueprintName = \"iOS\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      codeCoverageEnabled = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBB55ABB1C8F80020050DDA9\"\n               BuildableName = \"GlueKit-Test.xctest\"\n               BlueprintName = \"iOS Tests\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AB11C8F80020050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"iOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AB11C8F80020050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"iOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AB11C8F80020050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"iOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcschemes/GlueKit-macOS.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0900\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBB55AD31C8F88F20050DDA9\"\n               BuildableName = \"GlueKit.framework\"\n               BlueprintName = \"macOS\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      codeCoverageEnabled = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBB55ADC1C8F88F20050DDA9\"\n               BuildableName = \"GlueKit-Test.xctest\"\n               BlueprintName = \"macOS Tests\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AD31C8F88F20050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"macOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AD31C8F88F20050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"macOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AD31C8F88F20050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"macOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcschemes/GlueKit-tvOS.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0900\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBB55AFD1C8F8CBB0050DDA9\"\n               BuildableName = \"GlueKit.framework\"\n               BlueprintName = \"tvOS\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      codeCoverageEnabled = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBB55B061C8F8CBB0050DDA9\"\n               BuildableName = \"GlueKit-Test.xctest\"\n               BlueprintName = \"tvOS Tests\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AFD1C8F8CBB0050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"tvOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AFD1C8F8CBB0050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"tvOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AFD1C8F8CBB0050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"tvOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "GlueKit.xcodeproj/xcshareddata/xcschemes/GlueKit-watchOS.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0900\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"BBB55AF01C8F8BE00050DDA9\"\n               BuildableName = \"GlueKit.framework\"\n               BlueprintName = \"watchOS\"\n               ReferencedContainer = \"container:GlueKit.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AF01C8F8BE00050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"watchOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"BBB55AF01C8F8BE00050DDA9\"\n            BuildableName = \"GlueKit.framework\"\n            BlueprintName = \"watchOS\"\n            ReferencedContainer = \"container:GlueKit.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "GlueKit.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Carthage/Checkouts/SipHash/SipHash.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Carthage/Checkouts/BTree/BTree.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:GlueKit.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "GlueKit.xcworkspace/xcshareddata/GlueKit.xcscmblueprint",
    "content": "{\n  \"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey\" : \"1C1227F33F1818028D5EE61FD15F57BEC36D44F4\",\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey\" : {\n\n  },\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey\" : {\n    \"05D6826B0162543BD57EFC4EE6354EB49FD59438\" : 9223372036854775807,\n    \"FB48966E443D25259D3CA0BE6E56D2D7343B7F97\" : 9223372036854775807,\n    \"1C1227F33F1818028D5EE61FD15F57BEC36D44F4\" : 9223372036854775807\n  },\n  \"DVTSourceControlWorkspaceBlueprintIdentifierKey\" : \"46A01E16-332E-44AB-A9D5-63D415AD87CA\",\n  \"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey\" : {\n    \"05D6826B0162543BD57EFC4EE6354EB49FD59438\" : \"GlueKit\\/Carthage\\/Checkouts\\/BTree\\/\",\n    \"FB48966E443D25259D3CA0BE6E56D2D7343B7F97\" : \"GlueKit\\/Carthage\\/Checkouts\\/SipHash\\/\",\n    \"1C1227F33F1818028D5EE61FD15F57BEC36D44F4\" : \"GlueKit\\/\"\n  },\n  \"DVTSourceControlWorkspaceBlueprintNameKey\" : \"GlueKit\",\n  \"DVTSourceControlWorkspaceBlueprintVersion\" : 204,\n  \"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey\" : \"GlueKit.xcworkspace\",\n  \"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey\" : [\n    {\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey\" : \"https:\\/\\/github.com\\/lorentey\\/BTree.git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey\" : \"com.apple.dt.Xcode.sourcecontrol.Git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey\" : \"05D6826B0162543BD57EFC4EE6354EB49FD59438\"\n    },\n    {\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey\" : \"https:\\/\\/github.com\\/lorentey\\/GlueKit.git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey\" : \"com.apple.dt.Xcode.sourcecontrol.Git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey\" : \"1C1227F33F1818028D5EE61FD15F57BEC36D44F4\"\n    },\n    {\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey\" : \"https:\\/\\/github.com\\/lorentey\\/SipHash.git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey\" : \"com.apple.dt.Xcode.sourcecontrol.Git\",\n      \"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey\" : \"FB48966E443D25259D3CA0BE6E56D2D7343B7F97\"\n    }\n  ]\n}"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015–2017 Károly Lőrentey\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version:4.0\nimport PackageDescription\n\nlet package = Package(\n    name: \"GlueKit\",\n    products: [\n        .library(name: \"GlueKit\", type: .dynamic, targets: [\"GlueKit\"])\n    ],\n    dependencies: [\n        .package(url: \"https://github.com/attaswift/SipHash\", from: \"1.2.0\"),\n        .package(url: \"https://github.com/attaswift/BTree\", from: \"4.1.0\")\n    ],\n    targets: [\n        .target(name: \"GlueKit\", dependencies: [\"BTree\", \"SipHash\"], path: \"Sources\"),\n        .testTarget(name: \"GlueKitTests\", dependencies: [\"GlueKit\"], path: \"Tests/GlueKitTests\"),\n        .testTarget(name: \"PerformanceTests\", dependencies: [\"GlueKit\"], path: \"Tests/PerformanceTests\")\n    ],\n    swiftLanguageVersions: [4]\n)\n"
  },
  {
    "path": "README.md",
    "content": "# GlueKit\n\n[![Swift 3](https://img.shields.io/badge/Swift-3.0-blue.svg)](https://swift.org) \n[![License](https://img.shields.io/badge/licence-MIT-blue.svg)](https://github.com/attaswift/GlueKit/blob/master/LICENSE.md)\n[![Platform](https://img.shields.io/badge/platforms-macOS%20∙%20iOS%20∙%20watchOS%20∙%20tvOS-blue.svg)](https://developer.apple.com/platforms/)\n\n[![Build Status](https://travis-ci.org/attaswift/GlueKit.svg?branch=master)](https://travis-ci.org/attaswift/GlueKit)\n[![Code Coverage](https://codecov.io/github/attaswift/GlueKit/coverage.svg?branch=master)](https://codecov.io/github/attaswift/GlueKit?branch=master)\n\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg)](https://github.com/Carthage/Carthage)\n[![CocoaPod Version](https://img.shields.io/cocoapods/v/GlueKit.svg)](http://cocoapods.org/pods/GlueKit)\n\n> :warning: **WARNING** :warning: This project is in a _prerelease_ state. There\n> is active work going on that will result in API changes that can/will break\n> code while things are finished. Use with caution.\n\nGlueKit is a Swift framework for creating observables and manipulating them in interesting and useful ways.\nIt is called GlueKit because it lets you stick stuff together. \n\nGlueKit contains type-safe analogues for Cocoa's [Key-Value Coding][KVC] and [Key-Value Observing][KVO] subsystems, \nwritten in pure Swift.\nBesides providing the basic observation mechanism, GlueKit also supports full-blown *key path*\nobserving, where a sequence of properties starting at a particular entity is observed at once. (E.g., you can observe\na person's best friend's favorite color, which might change whenever the person gets a new best friend, or when the friend\nchanges their mind about which color they like best.)\n\n[KVC]: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/Overview.html\n[KVO]: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html\n\n(Note though that GlueKit's keys are functions so they aren't as easy to serialize as KVC's string-based keys and key paths.\nIt is definitely possible to implement serializable type-safe keys in Swift; but it involves some boilerplate code \nthat's better handled by code generation or core language enhancements such as property behaviors or improved \nreflection capabilities.)\n\nLike KVC/KVO, GlueKit supports observing not only individual values, but also collections like sets or arrays.\nThis includes full support for key path observing, too -- e.g., you can observe a person's children's children \nas a single set.\nThese observable collections report fine-grained incremental changes (e.g., \"'foo' was inserted at index 5\"), allowing\nyou to efficiently react to their changes.\n\nBeyond key path observing, GlueKit also provides a rich set of transformations and combinations for observables\nas a more flexible and extensible Swift version of KVC's \n[collection operators][KVC ops]. E.g., given an observable array of integers, you can (efficiently!) observe \nthe sum of its elements; you can filter it for elements that match a particular predicate; you can get an observable\nconcatenation of it with another observable array; and you can do much more.\n\n[KVC ops]: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/CollectionOperators.html\n\nYou can use GlueKit's observable arrays to efficiently provide data to a `UITableView` or `UICollectionView`, including\nproviding them with incremental changes for animated updates. This functionality is roughly equivalent to what\n[`NSFetchedResultsController`][NSFRC] does in Core Data.\n\n[NSFRC]: https://developer.apple.com/reference/coredata/nsfetchedresultscontroller\n\nGlueKit is written in pure Swift; it does not require the Objective-C runtime for its functionality. \nHowever, it does provide easy-to-use adapters that turn KVO-compatible key paths on NSObjects into GlueKit observables.\n\nGlueKit hasn't been officially released yet. Its API is still in flux, and it has wildly outdated and woefully \nincomplete documentation. However, the project is getting close to a feature set that would make a coherent 1.0 version;\nI expect to have a useful first release before the end of 2016.\n\n##  Presentation\n\nKároly gave a talk on GlueKit during [Functional Swift Conference 2016][FunSwift16] in Budapest.\n[Watch the video][funvideo] or [read the slides][slides].\n\n[FunSwift16]: http://2016.funswiftconf.com\n[slides]: https://vellum.tech/assets/FunSwift2016%20-%20GlueKit.pdf\n[funvideo]: https://www.youtube.com/watch?v=98jsahDV4ts\n\n## Installation\n### CocoaPods\n\nIf you use CocoaPods, you can start using GlueKit by including it as a dependency in your  `Podfile`:\n\n```\npod 'GlueKit', :git => 'https://github.com/attaswift/GlueKit.git'\n```\n\n(There are no official releases of GlueKit yet; the API is incomplete and very unstable for now.)\n\n### Carthage\n\nFor Carthage, add the following line to your `Cartfile`:\n\n```\ngithub \"attaswift/GlueKit\" \"<commit-hash>\"\n```\n\n(You have to use a specific commit hash, because there are no official releases of GlueKit yet; the API is incomplete and very unstable for now.)\n\n### Swift Package Manager\n\nFor Swift Package Manager, add the following entry to the dependencies list inside your `Package.swift` file:\n\n```\n.Package(url: \"https://github.com/attaswift/GlueKit.git\", branch: master)\n```\n\n### Standalone Development\n\nIf you don't use CocoaPods, Carthage or SPM, you need to clone GlueKit, [BTree][btree] and [SipHash][siphash], \nand add references to their `xcodeproj` files to your project's workspace. You may put the clones wherever you like,\nbut if you use Git for your app development, it is a good idea to set them up as submodules of your app's top-level \nGit repository.\n\n[btree]: https://github.com/attaswift/BTree\n[siphash]: https://github.com/attaswift/SipHash\n\nTo link your application binary with GlueKit, just add `GlueKit.framework`, `BTree.framework` and `SipHash.framework`\nfrom the BTree project to the Embedded Binaries section of your app target's General page in Xcode.\nAs long as the GlueKit and BTree project files are referenced in your workspace, these frameworks will be listed in \nthe \"Choose items to add\" sheet that opens when you click on the \"+\" button of your target's Embedded Binaries list.\n\nThere is no need to do any additional setup beyond adding the framework targets to Embedded Binaries.\n\n### Working on GlueKit Itself\n\nIf you want to do some work on GlueKit on its own, without embedding it in an application, \nsimply clone this repo with the `--recursive` option, open `GlueKit.xcworkspace`, and start hacking.\n\n```\ngit clone --recursive https://github.com/attaswift/GlueKit.git GlueKit\nopen GlueKit/GlueKit.xcworkspace\n```\n\n### Importing GlueKit\n\nOnce you've made GlueKit available in your project, you need to import it at the top of each  `.swift` file in \nwhich you want to use its features:\n\n```\nimport GlueKit\n```\n\n## Similar frameworks\n\nSome of GlueKit's constructs can be matched with those in discrete reactive frameworks, such as \n[ReactiveCocoa](https://github.com/ReactiveCocoa/ReactiveCocoa), \n[RxSwift](https://github.com/ReactiveX/RxSwift), \n[ReactKit](https://github.com/ReactKit/ReactKit),\n[Interstellar](https://github.com/JensRavens/Interstellar), and others. \nSometimes GlueKit even uses the same name for the same concept. But often it doesn't (sorry).\n\nGlueKit concentrates on creating a useful model for observables, rather than trying to unify \nobservable-like things with task-like things. \nGlueKit explicitly does not attempt to directly model networking operations \n(although a networking support library could certainly use GlueKit to implement some of its features).\nAs such, GlueKit's source/signal/stream concept transmits simple values; it doesn't wrap them in\n `Event`s. \n\n\nI have several reasons I chose to create GlueKit instead of just using a better established and\nbug-free library:\n\n- I wanted to have some experience with reactive stuff, and you can learn a lot about a paradigm by \n  trying to construct its foundations on your own. The idea is that I start simple and add things as \n  I find I need them. I want to see if I arrive at the same problems and solutions as the \n  Smart People who created the popular frameworks. Some common reactive patterns are not obviously \n  right at first glance.\n- I wanted to experiment with reentrant observables, where an observer is allowed to trigger updates \n  to the observable to which it's connected. I found no well-known implementation of Observable that \n  gets this *just right*.\n- Building a library is a really fun diversion!\n\n## Overview\n\n[The GlueKit Overview](https://github.com/attaswift/GlueKit/blob/master/Documentation/Overview.md)\ndescribes the basic concepts of GlueKit.\n\n## Appetizer\n\nLet's say you're writing a bug tracker application that has a list of projects, each with its own \nset of issues. With GlueKit, you'd use `Variable`s to define your model's attributes and relationships:\n\n```Swift\nclass Project {\n    let name: Variable<String>\n    let issues: ArrayVariable<Issue>\n}\n\nclass Account {\n    let name: Variable<String>\n    let email: Variable<String>\n}\n\nclass Issue {\n    let identifier: Variable<String>\n    let owner: Variable<Account>\n    let isOpen: Variable<Bool>\n    let created: Variable<NSDate>\n}\n\nclass Document {\n    let accounts: ArrayVariable<Account>\n    let projects: ArrayVariable<Project>\n}\n```\n\nYou can use a `let observable: Variable<Foo>` like you would a `var raw: Foo` property, except \nyou need to write `observable.value` whenever you'd write `raw`:\n\n```Swift\n// Raw Swift       ===>      // GlueKit                                    \nvar a = 42          ;        let b = Variable<Int>(42) \nprint(\"a = \\(a)\")   ;        print(\"b = \\(b.value\\)\")\na = 7               ;        b.value = 7\n```\n\nGiven the model above, in Cocoa you could specify key paths for accessing various parts of the model from a\n`Document` instance. For example, to get the email addresses of all issue owners in one big unsorted array, \nyou'd use the Cocoa key path `\"projects.issues.owner.email\"`. GlueKit is able to do this too, although\nit uses a specially constructed Swift closure to represent the key path:\n\n```Swift\nlet cocoaKeyPath: String = \"projects.issues.owner.email\"\n\nlet swiftKeyPath: Document -> AnyObservableValue<[String]> = { document in \n    document.projects.flatMap{$0.issues}.flatMap{$0.owner}.map{$0.email} \n}\n```\n\n(The type declarations are included to make it clear that GlueKit is fully type-safe. Swift's type inference is able\nto find these out automatically, so typically you'd omit specifying types in declarations like this.)\nThe GlueKit syntax is certainly much more verbose, but in exchange it is typesafe, much more flexible, and also extensible. \nPlus, there is a visual difference between selecting a single value (`map`) or a collection of values (`flatMap`), \nwhich alerts you that using this key path might be more expensive than usual. (GlueKit's key paths are really just \ncombinations of observables. `map` is a combinator that is used to build one-to-one key paths; there are many other\ninteresting combinators available.)\n\nIn Cocoa, you would get the current list of emails using KVC's accessor method. In GlueKit, if you give the key path a\ndocument instance, it returns an `AnyObservableValue` that has a `value` property that you can get. \n\n```Swift\nlet document: Document = ...\nlet cocoaEmails: AnyObject? = document.valueForKeyPath(cocoaKeyPath)\nlet swiftEmails: [String] = swiftKeyPath(document).value\n```\n\nIn both cases, you get an array of strings. However, Cocoa returns it as an optional `AnyObject` that you'll need to\nunwrap and cast to the correct type yourself (you'll want to hold your nose while doing so). Boo! \nGlueKit knows what type the result is going to be, so it gives it to you straight. Yay!\n\nNeither Cocoa nor GlueKit allows you to update the value at the end of this key path; however, with Cocoa, you only find\nthis out at runtime, while with GlueKit, you get a nice compiler error:\n\n```Swift\n// Cocoa: Compiles fine, but oops, crash at runtime\ndocument.setValue(\"karoly@example.com\", forKeyPath: cocoaKeyPath)\n// GlueKit/Swift: error: cannot assign to property: 'value' is a get-only property\nswiftKeyPath(document).value = \"karoly@example.com\"\n```\n\nYou'll be happy to know that one-to-one key paths are assignable in both Cocoa and GlueKit:\n\n```Swift\nlet issue: Issue = ...\n/* Cocoa */   issue.setValue(\"karoly@example.com\", forKeyPath: \"owner.email\") // OK\n/* GlueKit */ issue.owner.map{$0.email}.value = \"karoly@example.com\"  // OK\n```\n\n(In GlueKit, you generally just use the observable combinators directly instead of creating key path entities.\nSo we're going to do that from now on. Serializable type-safe key paths require additional work, which is better\nprovided by a potentional future model object framework built on top of GlueKit.)\n\nMore interestingly, you can ask to be notified whenever a key path changes its value.\n\n```Swift\n// GlueKit\nlet c = document.projects.flatMap{$0.issues}.flatMap{$0.owner}.map{$0.name}.subscribe { emails in \n    print(\"Owners' email addresses are: \\(emails)\")\n}\n// Call c.disconnect() when you get bored of getting so many emails.\n\n// Cocoa\nclass Foo {\n    static let context: Int8 = 0\n    let document: Document\n    \n    init(document: Document) {\n        self.document = document\n        document.addObserver(self, forKeyPath: \"projects.issues.owner.email\", options: .New, context:&context)\n    }\n    deinit {\n        document.removeObserver(self, forKeyPath: \"projects.issues.owner.email\", context: &context)\n    }\n    func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, \n                                change change: [String : AnyObject]?, \n                                context context: UnsafeMutablePointer<Void>) {\n        if context == &self.context {\n\t    print(\"Owners' email addresses are: \\(change[NSKeyValueChangeNewKey]))\n        }\n        else {\n            super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)\n        }\n    }\n}\n```\n\nWell, Cocoa is a mouthful, but people tend to wrap this up in their own abstractions. In both cases, a new set of emails is\nprinted whenever the list of projects changes, or the list of issues belonging to any project changes, or the owner of any\nissue changes, or if the email address is changed on an individual account.\n\n\nTo present a more down-to-earth example, let's say you want to create a view model for a project summary screen that\ndisplays various useful data about the currently selected project. GlueKit's observable combinators make it simple to\nput together data derived from our model objects. The resulting fields in the view model are themselves observable,\nand react to changes to any of their dependencies on their own.\n\n```Swift\nclass ProjectSummaryViewModel {\n    let currentDocument: Variable<Document> = ...\n    let currentAccount: Variable<Account?> = ...\n    \n    let project: Variable<Project> = ...\n    \n    /// The name of the current project.\n\tvar projectName: Updatable<String> { \n\t    return project.map { $0.name } \n\t}\n\t\n    /// The number of issues (open and closed) in the current project.\n\tvar isssueCount: AnyObservableValue<Int> { \n\t    return project.selectCount { $0.issues }\n\t}\n\t\n    /// The number of open issues in the current project.\n\tvar openIssueCount: AnyObservableValue<Int> { \n\t    return project.selectCount({ $0.issues }, filteredBy: { $0.isOpen })\n\t}\n\t\n    /// The ratio of open issues to all issues, in percentage points.\n    var percentageOfOpenIssues: AnyObservableValue<Int> {\n        // You can use the standard arithmetic operators to combine observables.\n    \treturn AnyObservableValue.constant(100) * openIssueCount / issueCount\n    }\n    \n    /// The number of open issues assigned to the current account.\n    var yourOpenIssues: AnyObservableValue<Int> {\n        return project\n            .selectCount({ $0.issues }, \n                filteredBy: { $0.isOpen && $0.owner == self.currentAccount })\n    }\n    \n    /// The five most recently created issues assigned to the current account.\n    var yourFiveMostRecentIssues: AnyObservableValue<[Issue]> {\n        return project\n            .selectFirstN(5, { $0.issues }, \n                filteredBy: { $0.isOpen && $0.owner == currentAccount }),\n                orderBy: { $0.created < $1.created })\n    }\n\n    /// An observable version of NSLocale.currentLocale().\n    var currentLocale: AnyObservableValue<NSLocale> {\n        let center = NSNotificationCenter.defaultCenter()\n\t\tlet localeSource = center\n\t\t    .source(forName: NSCurrentLocaleDidChangeNotification)\n\t\t    .map { _ in NSLocale.currentLocale() }\n        return AnyObservableValue(getter: { NSLocale.currentLocale() }, futureValues: localeSource)\n    }\n    \n    /// An observable localized string.\n    var localizedIssueCountFormat: AnyObservableValue<String> {\n        return currentLocale.map { _ in \n            return NSLocalizedString(\"%1$d of %2$d issues open (%3$d%%)\",\n                comment: \"Summary of open issues in a project\")\n        }\n    }\n    \n    /// An observable text for a label.\n    var localizedIssueCountString: AnyObservableValue<String> {\n        return AnyObservableValue\n            // Create an observable of tuples containing values of four observables\n            .combine(localizedIssueCountFormat, issueCount, openIssueCount, percentageOfOpenIssues)\n            // Then convert each tuple into a single localized string\n            .map { format, all, open, percent in \n                return String(format: format, open, all, percent)\n            }\n    }\n}\n```\n\n(Note that some of the operations above aren't implemented yet. Stay tuned!)\n\nWhenever the model is updated or another project or account is selected, the affected `Observable`s \nin the view model are recalculated accordingly, and their subscribers are notified with the updated\nvalues. \nGlueKit does this in a surprisingly efficient manner---for example, closing an issue in\na project will simply decrement a counter inside `openIssueCount`; it won't recalculate the issue\ncount from scratch. (Obviously, if the user switches to a new project, that change will trigger a recalculation of that project's issue counts from scratch.) Observables aren't actually calculating anything until and unless they have subscribers.\n\nOnce you have this view model, the view controller can simply subscribe its observables to various\nlabels displayed in the view hierarchy:\n\n```Swift\nclass ProjectSummaryViewController: UIViewController {\n    private let visibleConnections = Connector()\n    let viewModel: ProjectSummaryViewModel\n    \n    // ...\n    \n    override func viewWillAppear() {\n        super.viewWillAppear()\n        \n\t    viewModel.projectName.values\n\t        .subscribe { name in\n\t            self.titleLabel.text = name\n\t        }\n\t        .putInto(visibleConnections)\n\t     \n\t    viewModel.localizedIssueCountString.values\n\t        .subscribe { text in\n\t            self.subtitleLabel.text = text\n\t        }\n\t        .putInto(visibleConnections)\n\t        \n        // etc. for the rest of the observables in the view model\n    }\n    \n    override func viewDidDisappear() {\n        super.viewDidDisappear()\n        visibleConnections.disconnect()\n    }\n}\n```\n\nSetting up the connections in `viewWillAppear` ensures that the view model's complex observer\ncombinations are kept up to date only while the project summary is displayed on screen.\n\nThe `projectName` property in `ProjectSummaryViewModel` is declared an `Updatable`, so you can \nmodify its value. Doing that updates the name of the current project: \n\n```Swift\nviewModel.projectName.value = \"GlueKit\"   // Sets the current project's name via a key path\nprint(viewModel.project.name.value)       // Prints \"GlueKit\"\n```\n\n\n"
  },
  {
    "path": "Sources/Abstract.swift",
    "content": "//\n//  Abstract.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-22.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\ninternal func abstract() -> Never {\n    fatalError(\"Unimplemented abstract method\")\n}\n"
  },
  {
    "path": "Sources/AccumulatedSource.swift",
    "content": "//\n//  AccumulatedSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2017-04-23.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension SourceType {\n    public func accumulated<R>(_ initial: R, _ next: @escaping (R, Value) -> R) -> AnyObservableValue<R> {\n        return AccumulatedSource(self, initial, next).anyObservableValue\n    }\n\n    public func counted() -> AnyObservableValue<Int> {\n        return accumulated(0) { value, _ in value + 1 }\n    }\n}\n\nprivate class AccumulatedSource<Value, S>: _BaseObservableValue<Value> where S: SourceType {\n    let source: S\n    let next: (Value, S.Value) -> Value\n    var _value: Value\n\n    struct Sink<R, S: SourceType>: UniqueOwnedSink {\n        typealias Owner = AccumulatedSource<R, S>\n        unowned(unsafe) let owner: Owner\n        func receive(_ value: S.Value) {\n            owner.beginTransaction()\n            let old = owner._value\n            let new = owner.next(owner._value, value)\n            owner._value = new\n            owner.sendChange(ValueChange(from: old, to: new))\n            owner.endTransaction()\n        }\n    }\n\n    init(_ source: S, _ initial: Value, _ next: @escaping (Value, S.Value) -> Value) {\n        self.source = source\n        self.next = next\n        self._value = initial\n        super.init()\n        source.add(Sink<Value, S>(owner: self))\n    }\n\n    deinit {\n        source.remove(Sink<Value, S>(owner: self))\n    }\n\n    override var value: Value { return _value }\n}\n"
  },
  {
    "path": "Sources/ArrayBasedTableViewDataSource.swift",
    "content": "//\n//  ArrayBasedTableViewDataSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2017-04-24.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport UIKit\n\nextension IndexSet {\n    func toIndexPaths(section: Int = 0) -> [IndexPath] {\n        return self.map { IndexPath(row: $0, section: section) }\n    }\n}\n\npublic func <-- <Element, Source: ObservableArrayType>(target: DependentArray<Element>, source: Source) where Source.Element == Element {\n    target.origin = source.anyObservableArray\n}\n\npublic class DependentArray<Element> {\n    private var _itemsRef = Variable<AnyObservableArray<Element>>(.constant([]))\n    private var _items: AnyObservableArray<Element>\n    public let changes: AnySource<ArrayChange<Element>>\n\n    public init() {\n        self._items = _itemsRef.unpacked()\n        self.changes = _items.changes\n    }\n\n    public var origin: AnyObservableArray<Element> {\n        get {\n            return _items\n        }\n        set {\n            _itemsRef.value = newValue\n        }\n    }\n}\n\npublic class ArrayBasedTableViewDataSource<Item: Hashable, Cell: UITableViewCell>: NSObject, UITableViewDataSource {\n    public let tableView: UITableView\n    public let reuseIdentifier: String\n    public let cellLoader: (Cell, Item) -> Void\n\n    public let items = DependentArray<Item>()\n\n    private struct Sink: UniqueOwnedSink {\n        typealias Owner = ArrayBasedTableViewDataSource<Item, Cell>\n        unowned(unsafe) let owner: Owner\n        func receive(_ change: ArrayChange<Item>) { owner.receive(change) }\n    }\n\n    public init(tableView: UITableView, reuseIdentifier: String, cellLoader: @escaping (Cell, Item) -> Void) {\n        self.tableView = tableView\n        self.reuseIdentifier = reuseIdentifier\n        self.cellLoader = cellLoader\n        super.init()\n\n        self.items.changes.add(Sink(owner: self))\n        tableView.dataSource = self\n    }\n\n    deinit {\n        self.items.changes.remove(Sink(owner: self))\n    }\n\n    public convenience init(tableView: UITableView, reuseIdentifier: String) {\n        self.init(tableView: tableView, reuseIdentifier: reuseIdentifier, cellLoader: { cell, item in\n            cell.textLabel!.text = \"\\(item)\"\n        })\n    }\n\n    private func receive(_ change: ArrayChange<Item>) {\n        guard !change.isEmpty else { return }\n        let batch = change.separated()\n        //print(\"Batch: count=\\(change.initialCount)/\\(change.finalCount), deleted=\\(Array(batch.deleted)), inserted=\\(Array(batch.inserted)), moved=\\(batch.moved)\")\n        assert(batch.change.finalCount == items.origin.count)\n\n        tableView.beginUpdates()\n        tableView.deleteRows(at: batch.deleted.toIndexPaths(), with: .fade)\n        tableView.insertRows(at: batch.inserted.toIndexPaths(), with: .fade)\n        for (from, to) in batch.moved {\n            tableView.moveRow(at: IndexPath(row: from, section: 0), to: IndexPath(row: to, section: 0))\n            if let cell = tableView.cellForRow(at: IndexPath(row: from, section: 0)) as? Cell {\n                cellLoader(cell, items.origin[to])\n            }\n        }\n        tableView.endUpdates()\n    }\n\n    public func numberOfSections(in tableView: UITableView) -> Int {\n        return 1\n    }\n\n    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\n        guard section == 0 else { return 0 }\n        return items.origin.count\n    }\n\n    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {\n        precondition(indexPath.section == 0)\n        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! Cell\n        cellLoader(cell, items.origin[indexPath.row])\n        return cell\n    }\n\n\n    public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {\n        return nil\n    }\n\n    public func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {\n        return nil\n    }\n\n\n    public func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {\n        return false\n    }\n\n    public func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {\n        return false\n    }\n}\n\n#endif\n"
  },
  {
    "path": "Sources/ArrayChange.swift",
    "content": "//\n//  ArrayChange.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// Describes a single modification of an array. The modification can be an insertion, a removal, a replacement or\n/// a generic range replacement. All indices are understood to be based in the original array, before this modification\n/// has taken place.\n///\n/// Every modification can be converted to a range replacement by using the `range` and `elements` properties.\n/// There is an initializer to convert a pair of `range` and `elements` back into a modification.\npublic enum ArrayModification<Element> {\n    /// The insertion of a single element at the specified position.\n    case insert(Element, at: Int)\n    /// The removal of a single element at the specified position.\n    case remove(Element, at: Int)\n    /// The replacement of a single element at the specified position with the specified new element.\n    case replace(Element, at: Int, with: Element)\n    /// The replacement of the specified contiguous range of elements with the specified new list of elements.\n    /// The count of the range need not equal the replacement element count.\n    ///\n    /// Note that all other modification cases have an equivalent range replacement.\n    /// We chose to keep them separate only because they are more expressive that way.\n    case replaceSlice([Element], at: Int, with: [Element])\n\n    /// Convert a contiguous replacement range and a replacement list of elements into a modification.\n    public init?(replacing old: [Element], at index: Int, with new: [Element]) {\n        switch (old.count, new.count) {\n        case (0, 0):\n            return nil\n        case (0, 1):\n            self = .insert(new[0], at: index)\n        case (1, 0):\n            self = .remove(old[0], at: index)\n        case (1, 1):\n            self = .replace(old[0], at: index, with: new[0])\n        default:\n            self = .replaceSlice(old, at: index, with: new)\n        }\n\n    }\n\n    /// The effect of this modification on the element count of the array.\n    var deltaCount: Int {\n        switch self {\n        case .insert(_, at: _): return 1\n        case .remove(_, at: _): return -1\n        case .replace(_, at: _, with: _): return 0\n        case .replaceSlice(let old, at: _, with: let new): return new.count - old.count\n        }\n    }\n\n    public var startIndex: Int {\n        switch self {\n        case .insert(_, at: let index): return index\n        case .remove(_, at: let index): return index\n        case .replace(_, at: let index, with: _): return index\n        case .replaceSlice(_, at: let index, with: _): return index\n        }\n    }\n\n    public var inputCount: Int {\n        switch self {\n        case .insert(_, at: _):\n            return 0\n        case .remove(_, at: _):\n            return 1\n        case .replace(_, at: _, with: _):\n            return 1\n        case .replaceSlice(let old, at: _, with: _):\n            return old.count\n        }\n    }\n\n    public var outputCount: Int {\n        switch self {\n        case .insert(_, at: _):\n            return 1\n        case .remove(_, at: _):\n            return 0\n        case .replace(_, at: _, with: _):\n            return 1\n        case .replaceSlice(_, at: _, with: let new):\n            return new.count\n        }\n    }\n\n    /// The range (in the original array) that this modification replaces, when converted into a range modification.\n    public var inputRange: CountableRange<Int> {\n        return startIndex ..< startIndex + inputCount\n    }\n\n    /// The range (in the resulting array) that this modification changed.\n    public var outputRange: CountableRange<Int> {\n        return startIndex ..< startIndex + outputCount\n    }\n\n    /// The replacement elements that get inserted by this modification.\n    public var newElements: [Element] {\n        switch self {\n        case .insert(let e, at: _):\n            return [e]\n        case .remove(_, at: _):\n            return []\n        case .replace(_, at: _, with: let e):\n            return [e]\n        case .replaceSlice(_, at: _, with: let es):\n            return es\n        }\n    }\n\n    /// The original elements that this modification removes/changes.\n    public var oldElements: [Element] {\n        switch self {\n        case .insert(_, at: _):\n            return []\n        case .remove(let e, at: _):\n            return [e]\n        case .replace(let e, at: _, with: _):\n            return [e]\n        case .replaceSlice(let es, at: _, with: _):\n            return es\n        }\n    }\n\n    var reversed: ArrayModification<Element> {\n        switch self {\n        case .insert(let new, at: let index):\n            return .remove(new, at: index)\n        case .remove(let old, at: let index):\n            return .insert(old, at: index)\n        case .replace(let old, at: let index, with: let new):\n            return .replace(new, at: index, with: old)\n        case .replaceSlice(let old, at: let index, with: let new):\n            return .replaceSlice(new, at: index, with: old)\n        }\n    }\n\n\n    /// Try to merge `mod` into this modification and return the result.\n    func merged(with mod: ArrayModification<Element>) -> ArrayModificationMergeResult<Element> {\n        let start1 = self.startIndex\n        let start2 = mod.startIndex\n\n        let outputCount1 = self.outputCount\n        let outputEnd1 = start1 + outputCount1\n\n        let inputCount2 = mod.inputCount\n        let inputEnd2 = start2 + inputCount2\n\n\n        if outputEnd1 < start2 {\n            // New range affects indices greater than our range\n            return .disjunctOrderedAfter\n        }\n        if inputEnd2 < start1 {\n            // New range affects indices earlier than our range\n            return .disjunctOrderedBefore\n        }\n\n        // There is some overlap or the ranges are touching each other.\n        let combinedStart = min(start1, start2)\n\n        let oldElements2 = mod.oldElements\n        var combinedOld = self.oldElements\n        if start2 < start1 {\n            combinedOld.insert(contentsOf: oldElements2[0 ..< start1 - start2], at: 0)\n        }\n        let c = inputEnd2 - outputEnd1\n        if c > 0 {\n            combinedOld.append(contentsOf: oldElements2.suffix(c))\n        }\n\n        var combinedNew = self.newElements\n        combinedNew.replaceSubrange(max(0, start2 - start1) ..< min(outputCount1, inputEnd2 - start1), with: mod.newElements)\n\n        if let mod = ArrayModification(replacing: combinedOld, at: combinedStart, with: combinedNew) {\n            return .collapsedTo(mod)\n        }\n        return .collapsedToNoChange\n    }\n\n    /// Transform each element in this modification using the function `transform`.\n    public func map<Result>(_ transform: (Element) -> Result) -> ArrayModification<Result> {\n        switch self {\n        case .insert(let new, at: let i):\n            return .insert(transform(new), at: i)\n        case .remove(let old, at: let i):\n            return .remove(transform(old), at: i)\n        case .replace(let old, at: let i, with: let new):\n            return .replace(transform(old), at: i, with: transform(new))\n        case .replaceSlice(let old, at: let i, with: let new):\n            return .replaceSlice(old.map(transform), at: i, with: new.map(transform))\n        }\n    }\n\n    /// Call `body` on each old element in this modification.\n    public func forEachOldElement(_ body: (Element) -> Void) {\n        switch self {\n        case .insert(_, at: _):\n            break\n        case .remove(let old, at: _):\n            body(old)\n        case .replace(let old, at: _, with: _):\n            body(old)\n        case .replaceSlice(let old, at: _, with: _):\n            old.forEach(body)\n        }\n    }\n\n    /// Call `body` on each new element in this modification.\n    public func forEachNewElement(_ body: (Element) -> Void) {\n        switch self {\n        case .insert(let new, at: _):\n            body(new)\n        case .remove(_, at: _):\n            break\n        case .replace(_, at: _, with: let new):\n            body(new)\n        case .replaceSlice(_, at: _, with: let new):\n            new.forEach(body)\n        }\n    }\n\n\n    /// Add the specified delta to all indices in this modification.\n    public func shift(_ delta: Int) -> ArrayModification<Element> {\n        switch self {\n        case .insert(let new, at: let i):\n            return .insert(new, at: i + delta)\n        case .remove(let old, at: let i):\n            return .remove(old, at: i + delta)\n        case .replace(let old, at: let i, with: let new):\n            return .replace(old, at: i + delta, with: new)\n        case .replaceSlice(let old, at: let i, with: let new):\n            return .replaceSlice(old, at: i + delta, with: new)\n        }\n    }\n}\n\nextension ArrayModification where Element: Equatable {\n    /// Returns an array of modifications that perform the same update as this one, except all cases are removed where\n    /// an element is replaced by a value that is equal to it.\n    public func removingEqualChanges() -> [ArrayModification] {\n        switch self {\n        case .insert(_, at: _):\n            return [self]\n        case .remove(_, at: _):\n            return [self]\n        case .replace(let old, at: _, with: let new):\n            return old == new ? [] : [self]\n        case .replaceSlice(let old, at: let index, with: let new):\n            var result: [ArrayModification<Element>] = []\n\n            var start = 0\n            for i in 0 ..< min(old.count, new.count) {\n                if old[i] == new[i] {\n                    if start < i {\n                        if let mod = ArrayModification(replacing: Array(old[start ..< i]), at: index + start, with: Array(new[start ..< i])) {\n                            result.append(mod)\n                        }\n                    }\n                    start = i + 1\n                }\n            }\n            if old.count != new.count || start < old.count {\n                if let mod = ArrayModification(replacing: Array(old.suffix(from: start)), at: index + start, with: Array(new.suffix(from: start))) {\n                    result.append(mod)\n                }\n            }\n            return result\n        }\n    }\n\n    /// Returns true iff the result array is equal to the original, i.e. if it doesn't change anything, or only replaces\n    /// values with equal values.\n    public var isIdentity: Bool {\n        switch self {\n        case .insert(_, at: _):\n            return false\n        case .remove(_, at: _):\n            return false\n        case .replace(let old, at: _, with: let new):\n            return old == new\n        case .replaceSlice(let old, at: _, with: let new):\n            return old == new\n        }\n    }\n}\n\n/// The result of an attempt at merging two array modifications.\ninternal enum ArrayModificationMergeResult<Element> {\n    /// The modifications are disjunct, and the new modification changes indexes below the old.\n    case disjunctOrderedBefore\n    /// The modifications are disjunct, and the new modification changes indexes above the old.\n    case disjunctOrderedAfter\n    /// The modifications are intersecting, and cancel each other out.\n    case collapsedToNoChange\n    /// The modifications are intersecting, and merge to the specified new modification.\n    case collapsedTo(ArrayModification<Element>)\n}\n\nextension ArrayModification: CustomStringConvertible, CustomDebugStringConvertible {\n    public var description: String {\n        switch self {\n        case .insert(let new, at: let i):\n            return \".insert(\\(new), at: \\(i))\"\n        case .remove(let old, at: let i):\n            return \".remove(\\(old), at: \\(i))\"\n        case .replace(let old, at: let i, with: let new):\n            return \".replace(\\(old), at: \\(i), with: \\(new))\"\n        case .replaceSlice(let old, at: let i, with: let new):\n            let oldString = \"[\\(old.map { \"\\($0)\" }.joined(separator: \", \"))]\"\n            let newString = \"[\\(new.map { \"\\($0)\" }.joined(separator: \", \"))]\"\n            return \".replaceSlice(\\(oldString), at: \\(i), with: \\(newString))\"\n        }\n    }\n\n    public var debugDescription: String {\n        switch self {\n        case .insert(let new, at: let i):\n            return \".insert(\\(String(reflecting: new)), at: \\(i))\"\n        case .remove(let old, at: let i):\n            return \".remove(\\(String(reflecting: old)), at: \\(i))\"\n        case .replace(let old, at: let i, with: let new):\n            return \".replace(\\(String(reflecting: old)), at: \\(i), with: \\(String(reflecting: new)))\"\n        case .replaceSlice(let old, at: let i, with: let new):\n            let oldString = \"[\\(old.map { String(reflecting: $0) }.joined(separator: \", \"))]\"\n            let newString = \"[\\(new.map { String(reflecting: $0) }.joined(separator: \", \"))]\"\n            return \".replaceSlice(\\(oldString), at: \\(i), with: \\(newString))\"\n        }\n    }\n}\n\nextension ArrayModification: CustomPlaygroundQuickLookable {\n    public var customPlaygroundQuickLook: PlaygroundQuickLook {\n        return .text(description)\n    }\n}\n\nextension RangeReplaceableCollection where Index == Int {\n    /// Apply `modification` to this array in place.\n    public mutating func apply(_ modification: ArrayModification<Iterator.Element>) {\n        switch modification {\n        case .insert(let element, at: let index):\n            self.insert(element, at: index)\n        case .remove(_, at: let index):\n            self.remove(at: index)\n        case .replace(_, at: let index, with: let new):\n            self.replaceSubrange(index ..< index + 1, with: [new])\n        case .replaceSlice(let old, at: let index, with: let new):\n            self.replaceSubrange(index ..< index + old.count, with: new)\n        }\n    }\n}\n\npublic func ==<Element: Equatable>(a: ArrayModification<Element>, b: ArrayModification<Element>) -> Bool {\n    return a.startIndex == b.startIndex\n        && a.inputCount == b.inputCount\n        && a.outputCount == b.outputCount\n        && a.oldElements == b.oldElements\n        && a.newElements == b.newElements\n}\npublic func !=<Element: Equatable>(a: ArrayModification<Element>, b: ArrayModification<Element>) -> Bool {\n    return !(a == b)\n}\n\n\n//MARK: ArrayChange\n\n/// ArrayChange describes a series of one or more modifications to an array. Each modification is the replacement of\n/// a contiguous range of elements with another set of elements (see `ArrayModification`).\n///\n/// You can efficiently merge array changes together forming a single change, without constructing the whole array\n/// in between. You can also transform values contained array changes using any transform function.\n///\n/// Array changes may only be applied on arrays that have the same number of elements as the original array.\n///\n/// - SeeAlso: ArrayModification, AnyObservableArray, ArrayVariable\npublic struct ArrayChange<Element>: ChangeType {\n    public typealias Value = [Element]\n\n    /// The expected initial count of elements in the array on the input of this change.\n    public private(set) var initialCount: Int\n\n    /// The expected change in the count of elements in the array as a result of this change.\n    public var deltaCount: Int { return modifications.reduce(0) { s, mod in s + mod.deltaCount } }\n\n    public var countChange: ValueChange<Int> { return .init(from: initialCount, to: finalCount) }\n\n    public var finalCount: Int { return initialCount + deltaCount }\n\n    /// The sequence of independent modifications to apply, in order of the start indexes of their ranges.\n    /// All indices are understood to be in the array resulting from the original array by applying all\n    /// earlier modifications. (So you can simply loop over the modifications and apply them one by one.)\n    public private(set) var modifications: [ArrayModification<Element>] = []\n\n    public init(initialCount: Int) {\n        self.initialCount = initialCount\n        self.modifications = []\n    }\n\n    internal init(initialCount: Int, modifications: [ArrayModification<Element>]) {\n        self.initialCount = initialCount\n        self.modifications = modifications\n    }\n\n    /// Initializes a change with `count` as the expected initial count and consisting of `modification`.\n    public init(initialCount: Int, modification: ArrayModification<Element>) {\n        self.initialCount = initialCount\n        self.modifications = [modification]\n    }\n\n    /// Initializes a change that simply replaces all elements in `previousValue` with the ones in `newValue`.\n    public init(from previousValue: Value, to newValue: Value) {\n        // Elements aren't necessarily equatable here, so this is the best we can do.\n        if let mod = ArrayModification(replacing: previousValue, at: 0, with: newValue) {\n            self.init(initialCount: previousValue.count, modification: mod)\n        }\n        else {\n            self.init(initialCount: previousValue.count)\n        }\n    }\n\n    /// Returns true if this change contains no actual changes to the array.\n    /// This can happen if a series of merged changes cancel each other out---such as the insertion of an element\n    /// and the subsequent removal of the same.\n    public var isEmpty: Bool { return modifications.isEmpty }\n\n    public mutating func add(_ new: ArrayModification<Element>) {\n        var pos = modifications.count - 1\n        var m = new\n        while pos >= 0 {\n            let old = modifications[pos]\n            let res = old.merged(with: m)\n            switch res {\n            case .disjunctOrderedAfter:\n                modifications.insert(m, at: pos + 1)\n                return\n            case .disjunctOrderedBefore:\n                modifications[pos] = old.shift(m.deltaCount)\n                pos -= 1\n                continue\n            case .collapsedToNoChange:\n                modifications.remove(at: pos)\n                return\n            case .collapsedTo(let merged):\n                modifications.remove(at: pos)\n                m = merged\n                pos -= 1\n                continue\n            }\n        }\n        modifications.insert(m, at: 0)\n    }\n\n    public func apply(on value: inout Array<Element>) {\n        precondition(value.count == initialCount)\n        value.apply(self)\n    }\n\n    /// Merge `other` into this change, modifying it in place.\n    /// `other.initialCount` must be equal to `self.finalCount`, or the merge will report a fatal error.\n    public mutating func merge(with other: ArrayChange<Element>) {\n        precondition(finalCount == other.initialCount)\n        for m in other.modifications {\n            add(m)\n        }\n    }\n\n    /// Returns a new change that contains all changes in this change plus all changes in `other`.\n    /// `other.initialCount` must be equal to `self.finalCount`, or the merge will report a fatal error.\n    public func merged(with other: ArrayChange<Element>) -> ArrayChange<Element> {\n        var result = self\n        result.merge(with: other)\n        return result\n    }\n\n    public func reversed() -> ArrayChange {\n        var result = ArrayChange(initialCount: self.finalCount)\n        var delta = 0\n        for mod in self.modifications {\n            result.add(mod.reversed.shift(delta))\n            delta -= mod.deltaCount\n        }\n        return result\n    }\n\n    /// Transform all element values contained in this change using the `transform` function.\n    public func map<Result>(_ transform: (Element) -> Result) -> ArrayChange<Result> {\n        return ArrayChange<Result>(initialCount: initialCount, modifications: modifications.map { $0.map(transform) })\n    }\n\n    /// Call `body` on each element value that is removed by this change.\n    public func forEachOld(_ body: (Element) -> Void) {\n        modifications.forEach { $0.forEachOldElement(body) }\n    }\n\n    /// Call `body` on each element value that is added by this change.\n    public func forEachNew(_ body: (Element) -> Void) {\n        modifications.forEach { $0.forEachNewElement(body) }\n    }\n\n    /// Convert this change so that it modifies a range of items in a larger array.\n    ///\n    /// Modifications contained in the result will be the same as in this change, except they will \n    /// apply on the range `startIndex ..< startIndex + self.initialCount` in the wider array.\n    ///\n    /// - Parameter startIndex: The start index of the range to rebase this change into.\n    /// - Parameter count: The element count of the wider array to rebase this change into.\n    /// - Returns: A new change that applies the same modifications on a range inside a wider array.\n    public func widen(startIndex: Int, initialCount: Int) -> ArrayChange<Element> {\n        precondition(startIndex + self.initialCount <= initialCount)\n        if startIndex > 0 {\n            let mods = modifications.map { $0.shift(startIndex) }\n            return ArrayChange(initialCount: initialCount, modifications: mods)\n        }\n        else {\n            return ArrayChange(initialCount: initialCount, modifications: modifications)\n        }\n    }\n}\n\nextension ArrayChange: CustomStringConvertible {\n    public var description: String {\n        let type = String(describing: ArrayChange.self)\n        let c = modifications.count\n        return \"\\(type) initialCount: \\(initialCount), \\(c) modifications\"\n    }\n}\n\nextension ArrayChange: CustomDebugStringConvertible {\n    public var debugDescription: String {\n        let type = String(reflecting: ArrayChange.self)\n        let c = modifications.count\n        return \"\\(type) initialCount: \\(initialCount), \\(c) modifications\"\n    }\n}\n\nextension ArrayChange: CustomReflectable {\n    public var customMirror: Mirror {\n        return Mirror(self, children: [\"initialCount\": initialCount,\n                                       \"modifications\": modifications],\n                      displayStyle: .struct)\n    }\n}\n\nextension ArrayChange where Element: Equatable {\n    public func removingEqualChanges() -> ArrayChange {\n        return ArrayChange(initialCount: initialCount, modifications: modifications.flatMap { $0.removingEqualChanges() })\n    }\n}\n\npublic func ==<Element: Equatable>(a: ArrayChange<Element>, b: ArrayChange<Element>) -> Bool {\n    return (a.initialCount == b.initialCount\n        && a.modifications.elementsEqual(b.modifications, by: ==))\n}\npublic func !=<Element: Equatable>(a: ArrayChange<Element>, b: ArrayChange<Element>) -> Bool {\n    return !(a == b)\n}\n\nextension RangeReplaceableCollection where Index == Int, IndexDistance == Int {\n    /// Apply `change` to this array. The count of self must be the same as the initial count of `change`, or\n    /// the operation will report a fatal error.\n    public mutating func apply(_ change: ArrayChange<Element>) {\n        precondition(self.count == change.initialCount)\n        for modification in change.modifications {\n            self.apply(modification)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayChangeSeparation.swift",
    "content": "//\n//  ArrayChangeSeparation.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-27.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation // For IndexSet\n\nprivate func separationError() -> Never {\n    fatalError(\"Changes in arrays with duplicate elements cannot be separated\")\n}\n\nextension ArrayChange {\n    /// Return the set of indices at which elements will be deleted or updated from the array when this change is applied.\n    ///\n    /// The returned indices are relative to the original state of the array.\n    ///\n    /// This is intended to be given to a `UITableView` inside a `beginUpdates` block or a `UICollectionView` inside\n    /// a `performBatchUpdates` block.\n    ///\n    /// - SeeAlso: `separated()` for a more thorough analysis of the change, including detection of elements that were moved.\n    public var deletedIndices: IndexSet {\n        var result = IndexSet()\n        var delta = 0\n        for modification in modifications {\n            switch modification {\n            case .insert(_, at: _):\n                break\n            case .remove(_, at: let index):\n                result.insert(index - delta)\n            case .replace(_, at: let index, with: _):\n                result.insert(index - delta)\n            case .replaceSlice(let old, let index, with: _):\n                result.insert(integersIn: index - delta ..< index + old.count - delta)\n            }\n            delta += modification.deltaCount\n        }\n        return result\n    }\n\n    /// Return the set of indices at which elements will be inserted or updated in the array when this change is applied.\n    ///\n    /// The returned indices assume deletions were already done.\n    ///\n    /// This is intended to be given to a `UITableView` inside a `beginUpdates` block or a `UICollectionView` inside\n    /// a `performBatchUpdates` block.\n    ///\n    /// - SeeAlso: `separated()` for a more thorough analysis of the change, including detection of elements that were moved.\n    public var insertedIndices: IndexSet {\n        var result = IndexSet()\n        for modification in modifications {\n            switch modification {\n            case .insert(_, at: let index):\n                result.insert(index)\n            case .remove(_, at: _):\n                break\n            case .replace(_, at: let index, with: _):\n                result.insert(index)\n            case .replaceSlice(_, at: let index, with: let new):\n                result.insert(integersIn: index ..< index + new.count)\n            }\n        }\n        return result\n    }\n}\n\nextension ArrayChange where Element: Hashable {\n    /// Separates this change into components that can be directly fed into a `UITableView` or a `UICollectionView` as a batch update.\n    /// \n    /// - Requires: The array must not contain duplicate elements.\n    public func separated() -> SeparatedArrayChange<Element> {\n        return SeparatedArrayChange(self)\n    }\n}\n\npublic struct SeparatedArrayChange<Element: Hashable> {\n    // The original change.\n    public var change: ArrayChange<Element>\n\n    /// The indices that are to be deleted.\n    public var deleted = IndexSet()\n    /// The indices that are inserted.\n    public var inserted = IndexSet()\n    /// The old and new indices of elements that are to be moved.\n    /// (This includes elements that need to be refreshed.)\n    public var moved: [(from: Int, to: Int)] = []\n\n    init(_ change: ArrayChange<Element>) {\n        self.change = change\n\n        var deletedElements: [Element: Int] = [:]\n        var insertedElements: [Element: Int] = [:]\n        var delta = 0\n\n        for modification in change.modifications {\n            switch modification {\n            case .insert(let new, at: let index):\n                guard insertedElements.updateValue(index, forKey: new) == nil else { separationError() }\n            case .remove(let old, at: let index):\n                guard deletedElements.updateValue(index - delta, forKey: old) == nil else { separationError() }\n            case .replace(let old, at: let index, with: let new):\n                guard deletedElements.updateValue(index - delta, forKey: old) == nil else { separationError() }\n                guard insertedElements.updateValue(index, forKey: new) == nil else { separationError() }\n            case .replaceSlice(let old, at: let index, with: let new):\n                for i in 0 ..< min(old.count, new.count) {\n                    guard deletedElements.updateValue(index + i - delta, forKey: old[i]) == nil else { separationError() }\n                    guard insertedElements.updateValue(index + i, forKey: new[i]) == nil else { separationError() }\n                }\n\n                if old.count < new.count {\n                    for i in old.count ..< new.count {\n                        guard insertedElements.updateValue(index + i, forKey: new[i]) == nil else { separationError() }\n                    }\n                }\n                else if old.count > new.count {\n                    for i in new.count ..< old.count {\n                        guard deletedElements.updateValue(index + i - delta, forKey: old[i]) == nil else { separationError() }\n                    }\n                }\n            }\n            delta += modification.deltaCount\n        }\n\n        for (element, from) in deletedElements {\n            if let to = insertedElements[element] {\n                moved.append((from, to))\n                deletedElements.removeValue(forKey: element)\n                insertedElements.removeValue(forKey: element)\n            }\n        }\n\n        self.deleted = IndexSet(deletedElements.values)\n        self.inserted = IndexSet(insertedElements.values)\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayConcatenation.swift",
    "content": "//\n//  Concatenation.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-22.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableArrayType {\n    public func concatenate<A: ObservableArrayType>(with other: A) -> AnyObservableArray<Element>\n    where A.Element == Element {\n        return ArrayConcatenation(first: self, second: other).anyObservableArray\n    }\n}\n\npublic func +<A: ObservableArrayType, B: ObservableArrayType>(a: A, b: B) -> AnyObservableArray<A.Element>\nwhere A.Element == B.Element {\n    return a.concatenate(with: b)\n}\n\nfinal class ArrayConcatenation<First: ObservableArrayType, Second: ObservableArrayType>: _BaseObservableArray<First.Element>\nwhere First.Element == Second.Element {\n    typealias Element = First.Element\n    typealias Change = ArrayChange<Element>\n\n    private struct FirstSink: UniqueOwnedSink {\n        typealias Owner = ArrayConcatenation\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ArrayUpdate<First.Element>) {\n            owner.applyFirst(update)\n        }\n    }\n    \n    private struct SecondSink: UniqueOwnedSink {\n        typealias Owner = ArrayConcatenation\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ArrayUpdate<Second.Element>) {\n            owner.applySecond(update)\n        }\n    }\n    \n    let first: First\n    let second: Second\n\n    private var firstCount = -1\n    private var secondCount = -1\n\n    init(first: First, second: Second) {\n        self.first = first\n        self.second = second\n    }\n\n    override var isBuffered: Bool { return false }\n    override subscript(index: Int) -> Element {\n        let c = first.count\n        if index < c {\n            return first[index]\n        }\n        return second[index - c]\n    }\n\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        let c = first.count\n        if bounds.upperBound <= c {\n            return first[bounds]\n        }\n        if bounds.lowerBound >= c {\n            return second[bounds.lowerBound - c ..< bounds.upperBound - c]\n        }\n        return ArraySlice(first[bounds.lowerBound ..< c] + second[0 ..< bounds.upperBound - c])\n    }\n\n    override var value: [Element] { return first.value + second.value }\n    override var count: Int { return first.count + second.count }\n\n    override func activate() {\n        firstCount = first.count\n        secondCount = second.count\n        first.updates.add(FirstSink(owner: self))\n        second.updates.add(SecondSink(owner: self))\n    }\n\n    override func deactivate() {\n        first.updates.remove(FirstSink(owner: self))\n        second.updates.remove(SecondSink(owner: self))\n        firstCount = -1\n        secondCount = -1\n    }\n\n    func applyFirst(_ update: ArrayUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            precondition(self.firstCount == change.initialCount)\n            firstCount = change.finalCount\n            sendChange(change.widen(startIndex: 0, initialCount: change.initialCount + self.secondCount))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applySecond(_ update: ArrayUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            precondition(self.secondCount == change.initialCount)\n            secondCount = change.finalCount\n            sendChange(change.widen(startIndex: self.firstCount, initialCount: self.firstCount + change.initialCount))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayFilteringIndexmap.swift",
    "content": "//\n//  ArrayFilteringIndexmap.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport BTree\n\ninternal struct ArrayFilteringIndexmap<Element> {\n    let isIncluded: (Element) -> Bool\n    var matchingIndices = SortedSet<Int>()\n\n    init(initialValues values: [Element], isIncluded: @escaping (Element) -> Bool) {\n        self.isIncluded = isIncluded\n        for index in values.indices {\n            if isIncluded(values[index]) {\n                matchingIndices.insert(index)\n            }\n        }\n    }\n\n    mutating func apply(_ change: ArrayChange<Element>) -> ArrayChange<Element> {\n        var filteredChange = ArrayChange<Element>(initialCount: matchingIndices.count)\n        for mod in change.modifications {\n            switch mod {\n            case .insert(let element, at: let index):\n                matchingIndices.shift(startingAt: index, by: 1)\n                if isIncluded(element) {\n                    matchingIndices.insert(index)\n                    filteredChange.add(.insert(element, at: matchingIndices.offset(of: index)!))\n                }\n            case .remove(let element, at: let index):\n                if let filteredIndex = matchingIndices.offset(of: index) {\n                    filteredChange.add(.remove(element, at: filteredIndex))\n                }\n                matchingIndices.shift(startingAt: index + 1, by: -1)\n            case .replace(let old, at: let index, with: let new):\n                switch (matchingIndices.offset(of: index), isIncluded(new)) {\n                case (.some(let offset), true):\n                    filteredChange.add(.replace(old, at: offset, with: new))\n                case (.none, true):\n                    matchingIndices.insert(index)\n                    filteredChange.add(.insert(new, at: matchingIndices.offset(of: index)!))\n                case (.some(let offset), false):\n                    matchingIndices.remove(index)\n                    filteredChange.add(.remove(old, at: offset))\n                case (.none, false):\n                    // Do nothing\n                    break\n                }\n            case .replaceSlice(let old, at: let index, with: let new):\n                let filteredIndex = matchingIndices.prefix(upTo: index).count\n                let filteredOld = matchingIndices.intersection(elementsIn: index ..< index + old.count).map { old[$0 - index] }\n                var filteredNew: [Element] = []\n\n                matchingIndices.subtract(elementsIn: index ..< index + old.count)\n                matchingIndices.shift(startingAt: index + old.count, by: new.count - old.count)\n                for i in 0 ..< new.count {\n                    if isIncluded(new[i]) {\n                        matchingIndices.insert(index + i)\n                        filteredNew.append(new[i])\n                    }\n                }\n                if let mod = ArrayModification(replacing: filteredOld, at: filteredIndex, with: filteredNew) {\n                    filteredChange.add(mod)\n                }\n            }\n        }\n        return filteredChange\n    }\n\n    mutating func insert(_ index: Int) -> Int? {\n        guard !matchingIndices.contains(index) else { return nil }\n        matchingIndices.insert(index)\n        return matchingIndices.offset(of: index)!\n    }\n\n    mutating func remove(_ index: Int) -> Int? {\n        guard let filteredIndex = matchingIndices.offset(of: index) else { return nil }\n        matchingIndices.remove(index)\n        return filteredIndex\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayFilteringOnObservableBool.swift",
    "content": "//\n//  ArrayFilteringOnObservableBool.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableArrayType {\n    public func filter<Test: ObservableValueType>(_ isIncluded: @escaping (Element) -> Test) -> AnyObservableArray<Element>\n    where Test.Value == Bool {\n        return ArrayFilteringOnObservableBool<Self, Test>(parent: self, isIncluded: isIncluded).anyObservableArray\n    }\n\n    public func filter<Predicate: ObservableValueType>(_ isIncluded: Predicate) -> AnyObservableArray<Element>\n    where Predicate.Value == (Element) -> Bool {\n        return self.filter(isIncluded.map { predicate -> Optional<(Element) -> Bool> in predicate })\n    }\n\n    public func filter<Predicate: ObservableValueType>(_ isIncluded: Predicate) -> AnyObservableArray<Element>\n    where Predicate.Value == Optional<(Element) -> Bool> {\n        let reference: AnyObservableValue<AnyObservableArray<Element>> = isIncluded.map { predicate in\n            if let predicate: (Element) -> Bool = predicate {\n                return self.filter(predicate).anyObservableArray\n            }\n            else {\n                return self.anyObservableArray\n            }\n        }\n        return reference.unpacked()\n    }\n}\n\nprivate class ArrayFilteringOnObservableBool<Parent: ObservableArrayType, Test: ObservableValueType>: _BaseObservableArray<Parent.Element>\nwhere Test.Value == Bool {\n    typealias Element = Parent.Element\n    typealias Change = ArrayChange<Element>\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = ArrayFilteringOnObservableBool\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ArrayUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private final class FieldSink: SinkType, RefListElement {\n        typealias Owner = ArrayFilteringOnObservableBool\n        \n        unowned let owner: Owner\n        let field: Test\n        var refListLink = RefListLink<FieldSink>()\n        \n        init(owner: Owner, field: Test) {\n            self.owner = owner\n            self.field = field\n            \n            field.add(self)\n        }\n        \n        func disconnect() {\n            field.remove(self)\n        }\n        \n        func receive(_ update: ValueUpdate<Bool>) {\n            owner.applyFieldUpdate(update, from: self)\n        }\n    }\n\n    private let parent: Parent\n    private let isIncluded: (Element) -> Test\n\n    private var indexMapping: ArrayFilteringIndexmap<Element>\n    private var elementConnections = RefList<FieldSink>()\n\n    init(parent: Parent, isIncluded: @escaping (Element) -> Test) {\n        self.parent = parent\n        self.isIncluded = isIncluded\n        let elements = parent.value\n        self.indexMapping = ArrayFilteringIndexmap(initialValues: elements, isIncluded: { isIncluded($0).value })\n        super.init()\n        parent.updates.add(ParentSink(owner: self))\n        self.elementConnections = RefList(elements.lazy.map { FieldSink(owner: self, field: isIncluded($0)) })\n    }\n\n    deinit {\n        parent.updates.remove(ParentSink(owner: self))\n        self.elementConnections.forEach { $0.disconnect() }\n    }\n\n    private func applyParentUpdate(_ update: ArrayUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            for mod in change.modifications {\n                let inputRange = mod.inputRange\n                inputRange.forEach { elementConnections[$0].disconnect() }\n                elementConnections.replaceSubrange(inputRange, with: mod.newElements.map { FieldSink(owner: self, field: isIncluded($0)) })\n            }\n            let filteredChange = self.indexMapping.apply(change)\n            if !filteredChange.isEmpty {\n                sendChange(filteredChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    private func applyFieldUpdate(_ update: ValueUpdate<Bool>, from sink: FieldSink) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if change.old == change.new { return }\n            let index = elementConnections.index(of: sink)!\n            let c = indexMapping.matchingIndices.count\n            if change.new, let filteredIndex = indexMapping.insert(index) {\n                sendChange(ArrayChange(initialCount: c, modification: .insert(parent[index], at: filteredIndex)))\n            }\n            else if !change.new, let filteredIndex = indexMapping.remove(index) {\n                sendChange(ArrayChange(initialCount: c, modification: .remove(parent[index], at: filteredIndex)))\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool { return false }\n\n    override subscript(index: Int) -> Element {\n        return parent[indexMapping.matchingIndices[index]]\n    }\n\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        precondition(0 <= bounds.lowerBound && bounds.lowerBound <= bounds.upperBound && bounds.upperBound <= count)\n        var result: [Element] = []\n        result.reserveCapacity(bounds.count)\n        for index in indexMapping.matchingIndices[bounds] {\n            result.append(parent[index])\n        }\n        return ArraySlice(result)\n    }\n\n    override var value: Array<Element> {\n        return indexMapping.matchingIndices.map { parent[$0] }\n    }\n\n    override var count: Int {\n        return indexMapping.matchingIndices.count\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayFilteringOnPredicate.swift",
    "content": "//\n//  ArrayFilteringOnPredicate.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-09-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableArrayType {\n    public func filter(_ isIncluded: @escaping (Element) -> Bool) -> AnyObservableArray<Element> {\n        return ArrayFilteringOnPredicate<Self>(parent: self, isIncluded: isIncluded).anyObservableArray\n    }\n}\n\nprivate final class ArrayFilteringOnPredicate<Parent: ObservableArrayType>: _BaseObservableArray<Parent.Element> {\n    public typealias Element = Parent.Element\n    public typealias Change = ArrayChange<Element>\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = ArrayFilteringOnPredicate\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ArrayUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private let parent: Parent\n    private let isIncluded: (Element) -> Bool\n\n    private var indexMapping: ArrayFilteringIndexmap<Element>\n\n    init(parent: Parent, isIncluded: @escaping (Element) -> Bool) {\n        self.parent = parent\n        self.isIncluded = isIncluded\n        self.indexMapping = ArrayFilteringIndexmap(initialValues: parent.value, isIncluded: isIncluded)\n        super.init()\n        parent.add(ParentSink(owner: self))\n    }\n\n    deinit {\n        parent.remove(ParentSink(owner: self))\n    }\n\n    func applyParentUpdate(_ update: ArrayUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let filteredChange = self.indexMapping.apply(change)\n            if !filteredChange.isEmpty {\n                sendChange(filteredChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool {\n        return false\n    }\n\n    override subscript(index: Int) -> Element {\n        return parent[indexMapping.matchingIndices[index]]\n    }\n\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        precondition(0 <= bounds.lowerBound && bounds.lowerBound <= bounds.upperBound && bounds.upperBound <= count)\n        var result: [Element] = []\n        result.reserveCapacity(bounds.count)\n        for index in indexMapping.matchingIndices[bounds] {\n            result.append(parent[index])\n        }\n        return ArraySlice(result)\n    }\n\n    override var value: Array<Element> {\n        return indexMapping.matchingIndices.map { parent[$0] }\n    }\n\n    override var count: Int {\n        return indexMapping.matchingIndices.count\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayFolding.swift",
    "content": "//\n//  ArrayFolding.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableArrayType {\n    /// Returns an observable whose value is always equal to `self.value.reduce(initial, add)`.\n    ///\n    /// - Parameter initial: The accumulation starts with this initial value.\n    /// - Parameter add: A closure that adds an element of the array into an accumulated value.\n    /// - Parameter remove: A closure that cancels the effect of an earlier `add`.\n    /// - Returns: An observable value for the reduction of this array.\n    ///\n    /// - Note: Elements are added and removed in no particular order. \n    ///    (I.e., the underlying binary operation over `Result` must form an abelian group.)\n    ///\n    /// - SeeAlso: `sum()` which returns a reduction using addition.\n    public func reduce<Result>(_ initial: Result, add: @escaping (Result, Element) -> Result, remove: @escaping (Result, Element) -> Result) -> AnyObservableValue<Result> {\n        return ArrayFoldingByTwoWayFunction<Self, Result>(base: self, initial: initial, add: add, remove: remove).anyObservableValue\n    }\n}\n\nextension ObservableArrayType where Element: BinaryInteger {\n    /// Return the (observable) sum of the elements contained in this array.\n    public func sum() -> AnyObservableValue<Element> {\n        return reduce(0, add: +, remove: -)\n    }\n}\n\nprivate class ArrayFoldingByTwoWayFunction<Base: ObservableArrayType, Value>: _BaseObservableValue<Value> {\n    private var _value: Value\n\n    let add: (Value, Base.Element) -> Value\n    let remove: (Value, Base.Element) -> Value\n    var connection: Connection? = nil\n\n    init(base: Base, initial: Value, add: @escaping (Value, Base.Element) -> Value, remove: @escaping (Value, Base.Element) -> Value) {\n        self._value = base.value.reduce(initial, add)\n        self.add = add\n        self.remove = remove\n        super.init()\n\n        connection = base.updates.subscribe { [unowned self] in self.apply($0) }\n    }\n\n    deinit {\n        connection!.disconnect()\n    }\n\n    private func apply(_ update: ArrayUpdate<Base.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let old = _value\n            change.forEachOld { _value = remove(_value, $0) }\n            change.forEachNew { _value = add(_value, $0) }\n            sendChange(ValueChange(from: old, to: _value))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var value: Value { return _value }\n}\n"
  },
  {
    "path": "Sources/ArrayGatheringSource.swift",
    "content": "//\n//  ArrayGatheringSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2017-09-05.\n//  Copyright © 2017 Károly Lőrentey. All rights reserved.\n//\n\nextension ObservableArrayType where Element: SourceType {\n    public func gather() -> AnySource<Element.Value> {\n        return ArrayGatheringSource(self).anySource\n    }\n}\n\nprivate class ArrayGatheringSource<Origin: ObservableArrayType, Value>: _AbstractSource<Value>\nwhere Origin.Element: SourceType, Origin.Element.Value == Value {\n    let origin: Origin\n    var sinks: Set<AnySink<Value>> = []\n\n    private struct GatherSink: UniqueOwnedSink {\n        typealias Owner = ArrayGatheringSource\n        unowned let owner: Owner\n\n        func receive(_ value: ArrayUpdate<Origin.Element>) {\n            guard case let .change(change) = value else { return }\n            change.forEachOld { source in\n                for sink in owner.sinks {\n                    source.remove(sink)\n                }\n            }\n            change.forEachNew { source in\n                for sink in owner.sinks {\n                    source.add(sink)\n                }\n            }\n        }\n    }\n\n    init(_ origin: Origin) {\n        self.origin = origin\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        if sinks.isEmpty {\n            origin.add(GatherSink(owner: self))\n        }\n        let new = sinks.insert(sink.anySink).inserted\n        precondition(new)\n        for source in origin.value {\n            source.add(sink)\n        }\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        let result = sinks.remove(sink.anySink)!\n        for source in origin.value {\n            source.remove(result)\n        }\n        if sinks.isEmpty {\n            origin.remove(GatherSink(owner: self))\n        }\n        return result.opened()!\n    }\n}\n\n"
  },
  {
    "path": "Sources/ArrayMappingForArrayField.swift",
    "content": "//\n//  ArrayMappingForArrayField.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport BTree\n\nextension ObservableArrayType {\n    public func flatMap<Field: ObservableArrayType>(_ key: @escaping (Element) -> Field) -> AnyObservableArray<Field.Element> {\n        return ArrayMappingForArrayField<Self, Field>(parent: self, key: key).anyObservableArray\n    }\n}\n\n/// Maintains an index mapping for an operation mapping an array of arrays into a single flat array.\n///\n/// Terminology:\n/// - preindex, precount refers to indices/count of the original array of arrays.\n/// - postindex, postcount refers to indices/count of the resulting flat array.\nprivate struct Indexmap {\n    // TODO: A weight-augmented tree-backed list would work much better here.\n\n    // The ith element in this sorted bag gives us the starting postindex of the source array corresponding to preindex i.\n    // The bag always ends with an extra element with the overall count of elements.\n    private var postindices: SortedBag<Int> = [0]\n\n    var precount: Int { return postindices.count - 1 }\n    var postcount: Int { return postindices.last! }\n\n    func preindex(for postindex: Int) -> (preindex: Int, offset: Int) {\n        let p = postindices.indexOfLastElement(notAfter: postindex)!\n        let start = postindices[p]\n        let preindex = postindices.offset(of: p)\n        return (preindex, postindex - start)\n    }\n\n    func postindex(for preindex: Int) -> Int {\n        return postindices[preindex]\n    }\n\n    mutating func appendArray(withCount count: Int) {\n        postindices.insert(postcount + count)\n    }\n\n    mutating func replaceArrays(in prerange: Range<Int>, withCounts counts: [Int]) {\n        let postrange: Range<Int> = postindex(for: prerange.lowerBound) ..< postindex(for: prerange.upperBound)\n        let postdelta = counts.reduce(0, +) - postrange.count\n        for i in CountableRange(prerange).reversed() { // TODO: SortedBag.remove(offsetsIn: prerange)\n            postindices.remove(atOffset: i)\n        }\n        postindices.shift(startingAt: postindices.index(ofOffset: prerange.lowerBound), by: postdelta)\n\n        var poststart = postrange.lowerBound\n        for i in 0 ..< counts.count {\n            let count = counts[i]\n            postindices.insert(poststart)\n            poststart += count\n        }\n    }\n\n    mutating func setCount(forArrayAt preindex: Int, from old: Int, to new: Int) {\n        if old == new { return }\n        var i = postindices.index(ofOffset: preindex)\n        postindices.formIndex(after: &i)\n        postindices.shift(startingAt: i, by: new - old)\n    }\n}\n\nprivate final class ArrayMappingForArrayField<Parent: ObservableArrayType, Field: ObservableArrayType>: _BaseObservableArray<Field.Element> {\n    typealias Element = Field.Element\n\n    private final class FieldSink: SinkType, RefListElement {\n        typealias Owner = ArrayMappingForArrayField\n\n        unowned let owner: Owner\n        let field: Field\n        var refListLink = RefListLink<FieldSink>()\n\n        init(owner: Owner, field: Field) {\n            self.owner = owner\n            self.field = field\n            field.add(self)\n        }\n\n        func disconnect() {\n            field.remove(self)\n        }\n\n        func receive(_ update: ArrayUpdate<Field.Element>) {\n            owner.applyFieldUpdate(update, from: self)\n        }\n    }\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = ArrayMappingForArrayField\n\n        unowned(unsafe) let owner: Owner\n\n        func receive(_ update: ArrayUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private let parent: Parent\n    private let key: (Parent.Element) -> Field\n\n    private var fieldSinks = RefList<FieldSink>()\n    private var indexMapping = Indexmap()\n\n    init(parent: Parent, key: @escaping (Parent.Element) -> Field) {\n        self.parent = parent\n        self.key = key\n        super.init()\n\n        parent.updates.add(ParentSink(owner: self))\n        for pe in parent.value {\n            let field = key(pe)\n            fieldSinks.append(FieldSink(owner: self, field: field))\n            indexMapping.appendArray(withCount: field.count)\n        }\n    }\n\n    deinit {\n        parent.updates.remove(ParentSink(owner: self))\n        fieldSinks.forEach { $0.disconnect() }\n    }\n\n    private func applyParentUpdate(_ update: ArrayUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            precondition(change.initialCount == fieldSinks.count)\n            var transformedChange = ArrayChange<Element>(initialCount: indexMapping.postcount)\n            for mod in change.modifications {\n                let preindex = mod.startIndex\n                let postindex = indexMapping.postindex(for: preindex)\n                let oldFields = mod.oldElements.map { key($0) }\n                let newFields = mod.newElements.map { key($0) }\n\n                // Replace field connections.\n                let prerange: Range<Int> = preindex ..< preindex + oldFields.count\n                self.fieldSinks.forEach(in: prerange) { $0.disconnect() }\n                self.fieldSinks.replaceSubrange(prerange, with: newFields.map { FieldSink(owner: self, field: $0) })\n\n                // Update index mapping.\n                indexMapping.replaceArrays(in: prerange, withCounts: newFields.map { $0.count })\n\n                // Create new change component.\n                let oldValues = oldFields.flatMap { $0.value }\n                let newValues = newFields.flatMap { $0.value }\n                if let mod = ArrayModification(replacing: oldValues, at: postindex, with: newValues) {\n                    transformedChange.add(mod)\n                }\n            }\n            precondition(change.finalCount == fieldSinks.count)\n            if !transformedChange.isEmpty {\n                sendChange(transformedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    private func applyFieldUpdate(_ update: ArrayUpdate<Field.Element>, from sink: FieldSink) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let preindex = fieldSinks.index(of: sink)!\n            let postindex = indexMapping.postindex(for: preindex)\n            let transformedChange = change.widen(startIndex: postindex, initialCount: indexMapping.postcount)\n            indexMapping.setCount(forArrayAt: preindex, from: change.initialCount, to: change.finalCount)\n            sendChange(transformedChange)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool {\n        return false\n    }\n\n    override subscript(index: Int) -> Element {\n        let (preindex, offset) = indexMapping.preindex(for: index)\n        return key(parent[preindex])[offset]\n    }\n\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        let start = indexMapping.preindex(for: bounds.lowerBound)\n        let end = indexMapping.preindex(for: bounds.upperBound)\n\n        if start.preindex == end.preindex {\n            return key(parent[start.preindex])[start.offset ..< end.offset]\n        }\n        var result: [Element] = []\n        result.reserveCapacity(bounds.count)\n\n        let firstField = key(parent[start.preindex])\n        result.append(contentsOf: firstField[start.offset ..< firstField.count])\n\n        for i in start.preindex + 1 ..< end.preindex {\n            result.append(contentsOf: key(parent[i]).value)\n        }\n\n        let lastField = key(parent[end.preindex])\n        result.append(contentsOf: lastField[0 ..< end.offset])\n\n        precondition(result.count == bounds.count)\n        return ArraySlice(result)\n    }\n\n    override var value: Array<Element> {\n        return parent.value.flatMap { key($0).value }\n    }\n    \n    override var count: Int {\n        return indexMapping.postcount\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayMappingForValue.swift",
    "content": "//\n//  ArrayMappingForValue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-22.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableArrayType {\n    public func map<Output>(_ transform: @escaping (Element) -> Output) -> AnyObservableArray<Output> {\n        return ArrayMappingForValue(input: self, transform: transform).anyObservableArray\n    }\n}\n\nprivate final class ArrayMappingForValue<Element, Input: ObservableArrayType>: _AbstractObservableArray<Element> {\n    typealias Change = ArrayChange<Element>\n\n    let input: Input\n    let transform: (Input.Element) -> Element\n    let updateSource: AnySource<ArrayUpdate<Element>>\n\n    init(input: Input, transform: @escaping (Input.Element) -> Element) {\n        self.input = input\n        self.transform = transform\n        self.updateSource = input.updates.map { u in u.map { c in c.map(transform) } }\n        super.init()\n    }\n\n    override var isBuffered: Bool {\n        return false\n    }\n\n    override subscript(index: Int) -> Element {\n        return transform(input[index])\n    }\n\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        return ArraySlice(input[bounds].map(transform))\n    }\n    \n    override var count: Int {\n        return input.count\n    }\n\n    override var value: [Element] {\n        return input.value.map(transform)\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        updateSource.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return updateSource.remove(sink)\n    }\n\n    override var observableCount: AnyObservableValue<Int> {\n        return input.observableCount\n    }\n}\n\n\nextension ObservableArrayType {\n    public func bufferedMap<Output>(_ transform: @escaping (Element) -> Output) -> AnyObservableArray<Output> {\n        return BufferedArrayMappingForValue(self, transform: transform).anyObservableArray\n    }\n}\n\nprivate class BufferedArrayMappingForValue<Input, Output, Content: ObservableArrayType>: _BaseObservableArray<Output>\nwhere Content.Element == Input {\n    typealias Element = Output\n    typealias Change = ArrayChange<Output>\n\n    private struct BufferedMapSink: UniqueOwnedSink {\n        typealias Owner = BufferedArrayMappingForValue\n\n        unowned(unsafe) let owner: Owner\n\n        func receive(_ update: ArrayUpdate<Content.Element>) {\n            owner.apply(update)\n        }\n    }\n\n    let content: Content\n    let transform: (Input) -> Output\n    private var _value: [Output]\n    private var pendingChange: ArrayChange<Input>? = nil\n\n    init(_ content: Content, transform: @escaping (Input) -> Output) {\n        self.content = content\n        self.transform = transform\n        self._value = content.value.map(transform)\n        super.init()\n\n        content.add(BufferedMapSink(owner: self))\n    }\n\n    deinit {\n        content.remove(BufferedMapSink(owner: self))\n    }\n\n    func apply(_ update: Update<ArrayChange<Input>>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if pendingChange != nil {\n                pendingChange!.merge(with: change)\n            }\n            else {\n                pendingChange = change\n            }\n        case .endTransaction:\n            if let change = pendingChange {\n                pendingChange = nil\n                if isConnected {\n                    var mappedChange = Change(initialCount: value.count)\n                    for modification in change.modifications {\n                        switch modification {\n                        case .insert(let new, at: let index):\n                            let tnew = transform(new)\n                            mappedChange.add(.insert(tnew, at: index))\n                            _value.insert(tnew, at: index)\n                        case .remove(_, at: let index):\n                            let old = _value.remove(at: index)\n                            mappedChange.add(.remove(old, at: index))\n                        case .replace(_, at: let index, with: let new):\n                            let old = value[index]\n                            let tnew = transform(new)\n                            _value[index] = tnew\n                            mappedChange.add(.replace(old, at: index, with: tnew))\n                        case .replaceSlice(let old, at: let index, with: let new):\n                            let range = index ..< index + old.count\n                            let told = Array(value[range])\n                            let tnew = new.map(transform)\n                            mappedChange.add(.replaceSlice(told, at: index, with: tnew))\n                            _value.replaceSubrange(range, with: tnew)\n                        }\n                    }\n                    sendChange(mappedChange)\n                }\n                else {\n                    for modification in change.modifications {\n                        switch modification {\n                        case .insert(let new, at: let index):\n                            _value.insert(transform(new), at: index)\n                        case .remove(_, at: let index):\n                            _value.remove(at: index)\n                        case .replace(_, at: let index, with: let new):\n                            _value[index] = transform(new)\n                        case .replaceSlice(let old, at: let index, with: let new):\n                            _value.replaceSubrange(index ..< index + old.count, with: new.map(transform))\n                        }\n                    }\n                }\n            }\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool {\n        return true\n    }\n\n    override subscript(_ index: Int) -> Element {\n        return value[index]\n    }\n\n    override subscript(_ range: Range<Int>) -> ArraySlice<Element> {\n        return value[range]\n    }\n\n    override var value: [Element] { return _value }\n\n    override var count: Int {\n        return value.count\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayMappingForValueField.swift",
    "content": "//\n//  ArrayMappingForValueField.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableArrayType {\n    /// Return an observable array that consists of the values for the field specified by `key` for each element of this array.\n    public func map<Field: ObservableValueType>(_ key: @escaping (Element) -> Field) -> AnyObservableArray<Field.Value> {\n        return ArrayMappingForValueField(parent: self, key: key).anyObservableArray\n    }\n}\n\nprivate final class ArrayMappingForValueField<Parent: ObservableArrayType, Field: ObservableValueType>: _BaseObservableArray<Field.Value> {\n    typealias Element = Field.Value\n    typealias Change = ArrayChange<Element>\n\n    private final class FieldSink: SinkType, RefListElement {\n        unowned let owner: ArrayMappingForValueField\n        let field: Field\n        var refListLink = RefListLink<FieldSink>()\n\n        init(owner: ArrayMappingForValueField<Parent, Field>, field: Field) {\n            self.owner = owner\n            self.field = field\n            field.add(self)\n        }\n\n        func disconnect() {\n            field.remove(self)\n        }\n\n        func receive(_ update: ValueUpdate<Field.Value>) {\n            owner.applyFieldUpdate(update, from: self)\n        }\n    }\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = ArrayMappingForValueField\n\n        unowned let owner: Owner\n\n        func receive(_ update: ArrayUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n\n    private let parent: Parent\n    private let key: (Parent.Element) -> Field\n\n    private var fieldSinks = RefList<FieldSink>()\n\n    init(parent: Parent, key: @escaping (Parent.Element) -> Field) {\n        self.parent = parent\n        self.key = key\n    }\n\n    override var isBuffered: Bool { return false }\n\n    override subscript(index: Int) -> Element {\n        return key(parent[index]).value\n    }\n\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        return ArraySlice(parent[bounds].map { key($0).value })\n    }\n\n    override var value: [Element] {\n        return parent.value.map { key($0).value }\n    }\n\n    override var count: Int { return parent.count }\n\n    override func activate() {\n        let fields = parent.value.map(key)\n        parent.add(ParentSink(owner: self))\n        fieldSinks = RefList(fields.lazy.map { field in FieldSink(owner: self, field: field) })\n    }\n\n    override func deactivate() {\n        parent.remove(ParentSink(owner: self))\n        fieldSinks.forEach { $0.disconnect() }\n        fieldSinks.removeAll()\n    }\n\n    private func applyFieldUpdate(_ update: ValueUpdate<Element>, from sink: FieldSink) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let index = fieldSinks.index(of: sink)!\n            sendChange(ArrayChange(initialCount: fieldSinks.count,\n                                   modification: .replace(change.old, at: index, with: change.new)))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyParentUpdate(_ update: ArrayUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            precondition(fieldSinks.count == change.initialCount)\n            var newChange = ArrayChange<Element>(initialCount: change.initialCount)\n            for mod in change.modifications {\n                let start = mod.startIndex\n                var i = start\n                mod.forEachOldElement { old in\n                    fieldSinks[i].disconnect()\n                    i += 1\n                }\n                var sinks: [FieldSink] = []\n                mod.forEachNewElement { new in\n                    let field = key(new)\n                    sinks.append(FieldSink(owner: self, field: field))\n                }\n                fieldSinks.replaceSubrange(start ..< i, with: sinks)\n                newChange.add(mod.map { self.key($0).value })\n            }\n            precondition(fieldSinks.count == change.finalCount)\n            if !newChange.isEmpty {\n                sendChange(newChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/ArrayReference.swift",
    "content": "//\n//  ArrayReference.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-17.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType where Value: ObservableArrayType{\n    public func unpacked() -> AnyObservableArray<Value.Element> {\n        return UnpackedObservableArrayReference(self).anyObservableArray\n    }\n}\n\n/// A mutable reference to an `AnyObservableArray` that's also an observable array.\n/// You can switch to another target array without having to re-register subscribers.\nprivate final class UnpackedObservableArrayReference<Reference: ObservableValueType>: _BaseObservableArray<Reference.Value.Element>\nwhere Reference.Value: ObservableArrayType {\n    typealias Target = Reference.Value\n    typealias Element = Target.Element\n    typealias Change = ArrayChange<Element>\n\n    private struct ReferenceSink: UniqueOwnedSink {\n        typealias Owner = UnpackedObservableArrayReference\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ValueUpdate<Reference.Value>) {\n            owner.applyReferenceUpdate(update)\n        }\n    }\n    \n    private struct TargetSink: UniqueOwnedSink {\n        typealias Owner = UnpackedObservableArrayReference\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ArrayUpdate<Reference.Value.Element>) {\n            owner.applyTargetUpdate(update)\n        }\n    }\n    \n    private var _reference: Reference\n    private var _target: Reference.Value? = nil // Retained to make sure we keep it alive\n\n    init(_ reference: Reference) {\n        _reference = reference\n        super.init()\n    }\n\n    override func activate() {\n        _reference.updates.add(ReferenceSink(owner: self))\n        let target = _reference.value\n        _target = target\n        target.updates.add(TargetSink(owner: self))\n    }\n\n    override func deactivate() {\n        _target!.updates.remove(TargetSink(owner: self))\n        _reference.updates.remove(ReferenceSink(owner: self))\n    }\n\n    func applyReferenceUpdate(_ update: ValueUpdate<Target>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if isConnected {\n                _target!.remove(TargetSink(owner: self))\n                _target = change.new\n                _target!.add(TargetSink(owner: self))\n                sendChange(ArrayChange(from: change.old.value, to: change.new.value))\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyTargetUpdate(_ update: ArrayUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool { return false }\n    override subscript(_ index: Int) -> Element { return _reference.value[index] }\n    override subscript(_ range: Range<Int>) -> ArraySlice<Element> { return _reference.value[range] }\n    override var value: [Element] { return _reference.value.value }\n    override var count: Int { return _reference.value.count }\n}\n"
  },
  {
    "path": "Sources/ArrayVariable.swift",
    "content": "//\n//  ArrayVariable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-08.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nopen class ArrayVariable<Element>: _BaseUpdatableArray<Element>, ExpressibleByArrayLiteral {\n    public typealias Value = Array<Element>\n    public typealias Change = ArrayChange<Element>\n\n    fileprivate var _value: [Element]\n\n    public override init() {\n        _value = []\n    }\n    public init(_ elements: [Element]) {\n        _value = elements\n    }\n    public init<S: Sequence>(_ elements: S) where S.Iterator.Element == Element {\n        _value = Array(elements)\n    }\n    public init(elements: Element...) {\n        _value = elements\n    }\n    public required convenience init(arrayLiteral elements: Element...) {\n        self.init(elements)\n    }\n\n    override func rawApply(_ change: ArrayChange<Element>) {\n        _value.apply(change)\n    }\n\n    final public override var value: [Element] {\n        get {\n            return _value\n        }\n        set {\n            if isConnected {\n                let old = _value\n                beginTransaction()\n                _value = newValue\n                sendChange(ArrayChange(from: old, to: newValue))\n                endTransaction()\n            }\n            else {\n                _value = newValue\n            }\n        }\n    }\n\n    final public override var count: Int {\n        return _value.count\n    }\n\n    final public override var isBuffered: Bool {\n        return true\n    }\n\n    final public override subscript(index: Int) -> Element {\n        get {\n            return _value[index]\n        }\n        set {\n            if isConnected {\n                let old = _value[index]\n                beginTransaction()\n                _value[index] = newValue\n                sendChange(ArrayChange(initialCount: _value.count, modification: .replace(old, at: index, with: newValue)))\n                endTransaction()\n            }\n            else {\n                _value[index] = newValue\n            }\n        }\n    }\n\n    final public override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        get {\n            return value[bounds]\n        }\n        set {\n            if isConnected {\n                let oldCount = _value.count\n                let old = Array(_value[bounds])\n                beginTransaction()\n                _value[bounds] = newValue\n                sendChange(ArrayChange(initialCount: oldCount,\n                                        modification: .replaceSlice(old, at: bounds.lowerBound, with: Array(newValue))))\n                endTransaction()\n            }\n            else {\n                _value[bounds] = newValue\n            }\n        }\n    }\n}\n\n"
  },
  {
    "path": "Sources/BracketingSource.swift",
    "content": "//\n//  BracketingSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-25.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension SourceType {\n    /// Returns a version of this source that optionally prefixes or suffixes all observers' received values\n    /// with computed start/end values.\n    ///\n    /// For each new subscriber, the returned source evaluates `hello`; if it returns a non-nil value,\n    /// the value is sent to the sink; then the sink is added to `self`.\n    ///\n    /// For each subscriber that is to be removed, the returned source first removes it from `self`, then\n    /// evaluates `goodbye`; if it returns a non-nil value, the bracketing source sends it to the sink.\n    public func bracketed(hello: @escaping () -> Value?, goodbye: @escaping () -> Value?) -> AnySource<Value> {\n        return BracketingSource(self, hello: hello, goodbye: goodbye).anySource\n    }\n}\n\nprivate class BracketingSink<Sink: SinkType>: SinkType {\n    typealias Value = Sink.Value\n\n    let sink: Sink\n    var pendingValues: [Value]?\n    var removed = false\n\n    init(_ sink: Sink) {\n        self.sink = sink\n        self.pendingValues = nil\n    }\n\n    init(_ sink: Sink, _ initial: Value) {\n        self.sink = sink\n        self.pendingValues = [initial]\n    }\n\n    func receive(_ value: Value) {\n        if pendingValues == nil {\n            sink.receive(value)\n        }\n        else {\n            pendingValues!.append(value)\n        }\n    }\n\n    var hashValue: Int { return sink.hashValue }\n    static func ==(left: BracketingSink, right: BracketingSink) -> Bool {\n        return left.sink == right.sink\n    }\n}\n\nprivate final class BracketingSource<Input: SourceType>: _AbstractSource<Input.Value> {\n    typealias Value = Input.Value\n    let input: Input\n    let hello: () -> Value?\n    let goodbye: () -> Value?\n\n    init(_ input: Input, hello: @escaping () -> Value?, goodbye: @escaping () -> Value?) {\n        self.input = input\n        self.hello = hello\n        self.goodbye = goodbye\n    }\n\n    final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        if let greeting = hello() {\n            let bracketing = BracketingSink(sink, greeting)\n            input.add(bracketing)\n            while !bracketing.pendingValues!.isEmpty && !bracketing.removed {\n                let value = bracketing.pendingValues!.removeFirst()\n                bracketing.sink.receive(value)\n            }\n            bracketing.pendingValues = nil\n        }\n        else {\n            input.add(BracketingSink(sink))\n        }\n    }\n\n    @discardableResult\n    final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        let old = input.remove(BracketingSink(sink))\n        old.removed = true\n        if let farewell = goodbye() {\n            old.sink.receive(farewell)\n        }\n        return old.sink\n    }\n}\n"
  },
  {
    "path": "Sources/BufferedArray.swift",
    "content": "//\n//  BufferedArray.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-22.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableArrayType {\n    public func buffered() -> AnyObservableArray<Element> {\n        if isBuffered {\n            return anyObservableArray\n        }\n        return BufferedObservableArray(self).anyObservableArray\n    }\n}\n\ninternal class BufferedObservableArray<Content: ObservableArrayType>: _BaseObservableArray<Content.Element> {\n    typealias Element = Content.Element\n    typealias Change = ArrayChange<Element>\n\n    private struct BufferedSink: UniqueOwnedSink {\n        typealias Owner = BufferedObservableArray\n\n        unowned(unsafe) let owner: Owner\n\n        func receive(_ update: ArrayUpdate<Content.Element>) {\n            owner.applyUpdate(update)\n        }\n    }\n\n    private let _content: Content\n    private var _value: [Element]\n    private var _pendingChange: Change? = nil\n\n    init(_ content: Content) {\n        _content = content\n        _value = content.value\n        super.init()\n        _content.add(BufferedSink(owner: self))\n    }\n\n    deinit {\n        _content.remove(BufferedSink(owner: self))\n    }\n\n    func applyUpdate(_ update: ArrayUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if _pendingChange != nil {\n                _pendingChange!.merge(with: change)\n            }\n            else {\n                _pendingChange = change\n            }\n        case .endTransaction:\n            if let change = _pendingChange {\n                _value.apply(change)\n                _pendingChange = nil\n                sendChange(change)\n            }\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool {\n        return true\n    }\n\n    override subscript(_ index: Int) -> Content.Element {\n        return _value[index]\n    }\n\n    override subscript(_ range: Range<Int>) -> ArraySlice<Content.Element> {\n        return _value[range]\n    }\n\n    override var value: [Element] {\n        return _value\n    }\n\n    override var count: Int {\n        return _value.count\n    }\n}\n"
  },
  {
    "path": "Sources/BufferedSet.swift",
    "content": "//\n//  BufferedSet.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    public func buffered() -> AnyObservableSet<Element> {\n        if isBuffered {\n            return anyObservableSet\n        }\n        return BufferedObservableSet(self).anyObservableSet\n    }\n}\n\ninternal class BufferedObservableSet<Content: ObservableSetType>: _BaseObservableSet<Content.Element> {\n    typealias Element = Content.Element\n    typealias Change = SetChange<Element>\n\n    private struct BufferedSink: UniqueOwnedSink {\n        typealias Owner = BufferedObservableSet\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Content.Element>) {\n            owner.applyUpdate(update)\n        }\n    }\n    \n    private let _content: Content\n    private var _value: Set<Element>\n    private var _pendingChange: Change? = nil\n\n    init(_ content: Content) {\n        _content = content\n        _value = content.value\n        super.init()\n        _content.add(BufferedSink(owner: self))\n    }\n\n    deinit {\n        _content.remove(BufferedSink(owner: self))\n    }\n\n    func applyUpdate(_ update: SetUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if _pendingChange != nil {\n                _pendingChange!.merge(with: change)\n            }\n            else {\n                _pendingChange = change\n            }\n        case .endTransaction:\n            if let change = _pendingChange {\n                _value.apply(change)\n                _pendingChange = nil\n                sendChange(change)\n            }\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool {\n        return true\n    }\n\n    override var count: Int {\n        return _value.count\n    }\n\n    override var value: Set<Element> {\n        return _value\n    }\n\n    override func contains(_ member: Element) -> Bool {\n        return _value.contains(member)\n    }\n\n    override func isSubset(of other: Set<Element>) -> Bool {\n        return _value.isSubset(of: other)\n    }\n\n    override func isSuperset(of other: Set<Element>) -> Bool {\n        return _value.isSuperset(of: other)\n    }\n}\n"
  },
  {
    "path": "Sources/BufferedSource.swift",
    "content": "//\n//  BufferedSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-25.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension SourceType {\n    public func buffered() -> AnySource<Value> {\n        return BufferedSource(self).anySource\n    }\n}\n\nprivate final class BufferedSource<Input: SourceType>: SignalerSource<Input.Value>, SinkType {\n    typealias Value = Input.Value\n\n    private let source: Input\n\n    init(_ source: Input) {\n        self.source = source\n        super.init()\n    }\n\n    override func activate() {\n        source.add(self.unowned())\n    }\n\n    override func deactivate() {\n        source.remove(self.unowned())\n    }\n\n    func receive(_ value: Input.Value) {\n        signal.send(value)\n    }\n}\n"
  },
  {
    "path": "Sources/BufferedValue.swift",
    "content": "//\n//  Observable Transformations.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType {\n    public func buffered() -> AnyObservableValue<Value> {\n        return BufferedObservableValue(self).anyObservableValue\n    }\n}\n\nprivate struct BufferedObservableSink<Base: ObservableValueType>: UniqueOwnedSink {\n    typealias Owner = BufferedObservableValue<Base>\n\n    unowned(unsafe) let owner: Owner\n\n    func receive(_ update: ValueUpdate<Base.Value>) {\n        owner.apply(update)\n    }\n}\n\nprivate class BufferedObservableValue<Base: ObservableValueType>: _BaseObservableValue<Base.Value> {\n    typealias Value = Base.Value\n\n    private var _base: Base\n\n    private var _value: Value\n    private var _pending: Value? = nil\n\n    init(_ base: Base) {\n        self._base = base\n        self._value = base.value\n        super.init()\n\n        _base.updates.add(BufferedObservableSink(owner: self))\n    }\n\n    deinit {\n        _base.updates.remove(BufferedObservableSink(owner: self))\n    }\n\n    func apply(_ update: ValueUpdate<Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            _pending = change.new\n        case .endTransaction:\n            if let pending = _pending {\n                let old = _value\n                _value = pending\n                _pending = nil\n                sendChange(.init(from: old, to: _value))\n            }\n            endTransaction()\n        }\n    }\n\n    override var value: Value { return _value }\n}\n"
  },
  {
    "path": "Sources/CADisplayLink Extensions.swift",
    "content": "//\n//  CADisplayLink Extensions.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-03-17.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport QuartzCore\n\nprivate var associatedTargetKey: UInt8 = 0\n\npublic class CADisplayLinkSource: SignalerSource<CADisplayLink> {\n    public typealias Value = CADisplayLink\n\n    private var runLoop: RunLoop? = nil\n    public var displayLink: CADisplayLink? = nil\n\n    public override init() {\n        super.init()\n    }\n\n    override func activate() {\n        displayLink = CADisplayLink(target: self, selector: #selector(CADisplayLinkSource.tick(_:)))\n        precondition(self.runLoop == nil)\n        let runLoop = RunLoop.current\n        self.runLoop = runLoop\n        displayLink!.add(to: runLoop, forMode: RunLoopMode.commonModes)\n    }\n\n    override func deactivate() {\n        precondition(runLoop != nil)\n        displayLink!.remove(from: runLoop!, forMode: RunLoopMode.commonModes)\n        displayLink = nil\n        runLoop = nil\n    }\n\n    @objc private func tick(_ displayLink: CADisplayLink) {\n        signal.send(displayLink)\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/Change.swift",
    "content": "//\n//  Change.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-12.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// Describes a change to an observable value.\n/// An instance of a type implementing this protocol contains just enough information to describe the difference\n/// between the old value and the new value of the observable.\npublic protocol ChangeType {\n    associatedtype Value\n\n    /// Creates a new change description for a change that goes from `oldValue` to `newValue`.\n    init(from oldValue: Value, to newValue: Value)\n\n    /// Returns true if this change did not actually change the value of the observable.\n    /// Noop changes aren't usually sent by observables, but it is possible to get them by merging a sequence of\n    /// changes to a collection.\n    var isEmpty: Bool { get }\n\n    /// Applies this change on `value` in place.\n    /// Note that not all changes may be applicable on all values.\n    func apply(on value: inout Value)\n\n    /// Applies this change on `value` and returns the result.\n    /// Note that not all changes may be applicable on all values.\n    func applied(on value: Value) -> Value\n\n    /// Merge this change with the `next` change. The result is a single change description that describes the\n    /// change of performing `self` followed by `next`.\n    ///\n    /// The resulting instance may take a shortcut when producing the result value if some information in `self`\n    /// is overwritten by `next`.\n    func merged(with next: Self) -> Self\n\n    mutating func merge(with next: Self)\n\n    /// Reverse the direction of this change, i.e., return a change that undoes the effect of this change.\n    func reversed() -> Self\n}\n\n\nextension ChangeType {\n    /// Applies this change on `value` and returns the result.\n    /// Note that not all changes may be applicable on all values.\n    public func applied(on value: Value) -> Value {\n        var result = value\n        self.apply(on: &result)\n        return result\n    }\n\n    public func merged(with next: Self) -> Self {\n        var temp = self\n        temp.merge(with: next)\n        return temp\n    }\n}\n\n"
  },
  {
    "path": "Sources/ChangesSource.swift",
    "content": "//\n//  ChangesSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-22.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableType {\n    /// A source that reports changes to the value of this observable.\n    /// Changes reported correspond to complete transactions in `self.updates`.\n    public var changes: AnySource<Change> {\n        return ChangesSource(self).anySource\n    }\n}\n\nprivate class ChangesSinkState<Change: ChangeType> {\n    typealias Value = Update<Change>\n\n    var pending: Change? = nil\n\n    func apply(_ update: Update<Change>) -> Change? {\n        switch update {\n        case .beginTransaction:\n            precondition(pending == nil)\n        case .change(let change):\n            if pending == nil {\n                pending = change\n            }\n            else {\n                pending!.merge(with: change)\n            }\n        case .endTransaction:\n            if let change = pending {\n                pending = nil\n                if !change.isEmpty {\n                    return change\n                }\n            }\n        }\n        return nil\n    }\n}\n\nprivate struct ChangesSink<Wrapped: SinkType>: SinkType where Wrapped.Value: ChangeType {\n    typealias Change = Wrapped.Value\n    typealias Value = Update<Change>\n\n    let wrapped: Wrapped\n    let state: ChangesSinkState<Change>?\n\n    init(_ wrapped: Wrapped, withState needState: Bool) {\n        self.wrapped = wrapped\n        self.state = needState ? ChangesSinkState<Change>() : nil\n    }\n\n    func receive(_ update: Update<Change>) {\n        if let change = state?.apply(update) {\n            wrapped.receive(change)\n        }\n    }\n\n    var hashValue: Int {\n        return wrapped.hashValue\n    }\n\n    static func ==(left: ChangesSink, right: ChangesSink) -> Bool {\n        return left.wrapped == right.wrapped\n    }\n}\n\ninternal class ChangesSource<Observable: ObservableType>: _AbstractSource<Observable.Change> {\n    typealias Change = Observable.Change\n\n    let observable: Observable\n\n    init(_ observable: Observable) {\n        self.observable = observable\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Change {\n        observable.add(ChangesSink(sink, withState: true))\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Change {\n        let old = observable.remove(ChangesSink(sink, withState: false))\n        return old.wrapped\n    }\n}\n\nextension Connector {\n    @discardableResult\n    public func subscribe<Observable: ObservableType>(_ observable: Observable, to sink: @escaping (Observable.Change) -> Void) -> Connection {\n        return observable.changes.subscribe(sink).putInto(self)\n    }\n}\n"
  },
  {
    "path": "Sources/CompositeObservable.swift",
    "content": "//\n//  CompositeObservable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType {\n    public func combined<Other: ObservableValueType>(_ other: Other) -> AnyObservableValue<(Value, Other.Value)> {\n        return CompositeObservable(left: self, right: other, combinator: { ($0, $1) }).anyObservableValue\n    }\n\n    public func combined<A: ObservableValueType, B: ObservableValueType>(_ a: A, _ b: B) -> AnyObservableValue<(Value, A.Value, B.Value)> {\n        return combined(a).combined(b, by: { a, b in (a.0, a.1, b) })\n    }\n\n    public func combined<A: ObservableValueType, B: ObservableValueType, C: ObservableValueType>(_ a: A, _ b: B, _ c: C) -> AnyObservableValue<(Value, A.Value, B.Value, C.Value)> {\n        return combined(a, b).combined(c, by: { a, b in (a.0, a.1, a.2, b) })\n    }\n\n    public func combined<A: ObservableValueType, B: ObservableValueType, C: ObservableValueType, D: ObservableValueType>(_ a: A, _ b: B, _ c: C, _ d: D) -> AnyObservableValue<(Value, A.Value, B.Value, C.Value, D.Value)> {\n        return combined(a, b, c).combined(d, by: { a, b in (a.0, a.1, a.2, a.3, b) })\n    }\n\n    public func combined<A: ObservableValueType, B: ObservableValueType, C: ObservableValueType, D: ObservableValueType, E: ObservableValueType>(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> AnyObservableValue<(Value, A.Value, B.Value, C.Value, D.Value, E.Value)> {\n        return combined(a, b, c, d).combined(e, by: { a, b in (a.0, a.1, a.2, a.3, a.4, b) })\n    }\n\n\n    public func combined<Other: ObservableValueType, Output>(_ other: Other, by combinator: @escaping (Value, Other.Value) -> Output) -> AnyObservableValue<Output> {\n        return CompositeObservable(left: self, right: other, combinator: combinator).anyObservableValue\n    }\n\n    public func combined<A: ObservableValueType, B: ObservableValueType, Output>(_ a: A, _ b: B, by combinator: @escaping (Value, A.Value, B.Value) -> Output) -> AnyObservableValue<Output> {\n        return combined(a).combined(b, by: { a, b in combinator(a.0, a.1, b) })\n    }\n\n    public func combined<A: ObservableValueType, B: ObservableValueType, C: ObservableValueType, Output>(_ a: A, _ b: B, _ c: C, by combinator: @escaping (Value, A.Value, B.Value, C.Value) -> Output) -> AnyObservableValue<Output> {\n        return combined(a, b).combined(c, by: { a, b in combinator(a.0, a.1, a.2, b) })\n    }\n\n    public func combined<A: ObservableValueType, B: ObservableValueType, C: ObservableValueType, D: ObservableValueType, Output>(_ a: A, _ b: B, _ c: C, _ d: D, by combinator: @escaping (Value, A.Value, B.Value, C.Value, D.Value) -> Output) -> AnyObservableValue<Output> {\n        return combined(a, b, c).combined(d, by: { a, b in combinator(a.0, a.1, a.2, a.3, b) })\n    }\n\n    public func combined<A: ObservableValueType, B: ObservableValueType, C: ObservableValueType, D: ObservableValueType, E: ObservableValueType, Output>(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, by combinator: @escaping (Value, A.Value, B.Value, C.Value, D.Value, E.Value) -> Output) -> AnyObservableValue<Output> {\n        return combined(a, b, c, d).combined(e, by: { a, b in combinator(a.0, a.1, a.2, a.3, a.4, b) })\n    }\n}\n\nprivate struct LeftSink<Left: ObservableValueType, Right: ObservableValueType, Value>: UniqueOwnedSink {\n    typealias Owner = CompositeObservable<Left, Right, Value>\n\n    unowned let owner: Owner\n\n    func receive(_ update: ValueUpdate<Left.Value>) {\n        owner.applyLeftUpdate(update)\n    }\n}\n\nprivate struct RightSink<Left: ObservableValueType, Right: ObservableValueType, Value>: UniqueOwnedSink {\n    typealias Owner = CompositeObservable<Left, Right, Value>\n\n    unowned let owner: Owner\n\n    func receive(_ update: ValueUpdate<Right.Value>) {\n        owner.applyRightUpdate(update)\n    }\n}\n\n/// An AnyObservableValue that is calculated from two other observables.\nprivate final class CompositeObservable<Left: ObservableValueType, Right: ObservableValueType, Value>: _BaseObservableValue<Value> {\n    typealias Change = ValueChange<Value>\n\n    private let left: Left\n    private let right: Right\n    private let combinator: (Left.Value, Right.Value) -> Value\n\n    private var _leftValue: Left.Value? = nil\n    private var _rightValue: Right.Value? = nil\n    private var _value: Value? = nil\n\n    public init(left: Left, right: Right, combinator: @escaping (Left.Value, Right.Value) -> Value) {\n        self.left = left\n        self.right = right\n        self.combinator = combinator\n    }\n\n    deinit {\n        assert(_value == nil)\n    }\n\n    public override var value: Value {\n        if let value = _value { return value }\n        return combinator(left.value, right.value)\n    }\n\n    internal override func activate() {\n        assert(_value == nil)\n        let v1 = left.value\n        let v2 = right.value\n        _leftValue = v1\n        _rightValue = v2\n        _value = combinator(v1, v2)\n\n        left.add(LeftSink(owner: self))\n        right.add(RightSink(owner: self))\n    }\n\n    internal override func deactivate() {\n        left.remove(LeftSink(owner: self))\n        right.remove(RightSink(owner: self))\n        _value = nil\n        _leftValue = nil\n        _rightValue = nil\n    }\n\n    func applyLeftUpdate(_ update: ValueUpdate<Left.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            _leftValue = change.new\n            let old = _value!\n            let new = combinator(_leftValue!, _rightValue!)\n            _value = new\n            sendChange(ValueChange(from: old, to: new))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyRightUpdate(_ update: ValueUpdate<Right.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            _rightValue = change.new\n            let old = _value!\n            let new = combinator(_leftValue!, _rightValue!)\n            _value = new\n            sendChange(ValueChange(from: old, to: new))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n\n//MARK: Operations with observables of equatable values\n\npublic func == <A: ObservableValueType, B: ObservableValueType>(a: A, b: B) -> AnyObservableValue<Bool>\nwhere A.Value == B.Value, A.Value: Equatable {\n    return a.combined(b, by: ==)\n}\n\npublic func != <A: ObservableValueType, B: ObservableValueType>(a: A, b: B) -> AnyObservableValue<Bool>\nwhere A.Value == B.Value, A.Value: Equatable {\n    return a.combined(b, by: !=)\n}\n\n//MARK: Operations with observables of comparable values\n\npublic func < <A: ObservableValueType, B: ObservableValueType>(a: A, b: B) -> AnyObservableValue<Bool>\nwhere A.Value == B.Value, A.Value: Comparable {\n    return a.combined(b, by: <)\n}\n\npublic func > <A: ObservableValueType, B: ObservableValueType>(a: A, b: B) -> AnyObservableValue<Bool>\nwhere A.Value == B.Value, A.Value: Comparable {\n    return a.combined(b, by: >)\n}\n\npublic func <= <A: ObservableValueType, B: ObservableValueType>(a: A, b: B) -> AnyObservableValue<Bool>\nwhere A.Value == B.Value, A.Value: Comparable {\n    return a.combined(b, by: <=)\n}\n\npublic func >= <A: ObservableValueType, B: ObservableValueType>(a: A, b: B) -> AnyObservableValue<Bool>\nwhere A.Value == B.Value, A.Value: Comparable {\n    return a.combined(b, by: >=)\n}\n\npublic func min<A: ObservableValueType, B: ObservableValueType, Value: Comparable>(_ a: A, _ b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: min)\n}\n\npublic func max<A: ObservableValueType, B: ObservableValueType, Value: Comparable>(_ a: A, _ b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: max)\n}\n\n//MARK: Operations with observables of boolean values\n\npublic prefix func ! <O: ObservableValueType>(v: O) -> AnyObservableValue<Bool> where O.Value == Bool {\n    return v.map { !$0 }\n}\n\npublic func && <A: ObservableValueType, B: ObservableValueType>(a: A, b: B) -> AnyObservableValue<Bool>\nwhere A.Value == Bool, B.Value == Bool {\n    return a.combined(b, by: { a, b in a && b })\n}\n\npublic func || <A: ObservableValueType, B: ObservableValueType>(a: A, b: B) -> AnyObservableValue<Bool>\nwhere A.Value == Bool, B.Value == Bool {\n    return a.combined(b, by: { a, b in a || b })\n}\n\n//MARK: Operations with observables of integer arithmetic values\n\npublic prefix func - <O: ObservableValueType>(v: O) -> AnyObservableValue<O.Value> where O.Value: SignedNumeric {\n    return v.map { -$0 }\n}\n\npublic func + <A: ObservableValueType, B: ObservableValueType, Value: Numeric>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: +)\n}\n\npublic func - <A: ObservableValueType, B: ObservableValueType, Value: Numeric>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: -)\n}\n\npublic func * <A: ObservableValueType, B: ObservableValueType, Value: Numeric>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: *)\n}\n\npublic func / <A: ObservableValueType, B: ObservableValueType, Value: BinaryInteger>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: /)\n}\n\npublic func % <A: ObservableValueType, B: ObservableValueType, Value: BinaryInteger>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: %)\n}\n\n//MARK: Operations with floating point values\n\nextension ObservableValueType where Value: FloatingPoint {\n    public func squareRoot() -> AnyObservableValue<Value> {\n        return self.map { $0.squareRoot() }\n    }\n}\n\npublic func + <A: ObservableValueType, B: ObservableValueType, Value: FloatingPoint>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: +)\n}\n\npublic func - <A: ObservableValueType, B: ObservableValueType, Value: FloatingPoint>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: -)\n}\n\npublic func * <A: ObservableValueType, B: ObservableValueType, Value: FloatingPoint>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: *)\n}\n\npublic func / <A: ObservableValueType, B: ObservableValueType, Value: FloatingPoint>(a: A, b: B) -> AnyObservableValue<Value>\nwhere A.Value == Value, B.Value == Value {\n    return a.combined(b, by: /)\n}\n"
  },
  {
    "path": "Sources/CompositeUpdatable.swift",
    "content": "//\n//  CompositeUpdatable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension UpdatableValueType {\n    public func combined<Other: UpdatableValueType>(_ other: Other) -> AnyUpdatableValue<(Value, Other.Value)> {\n        return CompositeUpdatable(left: self, right: other).anyUpdatableValue\n    }\n\n    public func combined<A: UpdatableValueType, B: UpdatableValueType>(_ a: A, _ b: B) -> AnyUpdatableValue<(Value, A.Value, B.Value)> {\n        return combined(a).combined(b)\n            .map({ a, b in (a.0, a.1, b) },\n                 inverse: { v in ((v.0, v.1), v.2) })\n    }\n\n    public func combined<A: UpdatableValueType, B: UpdatableValueType, C: UpdatableValueType>(_ a: A, _ b: B, _ c: C) -> AnyUpdatableValue<(Value, A.Value, B.Value, C.Value)> {\n        return combined(a).combined(b).combined(c)\n        .map({ a, b in (a.0.0, a.0.1, a.1, b) },\n             inverse: { v in (((v.0, v.1), v.2), v.3) })\n    }\n\n    public func combined<A: UpdatableValueType, B: UpdatableValueType, C: UpdatableValueType, D: UpdatableValueType>(_ a: A, _ b: B, _ c: C, _ d: D) -> AnyUpdatableValue<(Value, A.Value, B.Value, C.Value, D.Value)> {\n        return combined(a).combined(b).combined(c).combined(d)\n            .map({ a, b in (a.0.0.0, a.0.0.1, a.0.1, a.1, b) },\n                 inverse: { v in ((((v.0, v.1), v.2), v.3), v.4) })\n    }\n\n    public func combined<A: UpdatableValueType, B: UpdatableValueType, C: UpdatableValueType, D: UpdatableValueType, E: UpdatableValueType>(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> AnyUpdatableValue<(Value, A.Value, B.Value, C.Value, D.Value, E.Value)> {\n        return combined(a).combined(b).combined(c).combined(d).combined(e)\n            .map({ a, b in (a.0.0.0.0, a.0.0.0.1, a.0.0.1, a.0.1, a.1, b) },\n                 inverse: { v in (((((v.0, v.1), v.2), v.3), v.4), v.5) })\n    }\n}\n\nprivate struct LeftSink<Left: UpdatableValueType, Right: UpdatableValueType>: UniqueOwnedSink {\n    typealias Owner = CompositeUpdatable<Left, Right>\n\n    unowned let owner: Owner\n\n    func receive(_ update: ValueUpdate<Left.Value>) {\n        owner.applyLeftUpdate(update)\n    }\n}\n\nprivate struct RightSink<Left: UpdatableValueType, Right: UpdatableValueType>: UniqueOwnedSink {\n    typealias Owner = CompositeUpdatable<Left, Right>\n\n    unowned let owner: Owner\n\n    func receive(_ update: ValueUpdate<Right.Value>) {\n        owner.applyRightUpdate(update)\n    }\n}\n\n\n/// An AnyUpdatableValue that is a composite of two other updatables.\nprivate final class CompositeUpdatable<Left: UpdatableValueType, Right: UpdatableValueType>: _BaseUpdatableValue<(Left.Value, Right.Value)> {\n    typealias Value = (Left.Value, Right.Value)\n    typealias Change = ValueChange<Value>\n\n    private let left: Left\n    private let right: Right\n    private var latest: Value? = nil\n\n    init(left: Left, right: Right) {\n        self.left = left\n        self.right = right\n    }\n\n    override func rawGetValue() -> Value {\n        if let latest = self.latest { return latest }\n        return (left.value, right.value)\n    }\n\n    override func rawSetValue(_ value: Value) {\n        left.apply(.beginTransaction)\n        right.apply(.beginTransaction)\n        left.value = value.0\n        right.value = value.1\n        right.apply(.endTransaction)\n        left.apply(.endTransaction)\n    }\n\n    override func activate() {\n        precondition(latest == nil)\n        latest = (left.value, right.value)\n        left.add(LeftSink(owner: self))\n        right.add(RightSink(owner: self))\n    }\n\n    override func deactivate() {\n        precondition(latest != nil)\n        left.remove(LeftSink(owner: self))\n        right.remove(RightSink(owner: self))\n        latest = nil\n    }\n\n    func applyLeftUpdate(_ update: ValueUpdate<Left.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let old = latest!\n            latest!.0 = change.new\n            sendChange(Change(from: old, to: latest!))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyRightUpdate(_ update: ValueUpdate<Right.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let old = latest!\n            latest!.1 = change.new\n            sendChange(Change(from: old, to: latest!))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/ComputedUpdatable.swift",
    "content": "//\n//  ComputedUpdatable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-11.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic final class ComputedUpdatable<Value>: _BaseUpdatableValue<Value> {\n    public let getter: () -> Value\n    public let setter: (Value) -> ()\n    public let refreshSource: AnySource<Void>?\n\n    private var _value: Value\n\n    private struct Sink<V>: UniqueOwnedSink {\n        typealias Owner = ComputedUpdatable<V>\n        unowned(unsafe) let owner: Owner\n        func receive(_ value: Void) {\n            owner.refresh()\n        }\n    }\n\n    public init(getter: @escaping () -> Value,\n                setter: @escaping (Value) -> (),\n                refreshSource: AnySource<Void>? = nil) {\n        self.getter = getter\n        self.setter = setter\n        self.refreshSource = refreshSource\n        self._value = getter()\n        super.init()\n        refreshSource?.add(Sink(owner: self))\n    }\n\n    deinit {\n        refreshSource?.remove(Sink(owner: self))\n    }\n\n    override func rawGetValue() -> Value {\n        return _value\n    }\n\n    override func rawSetValue(_ value: Value) {\n        setter(value)\n        _value = getter()\n    }\n\n    public func refresh() {\n        self.value = getter()\n    }\n}\n"
  },
  {
    "path": "Sources/Connect.swift",
    "content": "//\n//  Connect.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-22.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension SourceType {\n    /// Connect `sink` to this source. The sink will receive all values that this source produces in the future.\n    /// The connection will be kept active until the returned connection object is deallocated or explicitly disconnected.\n    ///\n    /// In GlueKit, a connection holds strong references to both its source and sink; thus sources (and sinks) are kept\n    /// alive at least as long as they have an active connection.\n    public func subscribe(_ sink: @escaping (Value) -> Void) -> Connection {\n        return ConcreteConnection(source: self, sink: sink)\n    }\n}\n\n/// An object that controls the lifetime of a closure's subscription to a source.\n///\n/// The closure's subscription to the source remains active until this object is deallocated\n/// or `disconnect` is called on it.\npublic class Connection {\n    internal init() {}\n    public func disconnect() { abstract() }\n}\n\n/// An object that controls the lifetime of a closure's subscription to a particular source.\ninternal class ConcreteConnection<Source: SourceType>: Connection {\n    typealias Value = Source.Value\n\n    var source: Source?\n    var sink: Optional<(Value) -> Void>\n\n    init(source: Source, sink: @escaping (Value) -> Void) {\n        self.source = source\n        self.sink = sink\n        super.init()\n\n        // Wrap the closure in a sink and add it to the source.\n        source.add(ClosureSink(ObjectIdentifier(self), sink))\n    }\n\n    deinit {\n        disconnect()\n    }\n\n    public override func disconnect() {\n        guard let source = self.source, let sink = self.sink else { return }\n\n        // Construct a dummy `ClosureSink` that looks identical to the original one and remove it from the source.\n        // At first glance, we could use a dummy closure here, because the closure isn't involved in the sink's identity.\n        // However, sources sometimes synchronously send farewell values to removed sinks using the instance \n        // given here --- so using e.g. an empty closure would lose these.\n        source.remove(ClosureSink(ObjectIdentifier(self), sink))\n\n        // Release resources associated with this connection.\n        self.source = nil\n        self.sink = nil\n    }\n}\n\nprivate struct ClosureSinkData<Value> {\n    /// The connection of this sink, serving as the unique identifier of it.\n    unowned let connection: Connection\n}\n\n/// A Sink that wraps a closure. `Hashable` is implemented by using the identity of the unique `Connection`\n/// object associated with the subscription.\ninternal struct ClosureSink<Value>: SinkType {\n    /// The object identifier of connection object.\n    /// The natural choice would be to use an unowned reference to the connection object itself;\n    /// but `Connection`'s `deinit` needs to be able to create `ClosureSink`s, and it's not a good \n    /// idea to create unowned references during deinit -- the semantics are unclear to me, and I get crashes.\n    private let identifier: ObjectIdentifier\n\n    /// The closure that is to be called when this sink receives a value.\n    private let sink: (Value) -> Void\n\n    init(_ identifier: ObjectIdentifier, _ sink: @escaping (Value) -> Void) {\n        self.identifier = identifier\n        self.sink = sink\n    }\n\n    func receive(_ value: Value) {\n        sink(value)\n    }\n\n    var hashValue: Int {\n        return identifier.hashValue\n    }\n\n    static func ==(left: ClosureSink, right: ClosureSink) -> Bool {\n        // Sink equality is based on the identity of the connection.\n        return left.identifier == right.identifier\n    }\n}\n\nextension Connector {\n    @discardableResult\n    public func connect<Source: SourceType>(_ source: Source, to sink: @escaping (Source.Value) -> Void) -> Connection {\n        return source.subscribe(sink).putInto(self)\n    }\n}\n"
  },
  {
    "path": "Sources/Connector.swift",
    "content": "//\n//  Connector.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension Connection {\n    /// Put this connection into `connector`. The connector will disconnect the connection when it is deallocated.\n    @discardableResult\n    public func putInto(_ connector: Connector) -> Connection {\n        connector.add(self)\n        return self\n    }\n}\n\n/// A class for controlling the lifecycle of connections.\n/// The connector owns a set of connections and forces them to disconnect when it is deallocated.\npublic class Connector {\n    private var connections: [Connection] = []\n\n    public init() {}\n\n    deinit {\n        disconnect()\n    }\n\n    fileprivate func add(_ connection: Connection) {\n        connections.append(connection)\n    }\n\n    public func disconnect() {\n        let cs = connections\n        connections.removeAll()\n        for c in cs {\n            c.disconnect()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/DependentValue.swift",
    "content": "//\n//  DependentValue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2017-04-23.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\ninfix operator <--\n\npublic func <-- <Value, Source: ObservableValueType>(target: DependentValue<Value>, source: Source) where Source.Value == Value {\n    target.origin = source.anyObservableValue\n}\n\npublic class DependentValue<Value> {\n    private let setter: (Value) -> ()\n    private var transactions: Int = 0\n    private var pending: Value?\n\n    internal var origin: AnyObservableValue<Value>? {\n        didSet {\n            receive(.beginTransaction)\n            oldValue?.remove(Sink<Value>(owner: self))\n            if let origin = origin {\n                pending = origin.value\n                origin.add(Sink<Value>(owner: self))\n            }\n            receive(.endTransaction)\n        }\n    }\n\n    private struct Sink<Value>: UniqueOwnedSink {\n        typealias Owner = DependentValue<Value>\n        unowned(unsafe) let owner: Owner\n        func receive(_ update: ValueUpdate<Value>) {\n            owner.receive(update)\n        }\n    }\n\n    public init(setter: @escaping (Value) -> ()) {\n        self.setter = setter\n        self.origin = nil\n    }\n\n    public init<Origin: ObservableValueType>(origin: Origin, setter: @escaping (Value) -> ()) where Origin.Value == Value {\n        self.setter = setter\n        self.origin = origin.anyObservableValue\n        origin.add(Sink<Value>(owner: self))\n    }\n\n    deinit {\n        origin?.remove(Sink<Value>(owner: self))\n    }\n\n    func receive(_ update: ValueUpdate<Value>) {\n        switch update {\n        case .beginTransaction:\n            transactions += 1\n        case .change(let change):\n            pending = change.new\n        case .endTransaction:\n            transactions -= 1\n            if transactions == 0, let pending = pending {\n                self.pending = nil\n                setter(pending)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/DispatchSource.swift",
    "content": "//\n//  DispatchSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-24.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\n\nextension SourceType {\n    public func dispatch(on queue: DispatchQueue) -> AnySource<Value> {\n        return TransformedSource(input: self, transform: SinkTransformForDispatchQueue(queue)).anySource\n    }\n\n    public func dispatch(on queue: OperationQueue) -> AnySource<Value> {\n        return TransformedSource(input: self, transform: SinkTransformForOperationQueue(queue)).anySource\n    }\n}\n\nfinal class SinkTransformForDispatchQueue<Value>: SinkTransform {\n    typealias Input = Value\n    typealias Output = Value\n\n    let queue: DispatchQueue\n\n    init(_ queue: DispatchQueue) {\n        self.queue = queue\n    }\n\n    func apply<Sink: SinkType>(_ input: Value, _ sink: Sink) where Sink.Value == Value {\n        queue.async {\n            sink.receive(input)\n        }\n    }\n}\n\nfinal class SinkTransformForOperationQueue<Value>: SinkTransform {\n    typealias Input = Value\n    typealias Output = Value\n\n    let queue: OperationQueue\n\n    init(_ queue: OperationQueue) {\n        self.queue = queue\n    }\n\n    func apply<Sink: SinkType>(_ input: Value, _ sink: Sink) where Sink.Value == Value {\n        if OperationQueue.current == queue {\n            sink.receive(input)\n        }\n        else {\n            queue.addOperation {\n                sink.receive(input)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/DistinctUnion.swift",
    "content": "//\n//  DistinctUnion.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-04.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableArrayType where Element: Hashable {\n    /// Returns an observable set that contains the same elements as this array.\n    public func distinctUnion() -> AnyObservableSet<Element> {\n        return DistinctUnion<Self>(self).anyObservableSet\n    }\n}\n\nprivate class DistinctUnion<Input: ObservableArrayType>: _BaseObservableSet<Input.Element>\nwhere Input.Element: Hashable {\n    typealias Element = Input.Element\n    typealias Change = SetChange<Element>\n\n    private struct DistinctSink: UniqueOwnedSink {\n        typealias Owner = DistinctUnion\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ArrayUpdate<Input.Element>) {\n            owner.apply(update)\n        }\n    }\n    \n    private let input: Input\n    private var members = Dictionary<Element, Int>()\n\n    init(_ input: Input) {\n        self.input = input\n        super.init()\n        for element in input.value {\n            _ = self.add(element)\n        }\n        input.updates.add(DistinctSink(owner: self))\n    }\n\n    deinit {\n        input.updates.remove(DistinctSink(owner: self))\n    }\n\n    func apply(_ update: ArrayUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var setChange = SetChange<Element>()\n            for mod in change.modifications {\n                mod.forEachOldElement {\n                    if remove($0) {\n                        setChange.remove($0)\n                    }\n                }\n                mod.forEachNewElement {\n                    if add($0) {\n                        setChange.insert($0)\n                    }\n                }\n            }\n            if !setChange.isEmpty {\n                sendChange(setChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    private func add(_ element: Element) -> Bool {\n        if let old = self.members[element] {\n            self.members[element] = old + 1\n            return false\n        }\n        self.members[element] = 1\n        return true\n    }\n\n    private func remove(_ element: Element) -> Bool {\n        let old = self.members[element]!\n        if old == 1 {\n            self.members[element] = nil\n            return true\n        }\n        self.members[element] = old - 1\n        return false\n    }\n\n    override var isBuffered: Bool { return true }\n    override var count: Int { return value.count }\n    override var value: Set<Element> { return Set(members.keys) }\n    override func contains(_ element: Element) -> Bool { return members[element] != nil }\n    override func isSubset(of other: Set<Element>) -> Bool {\n        guard count <= other.count else { return false }\n        for (key, _) in members {\n            guard other.contains(key) else { return false }\n        }\n        return true\n    }\n    override func isSuperset(of other: Set<Element>) -> Bool {\n        guard count >= other.count else { return false }\n        for element in other {\n            guard members[element] != nil else { return false }\n        }\n        return true\n    }\n}\n"
  },
  {
    "path": "Sources/DistinctValue.swift",
    "content": "//\n//  DistinctValue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport SipHash\n\nprivate class DistinctSinkState<V> {\n    typealias Value = ValueUpdate<V>\n\n    let areEquivalent: (V, V) -> Bool\n    var pending: ValueChange<V>? = nil\n\n    init(_ areEquivalent: @escaping (V, V) -> Bool) {\n        self.areEquivalent = areEquivalent\n    }\n\n    fileprivate func applyUpdate<Sink: SinkType>(_ update: Value, _ sink: Sink) where Sink.Value == Value {\n        switch update {\n        case .beginTransaction:\n            precondition(pending == nil)\n            sink.receive(update)\n        case .change(let change):\n            if pending == nil {\n                pending = change\n            }\n            else {\n                pending!.merge(with: change)\n            }\n        case .endTransaction:\n            if let change = pending, !areEquivalent(change.old, change.new) {\n                sink.receive(.change(change))\n            }\n            pending = nil\n            sink.receive(update)\n        }\n    }\n}\n\nprivate struct DistinctSink<V, Sink: SinkType>: SinkType, SipHashable where Sink.Value == ValueUpdate<V> {\n    typealias Value = ValueUpdate<V>\n\n    let owner: AnyObject\n    let sink: Sink\n    let state: DistinctSinkState<V>?\n\n    func receive(_ update: Value) {\n        state?.applyUpdate(update, sink)\n    }\n\n    func appendHashes(to hasher: inout SipHasher) {\n        hasher.append(ObjectIdentifier(owner))\n        hasher.append(sink)\n    }\n\n    static func ==(left: DistinctSink, right: DistinctSink) -> Bool {\n        return left.owner === right.owner && left.sink == right.sink\n    }\n}\n\npublic extension ObservableValueType {\n    public func distinct(_ areEquivalent: @escaping (Value, Value) -> Bool) -> AnyObservableValue<Value> {\n        return DistinctObservableValue(self, by: areEquivalent).anyObservableValue\n    }\n}\n\npublic extension ObservableValueType where Value: Equatable {\n    public func distinct() -> AnyObservableValue<Value> {\n        return distinct(==)\n    }\n}\n\nprivate class DistinctObservableValue<Input: ObservableValueType>: _AbstractObservableValue<Input.Value> {\n    typealias Value = Input.Value\n\n    private let input: Input\n    private let areEquivalent: (Value, Value) -> Bool\n\n    init(_ input: Input, by areEquivalent: @escaping (Value, Value) -> Bool) {\n        self.input = input\n        self.areEquivalent = areEquivalent\n    }\n\n    override var value: Value {\n        return input.value\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        input.add(DistinctSink(owner: self, sink: sink, state: DistinctSinkState(areEquivalent)))\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        let old = input.remove(DistinctSink(owner: self, sink: sink, state: nil))\n        return old.sink\n    }\n}\n\npublic extension UpdatableValueType {\n    public func distinct(_ areEquivalent: @escaping (Value, Value) -> Bool) -> AnyUpdatableValue<Value> {\n        return DistinctUpdatableValue(self, by: areEquivalent).anyUpdatableValue\n    }\n}\n\npublic extension UpdatableValueType where Value: Equatable {\n    public func distinct() -> AnyUpdatableValue<Value> {\n        return distinct(==)\n    }\n}\n\nprivate class DistinctUpdatableValue<Input: UpdatableValueType>: _AbstractUpdatableValue<Input.Value> {\n    typealias Value = Input.Value\n\n    private let input: Input\n    private let areEquivalent: (Value, Value) -> Bool\n\n    init(_ input: Input, by areEquivalent: @escaping (Value, Value) -> Bool) {\n        self.input = input\n        self.areEquivalent = areEquivalent\n    }\n\n    override var value: Value {\n        get {\n            return input.value\n        }\n        set {\n            input.value = newValue\n        }\n    }\n\n    override func apply(_ update: ValueUpdate<Value>) {\n        input.apply(update)\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        input.add(DistinctSink(owner: self, sink: sink, state: DistinctSinkState(areEquivalent)))\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        let old = input.remove(DistinctSink(owner: self, sink: sink, state: nil))\n        return old.sink\n    }\n}\n"
  },
  {
    "path": "Sources/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>FMWK</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(VERSION_STRING)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Sources/Locks.swift",
    "content": "//\n//  Locks.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-01.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\n\ninternal protocol Lockable {\n    func lock()\n    func unlock()\n    func withLock<Result>(_ block: () throws -> Result) rethrows -> Result\n}\n\nextension Lockable {\n    func withLock<Result>(_ block: () throws -> Result) rethrows -> Result {\n        lock()\n        defer { unlock() }\n        return try block()\n    }\n}\n\nstruct Lock: Lockable {\n    private let _lock: LockImplementation\n\n    init() {\n        if #available(macOS 10.12, iOS 10, watchOS 3.0, tvOS 10.0, *) {\n            self._lock = UnfairLock()\n        }\n        else {\n            self._lock = PosixMutex()\n        }\n    }\n    func lock() { _lock.lock() }\n    func unlock() { _lock.unlock() }\n}\n\nprivate class LockImplementation: Lockable {\n    init() {}\n\n    func lock() {}\n    func unlock() {}\n}\n\n@available(macOS 10.12, iOS 10, watchOS 3.0, tvOS 10.0, *)\nprivate final class UnfairLock: LockImplementation {\n    private var _lock = os_unfair_lock()\n\n    override func lock() {\n        os_unfair_lock_lock(&_lock)\n    }\n\n    override func unlock() {\n        os_unfair_lock_unlock(&_lock)\n    }\n}\n\nprivate final class PosixMutex: LockImplementation {\n    private var mutex = pthread_mutex_t()\n\n    override init() {\n        let result = pthread_mutex_init(&mutex, nil)\n        precondition(result == 0)\n    }\n\n    deinit {\n        let result = pthread_mutex_destroy(&mutex)\n        precondition(result == 0)\n    }\n\n    override func lock() {\n        let result = pthread_mutex_lock(&mutex)\n        precondition(result == 0)\n    }\n\n    override func unlock() {\n        let result = pthread_mutex_unlock(&mutex)\n        precondition(result == 0)\n    }\n}\n"
  },
  {
    "path": "Sources/MergedSource.swift",
    "content": "//\n//  MergedSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-04.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport SipHash\n\nextension Sequence where Element: SourceType {\n    public func gather() -> MergedSource<Element.Value> {\n        return MergedSource(sources: self)\n    }\n}\n\nextension SourceType {\n    /// Returns a source that merges self with `source`. The returned source will forward all values sent by either\n    /// of its two input sources to its own connected sinks.\n    ///\n    /// It is fine to chain multiple merges together: `MergedSource` has its own, specialized `merge` method to \n    /// collapse multiple merges into a single source.\n    public func merged<S: SourceType>(with source: S) -> MergedSource<Value> where S.Value == Value {\n        return MergedSource(sources: [self.anySource, source.anySource])\n    }\n\n    public static func merge(_ sources: Self...) -> MergedSource<Value> {\n        return MergedSource(sources: sources.map { s in s.anySource })\n    }\n\n    public static func merge<S: Sequence>(_ sources: S) -> MergedSource<Value> where S.Iterator.Element == Self {\n        return MergedSource(sources: sources.map { s in s.anySource })\n    }\n}\n\n/// A Source that receives all values from a set of input sources and forwards all to its own connected sinks.\n///\n/// Note that MergedSource only connects to its input sources while it has at least one connection of its own.\npublic final class MergedSource<Value>: SignalerSource<Value> {\n    public typealias SourceValue = Value\n\n    private let inputs: [AnySource<Value>]\n\n    /// Initializes a new merged source with `sources` as its input sources.\n    public init<S: Sequence>(sources: S) where S.Iterator.Element: SourceType, S.Iterator.Element.Value == Value {\n        self.inputs = sources.map { $0.anySource }\n    }\n\n    override func activate() {\n        for i in 0 ..< inputs.count {\n            inputs[i].add(MergedSink(source: self, index: i))\n        }\n    }\n\n    override func deactivate() {\n        for i in 0 ..< inputs.count {\n            inputs[i].remove(MergedSink(source: self, index: i))\n        }\n    }\n\n    fileprivate func receive(_ value: Value, from index: Int) {\n        signal.send(value)\n    }\n\n    /// Returns a new MergedSource that merges the same sources as self but also listens to `source`.\n    /// The returned source will forward all values sent by either of its input sources to its own connected sinks.\n    public func merged<Source: SourceType>(with source: Source) -> MergedSource<Value> where Source.Value == Value {\n        return MergedSource(sources: self.inputs + [source.anySource])\n    }\n}\n\nprivate struct MergedSink<Value>: SinkType, SipHashable {\n    let source: MergedSource<Value>\n    let index: Int\n\n    func receive(_ value: Value) {\n        source.receive(value, from: index)\n    }\n\n    func appendHashes(to hasher: inout SipHasher) {\n        hasher.append(ObjectIdentifier(source))\n        hasher.append(index)\n    }\n\n    static func ==(left: MergedSink, right: MergedSink) -> Bool {\n        return left.source === right.source && left.index == right.index\n    }\n}\n\n\n"
  },
  {
    "path": "Sources/NSButton Glue.swift",
    "content": "//\n//  NSButton Glue.swift\n//  macOS\n//\n//  Created by Károly Lőrentey on 2017-09-05.\n//  Copyright © 2017 Károly Lőrentey. All rights reserved.\n//\n\n#if os(macOS)\nimport AppKit\n\nextension NSButton {\n    @objc open dynamic override var glue: GlueForNSButton { return _glue() }\n}\n\npublic func <-- <V: UpdatableValueType>(target: GlueForNSButton.StateReceiver, model: V) where V.Value == NSControl.StateValue {\n    target.glue.model = model.anyUpdatableValue\n}\n\npublic func <-- <B: UpdatableValueType>(target: GlueForNSButton.StateReceiver, model: B) where B.Value == Bool {\n    target.glue.model = model.map({ $0 ? .on : .off }, inverse: { $0 == .off ? false : true })\n}\n\nopen class GlueForNSButton: GlueForNSControl {\n    private var object: NSButton { return owner as! NSButton }\n\n    public struct StateReceiver {\n        let glue: GlueForNSButton\n    }\n\n    public var state: StateReceiver { return StateReceiver(glue: self) }\n\n    private let modelConnector = Connector()\n    fileprivate var model: AnyUpdatableValue<NSControl.StateValue>? {\n        didSet {\n            modelConnector.disconnect()\n            if object.target === self {\n                object.target = nil\n                object.action = nil\n            }\n            if let model = model {\n                object.target = self\n                object.action = #selector(GlueForNSButton.buttonAction(_:))\n                modelConnector.connect(model.values) { [unowned self] value in\n                    self.object.state = value\n                }\n            }\n        }\n    }\n\n    @IBAction func buttonAction(_ sender: NSButton) {\n        self.model?.value = sender.state\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NSControl Glue.swift",
    "content": "//\n//  NSControl Glue.swift\n//  macOS\n//\n//  Created by Károly Lőrentey on 2017-09-05.\n//  Copyright © 2017 Károly Lőrentey. All rights reserved.\n//\n\n#if os(macOS)\nimport AppKit\n\nextension NSControl {\n    @objc open dynamic override var glue: GlueForNSControl { return _glue() }\n}\n\npublic func <-- <Value, Model: UpdatableValueType>(target: GlueForNSControl.ValueSlot<Value>, model: Model) where Model.Value == Value {\n    target.glue.setValueModel(model.anyUpdatableValue)\n}\npublic func <-- <Value, V: UpdatableValueType>(target: GlueForNSControl.ValueSlot<Value>, model: V) where V.Value == Value? {\n    target.glue.setValueModel(model.anyUpdatableValue)\n}\n\npublic func <-- <Value, Model: ObservableValueType>(target: GlueForNSControl.ConfigSlot<Value>, model: Model) where Model.Value == Value {\n    target.glue.setConfigSlot(target.keyPath, to: model.anyObservableValue)\n}\n\n    \nopen class GlueForNSControl: GlueForNSObject {\n    private var object: NSControl { return owner as! NSControl }\n    private var modelConnection: Connection? = nil\n    fileprivate var valueModel: AnyObservableValue<Any?>? = nil {\n        didSet {\n            modelConnection?.disconnect()\n            if let model = valueModel {\n                modelConnection = model.values.subscribe { [unowned self] value in\n                    self.object.objectValue = value\n                }\n                object.target = self\n                object.action = #selector(GlueForNSControl.controlAction(_:))\n            }\n        }\n    }\n    fileprivate var valueUpdater: ((Any?) -> Bool)? = nil\n\n    fileprivate func setValueModel<V>(_ model: AnyUpdatableValue<V>) {\n        self.valueUpdater = { value in\n            guard let v = value as? V else { return false }\n            model.value = v\n            return true\n        }\n        self.valueModel = model.map { $0 as Any? }\n    }\n\n    fileprivate func setValueModel<V>(_ model: AnyUpdatableValue<V?>) {\n        self.valueUpdater = { value in\n            model.value = value as? V\n            return true\n        }\n        self.valueModel = model.map { $0 as Any? }\n    }\n\n    @objc func controlAction(_ sender: NSControl) {\n        if valueUpdater?(sender.objectValue) != true {\n            sender.objectValue = valueModel?.value\n        }\n    }\n\n    public struct ValueSlot<Value> {\n        fileprivate let glue: GlueForNSControl\n    }\n    \n    public var intValue: ValueSlot<Int> { return ValueSlot<Int>(glue: self) }\n    public var doubleValue: ValueSlot<Double> { return ValueSlot(glue: self) }\n    public var stringValue: ValueSlot<String> { return ValueSlot(glue: self) }\n    public var attributedStringValue: ValueSlot<NSAttributedString> { return ValueSlot(glue: self) }\n\n    public struct ConfigSlot<Value> {\n        fileprivate let glue: GlueForNSControl\n        fileprivate let keyPath: ReferenceWritableKeyPath<NSControl, Value>\n    }\n    \n    var configModels: [AnyKeyPath: Connection] = [:]\n\n    func setConfigSlot<Value>(_ keyPath: ReferenceWritableKeyPath<NSControl, Value>, to model: AnyObservableValue<Value>) {\n        let connection = model.values.subscribe { [unowned object] value in\n            object[keyPath: keyPath] = value\n            _ = object\n        }\n        configModels.updateValue(connection, forKey: keyPath)?.disconnect()\n    }\n\n    public var isEnabled: ConfigSlot<Bool> { return ConfigSlot(glue: self, keyPath: \\.isEnabled) }\n    public var alignment: ConfigSlot<NSTextAlignment> { return ConfigSlot(glue: self, keyPath: \\.alignment) }\n    public var font: ConfigSlot<NSFont?> { return ConfigSlot(glue: self, keyPath: \\.font) }\n    public var lineBreakMode: ConfigSlot<NSParagraphStyle.LineBreakMode> { return ConfigSlot(glue: self, keyPath: \\.lineBreakMode) }\n    public var usesSingleLineMode: ConfigSlot<Bool> { return ConfigSlot(glue: self, keyPath: \\.usesSingleLineMode) }\n    public var formatter: ConfigSlot<Formatter?> { return ConfigSlot(glue: self, keyPath: \\.formatter) }\n    public var baseWritingDirection: ConfigSlot<NSWritingDirection> { return ConfigSlot(glue: self, keyPath: \\.baseWritingDirection) }\n}\n#endif\n"
  },
  {
    "path": "Sources/NSNotificationCenter Support.swift",
    "content": "//\n//  NSNotificationCenter Support.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\n\nextension NotificationCenter {\n    open override var glue: GlueForNotificationCenter {\n        return _glue()\n    }\n}\n\nopen class GlueForNotificationCenter: GlueForNSObject {\n    private var object: NotificationCenter { return owner as! NotificationCenter }\n\n    /// Creates a Source that observes the specified notifications and forwards it to its connected sinks.\n    ///\n    /// The returned source holds strong references to the notification center and the sender (if any).\n    /// The source will only observe the notification while a sink is actually connected.\n    ///\n    /// - Parameter name: The name of the notification to observe.\n    /// - Parameter sender: The sender of the notifications to observe, or nil for any object. This parameter is nil by default.\n    /// - Parameter queue: The operation queue on which the source will trigger. If you pass nil, the sinks are run synchronously on the thread that posted the notification. This parameter is nil by default.\n    /// - Returns: A Source that triggers when the specified notification is posted.\n    public func source(forName name: NSNotification.Name, sender: AnyObject? = nil, queue: OperationQueue? = nil) -> AnySource<Notification> {\n        return NotificationSource(center: object, name: name, sender: sender, queue: queue).anySource\n    }\n}\n\nprivate class NotificationSource: SignalerSource<Notification> {\n    let center: NotificationCenter\n    let name: NSNotification.Name\n    let sender: AnyObject?\n    let queue: OperationQueue?\n\n    init(center: NotificationCenter, name: NSNotification.Name, sender: AnyObject?, queue: OperationQueue?) {\n        self.center = center\n        self.name = name\n        self.sender = sender\n        self.queue = queue\n        super.init()\n    }\n\n    override func activate() {\n        center.addObserver(self, selector: #selector(didReceive(_:)), name: name, object: sender)\n    }\n\n    override func deactivate() {\n        center.removeObserver(self, name: name, object: sender)\n    }\n\n    @objc private func didReceive(_ notification: Notification) {\n        if let queue = queue {\n            queue.addOperation {\n                self.signal.send(notification)\n            }\n        }\n        else {\n            self.signal.send(notification)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/NSObject Glue.swift",
    "content": "//\n//  NSObject Glue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-04-11.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\n\nextension NSObjectProtocol where Self: NSObject {\n    public func observable<Value>(for keyPath: KeyPath<Self, Value>) -> AnyObservableValue<Value> {\n        return ModernKVOObservable(self, keyPath).anyObservableValue\n    }\n\n    public func updatable<Value>(for keyPath: ReferenceWritableKeyPath<Self, Value>) -> AnyUpdatableValue<Value> {\n        return ModernKVOUpdatable(self, keyPath).anyUpdatableValue\n    }\n}\n\nprivate class ModernKVOObservation<Root: NSObject, Value>: Hashable {\n    typealias Sink = AnySink<ValueUpdate<Value>>\n    let sink: Sink\n    var observation: NSKeyValueObservation!\n    var transactionCount: Int = 0\n    var pendingOld: Value? = nil\n    var pendingNew: Value? = nil\n\n    init(object: Root, keyPath: KeyPath<Root, Value>, sink: Sink) {\n        self.sink = sink.anySink\n        self.observation = object.observe(keyPath, options: [.prior, .old, .new], changeHandler: self.observeChange)\n    }\n\n    var hashValue: Int { return sink.hashValue }\n    public static func ==(left: ModernKVOObservation, right: ModernKVOObservation) -> Bool {\n        return left.sink == right.sink\n    }\n\n    func invalidate() {\n        observation.invalidate()\n        if transactionCount > 0 {\n            sink.receive(.endTransaction)\n        }\n    }\n\n    func closeTransaction() {\n        precondition(transactionCount > 0)\n        guard transactionCount == 1 else { transactionCount -= 1; return }\n        while let new = pendingNew {\n            let old = pendingOld!\n            pendingOld = new\n            pendingNew = nil\n            sink.receive(.change(.init(from: old, to: new)))\n            precondition(transactionCount > 0)\n        }\n        transactionCount -= 1\n        if transactionCount == 0 {\n            pendingOld = nil\n            sink.receive(.endTransaction)\n        }\n    }\n\n    func observeChange(object: Root, change: NSKeyValueObservedChange<Value>) {\n        if change.isPrior {\n            transactionCount += 1\n            if transactionCount == 1 {\n                precondition(pendingOld == nil)\n                // Weird round trip through Any is because change.oldValue/.newValue is nil if value is a nil optional.\n                pendingOld = ((change.oldValue as Any) as! Value)\n                sink.receive(.beginTransaction)\n            }\n        }\n        else {\n            precondition(transactionCount > 0)\n            // Weird round trip through Any is because change.oldValue/.newValue is nil if value is a nil optional.\n            pendingNew = ((change.newValue as Any) as! Value)\n            closeTransaction()\n        }\n    }\n}\n\n\nprivate class ModernKVOObservable<Root: NSObject, Value>: _AbstractObservableValue<Value> {\n    typealias Sink = AnySink<ValueUpdate<Value>>\n\n    let object: Root\n    let keyPath: KeyPath<Root, Value>\n\n    var sinks: [Sink: ModernKVOObservation<Root, Value>] = [:]\n\n    init(_ object: Root, _ keyPath: KeyPath<Root, Value>) {\n        self.object = object\n        self.keyPath = keyPath\n    }\n\n    override var value: Value {\n        return object[keyPath: keyPath]\n    }\n\n    override func add<Sink>(_ sink: Sink) where Sink: SinkType, Sink.Value == Update<Change> {\n        let r = sinks.updateValue(ModernKVOObservation(object: object, keyPath: keyPath, sink: sink.anySink),\n                                  forKey: sink.anySink)\n        precondition(r == nil)\n    }\n\n    override func remove<Sink>(_ sink: Sink) -> Sink where Sink: SinkType, Sink.Value == Update<Change> {\n        let (result, observation) = sinks.remove(at: sinks.index(forKey: sink.anySink)!)\n        observation.invalidate()\n        return result.opened()!\n    }\n}\n\nprivate class ModernKVOUpdatable<Root: NSObject, Value>: _AbstractUpdatableValue<Value> {\n    typealias Sink = AnySink<ValueUpdate<Value>>\n\n    let object: Root\n    let keyPath: ReferenceWritableKeyPath<Root, Value>\n\n    var sinks: [Sink: ModernKVOObservation<Root, Value>] = [:]\n\n    init(_ object: Root, _ keyPath: ReferenceWritableKeyPath<Root, Value>) {\n        self.object = object\n        self.keyPath = keyPath\n    }\n\n    override var value: Value {\n        get {\n            return object[keyPath: keyPath]\n        }\n        set {\n            object[keyPath: keyPath] = newValue\n        }\n    }\n\n    override func apply(_ update: Update<ValueChange<Value>>) {\n        switch update {\n        case .beginTransaction:\n            object.willChangeValue(for: keyPath)\n        case .change(let change):\n            object[keyPath: keyPath] = change.new\n        case .endTransaction:\n            object.didChangeValue(for: keyPath)\n        }\n    }\n\n    override func add<Sink>(_ sink: Sink) where Sink: SinkType, Sink.Value == Update<Change> {\n        let r = sinks.updateValue(ModernKVOObservation(object: object, keyPath: keyPath, sink: sink.anySink),\n                                  forKey: sink.anySink)\n        precondition(r == nil)\n    }\n\n    override func remove<Sink>(_ sink: Sink) -> Sink where Sink: SinkType, Sink.Value == Update<Change> {\n        let (result, observation) = sinks.remove(at: sinks.index(forKey: sink.anySink)!)\n        observation.invalidate()\n        return result.opened()!\n    }\n}\n\n//\n\nprivate var associatedObjectKeyForGlue: UInt8 = 0\n\nextension NSObject {\n    public func _glue<Glue: GlueForNSObject>() -> Glue {\n        if let glue = objc_getAssociatedObject(self, &associatedObjectKeyForGlue) {\n            return glue as! Glue\n        }\n        let glue = Glue(owner: self)\n        objc_setAssociatedObject(self, &associatedObjectKeyForGlue, glue, .OBJC_ASSOCIATION_RETAIN)\n        return glue\n    }\n}\n\nextension NSObject {\n    @objc open dynamic var glue: GlueForNSObject {\n        return _glue()\n    }\n}\n\nopen class GlueForNSObject: NSObject {\n    public unowned let owner: NSObject\n\n    public private(set) lazy var connector = Connector()\n    fileprivate var keyValueSources: [String: KVOSource] = [:]\n\n    public required init(owner: NSObject) {\n        self.owner = owner\n    }\n}\n\nextension GlueForNSObject {\n    // Key-Value Observing\n\n    /// Returns an observable for the value of a KVO-compatible key path.\n    /// Note that the object is retained by the returned source.\n    public func observable(forKeyPath keyPath: String) -> KVOObservable {\n        return KVOObservable(object: owner, keyPath: keyPath)\n    }\n\n    public func observable<T>(forKeyPath keyPath: String, as type: T.Type = T.self) -> AnyObservableValue<T> {\n        return KVOObservable(object: owner, keyPath: keyPath).forceCasted()\n    }\n\n    public func observable<T>(forKeyPath keyPath: String, as type: T?.Type = Optional<T>.self) -> AnyObservableValue<T?> {\n        return KVOObservable(object: owner, keyPath: keyPath).casted()\n    }\n\n    public func observable<T>(forKeyPath keyPath: String, defaultValue: T) -> AnyObservableValue<T> {\n        return KVOObservable(object: owner, keyPath: keyPath).casted(defaultValue: defaultValue)\n    }\n\n\n    public func updatable(forKey key: String) -> KVOUpdatable {\n        precondition(!key.contains(\".\"), \"Updatable key paths aren't supported; use GlueKit mappings instead\")\n        return KVOUpdatable(object: owner, key: key)\n    }\n\n    public func updatable<T>(forKey key: String, as type: T.Type = T.self) -> AnyUpdatableValue<T> {\n        precondition(!key.contains(\".\"), \"Updatable key paths aren't supported; use GlueKit mappings instead\")\n        return KVOUpdatable(object: owner, key: key).forceCasted()\n    }\n\n    public func updatable<T>(forKey key: String, as type: T?.Type = Optional<T>.self) -> AnyUpdatableValue<T?> {\n        precondition(!key.contains(\".\"), \"Updatable key paths aren't supported; use GlueKit mappings instead\")\n        return KVOUpdatable(object: owner, key: key).casted()\n    }\n\n    public func updatable<T>(forKey key: String, defaultValue: T) -> AnyUpdatableValue<T> {\n        precondition(!key.contains(\".\"), \"Updatable key paths aren't supported; use GlueKit mappings instead\")\n        return KVOUpdatable(object: owner, key: key).casted(defaultValue: defaultValue)\n    }\n}\n\nextension GlueForNSObject {\n    fileprivate static var observingContext: UInt8 = 0\n\n    fileprivate func add<Sink: SinkType>(_  sink: Sink, forKeyPath keyPath: String) where Sink.Value == ValueUpdate<Any?> {\n        if let source = keyValueSources[keyPath] {\n            source.add(sink)\n        }\n        else {\n            let source = KVOSource(object: owner, keyPath: keyPath)\n            keyValueSources[keyPath] = source\n            source.add(sink)\n        }\n    }\n\n    fileprivate func remove<Sink: SinkType>(_ sink: Sink, forKeyPath keyPath: String) -> Sink where Sink.Value == ValueUpdate<Any?> {\n        let source = keyValueSources[keyPath]!\n        let old = source.remove(sink)\n        return old\n    }\n\n    @objc open override func observeValue(forKeyPath keyPath: String?,\n                                            of object: Any?,\n                                            change: [NSKeyValueChangeKey : Any]?,\n                                            context: UnsafeMutableRawPointer?) {\n        if context == &GlueForNSObject.observingContext {\n            keyValueSources[keyPath!]!.process(change!)\n        }\n        else {\n            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)\n        }\n    }\n}\n\nprivate final class KVOSource: TransactionalSource<ValueChange<Any?>> {\n    unowned let object: NSObject\n    let keyPath: String\n\n    init(object: NSObject, keyPath: String) {\n        self.object = object\n        self.keyPath = keyPath\n    }\n\n    override func activate() {\n        object.addObserver(object.glue, forKeyPath: keyPath, options: [.old, .new, .prior], context: &GlueForNSObject.observingContext)\n    }\n\n    override func deactivate() {\n        object.removeObserver(object.glue, forKeyPath: keyPath, context: &GlueForNSObject.observingContext)\n    }\n\n    func process(_ change: [NSKeyValueChangeKey : Any]) {\n        if (change[.notificationIsPriorKey] as? NSNumber)?.boolValue == true {\n            beginTransaction()\n        }\n        else {\n            precondition(isInTransaction)\n            let oldValue = change[.oldKey]\n            let newValue = change[.newKey]\n            let old: Any? = (oldValue is NSNull ? nil : oldValue)\n            let new: Any? = (newValue is NSNull ? nil : newValue)\n            let change = ValueChange(from: old, to: new)\n            if isInOuterMostTransaction {\n                sendChange(change)\n            }\n            endTransaction()\n        }\n    }\n}\n\npublic struct KVOObservable: ObservableValueType {\n    public typealias Change = ValueChange<Any?>\n\n    public let object: NSObject\n    public let keyPath: String\n\n    public var value: Any? {\n        return object.value(forKeyPath: keyPath)\n    }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        object.glue.add(sink, forKeyPath: keyPath)\n    }\n\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return object.glue.remove(sink, forKeyPath: keyPath)\n    }\n}\n\npublic struct KVOUpdatable: UpdatableValueType {\n    public typealias Change = ValueChange<Any?>\n\n    public let object: NSObject\n    public let key: String\n\n    public var value: Any? {\n        get {\n            return object.value(forKey: key)\n        }\n        nonmutating set {\n            object.setValue(newValue, forKey: key)\n        }\n    }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        object.glue.add(sink, forKeyPath: key)\n    }\n\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return object.glue.remove(sink, forKeyPath: key)\n    }\n\n    public func apply(_ update: Update<ValueChange<Any?>>) {\n        switch update {\n        case .beginTransaction:\n            object.willChangeValue(forKey: key)\n        case .change(let change):\n            object.setValue(change.new, forKey: key)\n        case .endTransaction:\n            object.didChangeValue(forKey: key)\n        }\n    }\n}\n\n\n\n"
  },
  {
    "path": "Sources/NSPopUpButton Glue.swift",
    "content": "//\n//  NSPopUpButton Glue.swift\n//  macOS\n//\n//  Created by Károly Lőrentey on 2017-09-05.\n//  Copyright © 2017 Károly Lőrentey. All rights reserved.\n//\n\n#if os(macOS)\nimport AppKit\n\nextension NSPopUpButton {\n    @objc open dynamic override var glue: GlueForNSPopUpButton { return _glue() }\n}\n\npublic func <-- <Value>(target: GlueForNSPopUpButton, choices: NSPopUpButton.Choices<Value>) {\n    target.setChoices(choices)\n}\n\nextension NSPopUpButton {\n    public struct Choices<Value: Equatable> {\n        let model: AnyUpdatableValue<Value>\n        let values: AnyObservableArray<(label: String, value: Value)>\n\n        public init<U: UpdatableValueType, C: ObservableArrayType>(model: U, values: C) where U.Value == Value, C.Element == (label: String, value: Value) {\n            self.model = model.anyUpdatableValue\n            self.values = values.anyObservableArray\n        }\n\n        public init<U: UpdatableValueType, S: Sequence>(model: U, values: S) where U.Value == Value, S.Element == (label: String, value: Value) {\n            self.model = model.anyUpdatableValue\n            self.values = AnyObservableArray.constant(Array(values))\n        }\n\n        public init<U: UpdatableValueType>(model: U, values: DictionaryLiteral<String, Value>) where U.Value == Value {\n            self.model = model.anyUpdatableValue\n            self.values = AnyObservableArray.constant(Array(values.map { ($0.key, $0.value) }))\n        }\n    }\n}\n\nopen class GlueForNSPopUpButton: GlueForNSButton {\n    private var object: NSPopUpButton { return owner as! NSPopUpButton }\n\n    private var valueConnection: Connection? = nil\n    private var choicesConnection: Connection? = nil\n    private var update: (Any?) -> Void = { _ in }\n\n    fileprivate func setChoices<Value>(_ choices: NSPopUpButton.Choices<Value>) {\n\n        valueConnection?.disconnect()\n        choicesConnection?.disconnect()\n\n        update = { value in if let value = value as? Value { choices.model.value = value } }\n\n        choicesConnection = choices.values.anyObservableValue.values.subscribe { [unowned self] choices in\n            let menu = NSMenu()\n            choices.forEach { choice in\n                let item = NSMenuItem(title: choice.label, action: #selector(GlueForNSPopUpButton.choiceAction(_:)), keyEquivalent: \"\")\n                item.target = self\n                item.representedObject = choice.value\n                menu.addItem(item)\n            }\n            self.object.menu = menu\n        }\n\n        valueConnection = choices.model.values.subscribe { [unowned self] newValue in\n            if let item = self.object.menu?.items.first(where: { $0.representedObject as? Value == newValue }) {\n                if self.object.selectedItem != item {\n                    self.object.select(item)\n                }\n            }\n            else {\n                self.object.select(nil)\n            }\n        }\n    }\n\n    @IBAction func choiceAction(_ sender: NSMenuItem) {\n        update(sender.representedObject)\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/NSTextField Glue.swift",
    "content": "//\n//  NSTextField Glue.swift\n//  macOS\n//\n//  Created by Károly Lőrentey on 2017-09-05.\n//  Copyright © 2017 Károly Lőrentey. All rights reserved.\n//\n\n#if os(macOS)\nimport AppKit\n\nextension NSTextField {\n    @objc open dynamic override var glue: GlueForNSTextField { return _glue() }\n}\n\npublic func <-- <V: UpdatableValueType>(target: GlueForNSTextField.ValidatingValueReceiver, model: V) where V.Value: LosslessStringConvertible {\n    target.glue.setModel(model)\n}\n\nopen class GlueForNSTextField: GlueForNSControl {\n    private var object: NSTextField { return owner as! NSTextField }\n    private var delegate: Any? = nil\n\n    public struct ValidatingValueReceiver { let glue: GlueForNSTextField }\n    public var value: ValidatingValueReceiver { return ValidatingValueReceiver(glue: self) }\n\n    fileprivate func setModel<V: UpdatableValueType>(_ model: V) where V.Value: LosslessStringConvertible {\n        if let delegate = self.delegate as? GlueKitTextFieldDelegate<V.Value> {\n            delegate.model = model.anyUpdatableValue\n        }\n        else {\n            let delegate = GlueKitTextFieldDelegate(object, model)\n            self.delegate = delegate\n        }\n    }\n}\n\nclass GlueKitTextFieldDelegate<Value: LosslessStringConvertible>: NSObject, NSTextFieldDelegate {\n    unowned let view: NSTextField\n    var model: AnyUpdatableValue<Value> {\n        didSet { reconnect() }\n    }\n\n    init<V: UpdatableValueType>(_ view: NSTextField, _ model: V) where V.Value == Value {\n        self.view = view\n        self.model = model.anyUpdatableValue\n        super.init()\n        reconnect()\n    }\n\n    private var modelConnection: Connection? = nil\n    private func reconnect() {\n        view.delegate = self\n        modelConnection?.disconnect()\n        modelConnection = model.values.subscribe { [unowned self] value in\n            self.view.stringValue = \"\\(value)\"\n        }\n    }\n\n    func control(_ control: NSControl, textShouldEndEditing fieldEditor: NSText) -> Bool {\n        return Value(view.stringValue) != nil\n    }\n\n    override func controlTextDidEndEditing(_ obj: Notification) {\n        if let value = Value(view.stringValue) {\n            model.value = value\n        }\n        else {\n            view.stringValue = \"\\(model.value)\"\n        }\n    }\n\n    func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {\n        guard commandSelector == #selector(NSResponder.cancelOperation(_:)) else { return false }\n        view.stringValue = \"\\(model.value)\"\n        //textView.window?.makeFirstResponder(nil)\n        return true\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/ObservableArray.swift",
    "content": "//\n//  AnyObservableArray.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-11.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic typealias ArrayUpdate<Element> = Update<ArrayChange<Element>>\npublic typealias ArrayUpdateSource<Element> = AnySource<Update<ArrayChange<Element>>>\n\n//MARK: ObservableArrayType\n\n/// An observable array type; i.e., a read-only, array-like observable collection that provides efficient change\n/// notifications.\n///\n/// Changes to an observable array are broadcast as a sequence of `ArrayChange` values, which describe insertions,\n/// removals, and replacements.\n///\n/// Any `ObservableArrayType` can be converted into a type-erased representation using `AnyObservableArray`.\n/// For a concrete observable array, see `ArrayVariable`.\n///\n/// - SeeAlso: ObservableValueType, AnyObservableArray, UpdatableArrayType, ArrayVariable\npublic protocol ObservableArrayType: ObservableType, CustomReflectable where Change == ArrayChange<Element> {\n    associatedtype Element\n\n    // Required methods\n    var count: Int { get }\n    subscript(bounds: Range<Int>) -> ArraySlice<Element> { get }\n\n    // Extras\n    var isBuffered: Bool { get }\n    var value: [Element] { get }\n    subscript(index: Int) -> Element { get }\n    var observableCount: AnyObservableValue<Int> { get }\n\n    var anyObservableValue: AnyObservableValue<[Element]> { get }\n    var anyObservableArray: AnyObservableArray<Element> { get }\n}\n\nextension ObservableArrayType {\n    public var isBuffered: Bool {\n        return false\n    }\n\n    public var value: [Element] {\n        return Array(self[0 ..< count])\n    }\n\n    public subscript(_ index: Int) -> Element {\n        return self[index ..< index + 1].first!\n    }\n}\n\nextension ObservableArrayType {\n    internal var valueUpdates: AnySource<ValueUpdate<[Element]>> {\n        var value = self.value\n        return self.updates.map { event in\n            event.map { change in\n                let old = value\n                value.apply(change)\n                return ValueChange(from: old, to: value)\n            }\n        }.buffered()\n    }\n\n    public var anyObservableValue: AnyObservableValue<[Element]> {\n        return AnyObservableValue(getter: { self.value }, updates: self.valueUpdates)\n    }\n\n    public var observableCount: AnyObservableValue<Int> {\n        return AnyObservableValue(getter: { self.count },\n                                  updates: self.updates.map { $0.map { $0.countChange } })\n    }\n\n    public var anyObservableArray: AnyObservableArray<Element> {\n        return AnyObservableArray(box: ObservableArrayBox(self))\n    }\n}\n\nextension ObservableArrayType {\n    public var isEmpty: Bool {\n        return count == 0\n    }\n    \n    public var first: Element? {\n        guard count > 0 else { return nil }\n        return self[0]\n    }\n\n    public var last: Element? {\n        guard count > 0 else { return nil }\n        return self[count - 1]\n    }\n}\n\nextension ObservableArrayType {\n    public var customMirror: Mirror {\n        return Mirror(self, unlabeledChildren: self.value, displayStyle: .collection)\n    }\n}\n\n/// An observable array type; i.e., a read-only, array-like `CollectionType` that also provides efficient change\n/// notifications.\n///\n/// Changes to an observable array are broadcast as a sequence of `ArrayChange` values, which describe insertions,\n/// removals, and replacements.\n/// The count of elements in an `ObservableArrayType` is itself observable via its `observableCount` property.\n///\n/// Any `ObservableArrayType` can be converted into a type-erased representation using `AnyObservableArray`.\n/// For a concrete observable array, see `ArrayVariable`.\n///\n/// - SeeAlso: ObservableValueType, ObservableArrayType, UpdatableArrayType, ArrayVariable\npublic struct AnyObservableArray<Element>: ObservableArrayType {\n    public typealias Base = Array<Element>\n    public typealias Change = ArrayChange<Element>\n\n    let box: _AbstractObservableArray<Element>\n\n    init(box: _AbstractObservableArray<Element>) {\n        self.box = box\n    }\n\n    public init<A: ObservableArrayType>(_ array: A) where A.Element == Element {\n        self = array.anyObservableArray\n    }\n\n    public var isBuffered: Bool { return box.isBuffered }\n    public subscript(_ index: Int) -> Element { return box[index] }\n    public subscript(_ range: Range<Int>) -> ArraySlice<Element> { return box[range] }\n    public var value: Array<Element> { return box.value }\n    public var count: Int { return box.count }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        box.add(sink)\n    }\n\n    @discardableResult\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        return box.remove(sink)\n    }\n    public var observableCount: AnyObservableValue<Int> { return box.observableCount }\n    public var anyObservableValue: AnyObservableValue<[Element]> { return box.anyObservableValue }\n    public var anyObservableArray: AnyObservableArray<Element> { return self }\n}\n\nopen class _AbstractObservableArray<Element>: ObservableArrayType {\n    public typealias Base = Array<Element>\n    public typealias Change = ArrayChange<Element>\n\n    open var isBuffered: Bool { abstract() }\n    open subscript(_ index: Int) -> Element { abstract() }\n    open subscript(_ range: Range<Int>) -> ArraySlice<Element> { abstract() }\n    open var value: Array<Element> { abstract() }\n    open var count: Int { abstract() }\n\n    open func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        abstract()\n    }\n\n    @discardableResult\n    open func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        abstract()\n    }\n\n    open var observableCount: AnyObservableValue<Int> {\n        return AnyObservableValue(getter: { self.count },\n                                  updates: self.updates.map { $0.map { $0.countChange } })\n    }\n\n    open var anyObservableValue: AnyObservableValue<[Element]> {\n        return AnyObservableValue(getter: { self.value }, updates: self.valueUpdates)\n    }\n\n    public final var anyObservableArray: AnyObservableArray<Element> { return AnyObservableArray(box: self) }\n}\n\nopen class _BaseObservableArray<Element>: _AbstractObservableArray<Element>, TransactionalThing {\n    var _signal: TransactionalSignal<ArrayChange<Element>>? = nil\n    var _transactionCount = 0\n\n    public final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    public final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        return signal.remove(sink)\n    }\n\n    open func activate() {\n        // Do nothing\n    }\n\n    open func deactivate() {\n        // Do nothing\n    }\n}\n\ninternal final class ObservableArrayBox<Contents: ObservableArrayType>: _AbstractObservableArray<Contents.Element> {\n    typealias Element = Contents.Element\n\n    let contents: Contents\n\n    init(_ Contents: Contents) {\n        self.contents = Contents\n    }\n\n    override var isBuffered: Bool { return contents.isBuffered }\n    override subscript(_ index: Int) -> Element { return contents[index] }\n    override subscript(_ range: Range<Int>) -> ArraySlice<Element> { return contents[range] }\n    override var value: Array<Element> { return contents.value }\n    override var count: Int { return contents.count }\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        contents.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        return contents.remove(sink)\n    }\n    override var observableCount: AnyObservableValue<Int> { return contents.observableCount }\n    override var anyObservableValue: AnyObservableValue<[Element]> { return contents.anyObservableValue }\n}\n\ninternal final class ObservableArrayConstant<Element>: _AbstractObservableArray<Element> {\n    let _value: Array<Element>\n\n    init(_ value: [Element]) {\n        self._value = value\n    }\n\n    override var isBuffered: Bool { return true }\n    override subscript(_ index: Int) -> Element { return _value[index] }\n    override subscript(_ range: Range<Int>) -> ArraySlice<Element> { return _value[range] }\n    override var value: Array<Element> { return _value }\n    override var count: Int { return _value.count }\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        // Do nothing\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        return sink\n    }\n    override var observableCount: AnyObservableValue<Int> { return AnyObservableValue.constant(_value.count) }\n    override var anyObservableValue: AnyObservableValue<[Element]> { return AnyObservableValue.constant(_value) }\n}\n\nextension ObservableArrayType {\n    public static func constant(_ value: [Element]) -> AnyObservableArray<Element> {\n        return ObservableArrayConstant(value).anyObservableArray\n    }\n\n    public static func emptyConstant() -> AnyObservableArray<Element> {\n        return constant([])\n    }\n}\n"
  },
  {
    "path": "Sources/ObservableContains.swift",
    "content": "//\n//  ObservableContains.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    public func observableContains(_ member: Element) -> AnyObservableValue<Bool> {\n        return ObservableContains(input: self, member: member).anyObservableValue\n    }\n}\n\nprivate final class ObservableContains<Input: ObservableSetType>: _AbstractObservableValue<Bool> {\n    let input: Input\n    let member: Input.Element\n    let _updates: AnySource<ValueUpdate<Bool>>\n\n    init(input: Input, member: Input.Element) {\n        self.input = input\n        self.member = member\n        self._updates = input.updates.flatMap { update in\n            update.flatMap {\n                let old = $0.removed.contains(member)\n                let new = $0.inserted.contains(member)\n                if old == new {\n                    return nil\n                }\n                else {\n                    return ValueChange(from: old, to: new)\n                }\n            }\n        }\n    }\n\n    override var value: Bool {\n        return input.contains(member)\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        _updates.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return _updates.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Sources/ObservableSet.swift",
    "content": "//\n//  ObservableSet.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-12.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic typealias SetUpdate<Element: Hashable> = Update<SetChange<Element>>\npublic typealias SetUpdateSource<Element: Hashable> = AnySource<Update<SetChange<Element>>>\n\npublic protocol ObservableSetType: ObservableType where Change == SetChange<Element> {\n    associatedtype Element\n\n    typealias Base = Set<Element>\n\n    var isBuffered: Bool { get }\n    var count: Int { get }\n    var value: Set<Element> { get }\n    func contains(_ member: Element) -> Bool\n    func isSubset(of other: Set<Element>) -> Bool\n    func isSuperset(of other: Set<Element>) -> Bool\n\n    var observableCount: AnyObservableValue<Int> { get }\n    var anyObservableValue: AnyObservableValue<Base> { get }\n    var anyObservableSet: AnyObservableSet<Element> { get }\n}\n\nextension ObservableSetType {\n    public var isBuffered: Bool { return false }\n    public var count: Int { return value.count }\n    public func contains(_ member: Element) -> Bool { return value.contains(member) }\n    public func isSubset(of other: Set<Element>) -> Bool { return value.isSubset(of: other) }\n    public func isSuperset(of other: Set<Element>) -> Bool { return value.isSuperset(of: other) }\n\n    public var isEmpty: Bool { return count == 0 }\n\n    internal var valueUpdates: AnySource<ValueUpdate<Set<Element>>> {\n        var value = self.value\n        return self.updates.map { event in\n            event.map { change in\n                let old = value\n                value.apply(change)\n                return ValueChange(from: old, to: value)\n            }\n        }.buffered()\n    }\n\n    internal var countUpdates: AnySource<ValueUpdate<Int>> {\n        var count = self.count\n        return self.updates.map { update in\n            update.map { change in\n                let old = count\n                count += numericCast(change.inserted.count - change.removed.count)\n                return .init(from: old, to: count)\n            }\n        }.buffered()\n    }\n\n    public var observableCount: AnyObservableValue<Int> {\n        return AnyObservableValue(getter: { self.count }, updates: self.countUpdates)\n    }\n\n    public var anyObservableValue: AnyObservableValue<Base> {\n        return AnyObservableValue(getter: { self.value }, updates: self.valueUpdates)\n    }\n\n    public var anyObservableSet: AnyObservableSet<Element> {\n        return AnyObservableSet(box: ObservableSetBox(self))\n    }\n}\n\npublic struct AnyObservableSet<Element: Hashable>: ObservableSetType {\n    public typealias Base = Set<Element>\n    public typealias Change = SetChange<Element>\n\n    let box: _AbstractObservableSet<Element>\n\n    init(box: _AbstractObservableSet<Element>) {\n        self.box = box\n    }\n\n    public var isBuffered: Bool { return box.isBuffered }\n    public var count: Int { return box.count }\n    public var value: Set<Element> { return box.value }\n    public func contains(_ member: Element) -> Bool { return box.contains(member) }\n    public func isSubset(of other: Set<Element>) -> Bool { return box.isSubset(of: other) }\n    public func isSuperset(of other: Set<Element>) -> Bool { return box.isSuperset(of: other) }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        box.add(sink)\n    }\n\n    @discardableResult\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return box.remove(sink)\n    }\n\n    public var observableCount: AnyObservableValue<Int> { return box.observableCount }\n    public var anyObservableValue: AnyObservableValue<Set<Element>> { return box.anyObservableValue }\n    public var anyObservableSet: AnyObservableSet<Element> { return self }\n}\n\nopen class _AbstractObservableSet<Element: Hashable>: ObservableSetType {\n    public typealias Change = SetChange<Element>\n\n    open var value: Set<Element> { abstract() }\n\n    open func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<SetChange<Element>> {\n        abstract()\n    }\n\n    @discardableResult\n    open func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<SetChange<Element>> {\n        abstract()\n    }\n\n    open var isBuffered: Bool { return false }\n    open var count: Int { return value.count }\n    open func contains(_ member: Element) -> Bool { return value.contains(member) }\n    open func isSubset(of other: Set<Element>) -> Bool { return value.isSubset(of: other) }\n    open func isSuperset(of other: Set<Element>) -> Bool { return value.isSuperset(of: other) }\n\n    open var observableCount: AnyObservableValue<Int> {\n        return AnyObservableValue(getter: { self.count }, updates: self.countUpdates)\n    }\n\n    open var anyObservableValue: AnyObservableValue<Set<Element>> {\n        return AnyObservableValue(getter: { self.value }, updates: self.valueUpdates)\n    }\n\n    public final var anyObservableSet: AnyObservableSet<Element> {\n        return AnyObservableSet(box: self)\n    }\n}\n\nopen class _BaseObservableSet<Element: Hashable>: _AbstractObservableSet<Element>, TransactionalThing {\n    var _signal: TransactionalSignal<SetChange<Element>>? = nil\n    var _transactionCount = 0\n\n    public final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<SetChange<Element>> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    public final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<SetChange<Element>> {\n        return signal.remove(sink)\n    }\n\n    func activate() {\n        // Do nothing\n    }\n\n    func deactivate() {\n        // Do nothing\n    }\n}\n\nfinal class ObservableSetBox<Contents: ObservableSetType>: _AbstractObservableSet<Contents.Element> {\n    typealias Element = Contents.Element\n\n    let contents: Contents\n\n    init(_ contents: Contents) {\n        self.contents = contents\n    }\n\n    override var isBuffered: Bool { return contents.isBuffered }\n    override var count: Int { return contents.count }\n    override var value: Set<Element> { return contents.value }\n    override func contains(_ member: Element) -> Bool { return contents.contains(member) }\n    override func isSubset(of other: Set<Element>) -> Bool { return contents.isSubset(of: other) }\n    override func isSuperset(of other: Set<Element>) -> Bool { return contents.isSuperset(of: other) }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<SetChange<Element>> {\n        contents.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<SetChange<Element>> {\n        return contents.remove(sink)\n    }\n\n    override var observableCount: AnyObservableValue<Int> { return contents.observableCount }\n    override var anyObservableValue: AnyObservableValue<Set<Element>> { return contents.anyObservableValue }\n}\n\nclass ObservableConstantSet<Element: Hashable>: _AbstractObservableSet<Element> {\n    let contents: Set<Element>\n\n    init(_ contents: Set<Element>) {\n        self.contents = contents\n    }\n\n    override var isBuffered: Bool { return true }\n    override var count: Int { return contents.count }\n    override var value: Set<Element> { return contents }\n    override func contains(_ member: Element) -> Bool { return contents.contains(member) }\n    override func isSubset(of other: Set<Element>) -> Bool { return contents.isSubset(of: other) }\n    override func isSuperset(of other: Set<Element>) -> Bool { return contents.isSuperset(of: other) }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<SetChange<Element>> {\n        // Do nothing\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<SetChange<Element>> {\n        return sink\n    }\n\n    override var observableCount: AnyObservableValue<Int> { return AnyObservableValue.constant(contents.count) }\n    override var anyObservableValue: AnyObservableValue<Set<Element>> { return AnyObservableValue.constant(contents) }\n}\n\nextension ObservableSetType {\n    public static func constant(_ value: Set<Element>) -> AnyObservableSet<Element> {\n        return ObservableConstantSet(value).anyObservableSet\n    }\n\n    public static func emptyConstant() -> AnyObservableSet<Element> {\n        return constant([])\n    }\n}\n"
  },
  {
    "path": "Sources/ObservableType.swift",
    "content": "//\n//  ObservableValueType.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-04.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic protocol ObservableType {\n    associatedtype Value\n    associatedtype Change: ChangeType where Change.Value == Value\n\n    /// The current value of this observable.\n    var value: Value { get }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change>\n\n    @discardableResult\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change>\n}\n\nextension ObservableType {\n    /// A source that reports update transaction events for this observable.\n    public var updates: UpdateSource<Self> {\n        return UpdateSource(owner: self)\n    }\n}\n\nextension ObservableType {\n    /// A source that sends an empty value whenever the observable completes a transaction.\n    public var tick: AnySource<Void> {\n        return self.updates.flatMap { if case .endTransaction = $0 { return () }; return nil }\n    }\n}\n\npublic struct UpdateSource<Observable: ObservableType>: SourceType {\n    public typealias Value = Update<Observable.Change>\n\n    private let owner: Observable\n\n    init(owner: Observable) {\n        self.owner = owner\n    }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        owner.add(sink)\n    }\n\n    @discardableResult\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        return owner.remove(sink)\n    }\n}\n\npublic protocol UpdatableType: ObservableType {\n    /// The current value of this observable.\n    ///\n    /// The setter is nonmutating because the value ultimately needs to be stored in a reference type anyway.\n    var value: Value { get nonmutating set }\n\n    func apply(_ update: Update<Change>)\n}\n\nextension UpdatableType {\n    public func withTransaction<Result>(_ body: () -> Result) -> Result {\n        apply(.beginTransaction)\n        defer { apply(.endTransaction) }\n        return body()\n    }\n\n    public func apply(_ change: Change) {\n        if !change.isEmpty {\n            apply(.beginTransaction)\n            apply(.change(change))\n            apply(.endTransaction)\n        }\n    }\n}\n\nextension ObservableType {\n    public func subscribe<Updatable: UpdatableType>(to updatable: Updatable) -> Connection\n    where Updatable.Change == Change {\n        updatable.apply(.beginTransaction)\n        updatable.apply(.change(Change(from: updatable.value, to: self.value)))\n        let connection = updates.subscribe { update in updatable.apply(update) }\n        updatable.apply(.endTransaction)\n        return connection\n    }\n}\n\nextension Connector {\n    @discardableResult\n    public func subscribe<Observable: ObservableType>(_ observable: Observable, to sink: @escaping (Update<Observable.Change>) -> Void) -> Connection {\n        return observable.updates.subscribe(sink).putInto(self)\n    }\n}\n"
  },
  {
    "path": "Sources/ObservableValue.swift",
    "content": "//\n//  Observable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic typealias ValueUpdate<Value> = Update<ValueChange<Value>>\n\n/// An observable has a value that is readable at any time, and may change in response to certain events.\n/// Interested parties can sign up to receive notifications when the observable's value changes.\n///\n/// In GlueKit, observables are represented by types implementing `ObservableValueType`. They provide update notifications\n/// via either of two sources:\n///\n/// - `values` sends the initial value of the observable to each new sink, followed by the values of later updates.\n/// - `futureValues` skips the initial value and just sends values on future updates.\n///\n/// The simplest concrete observable is `Variable<Value>`, implementing a settable variable with an individual observable value.\n/// `ArrayVariable<Value>` implements an observable array of values, with efficient change notifications.\n///\n/// If you have one or more observables, you can use GlueKit's rich set of observable transformations and compositions\n/// to build observable expressions out of them.\n///\n/// Types implementing `ObservableValueType` are generally not type-safe; you must serialize all accesses to them\n/// (including connecting to any of their sources).\n///\npublic protocol ObservableValueType: ObservableType, CustomPlaygroundQuickLookable\nwhere Change == ValueChange<Value> {\n    /// Returns the type-erased version of this ObservableValueType.\n    var anyObservableValue: AnyObservableValue<Value> { get }\n}\n\nextension ObservableValueType {\n    /// Returns the type-erased version of this ObservableValueType.\n    public var anyObservableValue: AnyObservableValue<Value> {\n        return AnyObservableValue(self)\n    }\n\n    /// A source that delivers new values whenever this observable changes.\n    public var futureValues: AnySource<Value> { return changes.map { $0.new } }\n\n    /// A source that, for each new sink, immediately sends it the current value, and thereafter delivers updated values,\n    /// like `futureValues`. Implemented in terms of `futureValues` and `value`.\n    public var values: AnySource<Value> {\n        return futureValues.bracketed(hello: { self.value }, goodbye: { nil })\n    }\n}\n\nextension ObservableValueType {\n    public var customPlaygroundQuickLook: PlaygroundQuickLook {\n        return PlaygroundQuickLook.text(\"\\(value)\")\n    }\n}\n\n\n/// The type erased representation of an ObservableValueType that contains a single value with simple changes.\npublic struct AnyObservableValue<Value>: ObservableValueType {\n    public typealias Change = ValueChange<Value>\n\n    private let box: _AbstractObservableValue<Value>\n\n    init(box: _AbstractObservableValue<Value>) {\n        self.box = box\n    }\n    \n    /// Initializes an Observable from the given getter closure and source of future changes.\n    /// @param getter A closure that returns the current value of the observable at the time of the call.\n    /// @param futureValues A closure that returns a source that triggers whenever the observable changes.\n    public init<Updates: SourceType>(getter: @escaping () -> Value, updates: Updates) where Updates.Value == Update<Change> {\n        self.box = ObservableClosureBox(getter: getter, updates: updates)\n    }\n\n    public init<Base: ObservableValueType>(_ base: Base) where Base.Value == Value {\n        self.box = ObservableValueBox(base)\n    }\n\n    public var value: Value {\n        return box.value\n    }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        box.add(sink)\n    }\n\n    @discardableResult\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return box.remove(sink)\n    }\n\n    public var anyObservableValue: AnyObservableValue<Value> {\n        return self\n    }\n}\n\nopen class _AbstractObservableValue<Value>: ObservableValueType {\n    public typealias Change = ValueChange<Value>\n\n    open var value: Value { abstract() }\n\n    open func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> { abstract() }\n\n    @discardableResult\n    open func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> { abstract() }\n\n    public final var anyObservableValue: AnyObservableValue<Value> {\n        return AnyObservableValue(box: self)\n    }\n}\n\nopen class _BaseObservableValue<Value>: _AbstractObservableValue<Value>, TransactionalThing {\n    public typealias Change = ValueChange<Value>\n    var _signal: TransactionalSignal<ValueChange<Value>>? = nil\n    var _transactionCount: Int = 0\n\n    public final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    public final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n\n    open func activate() {\n        // Do nothing\n    }\n\n    open func deactivate() {\n        // Do nothing\n    }\n}\n\ninternal final class ObservableValueBox<Base: ObservableValueType>: _AbstractObservableValue<Base.Value> {\n    typealias Value = Base.Value\n\n    private let base: Base\n\n    init(_ base: Base) {\n        self.base = base\n    }\n    override var value: Value { return base.value }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        base.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return base.remove(sink)\n    }\n}\n\nprivate final class ObservableClosureBox<Value, Updates: SourceType>: _AbstractObservableValue<Value>\nwhere Updates.Value == Update<ValueChange<Value>> {\n    private let _value: () -> Value\n    private let _updates: Updates\n\n    public init(getter: @escaping () -> Value, updates: Updates) {\n        self._value = getter\n        self._updates = updates\n    }\n\n    override var value: Value { return _value() }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        _updates.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return _updates.remove(sink)\n    }\n}\n\npublic extension ObservableValueType {\n    /// Creates a constant observable wrapping the given value. The returned observable is not modifiable and it will not ever send updates.\n    public static func constant(_ value: Value) -> AnyObservableValue<Value> {\n        return ConstantObservable(value).anyObservableValue\n    }\n}\n\nprivate final class ConstantObservable<Value>: _AbstractObservableValue<Value> {\n    private let _value: Value\n\n    init(_ value: Value) { _value = value }\n\n    override var value: Value { return _value }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        // Do nothing\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        // Do nothing\n        return sink\n    }\n}\n\n\n"
  },
  {
    "path": "Sources/OwnedSink.swift",
    "content": "//\n//  StrongMethodSink.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-24.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport SipHash\n\nprotocol UniqueOwnedSink: SinkType {\n    associatedtype Owner: AnyObject\n\n    var owner: Owner { get }\n}\n\nextension UniqueOwnedSink {\n    var hashValue: Int {\n        return ObjectIdentifier(owner).hashValue\n    }\n\n    static func ==(left: Self, right: Self) -> Bool {\n        return left.owner === right.owner\n    }\n}\n\nprotocol OwnedSink: SinkType, SipHashable {\n    associatedtype Owner: AnyObject\n    associatedtype Identifier: Hashable\n\n    var owner: Owner { get }\n    var identifier: Identifier { get }\n}\n\nextension OwnedSink {\n    func appendHashes(to hasher: inout SipHasher) {\n        hasher.append(ObjectIdentifier(owner))\n        hasher.append(identifier)\n    }\n\n    static func ==(left: Self, right: Self) -> Bool {\n        return left.owner === right.owner && left.identifier == right.identifier\n    }\n}\n"
  },
  {
    "path": "Sources/RefList.swift",
    "content": "//\n//  RefList.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-09-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// An element in a reflist, with an opaque link to its parent node.\nprotocol RefListElement: class {\n    /// An opaque link to the element's parent node in the ref list.\n    var refListLink: RefListLink<Self> { get set }\n}\n\ninternal struct RefListLink<Element: RefListElement> {\n    fileprivate var _parent: UnownedReference<RefListNode<Element>>?\n\n    internal init() {\n        self._parent = nil\n    }\n}\n\nextension RefListElement {\n    fileprivate var parent: RefListNode<Self>? {\n        get {\n            return refListLink._parent?.value\n        }\n        set {\n            if let p = newValue {\n                refListLink._parent = UnownedReference(p)\n            }\n            else {\n                refListLink._parent = nil\n            }\n        }\n    }\n}\n\n/// A reflist is a B-tree backed random-access list data structure. It does not support copy-on-write mutation,\n/// but it supports parent links, allowing for efficient determination of any element's position in the list in O(log(n)) time.\n/// Elements in the refList may only be in a single list at a time.\ninternal final class RefList<Element: RefListElement>: RandomAccessCollection, MutableCollection, RangeReplaceableCollection {\n    fileprivate typealias Node = RefListNode<Element>\n    internal typealias Index = Int\n    internal typealias Indices = CountableRange<Int>\n    internal typealias Iterator = IndexingIterator<RefList>\n\n    fileprivate var root: Node\n\n    required convenience init() {\n        self.init(order: Node.defaultOrder)\n    }\n\n    required convenience init<S: Sequence>(_ elements: S) where S.Iterator.Element == Element {\n        // TODO: Implement bulk loader\n        self.init()\n        self.append(contentsOf: elements)\n    }\n\n    init(order: Int) {\n        self.root = Node(order: order)\n    }\n\n    internal var count: Int { return root.count }\n    internal var startIndex: Int { return 0 }\n    internal var endIndex: Int { return count }\n\n    internal subscript(index: Int) -> Element {\n        get {\n            let (node, slot) = self.slot(of: index)\n            return node.elements[slot]\n        }\n        set {\n            precondition(newValue.parent == nil)\n            let (node, slot) = self.slot(of: index)\n            let old = node.elements[slot]\n            node.elements[slot] = newValue\n            newValue.parent = node\n            old.parent = nil\n        }\n    }\n\n    internal subscript(bounds: Range<Int>) -> MutableRangeReplaceableRandomAccessSlice<RefList> {\n        get {\n            return .init(base: self, bounds: bounds)\n        }\n        set {\n            // Elements can only belong to a single RefList, but slices contain elements that are already in one.\n            fatalError(\"RefList does not support range replacement.\")\n        }\n    }\n\n    internal func forEach(in range: Range<Int>? = nil, body: (Element) throws -> ()) rethrows {\n        if let range = range, range != 0 ..< count {\n            try root.forEach(range, body)\n        }\n        else {\n            try root.forEach(body)\n        }\n    }\n\n    internal func index(of element: Element) -> Int? {\n        var node = element.parent!\n        var offset = node.offset(of: element)\n        while let parent = node.parent {\n            offset += parent.offset(of: node)\n            node = parent\n        }\n        precondition(node === root)\n        return offset\n    }\n\n    private func slot(of offset: Int) -> (node: Node, slot: Int) {\n        precondition(offset >= 0 && offset < count)\n        var offset = offset\n        var node = root\n        while !node.isLeaf {\n            let slot = node.slot(atOffset: offset)\n            if slot.match {\n                return (node, slot.index)\n            }\n            let child = node.children[slot.index]\n            offset -= slot.offset - child.count\n            node = child\n        }\n        return (node, offset)\n    }\n\n    internal func insert(_ element: Element, at index: Int) {\n        precondition(element.parent == nil)\n        precondition(index >= 0 && index <= count)\n        var pos = count - index\n        var splinter: (separator: Element, node: Node)? = nil\n        var element = element\n        root.edit(\n            descend: { node in\n                let slot = node.slot(atOffset: node.count - pos)\n                if !slot.match {\n                    // Continue descending.\n                    pos -= node.count - slot.offset\n                    return slot.index\n                }\n                if node.isLeaf {\n                    // Found the insertion point. Insert, then start ascending.\n                    node.insert(element, inSlot: slot.index)\n                    if node.isTooLarge {\n                        splinter = node.split()\n                    }\n                    return nil\n                }\n                // For internal nodes, put the new element in place of the old at the same offset,\n                // then continue descending toward the next offset, inserting the old element.\n                element = node.setElement(inSlot: slot.index, to: element)\n                pos = node.children[slot.index + 1].count\n                return slot.index + 1\n            },\n            ascend: { node, slot in\n                node.count += 1\n                if let s = splinter {\n                    s.separator.parent = node\n                    s.node.parent = node\n                    node.elements.insert(s.separator, at: slot)\n                    node.children.insert(s.node, at: slot + 1)\n                    splinter = node.isTooLarge ? node.split() : nil\n                }\n            }\n        )\n        if let s = splinter {\n            root = Node(left: root, separator: s.separator, right: s.node)\n        }\n        assert(element.parent != nil)\n    }\n\n    internal func insert<C: Collection>(contentsOf newElements: C, at index: Int) where C.Iterator.Element == Iterator.Element {\n        // TODO: Implement bulk insertion using join.\n        var i = index\n        for element in newElements {\n            self.insert(element, at: i)\n            i += 1\n        }\n    }\n\n    internal func append(_ newElement: Element) {\n        self.insert(newElement, at: count)\n    }\n\n    internal func append<S: Sequence>(contentsOf newElements: S) where S.Iterator.Element == Iterator.Element {\n        // TODO: Implement bulk insertion using join.\n        var i = count\n        for element in newElements {\n            self.insert(element, at: i)\n            i += 1\n        }\n    }\n\n    /// Remove and return the element at the specified offset.\n    ///\n    /// - Note: When you need to perform multiple modifications on the same tree,\n    ///   `BTreeCursor` provides an alternative interface that's often more efficient.\n    /// - Complexity: O(log(`count`))\n    @discardableResult\n    internal func remove(at index: Int) -> Element {\n        precondition(index >= 0 && index < count)\n        var pos = count - index\n        var matching: (node: Node, slot: Int)? = nil\n        var old: Element? = nil\n        root.edit(\n            descend: { node in\n                let slot = node.slot(atOffset: node.count - pos)\n                if !slot.match {\n                    // No match yet; continue descending.\n                    assert(!node.isLeaf)\n                    pos -= node.count - slot.offset\n                    return slot.index\n                }\n                if node.isLeaf {\n                    // The offset we're looking for is in a leaf node; we can remove it directly.\n                    old = node.elements.remove(at: slot.index)\n                    old!.parent = nil\n                    node.count -= 1\n                    return nil\n                }\n                // When the offset happens to fall in an internal node, remember the match and continue\n                // removing the next offset (which is guaranteed to be in a leaf node).\n                // We'll replace the removed element with this one during the ascend.\n                matching = (node, slot.index)\n                pos = node.children[slot.index + 1].count\n                return slot.index + 1\n            },\n            ascend: { node, slot in\n                node.count -= 1\n                if let m = matching, m.node === node {\n                    // We've removed the element at the next offset; put it back in place of the\n                    // element we actually want to remove.\n                    old!.parent = node\n                    old = node.setElement(inSlot: m.slot, to: old!)\n                    old!.parent = nil\n                    matching = nil\n                }\n                if node.children[slot].isTooSmall {\n                    node.fixDeficiency(slot)\n                }\n            }\n        )\n        if root.children.count == 1 {\n            assert(root.elements.count == 0)\n            root = root.children[0]\n            root.parent = nil\n        }\n        precondition(old?.parent == nil)\n        return old!\n    }\n\n    internal func removeSubrange(_ bounds: Range<Int>) {\n        // TODO: Make this more efficient.\n        for index in CountableRange(bounds).reversed() {\n            self.remove(at: index)\n        }\n    }\n\n    internal func replaceSubrange<C: Collection>(_ subrange: Range<Int>, with newElements: C) where C.Iterator.Element == Element {\n        // TODO: Make this more efficient.\n        self.removeSubrange(subrange)\n        self.insert(contentsOf: newElements, at: subrange.lowerBound)\n    }\n}\n\nfileprivate final class RefListNode<Element: RefListElement> {\n    typealias Node = RefListNode<Element>\n\n    var _parent: UnownedReference<RefListNode>?\n    var elements: [Element]\n    var children: [RefListNode]\n    var count: Int = 0\n    let order: Int\n    var depth: Int\n\n\n    static var defaultOrder: Int {\n        return Swift.max(16383 / MemoryLayout<Element>.stride, 31)\n    }\n\n    init(order: Int, elements: [Element], children: [Node], count: Int) {\n        precondition(elements.count <= order)\n        precondition(children.count == 0 || children.count == elements.count + 1)\n        self._parent = nil\n        self.elements = elements\n        self.children = children\n        self.count = count\n        self.order = order\n        self.depth = (children.count == 0 ? 0 : children[0].depth + 1)\n        elements.forEach { $0.parent = self }\n        children.forEach { $0.parent = self }\n    }\n\n    convenience init(order: Int = RefListNode.defaultOrder) {\n        self.init(order: order, elements: [], children: [], count: 0)\n    }\n\n    convenience init(left: Node, separator: Element, right: Node) {\n        precondition(left.order == right.order && left.depth == right.depth)\n        self.init(order: left.order, elements: [separator], children: [left, right], count: left.count + 1 + right.count)\n    }\n\n    convenience init(node: Node, slotRange: CountableRange<Int>) {\n        if node.isLeaf {\n            let elements = Array(node.elements[slotRange])\n            self.init(order: node.order, elements: elements, children: [], count: elements.count)\n        }\n        else if slotRange.count == 0 {\n            let n = node.children[slotRange.lowerBound]\n            self.init(order: n.order, elements: n.elements, children: n.children, count: n.count)\n        }\n        else {\n            let elements = Array(node.elements[slotRange])\n            let children = Array(node.children[slotRange.lowerBound ... slotRange.upperBound])\n            let count = children.reduce(elements.count) { $0 + $1.count }\n            self.init(order: node.order, elements: elements, children: children, count: count)\n        }\n    }\n\n    var parent: RefListNode? {\n        get {\n            return _parent?.value\n        }\n        set {\n            if let p = newValue {\n                _parent = UnownedReference(p)\n            }\n            else {\n                _parent = nil\n            }\n        }\n    }\n\n    var maxChildren: Int { return order }\n    var minChildren: Int { return (maxChildren + 1) / 2 }\n    var maxElements: Int { return maxChildren - 1 }\n    var minElements: Int { return minChildren - 1 }\n\n    var isLeaf: Bool { return depth == 0 }\n    var isTooSmall: Bool { return elements.count < minElements }\n    var isTooLarge: Bool { return elements.count > maxElements }\n    var isBalanced: Bool { return elements.count >= minElements && elements.count <= maxElements }\n}\n\nextension RefListNode {\n    func edit(descend: (Node) -> Int?, ascend: (Node, Int) -> Void) {\n        guard let slot = descend(self) else { return }\n        let child = children[slot]\n        child.edit(descend: descend, ascend: ascend)\n        ascend(self, slot)\n    }\n\n    func setElement(inSlot slot: Int, to element: Element) -> Element {\n        let old = elements[slot]\n        elements[slot] = element\n        element.parent = self\n        old.parent = nil\n        return old\n    }\n\n    func insert(_ element: Element, inSlot slot: Int) {\n        elements.insert(element, at: slot)\n        count += 1\n        element.parent = self\n    }\n\n    func offset(of element: Element) -> Int {\n        if isLeaf {\n            return elements.index { $0 === element }!\n        }\n        var offset = 0\n        var found = false\n        for i in 0 ..< elements.count {\n            offset += children[i].count\n            if elements[i] === element { found = true; break }\n            offset += 1\n        }\n        precondition(found)\n        return offset\n    }\n\n    func offset(of child: Node) -> Int {\n        var offset = 0\n        var found = false\n        for c in children {\n            if c === child { found = true; break }\n            offset += 1 + c.count\n        }\n        precondition(found)\n        return offset\n    }\n\n    /// Return the slot of the element at `offset` in the subtree rooted at this node.\n    func slot(atOffset offset: Int) -> (index: Int, match: Bool, offset: Int) {\n        assert(offset >= 0 && offset <= count)\n        if offset == count {\n            return (index: elements.count, match: isLeaf, offset: count)\n        }\n        if isLeaf {\n            return (offset, true, offset)\n        }\n        else if offset <= count / 2 {\n            var p = 0\n            for i in 0 ..< children.count - 1 {\n                let c = children[i].count\n                if offset == p + c {\n                    return (index: i, match: true, offset: p + c)\n                }\n                if offset < p + c {\n                    return (index: i, match: false, offset: p + c)\n                }\n                p += c + 1\n            }\n            let c = children.last!.count\n            precondition(count == p + c, \"Invalid B-Tree\")\n            return (index: children.count - 1, match: false, offset: count)\n        }\n        var p = count\n        for i in (1 ..< children.count).reversed() {\n            let c = children[i].count\n            if offset == p - (c + 1) {\n                return (index: i - 1, match: true, offset: offset)\n            }\n            if offset > p - (c + 1) {\n                return (index: i, match: false, offset: p)\n            }\n            p -= c + 1\n        }\n        let c = children.first!.count\n        precondition(p - c == 0, \"Invalid B-Tree\")\n        return (index: 0, match: false, offset: c)\n    }\n\n    /// Split this node into two, removing the high half of the nodes and putting them in a splinter.\n    ///\n    /// - Returns: A splinter consisting of a separator and a node containing the higher half of the original node.\n    func split() -> (separator: Element, node: Node) {\n        assert(isTooLarge)\n        return split(at: elements.count / 2)\n    }\n\n    /// Split this node into two at the key at index `median`, removing all elements at or above `median`\n    /// and putting them in a splinter.\n    ///\n    /// - Returns: A splinter consisting of a separator and a node containing the higher half of the original node.\n    func split(at median: Int) -> (separator: Element, node: Node) {\n        let count = elements.count\n        let separator = elements[median]\n        let splinter = Node(node: self, slotRange: median + 1 ..< count)\n        elements.removeSubrange(median ..< count)\n        if isLeaf {\n            self.count = median\n        }\n        else {\n            children.removeSubrange(median + 1 ..< count + 1)\n            self.count = median + children.reduce(0) { $0 + $1.count }\n        }\n        separator.parent = nil\n        return (separator, splinter)\n    }\n\n    /// Reorganize the tree rooted at `self` so that the undersize child in `slot` is corrected.\n    /// As a side effect of the process, `self` may itself become undersized, but all of its descendants\n    /// become balanced.\n    func fixDeficiency(_ slot: Int) {\n        assert(!isLeaf && children[slot].isTooSmall)\n        if slot > 0 && children[slot - 1].elements.count > minElements {\n            rotateRight(slot)\n        }\n        else if slot < children.count - 1 && children[slot + 1].elements.count > minElements {\n            rotateLeft(slot)\n        }\n        else if slot > 0 {\n            // Collapse deficient slot into previous slot.\n            collapse(slot - 1)\n        }\n        else {\n            // Collapse next slot into deficient slot.\n            collapse(slot)\n        }\n    }\n\n    func rotateRight(_ slot: Int) {\n        assert(slot > 0)\n\n        let previous = children[slot - 1]\n        let child = children[slot]\n\n        let e = elements[slot - 1]\n        child.elements.insert(e, at: 0)\n        e.parent = child\n\n        if !child.isLeaf {\n            let lastGrandChildBeforeSlot = previous.children.removeLast()\n            lastGrandChildBeforeSlot.parent = child\n            child.children.insert(lastGrandChildBeforeSlot, at: 0)\n\n            previous.count -= lastGrandChildBeforeSlot.count\n            child.count += lastGrandChildBeforeSlot.count\n        }\n        let element = previous.elements.removeLast()\n        element.parent = self\n        elements[slot - 1] = element\n        previous.count -= 1\n        child.count += 1\n    }\n\n    func rotateLeft(_ slot: Int) {\n        assert(slot < children.count - 1)\n        let child = children[slot]\n        let next = children[slot + 1]\n\n        let e = elements[slot]\n        e.parent = child\n        child.elements.append(e)\n        if !child.isLeaf {\n            let firstGrandChildAfterSlot = next.children.remove(at: 0)\n            firstGrandChildAfterSlot.parent = child\n            child.children.append(firstGrandChildAfterSlot)\n\n            next.count -= firstGrandChildAfterSlot.count\n            child.count += firstGrandChildAfterSlot.count\n        }\n        let element = next.elements.remove(at: 0)\n        element.parent = self\n        elements[slot] = element\n        child.count += 1\n        next.count -= 1\n    }\n\n    func collapse(_ slot: Int) {\n        assert(slot < children.count - 1)\n        let target = children[slot]\n\n        let collapsed = children.remove(at: slot + 1)\n        collapsed.parent = nil\n\n        let e = elements.remove(at: slot)\n        e.parent = target\n        target.elements.append(e)\n        target.count += 1\n\n        collapsed.elements.forEach { $0.parent = target }\n        target.elements.append(contentsOf: collapsed.elements)\n        target.count += collapsed.count\n        if !collapsed.isLeaf {\n            collapsed.children.forEach { $0.parent = target }\n            target.children.append(contentsOf: collapsed.children)\n        }\n        assert(target.isBalanced)\n    }\n}\n\nextension RefListNode {\n    func forEach(_ body: (Element) throws -> ()) rethrows {\n        if isLeaf {\n            try elements.forEach(body)\n        }\n        else {\n            for i in 0 ..< elements.count {\n                try children[i].forEach(body)\n                try body(elements[i])\n            }\n            try children[elements.count].forEach(body)\n        }\n    }\n\n    func forEach(_ range: Range<Int>, _ body: (Element) throws -> ()) rethrows {\n        if isLeaf {\n            for element in elements[range] {\n                try body(element)\n            }\n            return\n        }\n        var c = range.count\n        let slot = self.slot(atOffset: range.lowerBound)\n        guard range.count > 0 else { return }\n        if !slot.match {\n            let child = children[slot.index]\n            let childCount = child.count\n            let childStartOffset = slot.offset - childCount\n            let childRange: Range<Int> = range.lowerBound - childStartOffset ..< min(childCount, range.upperBound - childStartOffset)\n            try child.forEach(childRange, body)\n            c -= childRange.count\n        }\n        var index = slot.index\n        while c > 0 {\n            try body(elements[index])\n            c -= 1\n            guard c > 0 else { break }\n            index += 1\n            let child = children[index]\n            if c >= child.count {\n                try child.forEach(body)\n                c -= child.count\n            }\n            else {\n                try child.forEach(0 ..< c, body)\n                c = 0\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/Reference.swift",
    "content": "//\n//  Reference.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-13.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\ninternal struct UnownedReference<Target: AnyObject> {\n    unowned var value: Target\n\n    init(_ value: Target) {\n        self.value = value\n    }\n}\n\n\n"
  },
  {
    "path": "Sources/SetChange.swift",
    "content": "//\n//  SetChange.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-12.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic struct SetChange<Element: Hashable>: ChangeType {\n    public typealias Value = Set<Element>\n\n    public private(set) var removed: Set<Element>\n    public private(set) var inserted: Set<Element>\n\n    public init(removed: Set<Element> = [], inserted: Set<Element> = []) {\n        self.inserted = inserted\n        self.removed = removed\n    }\n\n    public init(from oldValue: Value, to newValue: Value) {\n        self.removed = oldValue.subtracting(newValue)\n        self.inserted = newValue.subtracting(oldValue)\n    }\n\n    public var isEmpty: Bool {\n        return inserted.isEmpty && removed.isEmpty\n    }\n\n    public func apply(on value: inout Set<Element>) {\n        value.subtract(removed)\n        value = inserted.union(value)\n    }\n\n    public func apply(on value: Value) -> Value {\n        return inserted.union(value.subtracting(removed))\n    }\n\n    public mutating func remove(_ element: Element) {\n        self.inserted.remove(element)\n        self.removed.update(with: element)\n    }\n\n    public mutating func insert(_ element: Element) {\n        self.inserted.update(with: element)\n    }\n\n    public mutating func merge(with next: SetChange) {\n        removed = next.removed.union(removed)\n        inserted = next.inserted.union(inserted.subtracting(next.removed))\n    }\n\n    public func merged(with next: SetChange) -> SetChange {\n        return SetChange(removed: next.removed.union(removed),\n                         inserted: next.inserted.union(inserted.subtracting(next.removed)))\n    }\n\n    public func reversed() -> SetChange {\n        return SetChange(removed: inserted, inserted: removed)\n    }\n\n    public func removingEqualChanges() -> SetChange {\n        let intersection = removed.intersection(inserted)\n        if intersection.isEmpty {\n            return self\n        }\n        return SetChange(removed: removed.subtracting(intersection), inserted: inserted.subtracting(intersection))\n    }\n}\n\nextension Set {\n    public mutating func apply(_ change: SetChange<Element>) {\n        self.subtract(change.removed)\n        for e in change.inserted {\n            self.update(with: e)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetFilteringOnObservableBool.swift",
    "content": "//\n//  SetFilteringOnObservableBool.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport SipHash\n\nextension ObservableSetType {\n    public func filter<Field: ObservableValueType>(_ isIncluded: @escaping (Element) -> Field) -> AnyObservableSet<Element> where Field.Value == Bool {\n        return SetFilteringOnObservableBool<Self, Field>(parent: self, isIncluded: isIncluded).anyObservableSet\n    }\n}\n\nprivate class SetFilteringOnObservableBool<Parent: ObservableSetType, Field: ObservableValueType>: _BaseObservableSet<Parent.Element>\nwhere Field.Value == Bool {\n    typealias Element = Parent.Element\n    typealias Change = SetChange<Element>\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = SetFilteringOnObservableBool\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private struct FieldSink: SinkType, SipHashable {\n        typealias Owner = SetFilteringOnObservableBool\n        \n        unowned(unsafe) let owner: Owner\n        let element: Parent.Element\n        \n        func receive(_ update: ValueUpdate<Field.Value>) {\n            owner.applyFieldUpdate(update, from: element)\n        }\n        \n        func appendHashes(to hasher: inout SipHasher) {\n            hasher.append(ObjectIdentifier(owner))\n            hasher.append(element)\n        }\n        \n        static func ==(left: FieldSink, right: FieldSink) -> Bool {\n            return left.owner === right.owner && left.element == right.element\n        }\n    }\n    \n    private let parent: Parent\n    private let isIncluded: (Element) -> Field\n\n    private var matchingElements: Set<Element> = []\n    private var fieldSinks: Dictionary<FieldSink, Field> = [:]\n\n    init(parent: Parent, isIncluded: @escaping (Element) -> Field) {\n        self.parent = parent\n        self.isIncluded = isIncluded\n    }\n\n    override var isBuffered: Bool { return false }\n\n    override var count: Int {\n        if isConnected { return matchingElements.count }\n        var count = 0\n        for element in parent.value {\n            if isIncluded(element).value {\n                count += 1\n            }\n        }\n        return count\n    }\n\n    override var value: Set<Element> {\n        if isConnected { return matchingElements }\n        return Set(self.parent.value.filter { isIncluded($0).value })\n    }\n\n    override func contains(_ member: Element) -> Bool {\n        if isConnected { return matchingElements.contains(member) }\n        return self.parent.contains(member) && isIncluded(member).value\n    }\n\n    override func isSubset(of other: Set<Element>) -> Bool {\n        if isConnected { return matchingElements.isSubset(of: other) }\n        for member in self.parent.value {\n            guard isIncluded(member).value else { continue }\n            guard other.contains(member) else { return false }\n        }\n        return true\n    }\n\n    override func isSuperset(of other: Set<Element>) -> Bool {\n        if isConnected { return matchingElements.isSuperset(of: other) }\n        for member in other {\n            guard isIncluded(member).value && parent.contains(member) else { return false }\n        }\n        return true\n    }\n\n    override func activate() {\n        for e in parent.value {\n            let test = self.isIncluded(e)\n            if test.value {\n                matchingElements.insert(e)\n            }\n            let sink = FieldSink(owner: self, element: e)\n            test.add(sink)\n            fieldSinks[sink] = test\n        }\n        parent.add(ParentSink(owner: self))\n    }\n\n    override func deactivate() {\n        parent.remove(ParentSink(owner: self))\n        for (sink, test) in fieldSinks {\n            test.remove(sink)\n        }\n        fieldSinks = [:]\n        matchingElements = []\n    }\n\n    func applyParentUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var c = SetChange<Element>()\n            for e in change.removed {\n                let sink = FieldSink(owner: self, element: e)\n                let test = fieldSinks.removeValue(forKey: sink)!\n                test.remove(sink)\n                if let old = self.matchingElements.remove(e) {\n                    c.remove(old)\n                }\n            }\n            for e in change.inserted {\n                let test = self.isIncluded(e)\n                let sink = FieldSink(owner: self, element: e)\n                test.add(sink)\n                let old = fieldSinks.updateValue(test, forKey: sink)\n                precondition(old == nil)\n                if test.value {\n                    matchingElements.insert(e)\n                    c.insert(e)\n                }\n            }\n            if !c.isEmpty {\n                sendChange(c)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: ValueUpdate<Bool>, from element: Parent.Element) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if !change.old && change.new {\n                matchingElements.insert(element)\n                sendChange(SetChange(inserted: [element]))\n            }\n            else if change.old && !change.new {\n                matchingElements.remove(element)\n                sendChange(SetChange(removed: [element]))\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetFilteringOnPredicate.swift",
    "content": "//\n//  SetFilteringOnPredicate.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-12.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    public func filter(_ isIncluded: @escaping (Element) -> Bool) -> AnyObservableSet<Element> {\n        return SetFilteringOnPredicate<Self>(parent: self, test: isIncluded).anyObservableSet\n    }\n\n    public func filter<Predicate: ObservableValueType>(_ isIncluded: Predicate) -> AnyObservableSet<Element>\n    where Predicate.Value == (Element) -> Bool {\n        return self.filter(isIncluded.map { predicate -> Optional<(Element) -> Bool> in predicate })\n    }\n\n    public func filter<Predicate: ObservableValueType>(_ isIncluded: Predicate) -> AnyObservableSet<Element>\n    where Predicate.Value == Optional<(Element) -> Bool> {\n        let reference: AnyObservableValue<AnyObservableSet<Element>> = isIncluded.map { predicate in\n            if let predicate: (Element) -> Bool = predicate {\n                return self.filter(predicate).anyObservableSet\n            }\n            else {\n                return self.anyObservableSet\n            }\n        }\n        return reference.unpacked()\n    }\n}\n\nprivate final class SetFilteringOnPredicate<Parent: ObservableSetType>: _BaseObservableSet<Parent.Element> {\n    public typealias Element = Parent.Element\n    public typealias Change = SetChange<Element>\n\n    private struct FilteringSink: UniqueOwnedSink {\n        typealias Owner = SetFilteringOnPredicate\n        \n        unowned let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private let parent: Parent\n    private let test: (Element) -> Bool\n\n    private var matchingElements: Set<Element> = []\n\n    init(parent: Parent, test: @escaping (Element) -> Bool) {\n        self.parent = parent\n        self.test = test\n    }\n\n    override var isBuffered: Bool {\n        return false\n    }\n    override var count: Int {\n        if isConnected { return matchingElements.count }\n        return parent.value.reduce(0) { test($1) ? $0 + 1 : $0 }\n    }\n    override var value: Set<Element> {\n        if isConnected { return matchingElements }\n        return Set(self.parent.value.filter(test))\n    }\n    override func contains(_ member: Element) -> Bool {\n        if isConnected { return matchingElements.contains(member) }\n        return self.parent.contains(member) && test(member)\n    }\n    override func isSubset(of other: Set<Element>) -> Bool {\n        if isConnected { return matchingElements.isSubset(of: other) }\n        for member in self.parent.value {\n            guard test(member) else { continue }\n            guard other.contains(member) else { return false }\n        }\n        return true\n    }\n    override func isSuperset(of other: Set<Element>) -> Bool {\n        if isConnected { return matchingElements.isSuperset(of: other) }\n        for member in other {\n            guard test(member) && parent.contains(member) else { return false }\n        }\n        return true\n    }\n\n    override func activate() {\n        for e in parent.value {\n            if test(e) {\n                matchingElements.insert(e)\n            }\n        }\n        parent.add(FilteringSink(owner: self))\n    }\n\n    override func deactivate() {\n        parent.remove(FilteringSink(owner: self))\n        matchingElements = []\n    }\n\n    func applyParentUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var c = SetChange<Element>()\n            for e in change.removed {\n                if let old = matchingElements.remove(e) {\n                    c.remove(old)\n                }\n            }\n            for e in change.inserted {\n                if self.test(e) {\n                    matchingElements.insert(e)\n                    c.insert(e)\n                }\n            }\n            if !c.isEmpty {\n                sendChange(c)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetFolding.swift",
    "content": "//\n//  SetFolding.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    /// Returns an observable whose value is always equal to `self.value.reduce(initial, add)`.\n    ///\n    /// - Parameter initial: The accumulation starts with this initial value.\n    /// - Parameter add: A closure that adds an element of the set into an accumulated value.\n    /// - Parameter remove: A closure that cancels the effect of an earlier `add`.\n    /// - Returns: An observable value for the reduction of this set.\n    ///\n    /// - Note: Elements are added and removed in no particular order.\n    ///    (I.e., the underlying binary operation over `Result` must form an abelian group.)\n    ///\n    /// - SeeAlso: `sum()` which returns a reduction using addition.\n    public func reduce<Result>(_ initial: Result, add: @escaping (Result, Element) -> Result, remove: @escaping (Result, Element) -> Result) -> AnyObservableValue<Result> {\n        return SetFoldingByTwoWayFunction<Self, Result>(parent: self, initial: initial, add: add, remove: remove).anyObservableValue\n    }\n}\n\nextension ObservableSetType where Element: BinaryInteger {\n    /// Return the (observable) sum of the elements contained in this set.\n    public func sum() -> AnyObservableValue<Element> {\n        return reduce(0, add: +, remove: -)\n    }\n}\n\nprivate class SetFoldingByTwoWayFunction<Parent: ObservableSetType, Value>: _BaseObservableValue<Value> {\n    private struct FoldingSink: UniqueOwnedSink {\n        typealias Owner = SetFoldingByTwoWayFunction\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyUpdate(update)\n        }\n    }\n    \n    let parent: Parent\n    let add: (Value, Parent.Element) -> Value\n    let remove: (Value, Parent.Element) -> Value\n\n    private var _value: Value\n\n    init(parent: Parent, initial: Value, add: @escaping (Value, Parent.Element) -> Value, remove: @escaping (Value, Parent.Element) -> Value) {\n        self.parent = parent\n        self.add = add\n        self.remove = remove\n\n        self._value = parent.value.reduce(initial, add)\n\n        super.init()\n\n        parent.add(FoldingSink(owner: self))\n    }\n\n    deinit {\n        parent.remove(FoldingSink(owner: self))\n    }\n\n    override var value: Value {\n        return _value\n    }\n\n    func applyUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let old = _value\n            for old in change.removed { _value = remove(_value, old) }\n            for new in change.inserted { _value = add(_value, new) }\n            sendChange(ValueChange(from: old, to: _value))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetGatheringSource.swift",
    "content": "//\n//  SetGatheringSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2017-09-05.\n//  Copyright © 2017 Károly Lőrentey. All rights reserved.\n//\n\nextension ObservableSetType where Element: SourceType {\n    public func gather() -> AnySource<Element.Value> {\n        return SetGatheringSource(self).anySource\n    }\n}\n\nprivate class SetGatheringSource<Origin: ObservableSetType, Value>: _AbstractSource<Value>\nwhere Origin.Element: SourceType, Origin.Element.Value == Value {\n    let origin: Origin\n    var sinks: Set<AnySink<Value>> = []\n\n    private struct GatherSink: UniqueOwnedSink {\n        typealias Owner = SetGatheringSource\n        unowned let owner: Owner\n\n        func receive(_ value: SetUpdate<Origin.Element>) {\n            guard case let .change(change) = value else { return }\n            change.removed.forEach { source in\n                for sink in owner.sinks {\n                    source.remove(sink)\n                }\n            }\n            change.inserted.forEach { source in\n                for sink in owner.sinks {\n                    source.add(sink)\n                }\n            }\n        }\n    }\n\n    init(_ origin: Origin) {\n        self.origin = origin\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        if sinks.isEmpty {\n            origin.add(GatherSink(owner: self))\n        }\n        let new = sinks.insert(sink.anySink).inserted\n        precondition(new)\n        for source in origin.value {\n            source.add(sink)\n        }\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        let result = sinks.remove(sink.anySink)!\n        for source in origin.value {\n            source.remove(result)\n        }\n        if sinks.isEmpty {\n            origin.remove(GatherSink(owner: self))\n        }\n        return result.opened()!\n    }\n}\n\n"
  },
  {
    "path": "Sources/SetMappingBase.swift",
    "content": "//\n//  SetMappingBase.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-05.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// An observable set where the value is internally represented as a dictionary of element multiplicities.\n/// This class implements the full `ObservableSetType` protocol, and serves as the base class for several transformations\n/// on observable sets.\nclass SetMappingBase<Element: Hashable>: _BaseObservableSet<Element> {\n    typealias Change = SetChange<Element>\n\n    private(set) var contents: [Element: Int] = [:]\n\n    /// Insert `newMember` into `state`, and return true iff it did not previously contain it.\n    final func insert(_ newMember: Element) -> Bool {\n        if let count = contents[newMember] {\n            contents[newMember] = count + 1\n            return false\n        }\n        contents[newMember] = 1\n        return true\n    }\n\n    /// Remove a single instance of `newMember` from `state`, and return true iff this was the last instance.\n    /// - Requires: `self.contains(member)`.\n    final func remove(_ member: Element) -> Bool {\n        guard let count = contents[member] else {\n            fatalError(\"Inconsistent change: \\(member) to be removed is not in result set\")\n        }\n        if count > 1 {\n            contents[member] = count - 1\n            return false\n        }\n        contents.removeValue(forKey: member)\n        return true\n    }\n\n    final override var isBuffered: Bool { return false }\n    final override var count: Int { return contents.count }\n    final override var value: Set<Element> { return Set(contents.keys) }\n    final override func contains(_ member: Element) -> Bool { return contents[member] != nil }\n    \n    final override func isSubset(of other: Set<Element>) -> Bool {\n        guard other.count >= contents.count else { return false }\n        for (key, _) in contents {\n            guard other.contains(key) else { return false }\n        }\n        return true\n    }\n\n    final override func isSuperset(of other: Set<Element>) -> Bool {\n        guard other.count <= contents.count else { return false }\n        for element in other {\n            guard contents[element] != nil else { return false }\n        }\n        return true\n    }\n}\n"
  },
  {
    "path": "Sources/SetMappingForArrayField.swift",
    "content": "//\n//  SetMappingForArrayField.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    public func flatMap<Field: ObservableArrayType>(_ key: @escaping (Element) -> Field) -> AnyObservableSet<Field.Element> where Field.Element: Hashable {\n        return SetMappingForArrayField<Self, Field>(parent: self, key: key).anyObservableSet\n    }\n}\n\nclass SetMappingForArrayField<Parent: ObservableSetType, Field: ObservableArrayType>: SetMappingBase<Field.Element>\nwhere Field.Element: Hashable {\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = SetMappingForArrayField\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private struct FieldSink: UniqueOwnedSink {\n        typealias Owner = SetMappingForArrayField\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ArrayUpdate<Field.Element>) {\n            owner.applyFieldUpdate(update)\n        }\n    }\n    \n    let parent: Parent\n    let key: (Parent.Element) -> Field\n\n    init(parent: Parent, key: @escaping (Parent.Element) -> Field) {\n        self.parent = parent\n        self.key = key\n        super.init()\n        parent.add(ParentSink(owner: self))\n\n        for e in parent.value {\n            let field = key(e)\n            field.add(FieldSink(owner: self))\n            for new in field.value {\n                _ = self.insert(new)\n            }\n        }\n    }\n\n    deinit {\n        parent.remove(ParentSink(owner: self))\n        for e in parent.value {\n            let field = key(e)\n            field.remove(FieldSink(owner: self))\n        }\n    }\n\n    func applyParentUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var transformedChange = SetChange<Element>()\n            for e in change.removed {\n                let field = key(e)\n                field.remove(FieldSink(owner: self))\n                for r in field.value {\n                    if self.remove(r) {\n                        transformedChange.remove(r)\n                    }\n                }\n            }\n            for e in change.inserted {\n                let field = key(e)\n                field.add(FieldSink(owner: self))\n                for i in field.value {\n                    if self.insert(i) {\n                        transformedChange.insert(i)\n                    }\n                }\n            }\n            if !transformedChange.isEmpty {\n                sendChange(transformedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: ArrayUpdate<Field.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var transformedChange = SetChange<Element>()\n            change.forEachOld { old in\n                if self.remove(old) {\n                    transformedChange.remove(old)\n                }\n            }\n            change.forEachNew { new in\n                if self.insert(new) {\n                    transformedChange.insert(new)\n                }\n            }\n            transformedChange = transformedChange.removingEqualChanges()\n            if !transformedChange.isEmpty {\n                sendChange(transformedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetMappingForSequence.swift",
    "content": "//\n//  SetMappingForSequence.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    public func flatMap<Result: Sequence>(_ key: @escaping (Element) -> Result) -> AnyObservableSet<Result.Iterator.Element> where Result.Iterator.Element: Hashable {\n        return SetMappingForSequence<Self, Result>(parent: self, key: key).anyObservableSet\n    }\n}\n\nclass SetMappingForSequence<Parent: ObservableSetType, Result: Sequence>: SetMappingBase<Result.Iterator.Element>\nwhere Result.Iterator.Element: Hashable {\n    typealias Element = Result.Iterator.Element\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = SetMappingForSequence\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.apply(update)\n        }\n    }\n    \n    let parent: Parent\n    let key: (Parent.Element) -> Result\n\n    init(parent: Parent, key: @escaping (Parent.Element) -> Result) {\n        self.parent = parent\n        self.key = key\n        super.init()\n        for e in parent.value {\n            for new in key(e) {\n                _ = self.insert(new)\n            }\n        }\n        parent.add(ParentSink(owner: self))\n    }\n\n    deinit {\n        parent.remove(ParentSink(owner: self))\n    }\n\n    func apply(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var transformedChange = SetChange<Element>()\n            for e in change.removed {\n                for old in key(e) {\n                    if self.remove(old) {\n                        transformedChange.remove(old)\n                    }\n                }\n            }\n            for e in change.inserted {\n                for new in key(e) {\n                    if self.insert(new) {\n                        transformedChange.insert(new)\n                    }\n                }\n            }\n            if !transformedChange.isEmpty {\n                sendChange(transformedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetMappingForSetField.swift",
    "content": "//\n//  SetMappingForSetField.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    public func flatMap<Field: ObservableSetType>(_ key: @escaping (Element) -> Field) -> AnyObservableSet<Field.Element> {\n        return SetMappingForSetField<Self, Field>(parent: self, key: key).anyObservableSet\n    }\n}\n\nclass SetMappingForSetField<Parent: ObservableSetType, Field: ObservableSetType>: SetMappingBase<Field.Element> {\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = SetMappingForSetField\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private struct FieldSink: UniqueOwnedSink {\n        typealias Owner = SetMappingForSetField\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Field.Element>) {\n            owner.applyFieldUpdate(update)\n        }\n    }\n    \n    let parent: Parent\n    let key: (Parent.Element) -> Field\n\n    init(parent: Parent, key: @escaping (Parent.Element) -> Field) {\n        self.parent = parent\n        self.key = key\n        super.init()\n        parent.add(ParentSink(owner: self))\n\n        for e in parent.value {\n            let field = key(e)\n            field.add(FieldSink(owner: self))\n            for new in field.value {\n                _ = self.insert(new)\n            }\n        }\n    }\n\n    deinit {\n        parent.remove(ParentSink(owner: self))\n        parent.value.forEach { e in\n            let field = key(e)\n            field.remove(FieldSink(owner: self))\n        }\n    }\n\n    func applyParentUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var transformedChange = SetChange<Element>()\n            for e in change.removed {\n                let field = key(e)\n                field.remove(FieldSink(owner: self))\n                for r in field.value {\n                    if self.remove(r) {\n                        transformedChange.remove(r)\n                    }\n                }\n            }\n            for e in change.inserted {\n                let field = key(e)\n                field.add(FieldSink(owner: self))\n                for i in field.value {\n                    if self.insert(i) {\n                        transformedChange.insert(i)\n                    }\n                }\n            }\n            if !transformedChange.isEmpty {\n                sendChange(transformedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: SetUpdate<Field.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var transformedChange = SetChange<Element>()\n            for old in change.removed {\n                if self.remove(old) {\n                    transformedChange.remove(old)\n                }\n            }\n            for new in change.inserted {\n                if self.insert(new) {\n                    transformedChange.insert(new)\n                }\n            }\n            if !transformedChange.isEmpty {\n                sendChange(transformedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetMappingForValue.swift",
    "content": "//\n//  SetMappingForValue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-05.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    /// Return an observable set that contains the results of injectively mapping the given closure over the elements of this set.\n    ///\n    /// - Parameter transform: A mapping closure. `transform` must be an injection; if it maps two nonequal elements into\n    ///     the same result, the transformation may trap or it may return invalid results.\n    ///\n    /// - SeeAlso: `map(_:)` for a slightly slower variant for use when the mapping is not injective.\n    public func injectiveMap<R: Hashable>(_ transform: @escaping (Element) -> R) -> AnyObservableSet<R> {\n        return InjectiveSetMappingForValue(parent: self, transform: transform).anyObservableSet\n    }\n}\n\nprivate final class InjectiveSetMappingForValue<Parent: ObservableSetType, Element: Hashable>: _BaseObservableSet<Element> {\n    typealias Change = SetChange<Element>\n\n    private struct InjectiveSink: UniqueOwnedSink {\n        typealias Owner = InjectiveSetMappingForValue\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.apply(update)\n        }\n    }\n    \n    let parent: Parent\n    let transform: (Parent.Element) -> Element\n\n    private var _value: Set<Element> = []\n\n    init(parent: Parent, transform: @escaping (Parent.Element) -> Element) {\n        self.parent = parent\n        self.transform = transform\n        super.init()\n\n        _value = Set(parent.value.map(transform))\n        parent.add(InjectiveSink(owner: self))\n    }\n\n    deinit {\n        parent.remove(InjectiveSink(owner: self))\n    }\n\n    func apply(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let mappedChange = SetChange(removed: Set(change.removed.lazy.map(transform)),\n                                         inserted: Set(change.inserted.lazy.map(transform)))\n            precondition(mappedChange.removed.count == change.removed.count, \"injectiveMap: transformation is not injective; use map() instead\")\n            precondition(mappedChange.inserted.count == change.inserted.count, \"injectiveMap: transformation is not injective; use map() instead\")\n            _value.apply(mappedChange)\n            if !mappedChange.isEmpty {\n                sendChange(mappedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool { return true }\n    override var count: Int { return parent.count }\n    override var value: Set<Element> { return _value }\n    override func contains(_ member: Element) -> Bool { return _value.contains(member) }\n    override func isSubset(of other: Set<Element>) -> Bool { return _value.isSubset(of: other) }\n    override func isSuperset(of other: Set<Element>) -> Bool { return _value.isSuperset(of: other) }\n}\n\nextension ObservableSetType {\n    /// Return an observable set that contains the results of mapping the given closure over the elements of this set.\n    ///\n    /// - Parameter transform: A mapping closure. `transform` does not need to be an injection; elements where\n    ///     `transform` returns the same result will be collapsed into a single entry in the result set.\n    ///\n    /// - SeeAlso: `injectivelyMap(_:)` for a slightly faster variant for when the mapping is injective.\n    public func map<R: Hashable>(_ transform: @escaping (Element) -> R) -> AnyObservableSet<R> {\n        return SetMappingForValue(parent: self, transform: transform).anyObservableSet\n    }\n}\n\nprivate final class SetMappingForValue<Parent: ObservableSetType, Element: Hashable>: SetMappingBase<Element> {\n    typealias Change = SetChange<Element>\n\n    private struct MapSink: UniqueOwnedSink {\n        typealias Owner = SetMappingForValue\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.apply(update)\n        }\n    }\n    \n    let parent: Parent\n    let transform: (Parent.Element) -> Element\n\n    private var connection: Connection? = nil\n\n    init(parent: Parent, transform: @escaping (Parent.Element) -> Element) {\n        self.parent = parent\n        self.transform = transform\n        super.init()\n        for element in parent.value {\n            _ = self.insert(transform(element))\n        }\n        parent.updates.add(MapSink(owner: self))\n    }\n\n    deinit {\n        parent.updates.remove(MapSink(owner: self))\n    }\n\n    func apply(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var mappedChange = SetChange<Element>()\n            for element in change.removed {\n                let transformed = transform(element)\n                if self.remove(transformed) {\n                    mappedChange.remove(transformed)\n                }\n            }\n            for element in change.inserted {\n                let transformed = transform(element)\n                if self.insert(transformed) {\n                    mappedChange.insert(transformed)\n                }\n            }\n            if !mappedChange.isEmpty {\n                sendChange(mappedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetMappingForValueField.swift",
    "content": "//\n//  SetMappingForValueField.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    /// Given an observable set and a closure that extracts an observable value from each element,\n    /// return an observable set that contains the extracted field values contained in this set.\n    ///\n    /// - Parameter key: A mapping closure, extracting an observable value from an element of this set.\n    public func map<Field: ObservableValueType>(_ key: @escaping (Element) -> Field) -> AnyObservableSet<Field.Value> where Field.Value: Hashable {\n        return SetMappingForValueField<Self, Field>(parent: self, key: key).anyObservableSet\n    }\n}\n\nclass SetMappingForValueField<Parent: ObservableSetType, Field: ObservableValueType>: SetMappingBase<Field.Value>\nwhere Field.Value: Hashable {\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = SetMappingForValueField\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private struct FieldSink: UniqueOwnedSink {\n        typealias Owner = SetMappingForValueField\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ValueUpdate<Field.Value>) {\n            owner.applyFieldUpdate(update)\n        }\n    }\n    \n    let parent: Parent\n    let key: (Parent.Element) -> Field\n\n    init(parent: Parent, key: @escaping (Parent.Element) -> Field) {\n        self.parent = parent\n        self.key = key\n        super.init()\n        parent.add(ParentSink(owner: self))\n\n        for e in parent.value {\n            let field = key(e)\n            field.add(FieldSink(owner: self))\n            _ = self.insert(field.value)\n        }\n    }\n\n    deinit {\n        parent.remove(ParentSink(owner: self))\n        for e in parent.value {\n            let field = key(e)\n            field.remove(FieldSink(owner: self))\n        }\n    }\n\n    func applyParentUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var transformedChange = SetChange<Element>()\n            for e in change.removed {\n                let field = key(e)\n                let value = field.value\n                field.remove(FieldSink(owner: self))\n                if self.remove(value) {\n                    transformedChange.remove(value)\n                }\n            }\n            for e in change.inserted {\n                let field = key(e)\n                let value = field.value\n                field.add(FieldSink(owner: self))\n                if self.insert(value) {\n                    transformedChange.insert(value)\n                }\n            }\n            if !transformedChange.isEmpty {\n                sendChange(transformedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: ValueUpdate<Field.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if change.old == change.new { return }\n            var transformedChange = SetChange<Element>()\n            if self.remove(change.old) {\n                transformedChange.remove(change.old)\n            }\n            if self.insert(change.new) {\n                transformedChange.insert(change.new)\n            }\n            if !transformedChange.isEmpty {\n                sendChange(transformedChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/SetReference.swift",
    "content": "//\n//  SetReference.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-17.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType where Value: ObservableSetType {\n    public func unpacked() -> AnyObservableSet<Value.Element> {\n        return UnpackedObservableSetReference(self).anyObservableSet\n    }\n}\n\n/// A mutable reference to an `AnyObservableSet` that's also an observable set.\n/// You can switch to another target set without having to re-register subscribers.\nprivate final class UnpackedObservableSetReference<Reference: ObservableValueType>: _BaseObservableSet<Reference.Value.Element>\nwhere Reference.Value: ObservableSetType {\n    typealias Target = Reference.Value\n    typealias Element = Target.Element\n    typealias Change = SetChange<Element>\n\n    private struct ReferenceSink: UniqueOwnedSink {\n        typealias Owner = UnpackedObservableSetReference\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: ValueUpdate<Reference.Value>) {\n            owner.applyReferenceUpdate(update)\n        }\n    }\n    \n    private struct TargetSink: UniqueOwnedSink {\n        typealias Owner = UnpackedObservableSetReference\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Reference.Value.Element>) {\n            owner.applyTargetUpdate(update)\n        }\n    }\n    \n    private var _reference: Reference\n    private var _target: Reference.Value? = nil // Retained to make sure we keep it alive\n\n    init(_ reference: Reference)  {\n        _reference = reference\n        super.init()\n    }\n\n    override func activate() {\n        _reference.add(ReferenceSink(owner: self))\n        let target = _reference.value\n        _target = target\n        target.add(TargetSink(owner: self))\n    }\n\n    override func deactivate() {\n        _target!.remove(TargetSink(owner: self))\n        _reference.remove(ReferenceSink(owner: self))\n    }\n\n    func applyReferenceUpdate(_ update: ValueUpdate<Target>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if isConnected {\n                _target!.remove(TargetSink(owner: self))\n                _target = change.new\n                _target!.add(TargetSink(owner: self))\n                sendChange(SetChange(from: change.old.value, to: change.new.value))\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyTargetUpdate(_ update: SetUpdate<Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool { return false }\n    override var count: Int { return _reference.value.count }\n    override var value: Set<Element> { return _reference.value.value }\n    override func contains(_ member: Element) -> Bool { return _reference.value.contains(member) }\n    override func isSubset(of other: Set<Element>) -> Bool { return _reference.value.isSubset(of: other) }\n    override func isSuperset(of other: Set<Element>) -> Bool { return _reference.value.isSuperset(of: other) }\n}\n"
  },
  {
    "path": "Sources/SetSortingByComparableField.swift",
    "content": "//\n//  SetSortingByMappingToObservableComparable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2017-05-01.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport SipHash\nimport BTree\n\nextension ObservableSetType where Element: AnyObject {\n    /// Given a transformation into an observable of a comparable type, return an observable array\n    /// containing transformed versions of elements in this set, in increasing order.\n    public func sorted<Field: ObservableValueType>(by transform: @escaping (Element) -> Field) -> AnyObservableArray<Element> where Field.Value: Comparable {\n        return SetSortingByComparableField(parent: self, transform: transform).anyObservableArray\n    }\n}\n\nprivate class SetSortingByComparableField<Parent: ObservableSetType, Field: ObservableValueType>: _BaseObservableArray<Parent.Element>\nwhere Parent.Element: AnyObject, Field.Value: Comparable {\n    typealias Element = Parent.Element\n    typealias Change = ArrayChange<Element>\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = SetSortingByComparableField\n\n        unowned(unsafe) let owner: Owner\n\n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n\n    private struct FieldSink: SinkType, SipHashable {\n        typealias Owner = SetSortingByComparableField\n\n        unowned(unsafe) let owner: Owner\n        let element: Parent.Element\n\n        func receive(_ update: ValueUpdate<Field.Value>) {\n            owner.applyFieldUpdate(update, from: element)\n        }\n\n        func appendHashes(to hasher: inout SipHasher) {\n            hasher.append(ObjectIdentifier(owner))\n            hasher.append(element)\n        }\n\n        static func ==(left: FieldSink, right: FieldSink) -> Bool {\n            return left.owner === right.owner && left.element == right.element\n        }\n    }\n    \n\n    private let parent: Parent\n    private let transform: (Parent.Element) -> Field\n\n    private var contents: BTree<Field.Value, Element> = .init()\n    private var fields: Dictionary<FieldSink, Field> = [:]\n\n    init(parent: Parent, transform: @escaping (Parent.Element) -> Field) {\n        self.parent = parent\n        self.transform = transform\n        super.init()\n\n        for element in parent.value {\n            let key = newElement(element)\n            _ = self.insert(key, element)\n        }\n        parent.add(ParentSink(owner: self))\n    }\n\n    deinit {\n        parent.remove(ParentSink(owner: self))\n        for (sink, field) in fields {\n            field.remove(sink)\n        }\n    }\n\n    private func newElement(_ element: Parent.Element) -> Field.Value {\n        let field = transform(element)\n        let sink = FieldSink(owner: self, element: element)\n        let old = fields.updateValue(field, forKey: sink)\n        field.add(sink)\n        precondition(old == nil)\n        return field.value\n    }\n\n    private func removeElement(_ element: Parent.Element) {\n        let sink = FieldSink(owner: self, element: element)\n        let field = fields.removeValue(forKey: sink)!\n        field.remove(sink)\n    }\n\n    private func insert(_ key: Field.Value, _ element: Element) -> ArrayModification<Element> {\n        return contents.withCursor(onKey: key, choosing: .after) { cursor in\n            let offset = cursor.offset\n            cursor.insert((key, element))\n            return .insert(element, at: offset)\n        }\n    }\n\n    private func remove(_ key: Field.Value, _ element: Element) -> ArrayModification<Element> {\n        return contents.withCursor(onKey: key, choosing: .first) { cursor in\n            while cursor.value !== element {\n                cursor.moveForward()\n                precondition(!cursor.isAtEnd, \"Inconsistent change: element removed is not in sorted set\")\n            }\n            let offset = cursor.offset\n            return .remove(element, at: offset)\n        }\n    }\n\n    func applyParentUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var arrayChange = ArrayChange<Element>(initialCount: contents.count)\n            for element in change.removed {\n                let key = transform(element).value\n                removeElement(element)\n                arrayChange.add(self.remove(key, element))\n            }\n            for element in change.inserted {\n                let key = newElement(element)\n                arrayChange.add(self.insert(key, element))\n            }\n            if !arrayChange.isEmpty {\n                sendChange(arrayChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: ValueUpdate<Field.Value>, from element: Parent.Element) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var arrayChange = ArrayChange<Element>(initialCount: self.contents.count)\n            if change.old == change.new { return }\n            arrayChange.add(remove(change.old, element))\n            arrayChange.add(insert(change.new, element))\n            if !arrayChange.isEmpty {\n                sendChange(arrayChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool { return false }\n    override subscript(index: Int) -> Element { return contents.element(atOffset: index).1 }\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> { return ArraySlice(contents.subtree(withOffsets: bounds).lazy.map { $0.1 }) }\n    override var value: Array<Element> { return Array(contents.lazy.map { $0.1 }) }\n    override var count: Int { return contents.count }\n}\n"
  },
  {
    "path": "Sources/SetSortingByComparator.swift",
    "content": "//\n//  SetSortingByComparator.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableSetType {\n    public func sorted(by areInIncreasingOrder: @escaping (Element, Element) -> Bool) -> AnyObservableArray<Element> {\n        let comparator = Comparator(areInIncreasingOrder)\n        return self\n            .sortedMap(by: { [unowned comparator] in ComparableWrapper($0, comparator) })\n            .map { [comparator] in _ = comparator; return $0.element }\n    }\n\n    public func sorted<Key: Comparable>(by key: @escaping (Element) -> Key) -> AnyObservableArray<Element> {\n        return self.sorted { a, b in key(a) < key(b) }\n    }\n\n    public func sorted<Comparator: ObservableValueType>(by comparator: Comparator) -> AnyObservableArray<Element>\n    where Comparator.Value == (Element, Element) -> Bool {\n        let reference: AnyObservableValue<AnyObservableArray<Element>> = comparator.map { comparator in\n            self.sorted(by: comparator).anyObservableArray\n        }\n        return reference.unpacked()\n    }\n\n    public func sorted<Key: Comparable, ObservableKey: ObservableValueType>(by key: ObservableKey) -> AnyObservableArray<Element>\n        where ObservableKey.Value == (Element) -> Key {\n            let reference: AnyObservableValue<AnyObservableArray<Element>> = key.map { key in\n                self.sorted(by: key).anyObservableArray\n            }\n            return reference.unpacked()\n    }\n\n}\n\nprivate final class Comparator<Element: Equatable> {\n    let comparator: (Element, Element) -> Bool\n\n    init(_ comparator: @escaping (Element, Element) -> Bool) {\n        self.comparator = comparator\n    }\n    func compare(_ a: Element, _ b: Element) -> Bool {\n        return comparator(a, b)\n    }\n}\n\nprivate struct ComparableWrapper<Element: Equatable>: Comparable {\n    unowned(unsafe) let comparator: Comparator<Element>\n    let element: Element\n\n    init(_ element: Element, _ comparator: Comparator<Element>) {\n        self.comparator = comparator\n        self.element = element\n    }\n    static func ==(a: ComparableWrapper<Element>, b: ComparableWrapper<Element>) -> Bool {\n        return !(a < b) && !(b < a)\n    }\n    static func <(a: ComparableWrapper<Element>, b: ComparableWrapper<Element>) -> Bool {\n        return a.comparator.compare(a.element, b.element)\n    }\n}\n"
  },
  {
    "path": "Sources/SetSortingByMappingToComparable.swift",
    "content": "//\n//  SetSortingByMappingToComparable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-15.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport BTree\n\nextension ObservableSetType {\n    /// Given a transformation into a comparable type, return an observable array containing transformed\n    /// versions of elements in this set, in increasing order.\n    public func sortedMap<Result: Comparable>(by transform: @escaping (Element) -> Result) -> AnyObservableArray<Result> {\n        return SetSortingByMappingToComparable(parent: self, transform: transform).anyObservableArray\n    }\n}\n\nextension ObservableSetType where Element: Comparable {\n    /// Return an observable array containing the members of this set, in increasing order.\n    public func sorted() -> AnyObservableArray<Element> {\n        return self.sortedMap { $0 }\n    }\n}\n\nprivate final class SetSortingByMappingToComparable<Parent: ObservableSetType, Element: Comparable>: _BaseObservableArray<Element> {\n    typealias Change = ArrayChange<Element>\n\n    private struct SortingSink: UniqueOwnedSink {\n        typealias Owner = SetSortingByMappingToComparable\n        \n        unowned(unsafe) let owner: Owner\n        \n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n    \n    private let parent: Parent\n    private let transform: (Parent.Element) -> Element\n\n    private var contents: Map<Element, Int> = [:]\n\n    init(parent: Parent, transform: @escaping (Parent.Element) -> Element) {\n        self.parent = parent\n        self.transform = transform\n        super.init()\n\n        for element in parent.value {\n            let transformed = transform(element)\n            contents[transformed] = (contents[transformed] ?? 0) + 1\n        }\n        parent.add(SortingSink(owner: self))\n    }\n\n    deinit {\n        parent.remove(SortingSink(owner: self))\n    }\n\n    func applyParentUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var arrayChange = ArrayChange<Element>(initialCount: contents.count)\n            for element in change.removed {\n                let transformed = transform(element)\n                guard let index = contents.index(forKey: transformed) else { fatalError(\"Removed element '\\(transformed)' not found in sorted set\") }\n                let count = contents[index].1\n                if count == 1 {\n                    let offset = contents.offset(of: index)\n                    let old = contents.remove(at: index)\n                    if isConnected {\n                        arrayChange.add(.remove(old.key, at: offset))\n                    }\n                }\n                else {\n                    contents[transformed] = count - 1\n                }\n            }\n            for element in change.inserted {\n                let transformed = transform(element)\n                if let count = contents[transformed] {\n                    precondition(count > 0)\n                    contents[transformed] = count + 1\n                }\n                else {\n                    contents[transformed] = 1\n                    if isConnected {\n                        let offset = contents.offset(of: transformed)!\n                        arrayChange.add(.insert(transformed, at: offset))\n                    }\n                }\n            }\n            if isConnected, !arrayChange.isEmpty {\n                sendChange(arrayChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool { return false }\n    override subscript(index: Int) -> Element { return contents.element(atOffset: index).0 }\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> { return ArraySlice(contents.submap(withOffsets: bounds).lazy.map { $0.0 }) }\n    override var value: Array<Element> { return Array(contents.lazy.map { $0.0 }) }\n    override var count: Int { return contents.count }\n}\n"
  },
  {
    "path": "Sources/SetSortingByMappingToObservableComparable.swift",
    "content": "//\n//  SetSortingByMappingToObservableComparable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport SipHash\nimport BTree\n\nextension ObservableSetType where Element: AnyObject {\n    /// Given a transformation into an observable of a comparable type, return an observable array\n    /// containing transformed versions of elements in this set, in increasing order.\n    public func sortedMap<Field: ObservableValueType>(by transform: @escaping (Element) -> Field) -> AnyObservableArray<Field.Value> where Field.Value: Comparable {\n        return SetSortingByMappingToObservableComparable(parent: self, transform: transform).anyObservableArray\n    }\n}\n\nprivate class SetSortingByMappingToObservableComparable<Parent: ObservableSetType, Field: ObservableValueType>: _BaseObservableArray<Field.Value>\nwhere Parent.Element: AnyObject, Field.Value: Comparable {\n    typealias Element = Field.Value\n    typealias Change = ArrayChange<Element>\n\n    private struct ParentSink: UniqueOwnedSink {\n        typealias Owner = SetSortingByMappingToObservableComparable\n\n        unowned(unsafe) let owner: Owner\n\n        func receive(_ update: SetUpdate<Parent.Element>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n\n    private struct FieldSink: SinkType, SipHashable {\n        typealias Owner = SetSortingByMappingToObservableComparable\n\n        unowned(unsafe) let owner: Owner\n        let element: Parent.Element\n\n        func receive(_ update: ValueUpdate<Field.Value>) {\n            owner.applyFieldUpdate(update, from: element)\n        }\n\n        func appendHashes(to hasher: inout SipHasher) {\n            hasher.append(ObjectIdentifier(owner))\n            hasher.append(element)\n        }\n\n        static func ==(left: FieldSink, right: FieldSink) -> Bool {\n            return left.owner === right.owner && left.element == right.element\n        }\n    }\n    \n\n    private let parent: Parent\n    private let transform: (Parent.Element) -> Field\n\n    private var contents: Map<Element, Int> = [:]\n    private var fields: Dictionary<FieldSink, Field> = [:]\n\n    init(parent: Parent, transform: @escaping (Parent.Element) -> Field) {\n        self.parent = parent\n        self.transform = transform\n        super.init()\n\n        for element in parent.value {\n            _ = self._insert(newElement(element))\n        }\n        parent.add(ParentSink(owner: self))\n    }\n\n    deinit {\n        parent.remove(ParentSink(owner: self))\n        for (sink, field) in fields {\n            field.remove(sink)\n        }\n    }\n\n    private func newElement(_ element: Parent.Element) -> Element {\n        let field = transform(element)\n        let sink = FieldSink(owner: self, element: element)\n        let old = fields.updateValue(field, forKey: sink)\n        field.add(sink)\n        precondition(old == nil)\n        return field.value\n    }\n\n    private func removeElement(_ element: Parent.Element) {\n        let sink = FieldSink(owner: self, element: element)\n        let field = fields.removeValue(forKey: sink)!\n        field.remove(sink)\n    }\n\n    private func _insert(_ key: Element) -> Bool {\n        if let count = contents[key] {\n            contents[key] = count + 1\n            return false\n        }\n        contents[key] = 1\n        return true\n    }\n\n    private func insert(_ key: Element) -> ArrayModification<Element>? {\n        return _insert(key) ? .insert(key, at: contents.offset(of: key)!) : nil\n    }\n\n    private func remove(_ key: Element) -> ArrayModification<Element>? {\n        guard let count = self.contents[key] else {\n            fatalError(\"Inconsistent change: element removed is not in sorted set\")\n        }\n        if count > 1 {\n            contents[key] = count - 1\n            return nil\n        }\n        let oldOffset = contents.offset(of: key)!\n        contents.removeValue(forKey: key)\n        return .remove(key, at: oldOffset)\n    }\n\n    func applyParentUpdate(_ update: SetUpdate<Parent.Element>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var arrayChange = ArrayChange<Element>(initialCount: contents.count)\n            for element in change.removed {\n                let key = transform(element).value\n                removeElement(element)\n                if let mod = self.remove(key) {\n                    arrayChange.add(mod)\n                }\n            }\n            for element in change.inserted {\n                let key = newElement(element)\n                if let mod = self.insert(key) {\n                    arrayChange.add(mod)\n                }\n            }\n            if !arrayChange.isEmpty {\n                sendChange(arrayChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: ValueUpdate<Element>, from element: Parent.Element) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            var arrayChange = ArrayChange<Element>(initialCount: self.contents.count)\n            if change.old == change.new { return }\n            if let mod = remove(change.old) {\n                arrayChange.add(mod)\n            }\n            if let mod = insert(change.new) {\n                arrayChange.add(mod)\n            }\n            if !arrayChange.isEmpty {\n                sendChange(arrayChange)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var isBuffered: Bool { return false }\n    override subscript(index: Int) -> Element { return contents.element(atOffset: index).0 }\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> { return ArraySlice(contents.submap(withOffsets: bounds).lazy.map { $0.0 }) }\n    override var value: Array<Element> { return Array(contents.lazy.map { $0.0 }) }\n    override var count: Int { return contents.count }\n}\n"
  },
  {
    "path": "Sources/SetVariable.swift",
    "content": "//\n//  SetVariable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-13.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nopen class SetVariable<Element: Hashable>: _BaseUpdatableSet<Element>, ExpressibleByArrayLiteral {\n    public typealias Value = Set<Element>\n    public typealias Change = SetChange<Element>\n\n    fileprivate var _value: Value\n\n    public override init() {\n        _value = []\n    }\n\n    public init(_ elements: [Element]) {\n        _value = Set(elements)\n    }\n\n    public init(_ elements: Set<Element>) {\n        _value = elements\n    }\n\n    public init<S: Sequence>(_ elements: S) where S.Iterator.Element == Element {\n        _value = Set(elements)\n    }\n\n    public init(elements: Element...) {\n        _value = Set(elements)\n    }\n\n    public required convenience init(arrayLiteral elements: Element...) {\n        self.init(elements)\n    }\n\n    final public override var isBuffered: Bool {\n        return true\n    }\n\n    public var isEmpty: Bool {\n        return _value.isEmpty\n    }\n\n    final public override var count: Int {\n        return _value.count\n    }\n\n    final public override var value: Value {\n        get {\n            return _value\n        }\n        set {\n            beginTransaction()\n            let v = _value\n            _value = newValue\n            sendChange(SetChange(removed: v, inserted: newValue))\n            endTransaction()\n        }\n    }\n\n    final public override func contains(_ member: Element) -> Bool {\n        return _value.contains(member)\n    }\n\n    final public override func isSubset(of other: Set<Element>) -> Bool {\n        return _value.isSubset(of: other)\n    }\n\n    final public override func isSuperset(of other: Set<Element>) -> Bool {\n        return _value.isSuperset(of: other)\n    }\n\n    override func rawApply(_ change: SetChange<Element>) {\n        _value.apply(change)\n    }\n\n    final public override func remove(_ member: Element) {\n        guard _value.contains(member) else { return }\n        if isConnected {\n            beginTransaction()\n            _value.remove(member)\n            sendChange(SetChange(removed: [member], inserted: []))\n            endTransaction()\n        }\n        else {\n            _value.remove(member)\n        }\n    }\n\n    final public override func insert(_ member: Element) {\n        guard !_value.contains(member) else { return }\n        if isConnected {\n            beginTransaction()\n            _value.insert(member)\n            sendChange(SetChange(removed: [], inserted: [member]))\n            endTransaction()\n        }\n        else {\n            _value.insert(member)\n        }\n    }\n\n    final public override func removeAll() {\n        guard !isEmpty else { return }\n        let value = self._value\n        if isConnected {\n            beginTransaction()\n            _value.removeAll()\n            sendChange(SetChange(removed: value, inserted: []))\n            endTransaction()\n        }\n        else {\n            _value.removeAll()\n        }\n    }\n\n\n    final public override func formUnion(_ other: Set<Element>) {\n        if isConnected {\n            beginTransaction()\n            let difference = other.subtracting(_value)\n            _value.formUnion(difference)\n            sendChange(SetChange(removed: [], inserted: difference))\n            endTransaction()\n        }\n        else {\n            _value.formUnion(other)\n        }\n    }\n\n    final public override func formIntersection(_ other: Set<Element>) {\n        if isConnected {\n            beginTransaction()\n            let difference = _value.subtracting(other)\n            _value.subtract(difference)\n            sendChange(SetChange(removed: difference, inserted: []))\n            endTransaction()\n        }\n        else {\n            _value.formIntersection(other)\n        }\n    }\n\n    final public override func formSymmetricDifference(_ other: Set<Element>) {\n        if isConnected {\n            beginTransaction()\n            let intersection = _value.intersection(other)\n            let additions = other.subtracting(self.value)\n            _value.formSymmetricDifference(other)\n            sendChange(SetChange(removed: intersection, inserted: additions))\n            endTransaction()\n        }\n        else {\n            _value.formSymmetricDifference(other)\n        }\n    }\n\n    final public override func subtract(_ other: Set<Element>) {\n        if isConnected {\n            beginTransaction()\n            let intersection = _value.intersection(other)\n            _value.subtract(other)\n            sendChange(SetChange(removed: intersection, inserted: []))\n            endTransaction()\n        }\n        else {\n            _value.subtract(other)\n        }\n    }\n}\n\nextension SetVariable {\n    public func update(with member: Element) -> Element? {\n        beginTransaction()\n        let old = _value.update(with: member)\n        if isConnected {\n            if let old = old {\n                sendChange(SetChange(removed: [old], inserted: [member]))\n            }\n            else {\n                sendChange(SetChange(removed: [], inserted: [member]))\n            }\n        }\n        endTransaction()\n        return old\n    }\n}\n"
  },
  {
    "path": "Sources/Signal.swift",
    "content": "//\n//  Signal.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\ninternal protocol SignalDelegate: class {\n    func activate()\n    func deactivate()\n}\n\nextension SignalDelegate {\n    func activate() {}\n    func deactivate() {}\n}\n\nprivate enum PendingItem<Value> {\n    case sendValue(Value)\n    case addSink(AnySink<Value>)\n}\n\n/// A Signal is both a source and a sink. Sending a value to a signal's sink forwards it to all sinks that are \n/// currently connected to the signal. The signal's sink is named \"send\", and it is available as a direct method.\n///\n/// The Five Rules of Signal:\n///\n/// 0. Signal only sends values to sinks that it receives via Signal.send(). All such values are forwarded to \n///    sinks connected at the time of the send (if any).\n/// 1. Sends are serialized. Signal defines a strict order between the values sent to it, forming a single \n///    sequence of values.\n/// 2. All sinks get the same values. Each sink receives a subsequence of the Signal's value sequence. No reordering,\n///    no skipping, no duplicates.\n/// 3. Connections are serialized with sends. Each sink's value subsequence starts with the first value that \n///    was (started to be) sent after it was connected (if any).\n/// 4. Disconnection is immediate. No new value is sent to a sink after its connection has finished disconnecting.\n///\n/// Some implementation notes:\n///\n/// The simplest nontrivial way to implement these rules is to make the Signal synchronous by serializing send() \n/// using a lock -- this is the way chosen by ReactiveCocoa and RxSwift. This makes reentrant send() calls deadlock, \n/// but that's probably a good thing. (You can emulate reentrant sends by scheduling an asyncronous send; however,\n/// that can visibly break value ordering.)\n///\n/// As an experiment, this particular Signal implementation allows send() to be called from any thread at any \n/// time---including reentrant send()s from a sink that is currently being executed by it. To ensure the rule set\n/// above, reentrant and concurrent sends and connects are asynchronous. They are ordered in a queue and performed \n/// at the end of the active send that first entered the signal. This implementation never invokes sinks recursively \n/// inside another sink invocation.\n///\n/// For reference, KVO's analogue to Signal in Foundation supports reentrancy, but its send() is synchronous. There \n/// is no way to satisfy the above rules in a system like that. KVO's designers chose to resolve this by always calling \n/// observers with the latest value of the observed key path. That's a nice pragmatic solution in the face of \n/// reentrancy, but it only makes sense when you have the concept of a current value, which Signal doesn't. \n/// (Although Variable does.)\n///\npublic class Signal<Value>: _AbstractSource<Value> {\n    internal weak var delegate: SignalDelegate?\n    private let lock = Lock()\n    private var sending = false\n    private var sinks: Set<AnySink<Value>> = []\n    private var pendingItems: [PendingItem<Value>] = []\n\n    public override init() {\n        self.delegate = nil\n        super.init()\n    }\n\n    internal init(delegate: SignalDelegate) {\n        self.delegate = delegate\n        super.init()\n    }\n\n    deinit {\n        precondition(sinks.count == 0 && pendingItems.count == 0)\n    }\n\n    /// Atomically return the pending value that needs to be sent next, or nil.\n    /// If there are no more values, exit the sending state.\n    private func _nextValueToSend(enterSending: Bool) -> Value? {\n        return lock.withLock {\n            if enterSending {\n                if self.sending { return nil }\n                self.sending = true\n            }\n            else {\n                assert(self.sending)\n            }\n            while case .some(let item) = self.pendingItems.first {\n                self.pendingItems.removeFirst()\n                switch item {\n                case .sendValue(let value):\n                    if !self.sinks.isEmpty { // Skip value if there are no sinks.\n                        // Send the next value to all ripe sinks.\n                        return value\n                    }\n                case .addSink(let sink):\n                    let (inserted, _) = self.sinks.insert(sink)\n                    precondition(inserted, \"Sink is already subscribed to this signal\")\n                }\n            }\n            // There are no more items to process.\n            self.sending = false\n            return nil\n        }\n    }\n\n    /// Synchronously send a value to all connected sinks.\n    private func _sendValueNow(_ value: Value) {\n        assert(lock.withLock { sending })\n\n        // Note that sinks are allowed to freely add or remove connections. \n        // This loop is constructed to support this correctly:\n        // - New sinks added while we are sending a value will not fire.\n        // - Sinks removed during the iteration will not fire.\n        for sink in lock.withLock({ self.sinks }) {\n            if lock.withLock({ self.sinks.contains(sink) }) {\n                sink.receive(value)\n            }\n        }\n    }\n\n    /// Send a value to all sinks currently connected to this Signal. The sinks are executed in undefined order.\n    ///\n    /// The sinks are normally executed synchronously. However, when two or more threads are sending values at the \n    /// same time, or when a connected sink sends a value back to this same signal, then only the send() arriving \n    /// first is synchronous; the rest are performed asynchronously on the thread of the first send(), before the \n    /// first send() returns.\n    ///\n    /// You may safely call this method from any thread, provided that the sinks are OK with running there.\n    public func send(_ value: Value) {\n        let path: Bool? = lock.withLock {\n            if sending {\n                self.pendingItems.append(.sendValue(value))\n                return nil // Value has been scheduled; somebody else will send it.\n            }\n            sending = true\n            if self.pendingItems.isEmpty {\n                return true\n            }\n            self.pendingItems.append(.sendValue(value))\n            return false\n        }\n        if let fast = path {\n            if fast {\n                // Fast track: We can send the value immediately.\n                _sendValueNow(value)\n            }\n            // Send remaining pending items in order.\n            while let v = _nextValueToSend(enterSending: false) {\n                _sendValueNow(v)\n            }\n        }\n    }\n\n    /// Append value to the queue of pending values. The value will be sent by a send() or sendNow() invocation.\n    /// (If sendNow() is already running (recursively up the call stack, or on another thread), then the value will be\n    /// sent by that invocation. If not, the first upcoming send will send the value.)\n    ///\n    /// Calls to sendLater() should always be followed by at least one call to sendNow().\n    ///\n    /// This construct is useful to control the ordering of notifications about changes to a value in the face of \n    /// concurrent modifications, without calling send() inside a lock. For example, here is a thread-safe, reentrant \n    /// counter that guarantees to send increasing counts, without holding a lock during sending:\n    ///\n    /// ```\n    /// public struct Counter {\n    ///     private let mutex = Mutex()\n    ///     private var count: Int = 0\n    ///     private let signal = Signal<Int>()\n    ///\n    ///     public var source: Source<Int> { return signal.source }\n    ///\n    ///     public mutating func increment() {\n    ///         let value: Int = mutex.withLock {\n    ///             let v = ++count\n    ///             signal.sendLater(v)\n    ///             return v\n    ///         }\n    ///         signal.sendNow()\n    ///         return value\n    ///     }\n    /// }\n    /// ```\n    internal func sendLater(_ value: Value) {\n        lock.withLock {\n            self.pendingItems.append(.sendValue(value))\n        }\n    }\n\n    /// Send all pending values immediately, or do nothing if the signal is already sending values elsewhere.\n    /// (On another thread, or if this is a recursive call of sendNow on the current thread.)\n    internal func sendNow() {\n        if let value = _nextValueToSend(enterSending: true) {\n            _sendValueNow(value)\n            while let value = _nextValueToSend(enterSending: false) {\n                _sendValueNow(value)\n            }\n        }\n    }\n\n    public override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        let sink = sink.anySink\n        let first: Bool = lock.withLock {\n            let first = self.sinks.isEmpty\n            if self.pendingItems.isEmpty {\n                let (inserted, _) = self.sinks.insert(sink)\n                precondition(inserted, \"Sink is already subscribed to this signal\")\n            }\n            else {\n                // Values that are currently pending should not be sent to this sink, but any future values should be.\n                self.pendingItems.append(.addSink(sink))\n            }\n            return first\n        }\n        if first {\n            delegate?.activate()\n        }\n    }\n\n    @discardableResult\n    public override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        let sink = sink.anySink\n        let (last, old): (Bool, AnySink<Value>) = lock.withLock {\n            var old = self.sinks.remove(sink)\n            if old == nil {\n                for i in 0 ..< pendingItems.count {\n                    if case .addSink(let s) = pendingItems[i], s == sink {\n                        old = s\n                        pendingItems.remove(at: i)\n                        break\n                    }\n                }\n            }\n            precondition(old != nil, \"Sink is not subscribed to this signal\")\n            return (self.sinks.isEmpty, old!)\n        }\n        if last {\n            delegate?.deactivate()\n        }\n        return old.opened()!\n    }\n\n    public var isConnected: Bool {\n        return lock.withLock { !self.sinks.isEmpty }\n    }\n}\n\nextension Signal {\n    public var asSink: AnySink<Value> { return SignalSink(self).anySink }\n}\n\nextension Signal where Value == Void {\n    public func send() {\n        self.send(())\n    }\n}\n\nprivate struct SignalSink<Value>: SinkType {\n    private let signal: Signal<Value>\n\n    init(_ signal: Signal<Value>) {\n        self.signal = signal\n    }\n\n    func receive(_ value: Value) {\n        signal.send(value)\n    }\n\n    var hashValue: Int {\n        return ObjectIdentifier(signal).hashValue\n    }\n\n    static func ==(left: SignalSink, right: SignalSink) -> Bool {\n        return left.signal === right.signal\n    }\n}\n"
  },
  {
    "path": "Sources/SimpleSources.swift",
    "content": "//\n//  SimpleSources.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension SourceType {\n    /// Returns a source that never fires.\n    public static func empty() -> AnySource<Value> {\n        return NeverSource<Value>().anySource\n    }\n\n    /// Returns a source that never fires.\n    public static func never() -> AnySource<Value> {\n        return NeverSource<Value>().anySource\n    }\n}\n\nclass NeverSource<Value>: _AbstractSource<Value> {\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        // Do nothing.\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        // Do nothing.\n        return sink\n    }\n}\n\nextension SourceType {\n    /// Returns a source that fires exactly once with the given value, then never again.\n    public static func just(_ value: Value) -> AnySource<Value> {\n        return JustSource(value).anySource\n    }\n}\n\nclass JustSource<Value>: _AbstractSource<Value> {\n    private var value: Value\n\n    init(_ value: Value) {\n        self.value = value\n        super.init()\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        sink.receive(value)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        return sink\n    }\n}\n"
  },
  {
    "path": "Sources/Sink.swift",
    "content": "//\n//  Sink.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-22.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic protocol SinkType: Hashable {\n    associatedtype Value\n    func receive(_ value: Value)\n\n    var anySink: AnySink<Value> { get }\n}\n\nextension SinkType {\n    public var anySink: AnySink<Value> {\n        return AnySink(SinkBox<Self>(self))\n    }\n}\n\nextension SinkType where Self: AnyObject {\n    public func unowned() -> AnySink<Value> {\n        return UnownedSink(self).anySink\n    }\n    public var hashValue: Int { return ObjectIdentifier(self).hashValue }\n    public static func ==(a: Self, b: Self) -> Bool { return a === b }\n}\n\npublic struct AnySink<Value>: SinkType {\n    // TODO: Replace this with a generalized protocol existential when Swift starts supporting those.\n    // (We always need to allocate a box for the sink, while an existential may have magical inline storage for \n    // tiny sinks -- say, less than three words.)\n\n    private let box: _AbstractSink<Value>\n\n    fileprivate init(_ box: _AbstractSink<Value>) {\n        self.box = box\n    }\n\n    public func receive(_ value: Value) {\n        box.receive(value)\n    }\n\n    public var anySink: AnySink<Value> {\n        return self\n    }\n\n    public var hashValue: Int {\n        return box.hashValue\n    }\n\n    public static func ==(left: AnySink, right: AnySink) -> Bool {\n        return left.box == right.box\n    }\n\n    public func opened<Sink: SinkType>(as type: Sink.Type = Sink.self) -> Sink? where Sink.Value == Value {\n        if let sink = self as? Sink { return sink }\n        if let sink = box as? Sink { return sink }\n        if let box = self.box as? SinkBox<Sink> { return box.contents }\n        return nil\n    }\n}\n\nfileprivate class _AbstractSink<Value>: SinkType {\n    // TODO: Eliminate this when Swift starts supporting generalized protocol existentials.\n\n    func receive(_ value: Value) { abstract() }\n\n    var hashValue: Int { abstract() }\n\n    func isEqual(to other: _AbstractSink<Value>) -> Bool { abstract() }\n\n    public static func ==(left: _AbstractSink<Value>, right: _AbstractSink<Value>) -> Bool {\n        return left.isEqual(to: right)\n    }\n\n    public final var anySink: AnySink<Value> {\n        return AnySink(self)\n    }\n}\n\nfileprivate class SinkBox<Wrapped: SinkType>: _AbstractSink<Wrapped.Value> {\n    // TODO: Eliminate this when Swift starts supporting generalized protocol existentials.\n\n    typealias Value = Wrapped.Value\n\n    fileprivate let contents: Wrapped\n\n    init(_ contents: Wrapped) {\n        self.contents = contents\n    }\n\n    override func receive(_ value: Value) {\n        contents.receive(value)\n    }\n\n    override var hashValue: Int {\n        return contents.hashValue\n    }\n\n    override func isEqual(to other: _AbstractSink<Wrapped.Value>) -> Bool {\n        guard let other = other as? SinkBox<Wrapped> else { return false }\n        return self.contents == other.contents\n    }\n}\n\nfileprivate class UnownedSink<Wrapped: SinkType & AnyObject>: _AbstractSink<Wrapped.Value> {\n    typealias Value = Wrapped.Value\n\n    unowned let wrapped: Wrapped\n\n    init(_ wrapped: Wrapped) {\n        self.wrapped = wrapped\n    }\n\n    override func receive(_ value: Value) {\n        wrapped.receive(value)\n    }\n\n    override var hashValue: Int {\n        return wrapped.hashValue\n    }\n\n    override func isEqual(to other: _AbstractSink<Wrapped.Value>) -> Bool {\n        guard let other = other as? UnownedSink<Wrapped> else { return false }\n        return self.wrapped == other.wrapped\n    }\n}\n"
  },
  {
    "path": "Sources/Source.swift",
    "content": "//\n//  Source.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// A Source is an entity that is able to produce values to other entities (called Sinks) that are connected to it.\n/// A source can be an observable value (see Variable<Value>), a KVO-compatible key path on an object \n/// (see NSObject.sourceForKeyPath), a notification (see NSNotificationCenter.sourceForNotification), \n/// a timer (see TimerSource), etc. etc.\n///\n/// Sources implement the `SourceType` protocol. It only has a single method, `subscribe`; it can be used to subscribe\n/// new sinks to values produced by this source.\n///\n/// `SourceType` is a protocol with an associated value, which can be sometimes inconvenient to work with. \n/// GlueKit provides the struct `Source<Value>` to represent a type-erased source.\n///\n/// A source is intended to be equivalent to a read-only propery. Therefore, while a source typically has a mechanism\n/// for sending values, this is intentionally outside the scope of `SourceType`. (But see `Signal<Value>`).\n///\n/// We represent a source by a struct holding the subscription closure; this allows extensions on it, which is convenient. \n/// GlueKit provides built-in extension methods for transforming sources to other kinds of sources.\n///\npublic protocol SourceType {\n    /// The type of values produced by this source.\n    associatedtype Value\n\n    /// Subscribe `sink` to this source, i.e., retain the sink and start calling its `receive` function \n    /// whenever this source produces a value. \n    /// The subscription remains active until `remove` is called with an identical sink.\n    ///\n    /// - SeeAlso: `subscribe`, `remove`\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value\n\n    /// Remove `sink`'s subscription to this source, i.e., stop calling the sink's `receive` function and release it.\n    /// The subscription remains active until `remove` is called with an identical sink.\n    ///\n    /// - Returns: The sink that was previously added to the sink. \n    ///     This may be distinguishable by the input parameter by identity comparison or some other means.\n    /// - SeeAlso: `subscribe`, `add`\n    @discardableResult\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value\n\n    /// A type-erased representation of this source.\n    var anySource: AnySource<Value> { get }\n}\n\n\nextension SourceType {\n    public var anySource: AnySource<Value> {\n        return AnySource(box: SourceBox(self))\n    }\n}\n\n/// A Source is an entity that is able to produce values to other entities (called Sinks) that are connected to it.\n/// A source can be an observable value (see Variable<Value>), a KVO-compatible key path on an object\n/// (see NSObject.sourceForKeyPath), a notification (see NSNotificationCenter.sourceForNotification),\n/// a timer (see TimerSource), etc. etc.\n///\n/// Sources implement the `SourceType` protocol. It only has a single method, `subscribe`; it can be used to subscribe\n/// new sinks to values produced by this source.\n///\n/// `SourceType` is a protocol with an associated value, which is sometimes inconvenient to work with. GlueKit\n/// provides the struct `Source<Value>` to represent a type-erased source.\n///\n/// A source is intended to be equivalent to a read-only propery. Therefore, while a source typically has a mechanism\n/// for sending values, this is intentionally outside the scope of `SourceType`. (But see `Signal<Value>`).\n///\n/// We represent a source by a struct holding the subscription closure; this allows extensions on it, which is convenient.\n/// GlueKit provides built-in extension methods for transforming sources to other kinds of sources.\n///\npublic struct AnySource<Value>: SourceType {\n    private let box: _AbstractSource<Value>\n\n    internal init(box: _AbstractSource<Value>) {\n        self.box = box\n    }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        box.add(sink)\n    }\n\n    @discardableResult\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        return box.remove(sink)\n    }\n\n    public var anySource: AnySource<Value> { return self }\n}\n\nopen class _AbstractSource<Value>: SourceType {\n    open func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value { abstract() }\n\n    @discardableResult\n    open func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value { abstract() }\n\n    public final var anySource: AnySource<Value> {\n        return AnySource(box: self)\n    }\n}\n\nopen class SignalerSource<Value>: _AbstractSource<Value>, SignalDelegate {\n    internal lazy var signal: Signal<Value> = .init(delegate: self)\n\n    public final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        self.signal.add(sink)\n    }\n\n    @discardableResult\n    public final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        return self.signal.remove(sink)\n    }\n\n    func activate() {}\n    func deactivate() {}\n}\n\ninternal class SourceBox<Base: SourceType>: _AbstractSource<Base.Value> {\n    typealias Value = Base.Value\n\n    let base: Base\n\n    init(_ base: Base) {\n        self.base = base\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        base.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        return base.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Sources/TimerSource.swift",
    "content": "//\n//  TimerSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\n\n// Some convenient extensions for DispatchTime, making it understand Foundation types\n\nextension DispatchWallTime {\n    internal init(_ date: Date) {\n        let secsSinceEpoch = date.timeIntervalSince1970\n        let spec = timespec(\n            tv_sec: __darwin_time_t(secsSinceEpoch),\n            tv_nsec: Int((secsSinceEpoch - floor(secsSinceEpoch)) * Double(NSEC_PER_SEC))\n        )\n        self.init(timespec: spec)\n    }\n}\n\nextension DispatchQueue {\n    func async(afterDelay interval: TimeInterval, execute block: @escaping @convention(block) () -> Void) {\n        self.asyncAfter(deadline: DispatchTime.now() + interval, execute: block)\n    }\n\n    func async(after date: Date, execute block: @escaping @convention(block) () -> Void) {\n        self.asyncAfter(wallDeadline: DispatchWallTime(date), execute: block)\n    }\n}\n\nprivate class AtomicToken {\n    // TODO: This should use atomics, which are currently (Xcode 8 beta 5) unavailable in Swift\n    private let lock = Lock()\n    private var token: Int = 0\n\n    @discardableResult\n    func increment() -> Int {\n        return lock.withLock {\n            token += 1\n            return token\n        }\n    }\n\n    func equals(_ value: Int) -> Bool {\n        return lock.withLock {\n            return token == value\n        }\n    }\n}\n\npublic typealias TimerSource = _TimerSource<Void>\n\n/// A Source that is firing at customizable intervals. The time of the each firing is determined by a user-supplied closure.\n///\n/// The timer interval should be relatively large (at least multiple seconds); this is not supposed to be a realtime timer.\n///\n/// Note that this source will only schedule an actual timer while there are sinks connected to it.\npublic final class _TimerSource<Dummy>: SignalerSource<Void> {\n\n    private let queue: DispatchQueue\n    private let next: () -> Date?\n    private var token = AtomicToken()\n\n    override func activate() {\n        start()\n    }\n\n    override func deactivate() {\n        stop()\n    }\n\n    /// Set up a new TimerSource that is scheduled on a given queue at the times determined by the supplied block.\n    /// @param queue The queue on which to schedule the timer. \n    ///    The signal will fire on this queue. If unspecified, the main queue is used.\n    /// @param next A closure that returns the next date the signal is supposed to fire, \n    ///    or nil if the timer should be paused indefinitely. The closure is executed on the queue in the first parameter.\n    ///\n    /// Note that the `next` closure will not be called immediately; the source waits for the first connection \n    /// before establishing a timer.\n    public init(queue: DispatchQueue = DispatchQueue.main, next: @escaping () -> Date?) {\n        self.queue = queue\n        self.next = next\n    }\n\n\n    /// Stop the timer. The timer will not fire again until start() is called.\n    public func stop() {\n        // Cancel the existing scheduling chain.\n        self.token.increment()\n    }\n\n    /// Start the timer, or if it is already running, recalculate the next firing date and reschedule the timer immediately.\n    /// Call this method when the dependencies of the `next` closure have changed since the last firing, and you want to the timer to apply the changes before it fires next.\n    public func start() {\n        // Start a new scheduling chain.\n        let frozenToken = token.increment()\n        queue.async {\n            self.scheduleNext(frozenToken)\n        }\n    }\n\n    private func scheduleNext(_ frozenToken: Int) {\n        guard token.equals(frozenToken) else { return }\n        if let nextDate = next() {\n            queue.async(after: nextDate) { [weak self] in self?.fireWithToken(frozenToken) }\n        }\n    }\n\n    private func fireWithToken(_ frozenToken: Int) {\n        guard token.equals(frozenToken) else { return }\n        self.signal.send()\n        scheduleNext(frozenToken)\n    }\n}\n\n/// Encapsulates information on a periodic timer and associated logic to determine firing dates.\n/// Tries to prevent timer drift by using walltime-based, absolute firing dates instead of relative ones.\nprivate struct PeriodicTimerData {\n    let start: Date\n    let interval: TimeInterval\n\n    var currentTick: Int {\n        let now = Date()\n        let elapsed = max(0, now.timeIntervalSince(start))\n        let tick = floor(elapsed / interval)\n        return Int(tick)\n    }\n\n    var dateOfNextTick: Date {\n        return start.addingTimeInterval(TimeInterval(currentTick + 1) * interval)\n    }\n}\n\npublic extension _TimerSource {\n    /// Creates a TimerSource that triggers periodically with a specific time interval.\n    ///\n    /// This source makes an effort to prevent timer drift by scheduling ticks at predetermined absolute time points,\n    /// but it only guarantees that ticks happen sometime after their scheduled trigger time, with no upper bound to the delay.\n    ///\n    /// If the system is busy (or sleeping) some ticks may be skipped.\n    ///\n    /// @param queue: The queue on which to schedule the timer. The signal will fire on this queue. If unspecified, the main queue is used.\n    /// @param start: The time at which the source should fire first, or nil to begin firing `interval` seconds from now.\n    /// @param interval: The minimum time period between the beginnings of subsequent firings.\n    public convenience init(queue: DispatchQueue = DispatchQueue.main, start: Date? = nil, interval: TimeInterval) {\n        assert(interval > 0)\n\n        let data = PeriodicTimerData(start: start ?? Date().addingTimeInterval(interval), interval: interval)\n        self.init(queue: queue, next: { [data] in data.dateOfNextTick })\n    }\n}\n"
  },
  {
    "path": "Sources/TransactionalThing.swift",
    "content": "//\n//  TransactionState.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-22.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n\ninternal class TransactionalSignal<Change: ChangeType>: Signal<Update<Change>> {\n    typealias Value = Update<Change>\n\n    var isInTransaction: Bool = false\n\n    public override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        if self.isInTransaction {\n            // Make sure the new subscriber knows we're in the middle of a transaction.\n            sink.receive(.beginTransaction)\n        }\n        super.add(sink)\n    }\n\n    @discardableResult\n    public override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        let old = super.remove(sink)\n        if self.isInTransaction {\n            // Wave goodbye by sending a virtual endTransaction that makes state management easier.\n            old.receive(.endTransaction)\n        }\n        return old\n    }\n}\n\nprotocol TransactionalThing: class, SignalDelegate {\n    associatedtype Change: ChangeType\n    \n    var _signal: TransactionalSignal<Change>? { get set }\n    var _transactionCount: Int { get set }\n}\n\nextension TransactionalThing {\n    var signal: TransactionalSignal<Change> {\n        if let signal = _signal { return signal }\n        let signal = TransactionalSignal<Change>()\n        signal.isInTransaction = _transactionCount > 0\n        signal.delegate = self\n        _signal = signal\n        return signal\n    }\n\n    func beginTransaction() {\n        _transactionCount += 1\n        if _transactionCount == 1, let signal = _signal {\n            signal.isInTransaction = true\n            signal.send(.beginTransaction)\n        }\n    }\n    \n    func sendChange(_ change: Change) {\n        precondition(_transactionCount > 0)\n        _signal?.send(.change(change))\n    }\n    \n    func sendIfConnected(_ change: @autoclosure () -> Change) {\n        if isConnected {\n            sendChange(change())\n        }\n    }\n    \n    func endTransaction() {\n        precondition(_transactionCount > 0)\n        _transactionCount -= 1\n        if _transactionCount == 0, let signal = _signal {\n            signal.isInTransaction = false\n            signal.send(.endTransaction)\n        }\n    }\n    \n    public func send(_ update: Update<Change>) {\n        switch update {\n        case .beginTransaction: beginTransaction()\n        case .change(let change): sendChange(change)\n        case .endTransaction: endTransaction()\n        }\n    }\n    \n    var isInTransaction: Bool { return _transactionCount > 0 }\n    var isConnected: Bool { return _signal?.isConnected ?? false }\n    var isActive: Bool { return isInTransaction || isConnected }\n    var isInOuterMostTransaction: Bool { return _transactionCount == 1 } // Used by KVO\n}\n\npublic class TransactionalSource<Change: ChangeType>: _AbstractSource<Update<Change>>, TransactionalThing {\n    internal var _signal: TransactionalSignal<Change>? = nil\n    internal var _transactionCount = 0\n\n    func activate() {\n    }\n    \n    func deactivate() {\n    }\n    \n    public override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        signal.add(sink)\n    }\n    \n    @discardableResult\n    public override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        return signal.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Sources/TransformedSink.swift",
    "content": "//\n//  TransformedSink.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-29.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport SipHash\n\npublic protocol SinkTransform: Hashable {\n    associatedtype Input\n    associatedtype Output\n\n    func apply<Sink: SinkType>(_ input: Input, _ sink: Sink) where Sink.Value == Output\n}\n\nextension SinkTransform where Self: AnyObject {\n    public var hashValue: Int { return ObjectIdentifier(self).hashValue }\n    public static func ==(a: Self, b: Self) -> Bool { return a === b }\n}\n\nextension SinkType {\n    func transform<Transform: SinkTransform>(_ transform: Transform) -> TransformedSink<Self, Transform> {\n        return TransformedSink(sink: self, transform: transform)\n    }\n}\n\npublic struct TransformedSink<Sink: SinkType, Transform: SinkTransform>: SinkType, SipHashable where Transform.Output == Sink.Value {\n    public let sink: Sink\n    public let transform: Transform\n\n    public func receive(_ value: Transform.Input) {\n        transform.apply(value, sink)\n    }\n\n    public func appendHashes(to hasher: inout SipHasher) {\n        hasher.append(sink)\n        hasher.append(transform)\n    }\n\n    public static func ==(left: TransformedSink, right: TransformedSink) -> Bool {\n        return left.sink == right.sink && left.transform == right.transform\n    }\n}\n\nclass SinkTransformFromClosure<I, O>: SinkTransform {\n    typealias Input = I\n    typealias Output = O\n\n    let transform: (Input, (Output) -> Void) -> Void\n\n    init(_ transform: @escaping (Input, (Output) -> Void) -> Void) {\n        self.transform = transform\n    }\n\n    func apply<Sink: SinkType>(_ input: Input, _ sink: Sink) where Sink.Value == Output {\n        transform(input, sink.receive)\n    }\n}\n\nclass SinkTransformToConstant<I, O>: SinkTransform {\n    typealias Input = I\n    typealias Output = O\n\n    let constant: O\n\n    init(_ constant: O) {\n        self.constant = constant\n    }\n\n    func apply<Sink: SinkType>(_ input: Input, _ sink: Sink) where Sink.Value == Output {\n        sink.receive(constant)\n    }\n}\n\nclass SinkTransformFromMapping<I, O>: SinkTransform {\n    typealias Input = I\n    typealias Output = O\n\n    let mapping: (Input) -> Output\n\n    init(_ mapping: @escaping (Input) -> Output) {\n        self.mapping = mapping\n    }\n\n    func apply<Sink: SinkType>(_ input: Input, _ sink: Sink) where Sink.Value == Output {\n        sink.receive(mapping(input))\n    }\n}\n\nclass SinkTransformFromOptionalMapping<I, O>: SinkTransform {\n    typealias Input = I\n    typealias Output = O\n\n    let mapping: (Input) -> Output?\n\n    init(_ mapping: @escaping (Input) -> Output?) {\n        self.mapping = mapping\n    }\n\n    func apply<Sink: SinkType>(_ input: Input, _ sink: Sink) where Sink.Value == Output {\n        if let output = mapping(input) {\n            sink.receive(output)\n        }\n    }\n}\n\nclass SinkTransformFromFilter<I>: SinkTransform {\n    typealias Input = I\n    typealias Output = I\n\n    let filter: (Input) -> Bool\n\n    init(_ filter: @escaping (Input) -> Bool) {\n        self.filter = filter\n    }\n\n    func apply<Sink: SinkType>(_ input: Input, _ sink: Sink) where Sink.Value == Output {\n        if filter(input) {\n            sink.receive(input)\n        }\n    }\n}\n\nclass SinkTransformFromSequence<Input, S: Sequence>: SinkTransform {\n    typealias Output = S.Iterator.Element\n\n    let transform: (Input) -> S\n\n    init(_ transform: @escaping (Input) -> S) {\n        self.transform = transform\n    }\n\n    func apply<Sink: SinkType>(_ input: Input, _ sink: Sink) where Sink.Value == Output {\n        for output in transform(input) {\n            sink.receive(output)\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/TransformedSource.swift",
    "content": "//\n//  TransformedSource.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nfinal class TransformedSource<Input: SourceType, Transform: SinkTransform>: _AbstractSource<Transform.Output> where Transform.Input == Input.Value {\n    let input: Input\n    let transform: Transform\n\n    init(input: Input, transform: Transform) {\n        self.input = input\n        self.transform = transform\n    }\n\n    final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Transform.Output {\n        self.input.add(sink.transform(transform))\n    }\n\n    @discardableResult\n    final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Transform.Output {\n        return self.input.remove(sink.transform(transform)).sink\n    }\n}\n\nextension SourceType {\n    /// Returns a source that, applies `transform` on each value produced by `self` and each subscriber sink.\n    ///\n    /// `transform` should be a pure function, i.e., one with no side effects or hidden parameters.\n    /// For each value that is received from `self`, it is called as many times as there are subscribers.\n    public func transform<Result>(_ type: Result.Type = Result.self, _ transform: @escaping (Value, (Result) -> Void) -> Void) -> AnySource<Result> {\n        return TransformedSource(input: self, transform: SinkTransformFromClosure(transform)).anySource\n    }\n\n    public func map<Output>(_ transform: @escaping (Value) -> Output) -> AnySource<Output> {\n        return TransformedSource(input: self, transform: SinkTransformFromMapping(transform)).anySource\n    }\n\n    public func flatMap<Output>(_ transform: @escaping (Value) -> Output?) -> AnySource<Output> {\n        return TransformedSource(input: self, transform: SinkTransformFromOptionalMapping(transform)).anySource\n    }\n\n    public func filter(_ predicate: @escaping (Value) -> Bool) -> AnySource<Value> {\n        return TransformedSource(input: self, transform: SinkTransformFromFilter(predicate)).anySource\n    }\n\n    public func flatMap<S: Sequence>(_ transform: @escaping (Value) -> S) -> AnySource<S.Iterator.Element> {\n        return TransformedSource(input: self, transform: SinkTransformFromSequence(transform)).anySource\n    }\n\n    public func mapToVoid() -> AnySource<Void> {\n        return TransformedSource(input: self, transform: SinkTransformToConstant(())).anySource\n    }\n\n    public func mapToConstant<C>(_ value: C) -> AnySource<C> {\n        return TransformedSource(input: self, transform: SinkTransformToConstant(value)).anySource\n    }\n}\n"
  },
  {
    "path": "Sources/TwoWayBinding.swift",
    "content": "//\n//  TwoWayBinding.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-24.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension UpdatableValueType {\n    /// Create a two-way binding from self to a target updatable. The target is updated to the current value of self.\n    /// All future updates will be synchronized between the two variables until the returned connection is disconnected.\n    /// To prevent infinite cycles, you must provide an equality test that returns true if two values are to be\n    /// considered equivalent.\n    public func bind<Target: UpdatableValueType>(to target: Target, by areEquivalent: @escaping (Value, Value) -> Bool) -> Connection where Target.Value == Value {\n        return BindConnection(source: self, target: target, by: areEquivalent)\n    }\n}\n\nprivate enum  BindOrigin {\n    case source\n    case target\n}\n\nprivate struct BindSink<Source: UpdatableValueType, Target: UpdatableValueType>: OwnedSink\nwhere Source.Value == Target.Value {\n    typealias Owner = BindConnection<Source, Target>\n\n    unowned let owner: Owner\n    let origin: BindOrigin\n\n    var identifier: BindOrigin { return origin }\n\n    init(owner: Owner, origin: BindOrigin) {\n        self.owner = owner\n        self.origin = origin\n    }\n\n    private func send(_ update: Update<ValueChange<Source.Value>>) {\n        switch origin {\n        case .source:\n            owner.target!.apply(update)\n        case .target:\n            owner.source!.apply(update)\n        }\n    }\n\n    private var destinationValue: Source.Value {\n        switch origin {\n        case .source:\n            return owner.target!.value\n        case .target:\n            return owner.source!.value\n        }\n    }\n\n    func receive(_ update: Update<ValueChange<Source.Value>>) {\n        switch update {\n        case .beginTransaction:\n            switch owner.transactionOrigin {\n            case nil:\n                owner.transactionOrigin = origin\n                send(update)\n            case .some(origin):\n                preconditionFailure(\"Duplicate transaction\")\n            case .some(_):\n                // Ignore\n                break\n            }\n        case .change(let change):\n            if !owner.areEquivalent!(change.new, destinationValue) {\n                send(update)\n            }\n        case .endTransaction:\n            switch owner.transactionOrigin {\n            case nil:\n                preconditionFailure(\"End received for nonexistent transaction\")\n            case .some(origin):\n                send(update)\n                owner.transactionOrigin = nil\n            case .some(_):\n                // Ignore\n                break\n            }\n        }\n    }\n}\n\nprivate final class BindConnection<Source: UpdatableValueType, Target: UpdatableValueType>: Connection\nwhere Source.Value == Target.Value {\n    typealias Value = Source.Value\n\n    var areEquivalent: ((Value, Value) -> Bool)?\n    var source: Source?\n    var target: Target?\n    var transactionOrigin: BindOrigin? = nil\n\n    init(source: Source, target: Target, by areEquivalent: @escaping (Value, Value) -> Bool) {\n        self.areEquivalent = areEquivalent\n        self.source = source\n        self.target = target\n        super.init()\n\n        source.add(BindSink(owner: self, origin: .source))\n        precondition(transactionOrigin == nil, \"Binding during an active transaction is not supported\")\n        target.add(BindSink(owner: self, origin: .target))\n        precondition(transactionOrigin == nil, \"Binding during an active transaction is not supported\")\n\n        if !areEquivalent(source.value, target.value) {\n            target.value = source.value\n        }\n    }\n\n    deinit {\n        disconnect()\n    }\n\n    override func disconnect() {\n        precondition(transactionOrigin == nil, \"Unbinding during an active transaction is not supported\")\n        if let source = self.source {\n            source.remove(BindSink(owner: self, origin: .source))\n        }\n        if let source = self.target {\n            source.remove(BindSink(owner: self, origin: .target))\n        }\n        self.areEquivalent = nil\n        self.source = nil\n        self.target = nil\n    }\n}\n\nextension UpdatableValueType where Value: Equatable {\n    /// Create a two-way binding from self to a target variable. The target is updated to the current value of self.\n    /// All future updates will be synchronized between the two variables until the returned connection is disconnected.\n    /// To prevent infinite cycles, the variables aren't synched when a bound variable is set to a value that is equal\n    /// to the value of its counterpart.\n    public func bind<Target: UpdatableValueType>(to target: Target) -> Connection where Target.Value == Value {\n        return self.bind(to: target, by: ==)\n    }\n}\n\nextension Connector {\n    @discardableResult\n    public func bind<Source: UpdatableValueType, Target: UpdatableValueType>(_ source: Source, to target: Target, by areEquivalent: @escaping (Source.Value, Source.Value) -> Bool) -> Connection\n        where Source.Value == Target.Value {\n            return source.bind(to: target, by: areEquivalent).putInto(self)\n    }\n\n    @discardableResult\n    public func bind<Value: Equatable, Source: UpdatableValueType, Target: UpdatableValueType>(_ source: Source, to target: Target) -> Connection\n        where Source.Value == Value, Target.Value == Value {\n            return self.bind(source, to: target, by: ==)\n    }\n}\n"
  },
  {
    "path": "Sources/Type Helpers.swift",
    "content": "//\n//  Type Helpers.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-03-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\n#if os(macOS)\n    import AppKit\n#elseif os(iOS) || os(tvOS)\n    import UIKit // For NSValue.CGPointValue and similar conversions\n#elseif os(watchOS)\n    import WatchKit\n#endif\n\nprivate func toString(_ value: Any?) -> String {\n    return value as! String\n}\nprivate func toBool(_ value: Any?) -> Bool {\n    let v = value as! NSNumber\n    return v.boolValue\n}\nprivate func toInt(_ value: Any?) -> Int {\n    let v = value as! NSNumber\n    return v.intValue\n}\nprivate func toFloat(_ value: Any?) -> Float {\n    let v = value as! NSNumber\n    return v.floatValue\n}\nprivate func toDouble(_ value: Any?) -> Double {\n    let v = value as! NSNumber\n    return v.doubleValue\n}\nprivate func toCGFloat(_ value: Any?) -> CGFloat {\n    let v = value as! NSNumber\n    return CGFloat(v.doubleValue)\n}\nprivate func toCGPoint(_ value: Any?) -> CGPoint {\n    let v = value as! NSValue\n    #if os(macOS)\n        return v.pointValue\n    #else\n        return v.cgPointValue\n    #endif\n}\nprivate func toCGSize(_ value: Any?) -> CGSize {\n    let v = value as! NSValue\n    #if os(macOS)\n        return v.sizeValue\n    #else\n        return v.cgSizeValue\n    #endif\n}\nprivate func toCGRect(_ value: Any?) -> CGRect {\n    let v = value as! NSValue\n    #if os(macOS)\n        return v.rectValue\n    #else\n        return v.cgRectValue\n    #endif\n}\nprivate let encodedCGAffineTransform = (CGFloat.NativeType.self == Double.self ? \"{CGAffineTransform=dddddd}\" : \"{CGAffineTransform=ffffff}\")\nprivate func toCGAffineTransform(_ value: Any?) -> CGAffineTransform {\n    let v = value as! NSValue\n    #if os(macOS)\n        precondition(String(cString: v.objCType) == encodedCGAffineTransform)\n        var transform = CGAffineTransform.identity\n        v.getValue(&transform)\n        return transform\n    #else\n        return v.cgAffineTransformValue\n    #endif\n}\n\n\n\npublic extension SourceType where Value == Any? {\n    /// Casts all values to Type using an unsafe cast. Signals a fatal error if a value isn't a Type.\n    func forceCasted<T: AnyObject>(to type: T.Type = T.self) -> AnySource<T> {\n        return self.map { $0 as! T }\n    }\n\n    func casted<T>(to type: T.Type = T.self) -> AnySource<T?> {\n        return self.map { $0 as? T }\n    }\n\n    func casted<T>(to type: T.Type = T.self, defaultValue: T) -> AnySource<T> {\n        return self.map { ($0 as? T) ?? defaultValue }\n    }\n\n    /// Casts all values to String via NSString. Signals a fatal error if a value isn't an NSString.\n    var asString: AnySource<String> { return map(toString) }\n\n    /// Converts all values to Bool using NSNumber.boolValue. Signals a fatal error if a value isn't an NSNumber.\n    var asBool: AnySource<Bool> { return map(toBool) }\n\n    /// Converts all values to Int using NSNumber.integerValue. Signals a fatal error if a value isn't an NSNumber.\n    var asInt: AnySource<Int> { return map(toInt) }\n\n    /// Converts all values to Float using NSNumber.floatValue. Signals a fatal error if a value isn't an NSNumber.\n    var asFloat: AnySource<Float> { return map(toFloat) }\n\n    /// Converts all values to Double using NSNumber.doubleValue. Signals a fatal error if a value isn't an NSNumber.\n    var asDouble: AnySource<Double> { return map(toDouble) }\n\n    /// Converts all values to CGFloat using NSNumber.doubleValue. Signals a fatal error if a value isn't an NSNumber.\n    var asCGFloat: AnySource<CGFloat> { return map(toCGFloat) }\n\n    /// Converts all values to CGPoint using NSValue.CGPointValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGPoint: AnySource<CGPoint> { return map(toCGPoint) }\n\n    /// Converts all values to CGSize using NSValue.CGSizeValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGSize: AnySource<CGSize> { return map(toCGSize) }\n\n    /// Converts all values to CGRect using NSValue.CGRectValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGRect: AnySource<CGRect> { return map(toCGRect) }\n\n    /// Converts all values to CGAffineTransformValue using NSValue.CGAffineTransformValue.  Signals a fatal error if a value isn't an NSValue.\n    var asCGAffineTransform: AnySource<CGAffineTransform> { return map(toCGAffineTransform) }\n}\n\npublic extension ObservableValueType where Value == Any? {\n    /// Casts all values to Type using a forced cast. Traps if a value can't be casted to the specified type.\n    func forceCasted<T>(to type: T.Type = T.self) -> AnyObservableValue<T> {\n        return self.map { $0 as! T }\n    }\n\n    func casted<T>(to type: T.Type = T.self) -> AnyObservableValue<T?> {\n        return self.map { $0 as? T }\n    }\n\n    func casted<T>(to type: T.Type = T.self, defaultValue: T) -> AnyObservableValue<T> {\n        return self.map { ($0 as? T) ?? defaultValue }\n    }\n\n    /// Casts all values to String via NSString. Signals a fatal error if a value isn't an NSString.\n    var asString: AnyObservableValue<String> { return self.map(toString) }\n\n    /// Converts all values to Bool using NSNumber.integerValue. Signals a fatal error if a value isn't an NSNumber.\n    var asBool: AnyObservableValue<Bool> { return self.map(toBool) }\n\n    /// Converts all values to Int using NSNumber.integerValue. Signals a fatal error if a value isn't an NSNumber.\n    var asInt: AnyObservableValue<Int> { return self.map(toInt) }\n\n    /// Converts all values to Float using NSNumber.floatValue. Signals a fatal error if a value isn't an NSNumber.\n    var asFloat: AnyObservableValue<Float> { return self.map(toFloat) }\n\n    /// Converts all values to Double using NSNumber.doubleValue. Signals a fatal error if a value isn't an NSNumber.\n    var asDouble: AnyObservableValue<Double> { return self.map(toDouble) }\n\n    /// Converts all values to CGFloat using NSNumber.doubleValue. Signals a fatal error if a value isn't an NSNumber.\n    var asCGFloat: AnyObservableValue<CGFloat> { return self.map(toCGFloat) }\n\n    /// Converts all values to CGPoint using NSValue.CGPointValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGPoint: AnyObservableValue<CGPoint> { return self.map(toCGPoint) }\n\n    /// Converts all values to CGSize using NSValue.CGSizeValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGSize: AnyObservableValue<CGSize> { return self.map(toCGSize) }\n\n    /// Converts all values to CGRect using NSValue.CGRectValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGRect: AnyObservableValue<CGRect> { return self.map(toCGRect) }\n\n    /// Converts all values to CGAffineTransformValue using NSValue.CGAffineTransformValue.  Signals a fatal error if a value isn't an NSValue.\n    var asCGAffineTransform: AnyObservableValue<CGAffineTransform> { return self.map(toCGAffineTransform) }\n}\n\npublic extension UpdatableValueType where Value == Any? {\n    /// Casts all values to Type using a forced cast. Traps if a value can't be casted to the specified type.\n    func forceCasted<T>(to type: T.Type = T.self) -> AnyUpdatableValue<T> {\n        return self.map({ $0 as! T }, inverse: { $0 as Any? })\n    }\n\n    func casted<T>(to type: T.Type = T.self) -> AnyUpdatableValue<T?> {\n        return self.map({ $0 as? T }, inverse: { $0 as Any? })\n    }\n\n    func casted<T>(to type: T.Type = T.self, defaultValue: T) -> AnyUpdatableValue<T> {\n        return self.map({ ($0 as? T) ?? defaultValue }, inverse: { $0 as Any? })\n    }\n\n    /// Casts all values to String via NSString. Signals a fatal error if a value isn't an NSString.\n    var asString: AnyUpdatableValue<String> { return self.map(toString, inverse: { $0 }) }\n\n    /// Converts all values to Bool using NSNumber.integerValue. Signals a fatal error if a value isn't an NSNumber.\n    var asBool: AnyUpdatableValue<Bool> { return self.map(toBool, inverse: { NSNumber(value: $0) }) }\n\n    /// Converts all values to Int using NSNumber.integerValue. Signals a fatal error if a value isn't an NSNumber.\n    var asInt: AnyUpdatableValue<Int> { return self.map(toInt, inverse: { NSNumber(value: $0) }) }\n\n    /// Converts all values to Float using NSNumber.floatValue. Signals a fatal error if a value isn't an NSNumber.\n    var asFloat: AnyUpdatableValue<Float> { return self.map(toFloat, inverse: { NSNumber(value: $0) }) }\n\n    /// Converts all values to Double using NSNumber.doubleValue. Signals a fatal error if a value isn't an NSNumber.\n    var asDouble: AnyUpdatableValue<Double> { return self.map(toDouble, inverse: { NSNumber(value: $0) }) }\n\n    /// Converts all values to CGFloat using NSNumber.doubleValue. Signals a fatal error if a value isn't an NSNumber.\n    var asCGFloat: AnyUpdatableValue<CGFloat> { return self.map(toCGFloat, inverse: { NSNumber(value: Double($0)) }) }\n\n    /// Converts all values to CGPoint using NSValue.CGPointValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGPoint: AnyUpdatableValue<CGPoint> {\n        return self.map(toCGPoint, inverse: {\n            #if os(macOS)\n                return NSValue(point: $0)\n            #else\n                return NSValue(cgPoint: $0)\n            #endif\n        })\n    }\n\n    /// Converts all values to CGSize using NSValue.CGSizeValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGSize: AnyUpdatableValue<CGSize> {\n        return self.map(toCGSize, inverse: {\n            #if os(macOS)\n                return NSValue(size: $0)\n            #else\n                return NSValue(cgSize: $0)\n            #endif\n        })\n    }\n\n    /// Converts all values to CGRect using NSValue.CGRectValue. Signals a fatal error if a value isn't an NSValue.\n    var asCGRect: AnyUpdatableValue<CGRect> {\n        return self.map(toCGRect, inverse: {\n            #if os(macOS)\n                return NSValue(rect: $0)\n            #else\n                return NSValue(cgRect: $0)\n            #endif\n        })\n    }\n\n    /// Converts all values to CGAffineTransformValue using NSValue.CGAffineTransformValue.  Signals a fatal error if a value isn't an NSValue.\n    var asCGAffineTransform: AnyUpdatableValue<CGAffineTransform> {\n        return self.map(toCGAffineTransform, inverse: {\n            #if os(macOS)\n                var transform = $0\n                return NSValue(bytes: &transform, objCType: encodedCGAffineTransform)\n            #else\n                return NSValue(cgAffineTransform: $0)\n            #endif\n        })\n    }\n}\n"
  },
  {
    "path": "Sources/UIBarButtonItem Extensions.swift",
    "content": "//\n//  UIBarButtonItem Extensions.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-04-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport UIKit\n\nprivate var associatedObjectKey: UInt8 = 0\nprivate let listenerAction = #selector(TargetActionListener.actionDidFire)\n\nextension UIBarButtonItem {\n\n    public var actionSource: AnySource<Void> {\n        if let target = objc_getAssociatedObject(self, &associatedObjectKey) as? TargetActionListener {\n            return target.signal.anySource\n        }\n        let target = TargetActionListener()\n        self.target = target\n        self.action = listenerAction\n        objc_setAssociatedObject(self, &associatedObjectKey, target, .OBJC_ASSOCIATION_RETAIN)\n        return target.signal.anySource\n    }\n\n    public convenience init(barButtonSystemItem systemItem: UIBarButtonSystemItem, actionBlock: (() -> ())? = nil) {\n        let target = TargetActionListener()\n        self.init(barButtonSystemItem: systemItem, target: target, action: listenerAction)\n        objc_setAssociatedObject(self, &associatedObjectKey, target, .OBJC_ASSOCIATION_RETAIN)\n\n        if let actionBlock = actionBlock {\n            self.glue.connector.connect(target.signal, to: actionBlock)\n        }\n    }\n\n    public convenience init(image: UIImage?, style: UIBarButtonItemStyle, actionBlock: (() -> ())? = nil) {\n        let target = TargetActionListener()\n        self.init(image: image, style: style, target: target, action: listenerAction)\n        objc_setAssociatedObject(self, &associatedObjectKey, target, .OBJC_ASSOCIATION_RETAIN)\n\n        if let actionBlock = actionBlock {\n            self.glue.connector.connect(target.signal, to: actionBlock)\n        }\n    }\n\n    public convenience init(image: UIImage?, landscapeImagePhone: UIImage?, style: UIBarButtonItemStyle, actionBlock: (() -> ())? = nil) {\n        let target = TargetActionListener()\n        self.init(image: image, landscapeImagePhone: landscapeImagePhone, style: style, target: target, action: listenerAction)\n        objc_setAssociatedObject(self, &associatedObjectKey, target, .OBJC_ASSOCIATION_RETAIN)\n\n        if let actionBlock = actionBlock {\n            self.glue.connector.connect(target.signal, to: actionBlock)\n        }\n    }\n\n    public convenience init(title: String?, style: UIBarButtonItemStyle, actionBlock: (() -> ())? = nil) {\n        let target = TargetActionListener()\n        self.init(title: title, style: style, target: target, action: listenerAction)\n        objc_setAssociatedObject(self, &associatedObjectKey, target, .OBJC_ASSOCIATION_RETAIN)\n\n        if let actionBlock = actionBlock {\n            self.glue.connector.connect(target.signal, to: actionBlock)\n        }\n    }\n}\n\nprivate class TargetActionListener: NSObject {\n    let signal = Signal<Void>()\n\n    @objc func actionDidFire() {\n        signal.send()\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/UIControl Glue.swift",
    "content": "//\n//  UIControl Glue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-03-11.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport UIKit\nimport SipHash\n\nprivate var associatedObjectKey: Int8 = 0\n\nextension UIControl {\n    open override var glue: GlueForUIControl {\n        return _glue()\n    }\n}\n\nopen class GlueForUIControl: GlueForNSObject {\n    private struct ControlEventsTargetKey: SipHashable {\n        let sink: AnySink<UIEvent>\n        let events: UIControlEvents\n        \n        func appendHashes(to hasher: inout SipHasher) {\n            hasher.append(sink)\n            hasher.append(events.rawValue)\n        }\n        \n        static func ==(left: ControlEventsTargetKey, right: ControlEventsTargetKey) -> Bool {\n            return left.sink == right.sink && left.events == right.events\n        }\n    }\n    \n    private final class ControlEventsTarget: NSObject {\n        let sink: AnySink<UIEvent>\n        \n        init(sink: AnySink<UIEvent>) {\n            self.sink = sink\n        }\n        \n        @objc func eventDidTrigger(_ sender: AnyObject, forEvent event: UIEvent) {\n            sink.receive(event)\n        }\n    }\n    \n    public struct ControlEventsSource: SourceType {\n        public typealias Value = UIEvent\n        \n        public let control: UIControl\n        public let events: UIControlEvents\n        \n        public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n            let target = control.glue.add(sink.anySink, for: events)\n            control.addTarget(target, action: #selector(ControlEventsTarget.eventDidTrigger(_:forEvent:)), for: events)\n        }\n        \n        public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n            let target = control.glue.remove(sink.anySink, for: events)\n            control.removeTarget(target, action: #selector(ControlEventsTarget.eventDidTrigger(_:forEvent:)), for: events)\n            return target.sink.opened()!\n        }\n    }\n    \n    private var object: UIControl { return owner as! UIControl }\n\n    private var targets: [ControlEventsTargetKey: ControlEventsTarget] = [:]\n\n    public func source(for events: UIControlEvents = .primaryActionTriggered) -> ControlEventsSource {\n        return ControlEventsSource(control: object, events: events)\n    }\n\n    private func add(_ sink: AnySink<UIEvent>, for events: UIControlEvents) -> ControlEventsTarget {\n        let target = ControlEventsTarget(sink: sink)\n        let key = ControlEventsTargetKey(sink: sink, events: events)\n        precondition(targets[key] == nil)\n        targets[key] = target\n        return target\n    }\n\n    private func remove(_ sink: AnySink<UIEvent>, for events: UIControlEvents) -> ControlEventsTarget {\n        let key = ControlEventsTargetKey(sink: sink, events: events)\n        let target = targets[key]!\n        targets[key] = nil\n        return target\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/UIDevice Glue.swift",
    "content": "//\n//  UIDevice Glue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-03-13.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport UIKit\n\nextension UIDevice {\n    open override var glue: GlueForUIDevice {\n        return _glue()\n    }\n}\n\nopen class GlueForUIDevice: GlueForNSObject {\n    private var object: UIDevice { return owner as! UIDevice }\n\n    public lazy var orientation: AnyObservableValue<UIDeviceOrientation>\n        = ObservableDeviceOrientation(self.object).anyObservableValue\n\n    public lazy var batteryState: AnyObservableValue<(UIDeviceBatteryState, Float)>\n        = ObservableBatteryState(self.object).anyObservableValue\n\n    public lazy var proximityState: AnyObservableValue<Bool>\n        = ObservableDeviceProximity(self.object).anyObservableValue\n}\n\nprivate struct DeviceOrientationSink: UniqueOwnedSink {\n    typealias Owner = ObservableDeviceOrientation\n\n    unowned let owner: Owner\n\n    func receive(_ notification: Notification) {\n        owner.receive(notification)\n    }\n}\n\nprivate final class ObservableDeviceOrientation: _BaseObservableValue<UIDeviceOrientation> {\n    unowned let device: UIDevice\n    var orientation: UIDeviceOrientation? = nil\n\n    init(_ device: UIDevice) {\n        self.device = device\n    }\n\n    override var value: UIDeviceOrientation {\n        return device.orientation\n    }\n\n    lazy var notificationSource: AnySource<Notification> = NotificationCenter.default.glue.source(forName: .UIDeviceOrientationDidChange, sender: self.device, queue: OperationQueue.main)\n\n    func receive(_ notification: Notification) {\n        beginTransaction()\n        let old = orientation!\n        let new = device.orientation\n        orientation = new\n        sendChange(.init(from: old, to: new))\n        endTransaction()\n    }\n\n    override func activate() {\n        device.beginGeneratingDeviceOrientationNotifications()\n        orientation = device.orientation\n        notificationSource.add(DeviceOrientationSink(owner: self))\n    }\n\n    override func deactivate() {\n        notificationSource.remove(DeviceOrientationSink(owner: self))\n        device.endGeneratingDeviceOrientationNotifications()\n        orientation = nil\n    }\n}\n\nprivate struct BatteryStateSink: UniqueOwnedSink {\n    typealias Owner = ObservableBatteryState\n\n    unowned let owner: Owner\n\n    func receive(_ notification: Notification) {\n        owner.receive(notification)\n    }\n}\n\nprivate var batteryKey: UInt8 = 0\n\nprivate final class ObservableBatteryState: _BaseObservableValue<(UIDeviceBatteryState, Float)> {\n    typealias Value = (UIDeviceBatteryState, Float)\n\n    unowned let device: UIDevice\n    var state: Value? = nil\n    var didEnableBatteryMonitoring = false\n\n    lazy var batteryStateSource: AnySource<Notification> = NotificationCenter.default.glue.source(forName: .UIDeviceBatteryStateDidChange, sender: self.device, queue: OperationQueue.main)\n    lazy var batteryLevelSource: AnySource<Notification> = NotificationCenter.default.glue.source(forName: .UIDeviceBatteryLevelDidChange, sender: self.device, queue: OperationQueue.main)\n\n    init(_ device: UIDevice) {\n        self.device = device\n    }\n\n    override var value: Value {\n        return (device.batteryState, device.batteryLevel)\n    }\n\n    func receive(_ notification: Notification) {\n        let old = state!\n        let new = (device.batteryState, device.batteryLevel)\n        if old != new {\n            beginTransaction()\n            state = new\n            sendChange(.init(from: old, to: new))\n            endTransaction()\n        }\n    }\n\n    override func activate() {\n        if !device.isBatteryMonitoringEnabled {\n            device.isBatteryMonitoringEnabled = true\n            didEnableBatteryMonitoring = true\n        }\n        state = (device.batteryState, device.batteryLevel)\n        batteryStateSource.add(BatteryStateSink(owner: self))\n        batteryLevelSource.add(BatteryStateSink(owner: self))\n    }\n\n    override func deactivate() {\n        batteryStateSource.remove(BatteryStateSink(owner: self))\n        batteryLevelSource.remove(BatteryStateSink(owner: self))\n        if didEnableBatteryMonitoring {\n            device.isBatteryMonitoringEnabled = false\n            didEnableBatteryMonitoring = false\n        }\n        state = nil\n    }\n}\n\nprivate struct DeviceProximitySink: UniqueOwnedSink {\n    typealias Owner = ObservableDeviceProximity\n\n    unowned let owner: Owner\n\n    func receive(_ notification: Notification) {\n        owner.receive(notification)\n    }\n}\n\nprivate var proximityKey: UInt8 = 0\n\nprivate final class ObservableDeviceProximity: _BaseObservableValue<Bool> {\n    unowned let device: UIDevice\n    \n    var state: Bool? = nil\n    var didEnableProximityMonitoring = false\n\n    lazy var notificationSource: AnySource<Notification> = NotificationCenter.default.glue.source(forName: .UIDeviceProximityStateDidChange, sender: self.device, queue: OperationQueue.main)\n\n    init(_ device: UIDevice) {\n        self.device = device\n    }\n\n    override var value: Bool {\n        return device.proximityState\n    }\n\n    func receive(_ notification: Notification) {\n        beginTransaction()\n        let old = state!\n        let new = device.proximityState\n        state = new\n        sendChange(.init(from: old, to: new))\n        endTransaction()\n    }\n\n    override func activate() {\n        if !device.isProximityMonitoringEnabled {\n            device.isProximityMonitoringEnabled = true\n            didEnableProximityMonitoring = true\n        }\n        state = device.proximityState\n        notificationSource.add(DeviceProximitySink(owner: self))\n    }\n\n    override func deactivate() {\n        notificationSource.remove(DeviceProximitySink(owner: self))\n        if didEnableProximityMonitoring {\n            device.isProximityMonitoringEnabled = false\n            didEnableProximityMonitoring = false\n        }\n        state = nil\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/UIGestureRecognizer Glue.swift",
    "content": "//\n//  UIGestureRecognizer Glue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-03-16.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport UIKit\n\nextension UIGestureRecognizer {\n    open override var glue: GlueForUIGestureRecognizer {\n        return _glue()\n    }\n}\n\nopen class GlueForUIGestureRecognizer: GlueForNSObject {\n    private var object: UIGestureRecognizer { return owner as! UIGestureRecognizer }\n\n    public lazy var state: AnyObservableValue<UIGestureRecognizerState>\n        = ObservableGestureRecognizerState(self.object).anyObservableValue\n}\n\nprivate class ObservableGestureRecognizerState: _BaseObservableValue<UIGestureRecognizerState> {\n    private unowned let _gestureRecognizer: UIGestureRecognizer\n    private var _value: UIGestureRecognizerState? = nil\n\n    init(_ gestureRecognizer: UIGestureRecognizer) {\n        _gestureRecognizer = gestureRecognizer\n    }\n\n    override var value: UIGestureRecognizerState {\n        return _gestureRecognizer.state\n    }\n\n    override func activate() {\n        _value = _gestureRecognizer.state\n        _gestureRecognizer.addTarget(self, action: #selector(ObservableGestureRecognizerState.gestureRecognizerDidFire))\n    }\n\n    override func deactivate() {\n        _gestureRecognizer.removeTarget(self, action: #selector(ObservableGestureRecognizerState.gestureRecognizerDidFire))\n        _value = nil\n    }\n\n    @objc func gestureRecognizerDidFire() {\n        beginTransaction()\n        let old = _value!\n        _value = _gestureRecognizer.state\n        sendChange(ValueChange(from: old, to: _value!))\n        endTransaction()\n    }\n}\n#endif\n"
  },
  {
    "path": "Sources/UILabel Glue.swift",
    "content": "//\n//  UILabel Glue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2017-04-23.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport UIKit\n\nextension UILabel {\n    open override var glue: GlueForUILabel {\n        return _glue()\n    }\n}\n\nopen class GlueForUILabel: GlueForNSObject {\n    private var object: UILabel { return owner as! UILabel }\n\n    public lazy var text: DependentValue<String?> = DependentValue { [unowned self] in self.object.text = $0 }\n    public lazy var textColor: DependentValue<UIColor> = DependentValue { [unowned self] in self.object.textColor = $0 }\n    public lazy var font: DependentValue<UIFont> = DependentValue { [unowned self] in self.object.font = $0 }\n    public lazy var textAlignment: DependentValue<NSTextAlignment> = DependentValue { [unowned self] in self.object.textAlignment = $0 }\n    public lazy var lineBreakMode: DependentValue<NSLineBreakMode> = DependentValue { [unowned self] in self.object.lineBreakMode = $0 }\n}\n#endif\n"
  },
  {
    "path": "Sources/UISearchBar Glue.swift",
    "content": "//\n//  UISearchBar Glue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2017-05-08.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport UIKit\n\nextension UISearchBar {\n    open override var glue: GlueForUISearchBar {\n        return _glue()\n    }\n}\n\nopen class GlueForUISearchBar: GlueForNSObject, UISearchBarDelegate {\n    private var object: UISearchBar { return owner as! UISearchBar }\n\n    public lazy var text: ComputedUpdatable<String?>\n        = ComputedUpdatable(\n            getter: { [unowned self] in self.object.text },\n            setter: { [unowned self] in self.object.text = $0 })\n\n    private lazy var _isEditing = Variable<Bool>(false)\n    public var isEditing: AnyObservableValue<Bool> { return _isEditing.anyObservableValue }\n\n    public required init(owner: NSObject) {\n        super.init(owner: owner)\n        object.delegate = self\n    }\n\n    public func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {\n        text.refresh()\n    }\n\n    public func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {\n        _isEditing.value = true\n    }\n\n    public func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {\n        _isEditing.value = false\n    }\n\n    public func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {\n        return true\n    }\n    public func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {\n        return true\n    }\n}\n\n#endif\n"
  },
  {
    "path": "Sources/UISwitch Glue.swift",
    "content": "//\n//  UISwitch Glue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-12.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n#if os(iOS)\nimport UIKit\n\nextension UISwitch {\n    open override var glue: GlueForUISwitch {\n        return _glue()\n    }\n}\n\nopen class GlueForUISwitch: GlueForUIControl {\n    private var object: UISwitch { return owner as! UISwitch }\n\n    public lazy var isOn: ComputedUpdatable<Bool>\n        = ComputedUpdatable(getter: { [unowned self] in self.object.isOn },\n                            setter: { [unowned self] in self.object.isOn = $0 },\n                            refreshSource: self.source(for: .valueChanged).mapToVoid())\n}\n\n#endif\n"
  },
  {
    "path": "Sources/UpdatableArray.swift",
    "content": "//\n//  UpdatableArray.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-11.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n//MARK: UpdatableArrayType\n\n/// An observable array that you can modify.\n///\n/// Note that while `UpdatableArrayType` and `UpdatableArray` implement some methods from `MutableCollectionType` and\n/// `RangeRaplacableCollectionType`, protocol conformance is intentionally not declared.\n///\n/// These collection protocols define their methods as mutable, which does not make sense for a generic updatable array,\n/// which is often a proxy that forwards these methods somewhere else (via some transformations).\n/// Also, it is not a good idea to do complex in-place manipulations (such as `sortInPlace`) on an array that has observers.\n/// Instead of `updatableArray.sortInPlace()`, which is not available, consider using\n/// `updatableArray.value = updatableArray.value.sort()`. The latter will probably be much more efficient.\npublic protocol UpdatableArrayType: ObservableArrayType, UpdatableType {\n\n    // Required members\n    var value: [Element] { get nonmutating set }\n    func apply(_ update: ArrayUpdate<Element>)\n    subscript(index: Int) -> Element { get nonmutating set }\n    subscript(bounds: Range<Int>) -> ArraySlice<Element> { get nonmutating set }\n\n    // The following are defined in extensions but may be specialized in implementations:\n\n    var anyUpdatableValue: AnyUpdatableValue<[Element]> { get }\n    var anyUpdatableArray: AnyUpdatableArray<Element> { get }\n}\n\nextension UpdatableArrayType {\n    public func apply(_ update: Update<ValueChange<[Element]>>) {\n        self.apply(update.map { change in ArrayChange(from: change.old, to: change.new) })\n    }\n\n    public var anyUpdatableValue: AnyUpdatableValue<[Element]> {\n        return AnyUpdatableValue(getter: { self.value },\n                                 apply: self.apply,\n                                 updates: self.valueUpdates)\n    }\n\n    public var anyUpdatableArray: AnyUpdatableArray<Element> {\n        return AnyUpdatableArray(box: UpdatableArrayBox(self))\n    }\n\n    public func replaceSubrange<C: Collection>(_ range: Range<Int>, with elements: C) where C.Iterator.Element == Element {\n        let old = Array(self[range])\n        let new = elements as? Array<Element> ?? Array(elements)\n        apply(ArrayChange(initialCount: self.count, modification: .replaceSlice(old, at: range.lowerBound, with: new)))\n    }\n\n    public func append(_ newElement: Element) {\n        let c = count\n        apply(ArrayChange(initialCount: c, modification: .insert(newElement, at: c)))\n    }\n\n    public func append<C: Collection>(contentsOf newElements: C) where C.Iterator.Element == Element {\n        let c = count\n        let new = newElements as? Array<Element> ?? Array(newElements)\n        apply(ArrayChange(initialCount: c, modification: .replaceSlice([], at: c, with: new)))\n    }\n\n    public func insert(_ newElement: Element, at i: Int) {\n        let c = count\n        apply(ArrayChange(initialCount: c, modification: .insert(newElement, at: i)))\n    }\n\n    public func insert<C: Collection>(contentsOf newElements: C, at i: Int) where C.Iterator.Element == Element {\n        let c = count\n        let new = newElements as? Array<Element> ?? Array(newElements)\n        apply(ArrayChange(initialCount: c, modification: .replaceSlice([], at: i, with: new)))\n    }\n\n    @discardableResult\n    public func remove(at index: Int) -> Element {\n        let c = count\n        let old = self[index]\n        apply(ArrayChange(initialCount: c, modification: .remove(old, at: index)))\n        return old\n    }\n\n    public func removeSubrange(_ subrange: Range<Int>) {\n        let c = count\n        let old = Array(self[subrange])\n        apply(ArrayChange(initialCount: c, modification: .replaceSlice(old, at: subrange.lowerBound, with: [])))\n    }\n\n    @discardableResult\n    public func removeFirst() -> Element {\n        let c = count\n        let old = self[0]\n        apply(ArrayChange(initialCount: c, modification: .remove(old, at: 0)))\n        return old\n    }\n\n    public func removeFirst(_ n: Int) {\n        let c = count\n        let old = Array(self[0 ..< n])\n        apply(ArrayChange(initialCount: c, modification: .replaceSlice(old, at: 0, with: [])))\n    }\n\n    @discardableResult\n    public func removeLast() -> Element {\n        let c = count\n        let old = self[c - 1]\n        apply(ArrayChange(initialCount: c, modification: .remove(old, at: c - 1)))\n        return old\n    }\n\n    public func removeLast(_ n: Int) {\n        let c = count\n        let old = Array(self[count - n ..< count])\n        apply(ArrayChange(initialCount: c, modification: .replaceSlice(old, at: count - n, with: [])))\n    }\n\n    public func removeAll() {\n        let c = count\n        let old = self.value\n        apply(ArrayChange(initialCount: c, modification: .replaceSlice(old, at: 0, with: [])))\n    }\n}\n\n\npublic struct AnyUpdatableArray<Element>: UpdatableArrayType {\n    public typealias Value = [Element]\n    public typealias Change = ArrayChange<Element>\n\n    let box: _AbstractUpdatableArray<Element>\n\n    init(box: _AbstractUpdatableArray<Element>) {\n        self.box = box\n    }\n\n    public init<Updatable: UpdatableArrayType>(_ base: Updatable) where Updatable.Element == Element {\n        self = base.anyUpdatableArray\n    }\n\n    public var isBuffered: Bool { return box.isBuffered }\n    public var count: Int { return box.count }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        box.add(sink)\n    }\n\n    @discardableResult\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        return box.remove(sink)\n    }\n\n    public var value: [Element] {\n        get { return box.value }\n        nonmutating set { box.value = newValue }\n    }\n    public subscript(index: Int) -> Element {\n        get { return box[index] }\n        nonmutating set { box[index] = newValue }\n    }\n\n    public subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        get { return box[bounds] }\n        nonmutating set { box[bounds] = newValue }\n    }\n\n    public func apply(_ update: Update<ArrayChange<Element>>) {\n        self.box.apply(update)\n    }\n\n    public var observableCount: AnyObservableValue<Int> { return box.observableCount }\n\n    public var anyObservableValue: AnyObservableValue<Array<Element>> { return box.anyObservableValue }\n    public var anyObservableArray: AnyObservableArray<Element> { return box.anyObservableArray }\n    public var anyUpdatableValue: AnyUpdatableValue<[Element]> { return box.anyUpdatableValue }\n    public var anyUpdatableArray: AnyUpdatableArray<Element> { return self }\n}\n\nopen class _AbstractUpdatableArray<Element>: _AbstractObservableArray<Element>, UpdatableArrayType {\n\n    open override var value: [Element] {\n        get { abstract() }\n        set { abstract() }\n    }\n    open override subscript(index: Int) -> Element {\n        get { abstract() }\n        set { abstract() }\n    }\n    open override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        get { abstract() }\n        set { abstract() }\n    }\n\n    open func apply(_ update: ArrayUpdate<Element>) { abstract() }\n\n    open var anyUpdatableValue: AnyUpdatableValue<[Element]> {\n        return AnyUpdatableValue(getter: { self.value },\n                                 apply: self.apply,\n                                 updates: self.valueUpdates)\n    }\n\n    public final var anyUpdatableArray: AnyUpdatableArray<Element> {\n        return AnyUpdatableArray(box: self)\n    }\n}\n\nopen class _BaseUpdatableArray<Element>: _AbstractUpdatableArray<Element>, TransactionalThing {\n    var _signal: TransactionalSignal<ArrayChange<Element>>? = nil\n    var _transactionCount = 0\n\n    func rawApply(_ change: ArrayChange<Element>) { abstract() }\n\n    public final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    public final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        return signal.remove(sink)\n    }\n\n    public final override func apply(_ update: Update<ArrayChange<Element>>) {\n        switch update {\n        case .beginTransaction:\n            self.beginTransaction()\n        case .change(let change):\n            self.rawApply(change)\n            self.sendChange(change)\n        case .endTransaction:\n            self.endTransaction()\n        }\n    }\n\n    open func activate() {\n        // Do nothing\n    }\n\n    open func deactivate() {\n        // Do nothing\n    }\n}\n\ninternal final class UpdatableArrayBox<Contents: UpdatableArrayType>: _AbstractUpdatableArray<Contents.Element> {\n    typealias Element = Contents.Element\n\n    var contents: Contents\n\n    init(_ contents: Contents) {\n        self.contents = contents\n    }\n\n    override func apply(_ update: ArrayUpdate<Element>) {\n        contents.apply(update)\n    }\n\n    override var value: [Element] {\n        get { return contents.value }\n        set { contents.value = newValue }\n    }\n\n    override subscript(index: Int) -> Element {\n        get { return contents[index] }\n        set { contents[index] = newValue }\n    }\n\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        get { return contents[bounds] }\n        set { contents[bounds] = newValue }\n    }\n\n    override var isBuffered: Bool { return contents.isBuffered }\n    override var count: Int { return contents.count }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        contents.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        return contents.remove(sink)\n    }\n\n    override var observableCount: AnyObservableValue<Int> { return contents.observableCount }\n    override var anyObservableValue: AnyObservableValue<[Element]> { return contents.anyObservableValue }\n    override var anyUpdatableValue: AnyUpdatableValue<Array<Contents.Element>> { return contents.anyUpdatableValue }\n}\n"
  },
  {
    "path": "Sources/UpdatableSet.swift",
    "content": "//\n//  UpdatableSet.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-08-13.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic protocol UpdatableSetType: ObservableSetType, UpdatableType {\n    var value: Base { get nonmutating set }\n    func apply(_ update: SetUpdate<Element>)\n\n    // Optional members\n    func remove(_ member: Element)\n    func insert(_ member: Element)\n    func removeAll()\n    func formUnion(_ other: Set<Element>)\n    func formIntersection(_ other: Set<Element>)\n    func formSymmetricDifference(_ other: Set<Element>)\n    func subtract(_ other: Set<Element>)\n    \n    var anyUpdatableValue: AnyUpdatableValue<Set<Element>> { get }\n    var anyUpdatableSet: AnyUpdatableSet<Element> { get }\n}\n\nextension UpdatableSetType {\n    public func remove(_ member: Element) {\n        // Note: This should be kept in sync with the same member in _AbstractUpdatableSet.\n        if contains(member) {\n            apply(SetChange(removed: [member]))\n        }\n    }\n\n    public func insert(_ member: Element) {\n        // Note: This should be kept in sync with the same member in _AbstractUpdatableSet.\n        if !contains(member) {\n            apply(SetChange(inserted: [member]))\n        }\n    }\n\n    public func removeAll() {\n        // Note: This should be kept in sync with the same member in _AbstractUpdatableSet.\n        if !isEmpty {\n            apply(SetChange(removed: self.value))\n        }\n    }\n\n    public func formUnion(_ other: Set<Element>) {\n        // Note: This should be kept in sync with the same member in _AbstractUpdatableSet.\n        let difference = other.subtracting(value)\n        self.apply(SetChange(inserted: difference))\n    }\n\n    public func formIntersection(_ other: Set<Element>) {\n        // Note: This should be kept in sync with the same member in _AbstractUpdatableSet.\n        let difference = value.subtracting(other)\n        self.apply(SetChange(removed: difference))\n    }\n\n    public func formSymmetricDifference(_ other: Set<Element>) {\n        // Note: This should be kept in sync with the same member in _AbstractUpdatableSet.\n        let value = self.value\n        let intersection = value.intersection(other)\n        let additions = other.subtracting(value)\n        self.apply(SetChange(removed: intersection, inserted: additions))\n    }\n\n    public func subtract(_ other: Set<Element>) {\n        // Note: This should be kept in sync with the same member in _AbstractUpdatableSet.\n        let intersection = value.intersection(other)\n        self.apply(SetChange(removed: intersection))\n    }\n\n    public func apply(_ update: ValueUpdate<Set<Element>>) {\n        self.apply(update.map { change in SetChange(from: change.old, to: change.new) })\n    }\n\n    public var anyUpdatableValue: AnyUpdatableValue<Set<Element>> {\n        return AnyUpdatableValue(\n            getter: { self.value },\n            apply: self.apply,\n            updates: self.valueUpdates)\n    }\n\n    public var anyUpdatableSet: AnyUpdatableSet<Element> {\n        return AnyUpdatableSet(box: UpdatableSetBox(self))\n    }\n}\n\npublic struct AnyUpdatableSet<Element: Hashable>: UpdatableSetType {\n    public typealias Value = Set<Element>\n    public typealias Base = Set<Element>\n    public typealias Change = SetChange<Element>\n\n    let box: _AbstractUpdatableSet<Element>\n\n    init(box: _AbstractUpdatableSet<Element>) {\n        self.box = box\n    }\n\n    public var isBuffered: Bool { return box.isBuffered }\n    public var count: Int { return box.count }\n    public var value: Set<Element> {\n        get { return box.value }\n        nonmutating set { box.value = newValue }\n    }\n    public func contains(_ member: Element) -> Bool { return box.contains(member) }\n    public func isSubset(of other: Set<Element>) -> Bool { return box.isSubset(of: other) }\n    public func isSuperset(of other: Set<Element>) -> Bool { return box.isSuperset(of: other) }\n\n    public func apply(_ update: SetUpdate<Element>) { box.apply(update) }\n    public func remove(_ member: Element) { box.remove(member) }\n    public func insert(_ member: Element) { box.insert(member) }\n    public func removeAll() { box.removeAll() }\n    public func formUnion(_ other: Set<Element>) { box.formUnion(other) }\n    public func formIntersection(_ other: Set<Element>) { box.formIntersection(other) }\n    public func formSymmetricDifference(_ other: Set<Element>) { box.formSymmetricDifference(other) }\n    public func subtract(_ other: Set<Element>) { box.subtract(other) }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<SetChange<Element>> {\n        box.add(sink)\n    }\n\n    @discardableResult\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<SetChange<Element>> {\n        return box.remove(sink)\n    }\n\n    public var observableCount: AnyObservableValue<Int> { return box.observableCount }\n\n    public var anyObservableValue: AnyObservableValue<Set<Element>> { return box.anyObservableValue }\n    public var anyObservableSet: AnyObservableSet<Element> { return box.anyObservableSet }\n    public var anyUpdatableValue: AnyUpdatableValue<Set<Element>> { return box.anyUpdatableValue }\n    public var anyUpdatableSet: AnyUpdatableSet<Element> { return self }\n}\n\nopen class _AbstractUpdatableSet<Element: Hashable>: _AbstractObservableSet<Element>, UpdatableSetType {\n    open override var value: Set<Element> {\n        get { abstract() }\n        set { abstract() }\n    }\n    open func apply(_ update: SetUpdate<Element>) { abstract() }\n\n    open func remove(_ member: Element) {\n        // Note: This should be kept in sync with the same member in the UpdatableSetType extension above.\n        if contains(member) {\n            apply(SetChange(removed: [member]))\n        }\n    }\n\n    open func insert(_ member: Element) {\n        // Note: This should be kept in sync with the same member in the UpdatableSetType extension above.\n        if !contains(member) {\n            apply(SetChange(inserted: [member]))\n        }\n    }\n\n    open func removeAll() {\n        // Note: This should be kept in sync with the same member in the UpdatableSetType extension above.\n        if !isEmpty {\n            apply(SetChange(removed: self.value))\n        }\n    }\n\n    open func formUnion(_ other: Set<Element>) {\n        // Note: This should be kept in sync with the same member in the UpdatableSetType extension above.\n        let difference = other.subtracting(value)\n        self.apply(SetChange(inserted: difference))\n    }\n\n    open func formIntersection(_ other: Set<Element>) {\n        // Note: This should be kept in sync with the same member in the UpdatableSetType extension above.\n        let difference = value.subtracting(other)\n        self.apply(SetChange(removed: difference))\n    }\n\n    open func formSymmetricDifference(_ other: Set<Element>) {\n        // Note: This should be kept in sync with the same member in the UpdatableSetType extension above.\n        let value = self.value\n        let intersection = value.intersection(other)\n        let additions = other.subtracting(value)\n        self.apply(SetChange(removed: intersection, inserted: additions))\n    }\n\n    open func subtract(_ other: Set<Element>) {\n        // Note: This should be kept in sync with the same member in the UpdatableSetType extension above.\n        let intersection = value.intersection(other)\n        self.apply(SetChange(removed: intersection))\n    }\n\n    open var anyUpdatableValue: AnyUpdatableValue<Set<Element>> {\n        return AnyUpdatableValue(\n            getter: { self.value },\n            apply: self.apply,\n            updates: self.valueUpdates)\n    }\n\n    public final var anyUpdatableSet: AnyUpdatableSet<Element> {\n        return AnyUpdatableSet(box: self)\n    }\n}\n\nopen class _BaseUpdatableSet<Element: Hashable>: _AbstractUpdatableSet<Element>, TransactionalThing {\n    public typealias Change = SetChange<Element>\n\n    var _signal: TransactionalSignal<SetChange<Element>>? = nil\n    var _transactionCount: Int = 0\n\n    func rawApply(_ change: Change) { abstract() }\n\n    public final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    public final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n\n    public final override func apply(_ update: Update<Change>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            rawApply(change)\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    open func activate() {\n        // Do nothing\n    }\n\n    open func deactivate() {\n        // Do nothing\n    }\n}\n\nfinal class UpdatableSetBox<Contents: UpdatableSetType>: _AbstractUpdatableSet<Contents.Element> {\n    typealias Element = Contents.Element\n    typealias Change = SetChange<Element>\n\n    let contents: Contents\n\n    init(_ contents: Contents) {\n        self.contents = contents\n    }\n\n    override var isBuffered: Bool { return contents.isBuffered }\n    override var count: Int { return contents.count }\n\n    override var value: Set<Element> {\n        get { return contents.value }\n        set { contents.value = newValue }\n    }\n\n    override func apply(_ update: SetUpdate<Element>) { contents.apply(update) }\n\n    override func remove(_ member: Element) { contents.remove(member) }\n    override func insert(_ member: Element) { contents.insert(member) }\n    override func removeAll() { contents.removeAll() }\n    override func formUnion(_ other: Set<Element>) { contents.formUnion(other) }\n    override func formIntersection(_ other: Set<Element>) { contents.formIntersection(other) }\n    override func formSymmetricDifference(_ other: Set<Element>) { contents.formSymmetricDifference(other) }\n    override func subtract(_ other: Set<Element>) { contents.subtract(other) }\n\n    override func contains(_ member: Element) -> Bool { return contents.contains(member) }\n    override func isSubset(of other: Set<Element>) -> Bool { return contents.isSubset(of: other) }\n    override func isSuperset(of other: Set<Element>) -> Bool { return contents.isSuperset(of: other) }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        contents.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return contents.remove(sink)\n    }\n\n    override var observableCount: AnyObservableValue<Int> { return contents.observableCount }\n\n    override var anyObservableValue: AnyObservableValue<Set<Element>> { return contents.anyObservableValue }\n    override var anyUpdatableValue: AnyUpdatableValue<Set<Element>> { return contents.anyUpdatableValue }\n}\n"
  },
  {
    "path": "Sources/UpdatableValue.swift",
    "content": "//\n//  Updatable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// An observable thing that also includes support for updating its value.\npublic protocol UpdatableValueType: ObservableValueType, UpdatableType {\n    /// Returns the type-erased version of this UpdatableValueType.\n    var anyUpdatableValue: AnyUpdatableValue<Value> { get }\n}\n\nextension UpdatableValueType {\n    /// Returns the type-erased version of this UpdatableValueType.\n    public var anyUpdatableValue: AnyUpdatableValue<Value> {\n        return AnyUpdatableValue(self)\n    }\n}\n\n/// The type erased representation of an UpdatableValueType.\npublic struct AnyUpdatableValue<Value>: UpdatableValueType {\n    public typealias Change = ValueChange<Value>\n\n    private let box: _AbstractUpdatableValue<Value>\n\n    init(box: _AbstractUpdatableValue<Value>) {\n        self.box = box\n    }\n\n    public init<Updates: SourceType>(getter: @escaping () -> Value,\n                                     apply: @escaping (Update<ValueChange<Value>>) -> Void,\n                                     updates: Updates)\n        where Updates.Value == Update<Change> {\n        self.box = UpdatableClosureBox(getter: getter,\n                                       apply: apply,\n                                       updates: updates)\n    }\n\n    public init<Base: UpdatableValueType>(_ base: Base) where Base.Value == Value {\n        self.box = UpdatableBox(base)\n    }\n\n    public var value: Value {\n        get { return box.value }\n        nonmutating set { box.value = newValue }\n    }\n\n    public func apply(_ update: Update<Change>) {\n        box.apply(update)\n    }\n\n    public func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        box.add(sink)\n    }\n\n    @discardableResult\n    public func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return box.remove(sink)\n    }\n\n    public var anyObservableValue: AnyObservableValue<Value> {\n        return box.anyObservableValue\n    }\n\n    public var anyUpdatableValue: AnyUpdatableValue<Value> {\n        return self\n    }\n}\n\nopen class _AbstractUpdatableValue<Value>: _AbstractObservableValue<Value>, UpdatableValueType {\n    public typealias Change = ValueChange<Value>\n\n    open override var value: Value {\n        get { abstract() }\n        set { abstract() }\n    }\n    open func apply(_ update: Update<Change>) { abstract() }\n\n    public final var anyUpdatableValue: AnyUpdatableValue<Value> { return AnyUpdatableValue(box: self) }\n}\n\nopen class _BaseUpdatableValue<Value>: _AbstractUpdatableValue<Value>, TransactionalThing {\n    var _signal: TransactionalSignal<ValueChange<Value>>? = nil\n    var _transactionCount = 0\n\n    func rawGetValue() -> Value { abstract() }\n    func rawSetValue(_ value: Value) { abstract() }\n\n    public final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    public final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n\n    public final override var value: Value {\n        get {\n            return rawGetValue()\n        }\n        set {\n            beginTransaction()\n            let old = rawGetValue()\n            rawSetValue(newValue)\n            sendChange(ValueChange(from: old, to: newValue))\n            endTransaction()\n        }\n    }\n\n    public final override func apply(_ update: Update<Change>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            rawSetValue(change.new)\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    open func activate() {\n        // Do nothing\n    }\n\n    open func deactivate() {\n        // Do nothing\n    }\n}\n\ninternal final class UpdatableBox<Base: UpdatableValueType>: _AbstractUpdatableValue<Base.Value> {\n    typealias Value = Base.Value\n    private let base: Base\n\n    init(_ base: Base) {\n        self.base = base\n    }\n\n    override var value: Value {\n        get { return base.value }\n        set { base.value = newValue }\n    }\n\n    override func apply(_ update: Update<ValueChange<Value>>) {\n        base.apply(update)\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        base.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return base.remove(sink)\n    }\n}\n\nprivate final class UpdatableClosureBox<Value, Updates: SourceType>: _AbstractUpdatableValue<Value>\nwhere Updates.Value == Update<ValueChange<Value>> {\n    /// The getter closure for the current value of this updatable.\n    private let _getter: () -> Value\n    private let _apply: (Update<ValueChange<Value>>) -> Void\n    /// A closure returning a source providing the values of future updates to this updatable.\n    private let _updates: Updates\n\n    public init(getter: @escaping () -> Value,\n                apply: @escaping (Update<ValueChange<Value>>) -> Void,\n                updates: Updates) {\n        self._getter = getter\n        self._apply = apply\n        self._updates = updates\n    }\n\n    override var value: Value {\n        get { return _getter() }\n        set {\n            _apply(.beginTransaction)\n            _apply(.change(ValueChange(from: _getter(), to: newValue)))\n            _apply(.endTransaction)\n        }\n    }\n\n    override func apply(_ update: Update<ValueChange<Value>>) {\n        _apply(update)\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        _updates.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return _updates.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Sources/Update.swift",
    "content": "//\n//  Update.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// Updates are events that describe a change that is happening to an observable.\n/// Observables only change inside transactions. A transaction consists three phases, represented\n/// by the three cases of this enum type:\n///\n/// - `beginTransaction` signals the start of a new transaction.\n/// - `change` describes a (partial) change to the value of the observable.\n///   Each transaction may include any number of such changes.\n/// - `endTransaction` closes the transaction.\n///\n/// While a transaction is in progress, the value of an observable includes all changes that have already been\n/// reported in updates.\n///\n/// Note that is perfectly legal for a transaction to include no actual changes.\npublic enum Update<Change: ChangeType> {\n    public typealias Value = Change.Value\n\n    /// Hang on, I feel a change coming up.\n    case beginTransaction\n    /// Here is one change, but I think there might be more coming.\n    case change(Change)\n    /// OK, I'm done changing.\n    case endTransaction\n}\n\nextension Update {\n    public var change: Change? {\n        if case let .change(change) = self { return change }\n        return nil\n    }\n\n    public func filter(_ test: (Change) -> Bool) -> Update<Change>? {\n        switch self {\n        case .beginTransaction, .endTransaction:\n            return self\n        case .change(let change):\n            if test(change) {\n                return self\n            }\n            return nil\n        }\n    }\n\n    public func map<Result: ChangeType>(_ transform: (Change) -> Result) -> Update<Result> {\n        switch self {\n        case .beginTransaction:\n            return .beginTransaction\n        case .change(let change):\n            return .change(transform(change))\n        case .endTransaction:\n            return .endTransaction\n        }\n    }\n\n    public func flatMap<Result: ChangeType>(_ transform: (Change) -> Result?) -> Update<Result>? {\n        switch self {\n        case .beginTransaction:\n            return .beginTransaction\n        case .change(let change):\n            guard let new = transform(change) else { return nil }\n            return .change(new)\n        case .endTransaction:\n            return .endTransaction\n        }\n    }\n\n}\n"
  },
  {
    "path": "Sources/ValueChange.swift",
    "content": "//\n//  ValueChange.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-04.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// A simple change description that includes a snapshot of the value before and after the change.\npublic struct ValueChange<Value>: ChangeType {\n    public var old: Value\n    public var new: Value\n\n    public init(from old: Value, to new: Value) {\n        self.old = old\n        self.new = new\n    }\n\n    public var isEmpty: Bool {\n        // There is no way to compare old and new at this level.\n        return false\n    }\n\n    public func apply(on value: inout Value) {\n        value = new\n    }\n\n    public func applied(on value: Value) -> Value {\n        return new\n    }\n\n    public mutating func merge(with next: ValueChange) {\n        self.new = next.new\n    }\n\n    public func merged(with next: ValueChange) -> ValueChange {\n        return .init(from: old, to: next.new)\n    }\n\n    public func reversed() -> ValueChange {\n        return .init(from: new, to: old)\n    }\n\n    public func map<R>(_ transform: (Value) -> R) -> ValueChange<R> {\n        return .init(from: transform(old), to: transform(new))\n    }\n}\n\nextension ValueChange: CustomStringConvertible {\n    public var description: String {\n        return \"\\(old) -> \\(new)\"\n    }\n}\n\npublic func ==<Value: Equatable>(a: ValueChange<Value>, b: ValueChange<Value>) -> Bool {\n    return a.old == b.old && a.new == b.new\n}\n\npublic func !=<Value: Equatable>(a: ValueChange<Value>, b: ValueChange<Value>) -> Bool {\n    return !(a == b)\n}\n"
  },
  {
    "path": "Sources/ValueMappingForArrayField.swift",
    "content": "//\n//  ValueMappingForArrayField.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType {\n\n    /// Map is an operator that implements key path coding and observing.\n    /// Given an observable parent and a key that selects an observable child component (a.k.a \"field\") of its value,\n    /// `map` returns a new observable that can be used to look up and modify the field and observe its changes\n    /// indirectly through the parent. If the field is an observable array, then the result will be, too.\n    ///\n    /// @param key: An accessor function that returns a component of self (a field) that is an observable array.\n    /// @returns A new observable array that tracks changes to both self and the field returned by `key`.\n    ///\n    /// For example, take the model for a hypothetical group chat system below.\n    /// ```\n    /// class Account {\n    ///     let name: Variable<String>\n    ///     let avatar: Variable<Image>\n    /// }\n    /// class Message {\n    ///     let author: Variable<Account>\n    ///     let text: Variable<String>\n    /// }\n    /// class Room {\n    ///     let latestMessage: AnyObservableValue<Message>\n    ///     let messages: ArrayVariable<Message>\n    ///     let newMessages: Source<Message>\n    /// }\n    /// let currentRoom: Variable<Room>\n    /// ```\n    ///\n    /// You can create an observable array for all messages in the current room with\n    /// ```Swift\n    /// let observable = currentRoom.map{$0.messages}\n    /// ```\n    /// Sinks connected to `observable.changes` will fire whenever the current room changes, or when the list of\n    /// messages is updated in the current room.  The observable can also be used to simply retrieve the list of messages\n    /// at any time.\n    ///\n    public func map<Field: ObservableArrayType>(_ key: @escaping (Value) -> Field) -> AnyObservableArray<Field.Element> {\n        return ValueMappingForArrayField(parent: self, key: key).anyObservableArray\n    }\n\n    public func map<Field: UpdatableArrayType>(_ key: @escaping (Value) -> Field) -> AnyUpdatableArray<Field.Element> {\n        return ValueMappingForUpdatableArrayField(parent: self, key: key).anyUpdatableArray\n    }\n}\n\n/// A source of changes for an AnyObservableArray field.\nprivate final class UpdateSourceForArrayField<Parent: ObservableValueType, Field: ObservableArrayType>\n: TransactionalSource<ArrayChange<Field.Element>> {\n    typealias Element = Field.Element\n    typealias Base = [Element]\n    typealias Change = ArrayChange<Element>\n\n    private struct ParentSink: OwnedSink {\n        typealias Owner = UpdateSourceForArrayField\n\n        unowned let owner: Owner\n        let identifier = 1\n\n        func receive(_ update: ValueUpdate<Parent.Value>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n\n    private struct FieldSink: OwnedSink {\n        typealias Owner = UpdateSourceForArrayField\n\n        unowned let owner: Owner\n        let identifier = 2\n\n        func receive(_ update: ArrayUpdate<Field.Element>) {\n            owner.applyFieldUpdate(update)\n        }\n    }\n\n    let parent: Parent\n    let key: (Parent.Value) -> Field\n\n    private var field: Field? = nil\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        self.parent = parent\n        self.key = key\n    }\n\n    override func activate() {\n        let field = key(parent.value)\n        parent.add(ParentSink(owner: self))\n        field.add(FieldSink(owner: self))\n        self.field = field\n    }\n\n    override func deactivate() {\n        parent.remove(ParentSink(owner: self))\n        field!.remove(FieldSink(owner: self))\n        field = nil\n    }\n\n    func applyParentUpdate(_ update: ValueUpdate<Parent.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let old = key(change.old).value\n            let field = self.key(change.new)\n            self.field!.remove(FieldSink(owner: self))\n            self.field = field\n            field.add(FieldSink(owner: self))\n            sendChange(.init(from: old, to: field.value))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: ArrayUpdate<Field.Element>) {\n        signal.send(update)\n    }\n}\n\nprivate final class ValueMappingForArrayField<Parent: ObservableValueType, Field: ObservableArrayType>: _AbstractObservableArray<Field.Element> {\n    typealias Element = Field.Element\n    typealias Change = ArrayChange<Element>\n\n    private let updateSource: UpdateSourceForArrayField<Parent, Field>\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        updateSource = UpdateSourceForArrayField(parent: parent, key: key)\n    }\n    var parent: Parent { return updateSource.parent }\n    var key: (Parent.Value) -> Field { return updateSource.key }\n    var field: Field { return updateSource.key(updateSource.parent.value) }\n\n    override var isBuffered: Bool { return field.isBuffered }\n    override subscript(_ index: Int) -> Element { return field[index] }\n    override subscript(_ range: Range<Int>) -> ArraySlice<Element> { return field[range] }\n    override var value: Array<Element> { return field.value }\n    override var count: Int { return field.count }\n    override var observableCount: AnyObservableValue<Int> { return parent.map { self.key($0).observableCount } }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        updateSource.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return updateSource.remove(sink)\n    }\n}\n\nprivate final class ValueMappingForUpdatableArrayField<Parent: ObservableValueType, Field: UpdatableArrayType>: _AbstractUpdatableArray<Field.Element> {\n    typealias Element = Field.Element\n    typealias Change = ArrayChange<Element>\n\n    let updateSource: UpdateSourceForArrayField<Parent, Field>\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        updateSource = UpdateSourceForArrayField(parent: parent, key: key)\n    }\n    var parent: Parent { return updateSource.parent }\n    var key: (Parent.Value) -> Field { return updateSource.key }\n    var field: Field { return updateSource.key(updateSource.parent.value) }\n\n    override var isBuffered: Bool { return field.isBuffered }\n    override subscript(_ index: Int) -> Element {\n        get { return field[index] }\n        set { field[index] = newValue }\n    }\n    override subscript(_ range: Range<Int>) -> ArraySlice<Element> {\n        get { return field[range] }\n        set { field[range] = newValue }\n    }\n    override var value: Array<Element> {\n        get { return field.value }\n        set { field.value = newValue }\n    }\n    override var count: Int { return field.count }\n    override var observableCount: AnyObservableValue<Int> { return parent.map { self.key($0).observableCount } }\n    override func apply(_ update: Update<ArrayChange<Field.Element>>) { field.apply(update) }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        updateSource.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return updateSource.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Sources/ValueMappingForSetField.swift",
    "content": "//\n//  ValueMappingForSetField.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType {\n    public func map<Field: ObservableSetType>(_ key: @escaping (Value) -> Field) -> AnyObservableSet<Field.Element> {\n        return ValueMappingForSetField<Self, Field>(parent: self, key: key).anyObservableSet\n    }\n\n    public func map<Field: UpdatableSetType>(_ key: @escaping (Value) -> Field) -> AnyUpdatableSet<Field.Element> {\n        return ValueMappingForUpdatableSetField<Self, Field>(parent: self, key: key).anyUpdatableSet\n    }\n}\n\nprivate final class UpdateSourceForSetField<Parent: ObservableValueType, Field: ObservableSetType>: TransactionalSource<SetChange<Field.Element>> {\n    typealias Element = Field.Element\n    typealias Change = SetChange<Element>\n    typealias Value = Update<Change>\n\n    private struct ParentSink: OwnedSink {\n        typealias Owner = UpdateSourceForSetField\n\n        unowned let owner: Owner\n        let identifier = 1\n\n        func receive(_ update: ValueUpdate<Parent.Value>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n\n    private struct FieldSink: OwnedSink {\n        typealias Owner = UpdateSourceForSetField\n\n        unowned let owner: Owner\n        let identifier = 2\n\n        func receive(_ update: SetUpdate<Field.Element>) {\n            owner.applyFieldUpdate(update)\n        }\n    }\n\n\n    let parent: Parent\n    let key: (Parent.Value) -> Field\n\n    private var _field: Field? = nil\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        self.parent = parent\n        self.key = key\n    }\n\n    fileprivate var field: Field {\n        if let field = self._field { return field }\n        return key(parent.value)\n    }\n\n    override func activate() {\n        let field = key(parent.value)\n        field.add(FieldSink(owner: self))\n        parent.add(ParentSink(owner: self))\n        _field = field\n    }\n\n    override func deactivate() {\n        parent.remove(ParentSink(owner: self))\n        _field!.remove(FieldSink(owner: self))\n        _field = nil\n    }\n\n    private func subscribe(to field: Field) {\n        _field!.remove(FieldSink(owner: self))\n        _field = field\n        field.add(FieldSink(owner: self))\n    }\n\n    func applyParentUpdate(_ update: ValueUpdate<Parent.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let oldValue = self._field!.value\n            let field = self.key(change.new)\n            self.subscribe(to: field)\n            sendChange(SetChange(removed: oldValue, inserted: field.value))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: SetUpdate<Field.Element>) {\n        send(update)\n    }\n}\n\nprivate final class ValueMappingForSetField<Parent: ObservableValueType, Field: ObservableSetType>: _AbstractObservableSet<Field.Element> {\n    typealias Element = Field.Element\n\n    private let updateSource: UpdateSourceForSetField<Parent, Field>\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        self.updateSource = .init(parent: parent, key: key)\n    }\n\n    var field: Field { return updateSource.field }\n\n    override var isBuffered: Bool { return field.isBuffered }\n    override var count: Int { return field.count }\n    override var value: Set<Element> { return field.value }\n    override func contains(_ member: Element) -> Bool { return field.contains(member) }\n    override func isSubset(of other: Set<Element>) -> Bool { return field.isSubset(of: other) }\n    override func isSuperset(of other: Set<Element>) -> Bool { return field.isSuperset(of: other) }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        updateSource.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return updateSource.remove(sink)\n    }\n}\n\nprivate final class ValueMappingForUpdatableSetField<Parent: ObservableValueType, Field: UpdatableSetType>: _AbstractUpdatableSet<Field.Element> {\n    typealias Element = Field.Element\n\n    private let updateSource: UpdateSourceForSetField<Parent, Field>\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        self.updateSource = .init(parent: parent, key: key)\n    }\n\n    var field: Field { return updateSource.field }\n\n    override var isBuffered: Bool { return field.isBuffered }\n    override var count: Int { return field.count }\n    override var value: Set<Element> {\n        get { return field.value }\n        set { field.value = newValue }\n    }\n    override func contains(_ member: Element) -> Bool { return field.contains(member) }\n    override func isSubset(of other: Set<Element>) -> Bool { return field.isSubset(of: other) }\n    override func isSuperset(of other: Set<Element>) -> Bool { return field.isSuperset(of: other) }\n\n    override func apply(_ update: SetUpdate<Element>) { field.apply(update) }\n\n    override func remove(_ member: Element) { field.remove(member) }\n    override func insert(_ member: Element) { field.insert(member) }\n    override func removeAll() { field.removeAll() }\n    override func formUnion(_ other: Set<Field.Element>) { field.formUnion(other) }\n    override func formIntersection(_ other: Set<Field.Element>) { field.formIntersection(other) }\n    override func formSymmetricDifference(_ other: Set<Field.Element>) { field.formSymmetricDifference(other) }\n    override func subtract(_ other: Set<Field.Element>) { field.subtract(other) }\n\n    final override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        updateSource.add(sink)\n    }\n\n    @discardableResult\n    final override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return updateSource.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Sources/ValueMappingForSourceField.swift",
    "content": "//\n//  ValueMappingForSourceField.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType {\n    /// Map is an operator that implements key path coding and observing.\n    /// Given an observable parent and a key that selects a child component (a.k.a \"field\") of its value that is a source,\n    /// `map` returns a new source that can be used subscribe to the field indirectly through the parent.\n    ///\n    /// - Parameter key: An accessor function that returns a component of self (a field) that is a SourceType.\n    ///\n    /// - Returns: A new source that sends the same values as the current source returned by key in the parent.\n    public func map<Source: SourceType>(_ key: @escaping (Value) -> Source) -> AnySource<Source.Value> {\n        return ValueMappingForSourceField(parent: self, key: key).anySource\n    }\n}\n\n/// A source of values for a Source field.\nprivate final class ValueMappingForSourceField<Parent: ObservableValueType, Field: SourceType>: SignalerSource<Field.Value> {\n    typealias Value = Field.Value\n\n    private struct SourceFieldSink: UniqueOwnedSink {\n        typealias Owner = ValueMappingForSourceField\n\n        unowned let owner: Owner\n\n        func receive(_ update: ValueUpdate<Parent.Value>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n\n    let parent: Parent\n    let key: (Parent.Value) -> Field\n\n    private var _field: Field? = nil\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        self.parent = parent\n        self.key = key\n    }\n\n    override func activate() {\n        precondition(_field == nil)\n        let field = key(parent.value)\n        _field = field\n        parent.add(SourceFieldSink(owner: self))\n        field.add(signal.asSink)\n    }\n\n    override func deactivate() {\n        _field!.remove(signal.asSink)\n        _field = nil\n        parent.remove(SourceFieldSink(owner: self))\n    }\n\n    func applyParentUpdate(_ update: ValueUpdate<Parent.Value>) {\n        switch update {\n        case .beginTransaction:\n            break\n        case .change(let change):\n            let field = key(change.new)\n            _field!.remove(signal.asSink)\n            _field = field\n            field.add(signal.asSink)\n        case .endTransaction:\n            break\n        }\n    }\n}\n"
  },
  {
    "path": "Sources/ValueMappingForValue.swift",
    "content": "//\n//  ValueMappingForValue.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\npublic extension ObservableValueType {\n    /// Returns an observable that calculates `transform` on all current and future values of this observable.\n    public func map<Output>(_ transform: @escaping (Value) -> Output) -> AnyObservableValue<Output> {\n        return ValueMappingForValue<Self, Output>(parent: self, transform: transform).anyObservableValue\n    }\n}\n\nprivate final class ValueMappingForValue<Parent: ObservableValueType, Value>: _AbstractObservableValue<Value> {\n    let parent: Parent\n    let transform: (Parent.Value) -> Value\n    let sinkTransform: SinkTransformFromMapping<ValueUpdate<Parent.Value>, ValueUpdate<Value>>\n\n    init(parent: Parent, transform: @escaping (Parent.Value) -> Value) {\n        self.parent = parent\n        self.transform = transform\n        self.sinkTransform = SinkTransformFromMapping { u in u.map { c in c.map(transform) } }\n    }\n\n    override var value: Value {\n        return transform(parent.value)\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        parent.add(TransformedSink(sink: sink, transform: sinkTransform))\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return parent.remove(TransformedSink(sink: sink, transform: sinkTransform)).sink\n    }\n}\n\nextension UpdatableValueType {\n    public func map<Output>(_ transform: @escaping (Value) -> Output, inverse: @escaping (Output) -> Value) -> AnyUpdatableValue<Output> {\n        return ValueMappingForUpdatableValue<Self, Output>(parent: self, transform: transform, inverse: inverse).anyUpdatableValue\n    }\n}\n\nprivate final class ValueMappingForUpdatableValue<Parent: UpdatableValueType, Value>: _AbstractUpdatableValue<Value> {\n    let parent: Parent\n    let transform: (Parent.Value) -> Value\n    let inverse: (Value) -> Parent.Value\n    let sinkTransform: SinkTransformFromMapping<ValueUpdate<Parent.Value>, ValueUpdate<Value>>\n\n    init(parent: Parent, transform: @escaping (Parent.Value) -> Value, inverse: @escaping (Value) -> Parent.Value) {\n        self.parent = parent\n        self.transform = transform\n        self.inverse = inverse\n        self.sinkTransform = SinkTransformFromMapping { u in u.map { c in c.map(transform) } }\n    }\n\n    override var value: Value {\n        get {\n            return transform(parent.value)\n        }\n        set {\n            parent.value = inverse(newValue)\n        }\n    }\n\n    override func apply(_ update: Update<ValueChange<Value>>) {\n        parent.apply(update.map { change in change.map(inverse) })\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        parent.add(TransformedSink(sink: sink, transform: sinkTransform))\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return parent.remove(TransformedSink(sink: sink, transform: sinkTransform)).sink\n    }\n}\n"
  },
  {
    "path": "Sources/ValueMappingForValueField.swift",
    "content": "//\n//  SelectOperator.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-06.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType {\n    /// Map is an operator that implements key path coding and observing.\n    /// Given an observable parent and a key that selects an observable child component (a.k.a \"field\") of its value,\n    /// `map` returns a new observable that can be used to look up and modify the field and observe its changes\n    /// indirectly through the parent.\n    ///\n    /// @param key: An accessor function that returns a component of self (a field) that is itself observable.\n    /// @returns A new observable that tracks changes to both self and the field returned by `key`.\n    ///\n    /// For example, take the model for a hypothetical group chat system below.\n    /// ```\n    /// class Account {\n    ///     let name: Variable<String>\n    ///     let avatar: Variable<Image>\n    /// }\n    /// class Message {\n    ///     let author: Variable<Account>\n    ///     let text: Variable<String>\n    /// }\n    /// class Room {\n    ///     let latestMessage: AnyObservableValue<Message>\n    ///     let newMessages: Source<Message>\n    ///     let messages: ArrayVariable<Message>\n    /// }\n    /// let currentRoom: Variable<Room>\n    /// ```\n    ///\n    /// You can create an observable for the latest message in the current room with\n    /// ```Swift\n    /// let observable = currentRoom.map{$0.latestMessage}\n    /// ```\n    /// Sinks connected to `observable.futureValues` will fire whenever the current room changes, or when a new\n    /// message is posted in the current room. The observable can also be used to simply retrieve the latest\n    /// message at any time.\n    ///\n    public func map<O: ObservableValueType>(_ key: @escaping (Value) -> O) -> AnyObservableValue<O.Value> {\n        return ValueMappingForValueField(parent: self, key: key).anyObservableValue\n    }\n}\n\n\n/// A source of changes for an Observable field.\nprivate final class ValueMappingForValueField<Parent: ObservableValueType, Field: ObservableValueType>: _BaseObservableValue<Field.Value> {\n    typealias Value = Field.Value\n    typealias Change = ValueChange<Value>\n\n    struct ParentSink: OwnedSink {\n        typealias Owner = ValueMappingForValueField<Parent, Field>\n\n        unowned let owner: Owner\n        let identifier = 1\n\n        func receive(_ update: ValueUpdate<Parent.Value>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n\n    struct FieldSink: OwnedSink {\n        typealias Owner = ValueMappingForValueField<Parent, Field>\n\n        unowned let owner: Owner\n        let identifier = 2\n\n        func receive(_ update: ValueUpdate<Field.Value>) {\n            owner.applyFieldUpdate(update)\n        }\n    }\n\n    let parent: Parent\n    let key: (Parent.Value) -> Field\n\n    private var currentValue: Field.Value? = nil\n    private var field: Field? = nil\n\n    override var value: Field.Value {\n        if let v = currentValue { return v }\n        return key(parent.value).value\n    }\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        self.parent = parent\n        self.key = key\n    }\n\n    override func activate() {\n        precondition(currentValue == nil)\n        let field = key(parent.value)\n        self.currentValue = field.value\n        subscribe(to: field)\n        parent.add(ParentSink(owner: self))\n    }\n\n    override func deactivate() {\n        precondition(currentValue != nil)\n        self.field!.remove(FieldSink(owner: self))\n        parent.remove(ParentSink(owner: self))\n        self.field = nil\n        self.currentValue = nil\n    }\n\n    private func subscribe(to field: Field) {\n        self.field?.remove(FieldSink(owner: self))\n        self.field = field\n        field.add(FieldSink(owner: self))\n    }\n\n    func applyParentUpdate(_ update: ValueUpdate<Parent.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let field = key(change.new)\n            let old = currentValue!\n            let new = field.value\n            currentValue = new\n            sendChange(ValueChange(from: old, to: new))\n            subscribe(to: field)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: ValueUpdate<Field.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let old = currentValue!\n            currentValue = change.new\n            sendChange(ValueChange(from: old, to: change.new))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n\nextension ObservableValueType {\n    public func flatMap<O: ObservableValueType>(_ key: @escaping (Value) -> O?) -> AnyObservableValue<O.Value?> {\n        return ValueMappingForOptionalValueField(parent: self, key: key).anyObservableValue\n    }\n}\n\nprivate final class ValueMappingForOptionalValueField<Parent: ObservableValueType, Field: ObservableValueType>: _BaseObservableValue<Field.Value?> {\n    typealias Value = Field.Value?\n    typealias Change = ValueChange<Value>\n\n    struct ParentSink: OwnedSink {\n        typealias Owner = ValueMappingForOptionalValueField<Parent, Field>\n\n        unowned let owner: Owner\n        let identifier = 1\n\n        func receive(_ update: ValueUpdate<Parent.Value>) {\n            owner.applyParentUpdate(update)\n        }\n    }\n\n    struct FieldSink: OwnedSink {\n        typealias Owner = ValueMappingForOptionalValueField<Parent, Field>\n\n        unowned let owner: Owner\n        let identifier = 2\n\n        func receive(_ update: ValueUpdate<Field.Value>) {\n            owner.applyFieldUpdate(update)\n        }\n    }\n\n    let parent: Parent\n    let key: (Parent.Value) -> Field?\n\n    private var activated = false\n    private var currentValue: Field.Value? = nil\n    private var field: Field? = nil\n\n    override var value: Value {\n        if activated { return currentValue }\n        return key(parent.value)?.value\n    }\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field?) {\n        self.parent = parent\n        self.key = key\n    }\n\n    override func activate() {\n        precondition(!activated)\n        activated = true\n        if let field = key(parent.value) {\n            self.currentValue = field.value\n            subscribe(to: field)\n        }\n        else {\n            self.currentValue = nil\n        }\n        parent.add(ParentSink(owner: self))\n    }\n\n    override func deactivate() {\n        precondition(activated)\n        self.field?.remove(FieldSink(owner: self))\n        parent.remove(ParentSink(owner: self))\n        self.field = nil\n        self.currentValue = nil\n        activated = false\n    }\n\n    private func subscribe(to field: Field) {\n        self.field?.remove(FieldSink(owner: self))\n        self.field = field\n        field.add(FieldSink(owner: self))\n    }\n\n    func applyParentUpdate(_ update: ValueUpdate<Parent.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let field = key(change.new)\n            let old = currentValue\n            let new = field?.value\n            currentValue = new\n            sendChange(ValueChange(from: old, to: new))\n            if let field = field {\n                subscribe(to: field)\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyFieldUpdate(_ update: ValueUpdate<Field.Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            let old = currentValue\n            currentValue = change.new\n            sendChange(ValueChange(from: old, to: change.new))\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n\nextension ObservableValueType {\n    /// Map is an operator that implements key path coding and observing.\n    /// Given an observable parent and a key that selects an observable child component (a.k.a \"field\") of its value,\n    /// `map` returns a new observable that can be used to look up and modify the field and observe its changes\n    /// indirectly through the parent. If the field is updatable, then the result will be, too.\n    ///\n    /// @param key: An accessor function that returns a component of self (a field) that is itself updatable.\n    /// @returns A new updatable that tracks changes to both self and the field returned by `key`.\n    ///\n    /// For example, take the model for a hypothetical group chat system below.\n    /// ```\n    /// class Account {\n    ///     let name: Variable<String>\n    ///     let avatar: Variable<Image>\n    /// }\n    /// class Message {\n    ///     let author: Variable<Account>\n    ///     let text: Variable<String>\n    /// }\n    /// class Room {\n    ///     let latestMessage: AnyObservableValue<Message>\n    ///     let messages: ArrayVariable<Message>\n    ///     let newMessages: Source<Message>\n    /// }\n    /// let currentRoom: Variable<Room>\n    /// ```\n    ///\n    /// You can create an updatable for the avatar image of the author of the latest message in the current room with\n    /// ```Swift\n    /// let updatable = currentRoom.map{$0.latestMessage}.map{$0.author}.map{$0.avatar}\n    /// ```\n    /// Sinks connected to `updatable.futureValues` will fire whenever the current room changes, or when a new message is posted\n    /// in the current room, or when the author of that message is changed, or when the current\n    /// author changes their avatar. The updatable can also be used to simply retrieve the avatar at any time,\n    /// or to update it.\n    ///\n    public func map<U: UpdatableValueType>(_ key: @escaping (Value) -> U) -> AnyUpdatableValue<U.Value> {\n        return ValueMappingForUpdatableField<Self, U>(parent: self, key: key).anyUpdatableValue\n    }\n}\n\nprivate final class ValueMappingForUpdatableField<Parent: ObservableValueType, Field: UpdatableValueType>: _AbstractUpdatableValue<Field.Value> {\n    typealias Value = Field.Value\n\n    private let _observable: ValueMappingForValueField<Parent, Field>\n\n    init(parent: Parent, key: @escaping (Parent.Value) -> Field) {\n        self._observable = ValueMappingForValueField<Parent, Field>(parent: parent, key: key)\n    }\n\n    override var value: Field.Value {\n        get {\n            return _observable.value\n        }\n        set {\n            _observable.key(_observable.parent.value).value = newValue\n        }\n    }\n\n    override func apply(_ update: Update<ValueChange<Field.Value>>) {\n        return _observable.key(_observable.parent.value).apply(update)\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        _observable.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return _observable.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Sources/ValueReference.swift",
    "content": "//\n//  ValueReference.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nextension ObservableValueType where Value: ObservableValueType {\n    public func unpacked() -> AnyObservableValue<Value.Value> {\n        return UnpackedObservableValueReference(self).anyObservableValue\n    }\n}\n\nprivate final class UnpackedObservableValueReference<Reference: ObservableValueType>: _BaseObservableValue<Reference.Value.Value>\nwhere Reference.Value: ObservableValueType {\n    typealias Target = Reference.Value\n    typealias Value = Target.Value\n    typealias Change = ValueChange<Value>\n\n    private struct ReferenceSink: UniqueOwnedSink {\n        typealias Owner = UnpackedObservableValueReference\n\n        unowned(unsafe) let owner: Owner\n\n        func receive(_ update: ValueUpdate<Reference.Value>) {\n            owner.applyReferenceUpdate(update)\n        }\n    }\n\n    private struct TargetSink: UniqueOwnedSink {\n        typealias Owner = UnpackedObservableValueReference\n\n        unowned(unsafe) let owner: Owner\n\n        func receive(_ update: ValueUpdate<Reference.Value.Value>) {\n            owner.applyTargetUpdate(update)\n        }\n    }\n\n    private var _reference: Reference\n    private var _target: Reference.Value? = nil // Retained to make sure we keep it alive\n\n    init(_ reference: Reference) {\n        _reference = reference\n        super.init()\n    }\n\n    override func activate() {\n        _reference.updates.add(ReferenceSink(owner: self))\n        let target = _reference.value\n        _target = target\n        target.updates.add(TargetSink(owner: self))\n    }\n\n    override func deactivate() {\n        _target!.updates.remove(TargetSink(owner: self))\n        _reference.updates.remove(ReferenceSink(owner: self))\n    }\n\n    func applyReferenceUpdate(_ update: ValueUpdate<Target>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            if isConnected {\n                _target!.remove(TargetSink(owner: self))\n                _target = change.new\n                _target!.add(TargetSink(owner: self))\n                sendChange(ValueChange(from: change.old.value, to: change.new.value))\n            }\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func applyTargetUpdate(_ update: ValueUpdate<Value>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    override var value: Value { return _reference.value.value }\n}\n"
  },
  {
    "path": "Sources/Variable.swift",
    "content": "//\n//  Variable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n/// A variable implements `UpdatableValueType` by having internal storage to a value.\n///\n/// - SeeAlso: UnownedVariable<Value>, WeakVariable<Value>\n///\nopen class Variable<Value>: _BaseUpdatableValue<Value> {\n    public typealias Change = ValueChange<Value>\n\n    private var _value: Value\n\n    /// Create a new variable with an initial value.\n    public init(_ value: Value) {\n        _value = value\n    }\n    override func rawGetValue() -> Value {\n        return _value\n    }\n    override func rawSetValue(_ value: Value) {\n        _value = value\n    }\n}\n\n/// An unowned variable contains an unowned reference to an object that can be read and updated. Updates are observable.\npublic class UnownedVariable<Value: AnyObject>: _BaseUpdatableValue<Value> {\n    public typealias Change = ValueChange<Value>\n\n    private unowned var _value: Value\n\n    /// Create a new variable with an initial value.\n    public init(_ value: Value) {\n        _value = value\n    }\n    override func rawGetValue() -> Value {\n        return _value\n    }\n    override func rawSetValue(_ value: Value) {\n        _value = value\n    }\n}\n\n/// A weak variable contains a weak reference to an object that can be read and updated. Updates are observable.\npublic class WeakVariable<Object: AnyObject>: _BaseUpdatableValue<Object?> {\n    public typealias Value = Object?\n    public typealias Change = ValueChange<Value>\n\n    private weak var _value: Object?\n\n    /// Create a new variable with a `nil` initial value.\n    public override init() {\n        _value = nil\n        super.init()\n    }\n\n    /// Create a new variable with an initial value.\n    public init(_ value: Value) {\n        _value = value\n        super.init()\n    }\n\n    override func rawGetValue() -> Value {\n        return _value\n    }\n    override func rawSetValue(_ value: Value) {\n        _value = value\n    }\n}\n\n\n//MARK: Experimental subclasses for specific types\n\n// It would be so much more convenient if Swift allowed me to define these as extensions...\n\npublic final class BoolVariable: Variable<Bool>, ExpressibleByBooleanLiteral {\n    public override init(_ value: Bool) {\n        super.init(value)\n    }\n    public init(booleanLiteral value: BooleanLiteralType) {\n        super.init(value)\n    }\n}\n\npublic final class IntVariable: Variable<Int>, ExpressibleByIntegerLiteral {\n    public override init(_ value: Int) {\n        super.init(value)\n    }\n    public init(integerLiteral value: IntegerLiteralType) {\n        super.init(value)\n    }\n}\n\npublic final class FloatingPointVariable<F: FloatingPoint>: Variable<F>, ExpressibleByFloatLiteral where F: ExpressibleByFloatLiteral {\n    public override init(_ value: F) {\n        super.init(value)\n    }\n    public init(floatLiteral value: F.FloatLiteralType) {\n        super.init(F(floatLiteral: value))\n    }\n}\n\npublic typealias FloatVariable = FloatingPointVariable<Float>\npublic typealias DoubleVariable = FloatingPointVariable<Double>\n\npublic final class StringVariable: Variable<String>, ExpressibleByStringLiteral {\n    public override init(_ value: String) {\n        super.init(value)\n    }\n    public init(unicodeScalarLiteral value: String.UnicodeScalarLiteralType) {\n        super.init(value)\n    }\n    public init(extendedGraphemeClusterLiteral value: String.ExtendedGraphemeClusterLiteralType) {\n        super.init(value)\n    }\n    public init(stringLiteral value: StringLiteralType) {\n        super.init(value)\n    }\n}\n\npublic final class OptionalVariable<Wrapped>: Variable<Optional<Wrapped>>, ExpressibleByNilLiteral {\n    public override init(_ value: Wrapped?) {\n        super.init(value)\n    }\n\n    public init(nilLiteral: ()) {\n        super.init(nil)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/AnySinkTests.swift",
    "content": "//\n//  AnySinkTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-25.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nprivate class TestSink: SinkType {\n    typealias Value = Int\n\n    func receive(_ value: Value) {\n        // Noop\n    }\n}\n\nclass AnySinkTests: XCTestCase {\n    func test_equality() {\n        let sink1 = MockSink<Int>()\n        let sink2 = MockSink<Int>()\n        let sink3 = TestSink()\n        let sink4 = TestSink()\n\n        XCTAssertEqual(sink1, sink1)\n        XCTAssertNotEqual(sink1, sink2)\n        XCTAssertNotEqual(sink3, sink4)\n\n        XCTAssertEqual(sink1.anySink, sink1.anySink)\n        XCTAssertNotEqual(sink1.anySink, sink2.anySink)\n        XCTAssertNotEqual(sink1.anySink, sink3.anySink)\n\n        XCTAssertEqual(sink1.anySink, sink1.anySink.anySink)\n    }\n\n    func test_hashValue() {\n        let sink = MockSink<Int>()\n\n        XCTAssertEqual(sink.hashValue, sink.anySink.hashValue)\n    }\n\n    func test_receive() {\n        let sink = MockSink<Int>()\n\n        sink.expecting(1) {\n            sink.receive(1)\n        }\n\n        sink.expecting(2) {\n            sink.anySink.receive(2)\n        }\n\n        sink.expecting(3) {\n            sink.anySink.anySink.receive(3)\n        }\n\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/AnySourceTests.swift",
    "content": "//\n//  AnySourceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-25.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nprivate class ForwardingSource<Source: SourceType>: SourceType {\n    typealias Value = Source.Value\n\n    let target: Source\n\n    init(_ target: Source) {\n        self.target = target\n    }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Value {\n        target.add(sink)\n    }\n\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Value {\n        return target.remove(sink)\n    }\n}\n\nclass AnySourceTests: XCTestCase {\n    func test_Works() {\n        let signal = Signal<Int>()\n        let source = signal.anySource\n\n        let sink = MockSink<Int>()\n\n        source.add(sink)\n\n        sink.expecting(1) {\n            signal.send(1)\n        }\n\n        source.remove(sink)\n\n        sink.expectingNothing {\n            signal.send(2)\n        }\n    }\n\n    func test_Idempotent() {\n        let signal = Signal<Int>()\n        let source = signal.anySource.anySource\n\n        let sink = MockSink<Int>()\n\n        source.add(sink)\n\n        sink.expecting(1) {\n            signal.send(1)\n        }\n\n        source.remove(sink)\n\n        sink.expectingNothing {\n            signal.send(2)\n        }\n    }\n\n    func test_Custom() {\n        let signal = Signal<Int>()\n        let source = ForwardingSource(signal).anySource\n\n        let sink = MockSink<Int>()\n\n        source.add(sink)\n\n        sink.expecting(1) {\n            signal.send(1)\n        }\n\n        source.remove(sink)\n\n        sink.expectingNothing {\n            signal.send(2)\n        }\n    }\n\n\n    func test_RetainsOriginal() {\n        weak var signal: Signal<Int>? = nil\n        var source: AnySource<Int>? = nil\n\n        do {\n            let s = Signal<Int>()\n            signal = s\n            source = s.anySource\n            withExtendedLifetime(s) {}\n        }\n\n        XCTAssertNotNil(signal)\n        XCTAssertNotNil(source)\n        source = nil\n        XCTAssertNil(signal)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayBufferingTests.swift",
    "content": "//\n//  ArrayBufferingTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass ArrayBufferingTests: XCTestCase {\n    func test_connectsImmediately() {\n        let observable = TestObservableArray([1, 2, 3])\n\n        do {\n            let buffered = observable.buffered()\n            XCTAssertTrue(observable.isConnected)\n            withExtendedLifetime(buffered) {}\n        }\n        XCTAssertFalse(observable.isConnected)\n    }\n\n    func test_properties() {\n        let observable = TestObservableArray([1, 2, 3])\n        let buffered = observable.buffered()\n\n        for b in [buffered, buffered.buffered()] {\n            XCTAssertEqual(b.isBuffered, true)\n            XCTAssertEqual(b[0], 1)\n            XCTAssertEqual(b[1], 2)\n            XCTAssertEqual(b[2], 3)\n            XCTAssertEqual(b[0 ..< 2], [1, 2])\n            XCTAssertEqual(b.value, [1, 2, 3])\n            XCTAssertEqual(b.count, 3)\n        }\n\n        observable.apply(ArrayChange(initialCount: 3, modification: .replace(2, at: 1, with: 4)))\n        XCTAssertEqual(buffered.value, [1, 4, 3])\n    }\n\n    func test_updates() {\n        let observable = TestObservableArray([1, 2, 3])\n        let buffered = observable.buffered()\n\n        let sink = MockArrayObserver(buffered)\n\n        sink.expecting([\"begin\", \"3.remove(3, at: 2)\", \"end\"]) {\n            observable.apply(ArrayChange(initialCount: 3, modification: .remove(3, at: 2)))\n        }\n        XCTAssertEqual(buffered.value, [1, 2])\n\n        sink.expecting(\"begin\") {\n            observable.beginTransaction()\n        }\n\n        sink.expectingNothing {\n            observable.apply(ArrayChange(initialCount: 2, modification: .replace(1, at: 0, with: 2)))\n        }\n        XCTAssertEqual(buffered.value, [1, 2])\n\n        sink.expectingNothing {\n            observable.apply(ArrayChange(initialCount: 2, modification: .insert(6, at: 2)))\n        }\n        XCTAssertEqual(buffered.value, [1, 2])\n\n        sink.expecting([\"2.replace(1, at: 0, with: 2).insert(6, at: 2)\", \"end\"]) {\n            observable.endTransaction()\n        }\n        XCTAssertEqual(buffered.value, [2, 2, 6])\n\n        sink.disconnect()\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayChangeSeparationTests.swift",
    "content": "//\n//  ArrayChangeSeparationTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\n/// Generate an exhaustive list of array changes, each consisting of a sequence of at most \n/// `depth` range replacements that insert at most `maxInsertion` elements.\nfunc generateArrayChanges(input: [Int], depth: Int, maxInsertion: Int, body: @escaping (ArrayChange<Int>) -> Void) {\n    func insertionsAtLevel(_ level: Int) -> [[Int]] {\n        // Returns an array of [], [30], [30, 31], ..., up to maxInsertionLength\n        let s = 10 * level\n        return (0...maxInsertion).map { (0..<$0).map { s + $0 } }\n    }\n\n    func recurse(level: Int, buffer: [Int], prefix: ArrayChange<Int>) {\n        if level >= depth { return }\n        for startIndex in buffer.startIndex...buffer.endIndex {\n            for endIndex in startIndex...buffer.endIndex {\n                let range = startIndex ..< endIndex\n\n                if range.count > 0 {\n                    // Move a slice\n                    let slice = Array(buffer[range])\n                    var b = buffer\n                    b.removeSubrange(range)\n                    for target in 0 ... buffer.count - range.count {\n                        if target == startIndex { continue }\n                        var next = b\n                        next.insert(contentsOf: slice, at: target)\n                        var change = prefix\n                        change.add(ArrayModification.replaceSlice(slice, at: startIndex, with: []))\n                        change.add(ArrayModification.replaceSlice([], at: target, with: slice))\n                        body(change)\n                        recurse(level: level + 1, buffer: next, prefix: change)\n                    }\n                }\n                for insertion in insertionsAtLevel(level) {\n                    if insertion.count == 0 && endIndex == startIndex {\n                        // Skip replacing empty with empty\n                        continue\n                    }\n                    var next = buffer\n                    next.replaceSubrange(range, with: insertion)\n                    let mod = ArrayModification.replaceSlice(Array(buffer[range]), at: startIndex, with: insertion)\n                    let change = prefix.merged(with: ArrayChange(initialCount: buffer.count, modification: mod))\n                    body(change)\n                    recurse(level: level + 1, buffer: next, prefix: change)\n                }\n            }\n        }\n    }\n\n    recurse(level: 0, buffer: input, prefix: ArrayChange<Int>(initialCount: input.count))\n}\n\nclass ArrayChangeSeparationTests: XCTestCase {\n    func testSimpleSeparation() {\n        let input = [-1, -2]\n        generateArrayChanges(input: input, depth: 3, maxInsertion: 2) { change in\n            // We'll emulate UITableView's content update logic, feed it the change and see if we \n            // arrive at a result that matches the updated array.\n            var output = input\n            output.apply(change)\n\n            var table = input\n            for index in change.deletedIndices.reversed() {\n                table.remove(at: index)\n            }\n            for index in change.insertedIndices {\n                table.insert(output[index], at: index)\n            }\n            XCTAssertEqual(table, output)\n        }\n    }\n\n    func testSeparation() {\n        let input = [-1, -2, -3]\n        generateArrayChanges(input: input, depth: 2, maxInsertion: 2) { change in\n            // We'll emulate UITableView's content update logic, feed it the change and see if we\n            // arrive at a result that matches the updated array.\n            var output = input\n            output.apply(change)\n\n            let sep = change.separated()\n            var table = input\n\n            var deleted = sep.deleted\n            var inserted = sep.inserted\n            var moveTargets = IndexSet()\n            var movedElements: [Int] = []\n\n            for (old, new) in sep.moved.sorted(by: { $0.1 < $1.1 }) {\n                moveTargets.insert(new)\n                movedElements.append(table[old])\n                deleted.insert(old)\n            }\n            inserted.formUnion(moveTargets)\n            for index in deleted.reversed() {\n                table.remove(at: index)\n            }\n            for index in inserted {\n                if moveTargets.contains(index) {\n                    table.insert(movedElements.removeFirst(), at: index)\n                }\n                else {\n                    table.insert(output[index], at: index)\n                }\n            }\n            XCTAssertEqual(table, output)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayChangeTests.swift",
    "content": "//\n//  ArrayChangeTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nclass ArrayChangeTests: XCTestCase {\n\n    func testCounts() {\n        var change = ArrayChange<String>(initialCount: 10)\n        change.add(.insert(\"foo\", at: 2))\n        change.add(.replace(\"foo\", at: 4, with: \"bar\"))\n        change.add(.remove(\"foo\", at: 0))\n        change.add(.replaceSlice([\"foo\", \"bar\"], at: 6, with: [\"1\", \"2\", \"3\"]))\n\n        XCTAssertEqual(change.initialCount, 10)\n        XCTAssertEqual(change.finalCount, 11)\n        XCTAssertEqual(change.deltaCount, 1)\n        XCTAssertTrue(change.countChange == ValueChange<Int>(from: 10, to: 11))\n    }\n\n    func testExerciseMerging() {\n        // Exhaustively test the merging of all variations of modification sequences.\n        let startSequence = [0, 1]\n        let maxLevels = 4\n        let maxInsertionLength = 2\n\n        func insertionsAtLevel(_ level: Int) -> [[Int]] {\n            // Returns an array of [], [30], [30, 31], ..., up to maxInsertionLength\n            let s = 10 * level\n            return (0...maxInsertionLength).map { (0..<$0).map { s + $0 } }\n        }\n\n        func printTrace(_ input: [Int], change: ArrayChange<Int>, output: [Int], trace: [ArrayModification<Int>], applied: [Int]) {\n            print(\"Given this input:\")\n            print(\"    \\(input)\")\n            print(\"This sequence of changes:\")\n            for t in trace {\n                print(\"    Replace \\(t.oldElements) at \\(t.startIndex) with \\(t.newElements)\")\n            }\n            print(\"Was collapsed to:\")\n            for m in change.modifications {\n                print(\"    Replace \\(m.oldElements) at \\(m.startIndex) with \\(m.newElements)\")\n            }\n            print(\"Which resulted in:\")\n            print(\"     \\(applied)\")\n            print(\"Instead of:\")\n            print(\"     \\(output)\")\n        }\n\n        func recurse(_ level: Int, input: [Int], change: ArrayChange<Int>, output: [Int], trace: [ArrayModification<Int>]) {\n            var applied = input\n            XCTAssertEqual(applied.count, change.initialCount)\n            for m in change.modifications {\n                if applied.count < m.inputRange.upperBound {\n                    printTrace(input, change: change, output: output, trace: trace, applied: applied)\n                    print()\n                }\n                if Array(applied[m.inputRange]) != m.oldElements {\n                    printTrace(input, change: change, output: output, trace: trace, applied: applied)\n                    XCTAssertEqual(Array(applied[m.inputRange]), m.oldElements)\n                }\n                applied.apply(m)\n            }\n            XCTAssertEqual(applied.count, change.finalCount)\n            if applied != output {\n                XCTAssertEqual(applied, output)\n                printTrace(input, change: change, output: output, trace: trace, applied: applied)\n                return\n            }\n\n            // Also do a quick test for reversing the change.\n            var undo = applied\n            undo.apply(change.reversed())\n            XCTAssertEqual(undo, input)\n\n            if level < maxLevels {\n                for startIndex in output.startIndex...output.endIndex {\n                    for endIndex in startIndex...output.endIndex {\n                        for insertion in insertionsAtLevel(level) {\n                            if insertion.count == 0 && endIndex == startIndex {\n                                // Skip replacing empty with empty\n                                continue\n                            }\n                            var nextOutput = output\n                            nextOutput.replaceSubrange(startIndex..<endIndex, with: insertion)\n                            let mod = ArrayModification.replaceSlice(Array(output[startIndex ..< endIndex]), at: startIndex, with: insertion)\n                            let nextChange = change.merged(with: ArrayChange(initialCount: output.count, modification: mod))\n                            recurse(level + 1, input: input, change: nextChange, output: nextOutput, trace: trace + [mod])\n                        }\n                    }\n                }\n            }\n        }\n\n        let startChange = ArrayChange<Int>(initialCount: startSequence.count)\n        recurse(1, input: startSequence, change: startChange, output: startSequence, trace: [])\n    }\n\n    func testMap() {\n        let c1 = ArrayChange<Int>(initialCount: 10, modification: .insert(1, at: 3))\n            .merged(with: ArrayChange<Int>(initialCount: 11, modification: .replace(11, at: 1, with: 2)))\n            .merged(with: ArrayChange<Int>(initialCount: 11, modification: .remove(13, at: 4)))\n            .merged(with: ArrayChange<Int>(initialCount: 10, modification: .replaceSlice([18, 19], at: 8, with: [5, 6])))\n\n        let c2 = ArrayChange<String>(initialCount: 10, modification: .insert(\"1\", at: 3))\n            .merged(with: ArrayChange<String>(initialCount: 11, modification: .replace(\"11\", at: 1, with: \"2\")))\n            .merged(with: ArrayChange<String>(initialCount: 11, modification: .remove(\"13\", at: 4)))\n            .merged(with: ArrayChange<String>(initialCount: 10, modification: .replaceSlice([\"18\", \"19\"], at: 8, with: [\"5\", \"6\"])))\n\n        let m = c1.map { \"\\($0)\" }\n        XCTAssertEqual(m.initialCount, c2.initialCount)\n        XCTAssertEqual(m.deltaCount, c2.deltaCount)\n        XCTAssert(m.modifications.elementsEqual(c2.modifications, by: ==))\n    }\n\n    func testApply() {\n        var array = [0, 1, 2, 3, 4]\n        var change = ArrayChange<Int>(initialCount: 5)\n        change.add(.insert(10, at: 2))\n        change.add(.remove(1, at: 1))\n        change.add(.replace(4, at: 4, with: 20))\n\n        change.apply(on: &array)\n\n        XCTAssertEqual(array, [0, 10, 2, 3, 20])\n    }\n\n    func testDescription() {\n        var change = ArrayChange<Int>(initialCount: 5)\n        change.add(.insert(10, at: 2))\n        change.add(.remove(1, at: 1))\n        change.add(.replace(4, at: 4, with: 20))\n\n        XCTAssertEqual(change.description, \"ArrayChange<Int> initialCount: 5, 2 modifications\")\n        XCTAssertEqual(change.debugDescription, \"GlueKit.ArrayChange<Swift.Int> initialCount: 5, 2 modifications\")\n    }\n\n    func testRemovingEqualChanges() {\n        var change = ArrayChange<Int>(initialCount: 5)\n        change.add(.remove(1, at: 1))\n        change.add(.insert(1, at: 1))\n        change.add(.replace(4, at: 4, with: 40))\n\n        XCTAssertEqual(change.modifications, [.replace(1, at: 1, with: 1), .replace(4, at: 4, with: 40)])\n        XCTAssertEqual(change.removingEqualChanges().modifications, [.replace(4, at: 4, with: 40)])\n    }\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayConcatenationTests.swift",
    "content": "//\n//  ArrayConcatenationTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass ArrayConcatenationTests: XCTestCase {\n    func testConcatenation() {\n        func check<O: ObservableArrayType>(a: [Int], b: [Int], c: O, file: StaticString = #file, line: UInt = #line) where O.Element == Int {\n            XCTAssertEqual(c.count, a.count + b.count, file: file, line: line)\n            let v = a + b\n            XCTAssertEqual(c.value, v, file: file, line: line)\n            for i in 0 ..< v.count {\n                XCTAssertEqual(c[i], v[i], file: file, line: line)\n                for j in i ..< v.count {\n                    XCTAssertEqual(c[i ..< j], v[i ..< j], file: file, line: line)\n                }\n            }\n        }\n\n        let a: ArrayVariable<Int> = [0, 1, 2]\n        let b: ArrayVariable<Int> = [10, 20]\n\n        let c = a + b\n\n        XCTAssertFalse(c.isBuffered)\n        XCTAssertEqual(c.count, 5)\n        XCTAssertEqual(c.value, [0, 1, 2, 10, 20])\n        XCTAssertEqual(c[0], 0)\n        XCTAssertEqual(c[1], 1)\n        XCTAssertEqual(c[2], 2)\n        XCTAssertEqual(c[3], 10)\n        XCTAssertEqual(c[4], 20)\n        check(a: a.value, b: b.value, c: c)\n\n        let mock = MockArrayObserver(c)\n\n        mock.expecting([\"begin\", \"5.insert(30, at: 5)\", \"end\"]) {\n            b.append(30)\n        }\n        check(a: a.value, b: b.value, c: c)\n\n        mock.expecting([\"begin\", \"6.insert(3, at: 3)\", \"end\"]) {\n            a.append(3)\n        }\n        check(a: a.value, b: b.value, c: c)\n\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayFilteringTests.swift",
    "content": "//\n//  ArrayFilteringTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-09-27.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nprivate class Book: Equatable, CustomStringConvertible {\n    let id: String\n    let title: Variable<String>\n\n    init(id: String, title: String) {\n        self.id = id\n        self.title = Variable(title)\n    }\n\n    var description: String {\n        return id\n    }\n\n    static func ==(a: Book, b: Book) -> Bool {\n        return a.title.value == b.title.value\n    }\n}\n\nclass ArrayFilteringTests: XCTestCase {\n\n    func test_filterOnPredicate_getters() {\n        let array: ArrayVariable<Int> = [1, 3, 5, 6]\n\n        let even = array.filter { $0 % 2 == 0 }\n\n        XCTAssertFalse(even.isBuffered)\n        XCTAssertEqual(even.count, 1)\n        XCTAssertEqual(even[0], 6)\n        XCTAssertEqual(even[0 ..< 1], ArraySlice([6]))\n        XCTAssertEqual(even.value, [6])\n\n        array.value = Array(0 ..< 10)\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [0, 2, 4, 6, 8])\n\n        array.remove(at: 3)\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [0, 2, 4, 6, 8])\n\n        array.remove(at: 3)\n        XCTAssertEqual(even.count, 4)\n        XCTAssertEqual(even.value, [0, 2, 6, 8])\n\n        array.insert(10, at: 2)\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [0, 10, 2, 6, 8])\n\n        array[2] = 12\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [0, 12, 2, 6, 8])\n\n        array[2] = 11\n        XCTAssertEqual(even.count, 4)\n        XCTAssertEqual(even.value, [0, 2, 6, 8])\n\n        array[2] = 9\n        XCTAssertEqual(even.count, 4)\n        XCTAssertEqual(even.value, [0, 2, 6, 8])\n\n        array[2] = 10\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [0, 10, 2, 6, 8])\n\n        array.removeAll()\n        XCTAssertEqual(even.count, 0)\n        XCTAssertEqual(even.value, [])\n    }\n\n    func test_filterOnPredicate_updates() {\n        let array: ArrayVariable<Int> = [0, 1, 2, 3, 4]\n\n        let evenMembers = array.filter { $0 % 2 == 0 }\n        let mock = MockArrayObserver<Int>(evenMembers)\n\n        mock.expecting([\"begin\", \"3.insert(6, at: 3)\", \"end\"]) {\n            array.insert(contentsOf: [5, 6, 7], at: 5)\n        }\n\n        mock.expecting([\"begin\", \"4.replaceSlice([2, 4], at: 1, with: [])\", \"end\"]) {\n            array.removeSubrange(1 ..< 5)\n        }\n    }\n\n    func test_filterOnObservableBool_getters() {\n        let b1 = Book(id: \"b1\", title: \"Winnie the Pooh\")\n        let b2 = Book(id: \"b2\", title: \"The Color of Magic\")\n        let b3 = Book(id: \"b3\", title: \"Structure and Interpretation of Computer Programs\")\n        let b4 = Book(id: \"b4\", title: \"Numerical Recipes in C++\")\n        let array: ArrayVariable<Book> = [b1, b2, b3, b4]\n\n        // Books with \"of\" in their title.\n        let filtered = array.filter { $0.title.map { $0.lowercased().contains(\"of\") } }\n\n        XCTAssertEqual(filtered.isBuffered, false)\n        XCTAssertEqual(filtered.count, 2)\n        XCTAssertEqual(filtered[0], b2)\n        XCTAssertEqual(filtered[1], b3)\n        XCTAssertEqual(filtered[0 ..< 2], ArraySlice([b2, b3]))\n        XCTAssertEqual(filtered.value, [b2, b3])\n\n        let b5 = Book(id: \"b5\", title: \"Of Mice and Men\")\n        array.append(b5)\n        XCTAssertEqual(filtered.count, 3)\n        XCTAssertEqual(filtered.value, [b2, b3, b5])\n\n        array.remove(at: 1)\n        XCTAssertEqual(filtered.count, 2)\n        XCTAssertEqual(filtered.value, [b3, b5])\n\n        b4.title.value = \"The TeXbook\"\n        XCTAssertEqual(filtered.count, 2)\n        XCTAssertEqual(filtered.value, [b3, b5])\n\n        b4.title.value = \"House of Leaves\"\n        XCTAssertEqual(filtered.count, 3)\n        XCTAssertEqual(filtered.value, [b3, b4, b5])\n\n        b4.title.value = \"Good Omens\"\n        XCTAssertEqual(filtered.count, 2)\n        XCTAssertEqual(filtered.value, [b3, b5])\n    }\n\n    func test_complex_updates() {\n        let b1 = Book(id: \"b1\", title: \"Winnie the Pooh\")\n        let b2 = Book(id: \"b2\", title: \"The Color of Magic\")\n        let b3 = Book(id: \"b3\", title: \"Structure and Interpretation of Computer Programs\")\n        let b4 = Book(id: \"b4\", title: \"Numerical Recipes in C++\")\n        let array: ArrayVariable<Book> = [b1, b2, b3, b4]\n\n        // Books with \"of\" in their title.\n        let filtered = array.filter { $0.title.map { $0.lowercased().contains(\"of\") } }\n        let mock = MockArrayObserver<Book>(filtered)\n\n        // filtered is [b2, b3]\n\n        let b5 = Book(id: \"b5\", title: \"Of Mice and Men\")\n        mock.expecting([\"begin\", \"2.insert(b5, at: 2)\", \"end\"]) {\n            array.append(b5)\n        }\n\n        // filtered is [b2, b3, b5]\n\n        mock.expecting([\"begin\", \"3.remove(b2, at: 0)\", \"end\"]) {\n            _ = array.remove(at: 1)\n        }\n\n        // filtered is [b3, b5]\n\n        mock.expecting([\"begin\", \"end\"]) {\n            b4.title.value = \"The TeXbook\"\n        }\n\n        // filtered is [b3, b5]\n\n        mock.expecting([\"begin\", \"2.insert(b4, at: 1)\", \"end\"]) {\n            b4.title.value = \"House of Leaves\"\n        }\n\n        // filtered is [b3, b4, b5]\n\n        mock.expecting([\"begin\", \"3.remove(b4, at: 1)\", \"end\"]) {\n            b4.title.value = \"Good Omens\"\n        }\n\n        // filtered is [b3, b5]\n    }\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayFoldingTests.swift",
    "content": "//\n//  ArrayFoldingTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass ArrayFoldingTests: XCTestCase {\n    \n    func testSum() {\n        let array = ArrayVariable<Int>([1, 2, 3])\n        let sum = array.sum()\n\n        XCTAssertEqual(sum.value, 6)\n\n        array.append(4)\n        XCTAssertEqual(sum.value, 10)\n\n        array.insert(5, at: 1)\n        XCTAssertEqual(sum.value, 15)\n\n        array.remove(at: 0)\n        XCTAssertEqual(sum.value, 14)\n\n        array.removeAll()\n        XCTAssertEqual(sum.value, 0)\n    }        \n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayMappingTests.swift",
    "content": "//\n//  SelectOperatorTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-06.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nprivate class Book {\n    let title: StringVariable\n    let authors: ArrayVariable<String>\n\n    init(_ title: String, _ authors: [String] = []) {\n        self.title = .init(title)\n        self.authors = .init(authors)\n    }\n}\n\nclass ArrayMappingTests: XCTestCase {\n\n    func test_map_value() {\n        let b1 = Book(\"foo\")\n        let b2 = Book(\"bar\")\n        let b3 = Book(\"baz\")\n        let books: ArrayVariable<Book> = [b1, b2, b3]\n\n        // Ignoring observability like this isn't a good idea; if we change the title of a book, the titles\n        // array won't get updated. However, it simplifies testing that we don't need to set up a read-only\n        // property in our fixture.\n        let titles = books.map{ $0.title.value }\n\n        XCTAssertFalse(titles.isBuffered)\n        XCTAssertEqual(titles.count, 3)\n        XCTAssertEqual(titles.observableCount.value, 3)\n        XCTAssertEqual(titles[0], \"foo\")\n        XCTAssertEqual(titles[1 ..< 3], ArraySlice([\"bar\", \"baz\"]))\n\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\"])\n\n        let mock = MockArrayObserver(titles)\n\n        mock.expecting([\"begin\", \"3.insert(fred, at: 3)\", \"end\"]) {\n            books.append(Book(\"fred\"))\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\", \"fred\"])\n        mock.expecting([\"begin\", \"4.remove(bar, at: 1)\", \"end\"]) {\n            _ = books.remove(at: 1)\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"baz\", \"fred\"])\n        mock.expecting([\"begin\", \"3.replace(foo, at: 0, with: fuzzy)\", \"end\"]) {\n            _ = books[0] = Book(\"fuzzy\")\n        }\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"baz\", \"fred\"])\n        let barney = Book(\"barney\")\n        mock.expecting([\"begin\", \"3.replaceSlice([baz, fred], at: 1, with: [barney])\", \"end\"]) {\n            _ = books.replaceSubrange(1 ..< 3, with: [barney])\n        }\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"barney\"])\n\n        // The observable doesn't know the title of a book may change, so it won't notice when we modify it.\n        mock.expectingNothing {\n            barney.title.value = \"bazaar\"\n        }\n        // However, this particular observable generates results on the fly, so the pull-based API includes the change.\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"bazaar\"])\n    }\n\n    func test_bufferedMap_observed() {\n        let b1 = Book(\"foo\")\n        let b2 = Book(\"bar\")\n        let b3 = Book(\"baz\")\n        let books: ArrayVariable<Book> = [b1, b2, b3]\n\n        // Ignoring observability like this isn't a good idea; if we change the title of a book, the titles\n        // array won't get updated. However, it simplifies testing that we don't need to set up a read-only\n        // property in our fixture.\n        let titles = books.bufferedMap{ $0.title.value }\n\n        XCTAssertTrue(titles.isBuffered)\n        XCTAssertEqual(titles.count, 3)\n        XCTAssertEqual(titles.observableCount.value, 3)\n        XCTAssertEqual(titles[0], \"foo\")\n        XCTAssertEqual(titles[1 ..< 3], ArraySlice([\"bar\", \"baz\"]))\n\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\"])\n\n        let mock = MockArrayObserver(titles)\n\n        mock.expecting([\"begin\", \"3.insert(fred, at: 3)\", \"end\"]) {\n            books.append(Book(\"fred\"))\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\", \"fred\"])\n        mock.expecting([\"begin\", \"4.remove(bar, at: 1)\", \"end\"]) {\n            _ = books.remove(at: 1)\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"baz\", \"fred\"])\n        mock.expecting([\"begin\", \"3.replace(foo, at: 0, with: fuzzy)\", \"end\"]) {\n            _ = books[0] = Book(\"fuzzy\")\n        }\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"baz\", \"fred\"])\n        let barney = Book(\"barney\")\n        mock.expecting([\"begin\", \"3.replaceSlice([baz, fred], at: 1, with: [barney])\", \"end\"]) {\n            _ = books.replaceSubrange(1 ..< 3, with: [barney])\n        }\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"barney\"])\n\n        // The observable doesn't know the title of a book may change, so it won't notice when we modify it.\n        mock.expectingNothing {\n            barney.title.value = \"bazaar\"\n        }\n        // The observable is buffered, so if we pull a value out of it, it won't include the update.\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"barney\"])\n    }\n\n    func test_bufferedMap_unobserved() {\n        let b1 = Book(\"foo\")\n        let b2 = Book(\"bar\")\n        let b3 = Book(\"baz\")\n        let books: ArrayVariable<Book> = [b1, b2, b3]\n\n        let titles = books.bufferedMap{ $0.title.value }\n\n        // If the buffered map is not observed, it runs a differed code path, so test that as well.\n        books.append(Book(\"fred\"))\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\", \"fred\"])\n        _ = books.remove(at: 1)\n        XCTAssertEqual(titles.value, [\"foo\", \"baz\", \"fred\"])\n        _ = books[0] = Book(\"fuzzy\")\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"baz\", \"fred\"])\n        let barney = Book(\"barney\")\n        _ = books.replaceSubrange(1 ..< 3, with: [barney])\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"barney\"])\n\n        // The observable doesn't know the title of a book may change, so it won't notice when we modify it.\n        barney.title.value = \"bazaar\"\n        // The observable is buffered, so if we pull a value out of it, it won't include the update.\n        XCTAssertEqual(titles.value, [\"fuzzy\", \"barney\"])\n    }\n\n    func test_map_valueField() {\n        let b1 = Book(\"foo\")\n        let b2 = Book(\"bar\")\n        let b3 = Book(\"baz\")\n        let books: ArrayVariable<Book> = [b1, b2, b3]\n\n        let titles = books.map{$0.title}\n\n        XCTAssertFalse(titles.isBuffered)\n        XCTAssertEqual(titles.count, 3)\n        XCTAssertEqual(titles[0], \"foo\")\n        XCTAssertEqual(titles[1 ..< 3], ArraySlice([\"bar\", \"baz\"]))\n\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\"])\n\n        let mock = MockArrayObserver(titles)\n\n        let b4 = Book(\"fred\")\n        mock.expecting([\"begin\", \"3.insert(fred, at: 3)\", \"end\"]) {\n            books.append(b4)\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\", \"fred\"])\n        mock.expecting([\"begin\", \"4.remove(bar, at: 1)\", \"end\"]) {\n            _ = books.remove(at: 1)\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"baz\", \"fred\"])\n        mock.expecting([\"begin\", \"3.replace(baz, at: 1, with: bazaar)\", \"end\"]) {\n            b3.title.value = \"bazaar\"\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"bazaar\", \"fred\"])\n    }\n\n    func test_flatMap_arrayField() {\n        let b1 = Book(\"foo\", [\"a\", \"b\", \"c\"])\n        let b2 = Book(\"bar\", [\"b\", \"d\"])\n        let b3 = Book(\"baz\", [\"a\"])\n        let b4 = Book(\"zoo\", [])\n        let books: ArrayVariable<Book> = [b1, b2, b3, b4]\n\n        let authors = books.flatMap{$0.authors}\n\n        XCTAssertEqual(authors.isBuffered, false)\n        XCTAssertEqual(authors.value, [\n            /*b1*/ \"a\", \"b\", \"c\",\n            /*b2*/ \"b\", \"d\",\n            /*b3*/ \"a\",\n            /*b4*/\n        ])\n        XCTAssertEqual(authors.count, 6)\n        XCTAssertEqual(authors[0], \"a\")\n        XCTAssertEqual(authors[4], \"d\")\n        XCTAssertEqual(authors[2..<4], ArraySlice([\"c\", \"b\"]))\n\n        func checkSlices(file: StaticString = #file, line: UInt = #line) {\n            let value = authors.value\n            for i in 0 ..< authors.count {\n                for j in i ..< authors.count {\n                    XCTAssertEqual(authors[i ..< j], value[i ..< j], file: file, line: line)\n                }\n            }\n        }\n\n        checkSlices()\n\n        let mock = MockArrayObserver(authors)\n\n        let b5 = Book(\"fred\", [\"e\"])\n        mock.expecting([\"begin\", \"6.insert(e, at: 6)\", \"end\"]) {\n            books.append(b5)\n        }\n        XCTAssertEqual(authors.value, [\n            /*b1*/ \"a\", \"b\", \"c\",\n            /*b2*/ \"b\", \"d\",\n            /*b3*/ \"a\",\n            /*b4*/\n            /*b5*/ \"e\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"7.replaceSlice([b, d], at: 3, with: [])\", \"end\"]) {\n            _ = books.remove(at: 1) // b2\n        }\n        XCTAssertEqual(authors.value, [\n            /*b1*/ \"a\", \"b\", \"c\",\n            /*b3*/ \"a\",\n            /*b4*/\n            /*b5*/ \"e\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"5.replaceSlice([], at: 0, with: [b, d])\", \"end\"]) {\n            books.insert(b2, at: 0)\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"b\", \"d\",\n            /*b1*/ \"a\", \"b\", \"c\",\n            /*b3*/ \"a\",\n            /*b4*/\n            /*b5*/ \"e\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"7.insert(*, at: 1)\", \"end\"]) {\n            b2.authors.insert(\"*\", at: 1)\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"b\", \"*\", \"d\",\n            /*b1*/ \"a\", \"b\", \"c\",\n            /*b3*/ \"a\",\n            /*b4*/\n            /*b5*/ \"e\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"8.replace(*, at: 1, with: f)\", \"end\"]) {\n            b2.authors[1] = \"f\"\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"b\", \"f\", \"d\",\n            /*b1*/ \"a\", \"b\", \"c\",\n            /*b3*/ \"a\",\n            /*b4*/\n            /*b5*/ \"e\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"8.insert(g, at: 8)\", \"end\"]) {\n            b5.authors.append(\"g\")\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"b\", \"f\", \"d\",\n            /*b1*/ \"a\", \"b\", \"c\",\n            /*b3*/ \"a\",\n            /*b4*/\n            /*b5*/ \"e\", \"g\"\n        ])\n        checkSlices()\n\n        // Remove all authors from each book, one by one.\n\n        mock.expecting([\"begin\", \"9.remove(a, at: 6)\", \"end\"]) {\n            b3.authors.value = []\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"b\", \"f\", \"d\",\n            /*b1*/ \"a\", \"b\", \"c\",\n            /*b3*/\n            /*b4*/\n            /*b5*/ \"e\", \"g\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"8.replaceSlice([a, b, c], at: 3, with: [])\", \"end\"]) {\n            b1.authors.value = []\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"b\", \"f\", \"d\",\n            /*b1*/\n            /*b3*/\n            /*b4*/\n            /*b5*/ \"e\", \"g\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"5.replaceSlice([], at: 5, with: [b, f, d, e, g])\", \"end\"]) {\n            books.append(contentsOf: books.value)\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"b\", \"f\", \"d\",\n            /*b1*/\n            /*b3*/\n            /*b4*/\n            /*b5*/ \"e\", \"g\",\n            /*b2*/ \"b\", \"f\", \"d\",\n            /*b1*/\n            /*b3*/\n            /*b4*/\n            /*b5*/ \"e\", \"g\"\n        ])\n        checkSlices()\n\n        mock.expectingOneOf([\n            [\"begin\", \"10.replaceSlice([b, f, d], at: 0, with: [])\", \"7.replaceSlice([b, f, d], at: 2, with: [])\", \"end\"],\n            [\"begin\", \"10.replaceSlice([b, f, d], at: 5, with: [])\", \"7.replaceSlice([b, f, d], at: 0, with: [])\", \"end\"]\n        ]) {\n            b2.authors.value = []\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/\n            /*b1*/\n            /*b3*/\n            /*b4*/\n            /*b5*/ \"e\", \"g\",\n            /*b2*/\n            /*b1*/\n            /*b3*/\n            /*b4*/\n            /*b5*/ \"e\", \"g\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"4.replaceSlice([e, g], at: 2, with: [])\", \"end\"]) {\n            books.removeSubrange(5 ..< 10)\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/\n            /*b1*/\n            /*b3*/\n            /*b4*/\n            /*b5*/ \"e\", \"g\"\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"2.replaceSlice([e, g], at: 0, with: [])\", \"end\"]) {\n            b5.authors.value = []\n        }\n        XCTAssertEqual(authors.value, [\n            // b2 b1 b3 b4 b5\n        ])\n        checkSlices()\n\n        // At this point, no book has any author.\n\n        mock.expecting([\"begin\", \"end\"]) {\n            books.append(contentsOf: books.value)\n        }\n        XCTAssertEqual(authors.value, [\n            // b2 b1 b3 b4 b5 b2 b1 b3 b4 b5\n        ])\n        checkSlices()\n\n        mock.expectingOneOf([\n            [\"begin\", \"0.replaceSlice([], at: 0, with: [3a, 3b])\", \"2.replaceSlice([], at: 0, with: [3a, 3b])\", \"end\"],\n            [\"begin\", \"0.replaceSlice([], at: 0, with: [3a, 3b])\", \"2.replaceSlice([], at: 2, with: [3a, 3b])\", \"end\"],\n        ]) {\n            b3.authors.value = [\"3a\", \"3b\"]\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/\n            /*b1*/\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/\n            /*b2*/\n            /*b1*/\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/\n        ])\n        checkSlices()\n\n        mock.expectingOneOf([\n            [\"begin\", \"4.insert(1, at: 0)\", \"5.insert(1, at: 3)\", \"end\"],\n            [\"begin\", \"4.insert(1, at: 2)\", \"5.insert(1, at: 0)\", \"end\"],\n        ]) {\n            b1.authors.value = [\"1\"]\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/\n            /*b1*/ \"1\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/\n            /*b2*/\n            /*b1*/ \"1\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"6.replaceSlice([3a, 3b], at: 4, with: [])\", \"end\"]) {\n            books.removeSubrange(7 ..< 10)\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/\n            /*b1*/ \"1\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/\n            /*b2*/\n            /*b1*/ \"1\",\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"4.insert(5a, at: 3)\", \"end\"]) {\n            b5.authors.append(\"5a\")\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/\n            /*b1*/ \"1\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/ \"5a\",\n            /*b2*/\n            /*b1*/ \"1\",\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"5.insert(5b, at: 4)\", \"end\"]) {\n            b5.authors.append(\"5b\")\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/\n            /*b1*/ \"1\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/ \"5a\", \"5b\",\n            /*b2*/\n            /*b1*/ \"1\",\n        ])\n        checkSlices()\n\n        mock.expectingOneOf([\n            [\"begin\", \"6.insert(2, at: 0)\", \"7.insert(2, at: 6)\", \"end\"],\n            [\"begin\", \"6.insert(2, at: 5)\", \"7.insert(2, at: 0)\", \"end\"],\n        ]) {\n            b2.authors.append(\"2\")\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"2\",\n            /*b1*/ \"1\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/ \"5a\", \"5b\",\n            /*b2*/ \"2\",\n            /*b1*/ \"1\",\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"8.remove(2, at: 6)\", \"end\"]) {\n            _ = books.remove(at: 5) // b2\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"2\",\n            /*b1*/ \"1\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/ \"5a\", \"5b\",\n            /*b1*/ \"1\",\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"7.remove(1, at: 1)\", \"end\"]) {\n            _ = books.remove(at: 1) // b1\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"2\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/ \"5a\", \"5b\",\n            /*b1*/ \"1\",\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"6.replaceSlice([5a, 5b], at: 3, with: [])\", \"end\"]) {\n            b5.authors.value = []\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"2\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/\n            /*b1*/ \"1\",\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"4.remove(1, at: 3)\", \"end\"]) {\n            _ = books.removeLast() // b1\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"2\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n            /*b5*/\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"end\"]) {\n            _ = books.removeLast() // b5\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/ \"2\",\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"3.remove(2, at: 0)\", \"end\"]) {\n            b2.authors.value = []\n        }\n        XCTAssertEqual(authors.value, [\n            /*b2*/\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"end\"]) {\n            _ = books.removeFirst() // b2\n        }\n        XCTAssertEqual(authors.value, [\n            /*b3*/ \"3a\", \"3b\",\n            /*b4*/\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"end\"]) {\n            _ = books.removeLast() // b4\n        }\n        XCTAssertEqual(authors.value, [\n            /*b3*/ \"3a\", \"3b\",\n        ])\n        checkSlices()\n\n        mock.expecting([\"begin\", \"2.replaceSlice([3a, 3b], at: 0, with: [])\", \"end\"]) {\n            _ = books.removeLast() // b3\n        }\n        XCTAssertEqual(authors.value, [])\n        checkSlices()\n    }\n}\n\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayModificationTests.swift",
    "content": "//\n//  ArrayModificationTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\n@testable import GlueKit\n\nprivate func ==<T: Equatable>(a: ArrayModificationMergeResult<T>, b: ArrayModificationMergeResult<T>) -> Bool {\n    switch a {\n    case .disjunctOrderedAfter:\n        if case .disjunctOrderedAfter = b {\n            return true\n        }\n        return false\n    case .disjunctOrderedBefore:\n        if case .disjunctOrderedBefore = b {\n            return true\n        }\n        return false\n    case .collapsedToNoChange:\n        if case .collapsedToNoChange = b {\n            return true\n        }\n        return false\n    case .collapsedTo(let ae):\n        if case .collapsedTo(let be) = b {\n            return ae == be\n        }\n        return false\n    }\n}\n\nfunc ==<Element: Equatable>(a: [ArrayModification<Element>], b: [ArrayModification<Element>]) -> Bool {\n    return a.elementsEqual(b, by: ==)\n}\nfunc !=<Element: Equatable>(a: [ArrayModification<Element>], b: [ArrayModification<Element>]) -> Bool {\n    return !(a == b)\n}\n\nfunc XCTAssertEqual<Element: Equatable>(_ a: [ArrayModification<Element>], _ b: [ArrayModification<Element>], file: StaticString = #file, line: UInt = #line) {\n    if a != b {\n        XCTFail(\"\\(a) is not equal to \\(b)\", file: file, line: line)\n    }\n}\n\nclass ArrayModificationTests: XCTestCase {\n\n    func testInsertion() {\n        var a = [1, 2, 3]\n        let mod = ArrayModification.insert(10, at: 2)\n\n        XCTAssertEqual(mod.deltaCount, 1)\n        XCTAssertEqual(mod.startIndex, 2)\n        XCTAssertEqual(mod.inputRange, 2..<2)\n        XCTAssertEqual(mod.outputRange, 2..<3)\n        XCTAssertEqual(mod.oldElements, [])\n        XCTAssertEqual(mod.newElements, [10])\n\n        a.apply(mod)\n        XCTAssertEqual(a, [1, 2, 10, 3])\n\n        XCTAssert(mod.reversed == .remove(10, at: 2))\n        XCTAssert(mod.map { \"\\($0)\" } == .insert(\"10\", at: 2))\n    }\n\n    func testRemoval() {\n        var a = [1, 2, 3]\n        let mod = ArrayModification<Int>.remove(2, at: 1)\n\n        XCTAssertEqual(mod.deltaCount, -1)\n        XCTAssertEqual(mod.startIndex, 1)\n        XCTAssertEqual(mod.inputRange, 1..<2)\n        XCTAssertEqual(mod.outputRange, 1..<1)\n        XCTAssertEqual(mod.oldElements, [2])\n        XCTAssertEqual(mod.newElements, [])\n\n        a.apply(mod)\n        XCTAssertEqual(a, [1, 3])\n\n        XCTAssert(mod.reversed == .insert(2, at: 1))\n        XCTAssert(mod.map { \"\\($0)\" } == .remove(\"2\", at: 1))\n    }\n\n    func testReplacement() {\n        var a = [1, 2, 3]\n        let mod = ArrayModification.replace(2, at: 1, with: 10)\n\n        XCTAssertEqual(mod.deltaCount, 0)\n        XCTAssertEqual(mod.startIndex, 1)\n        XCTAssertEqual(mod.inputRange, 1..<2)\n        XCTAssertEqual(mod.outputRange, 1..<2)\n        XCTAssertEqual(mod.oldElements, [2])\n        XCTAssertEqual(mod.newElements, [10])\n\n        a.apply(mod)\n        XCTAssertEqual(a, [1, 10, 3])\n\n        XCTAssert(mod.reversed == .replace(10, at: 1, with: 2))\n        XCTAssert(mod.map { \"\\($0)\" } == .replace(\"2\", at: 1, with: \"10\"))\n    }\n\n    func testRangeReplacement() {\n        var a = [1, 2, 3]\n        let mod = ArrayModification.replaceSlice([2], at: 1, with: [10, 20])\n\n        XCTAssertEqual(mod.deltaCount, 1)\n        XCTAssertEqual(mod.startIndex, 1)\n        XCTAssertEqual(mod.inputRange, 1..<2)\n        XCTAssertEqual(mod.outputRange, 1..<3)\n        XCTAssertEqual(mod.oldElements, [2])\n        XCTAssertEqual(mod.newElements, [10, 20])\n\n        a.apply(mod)\n        XCTAssertEqual(a, [1, 10, 20, 3])\n\n        XCTAssert(mod.reversed == .replaceSlice([10, 20], at: 1, with: [2]))\n        XCTAssert(mod.map { \"\\($0)\" } == ArrayModification.replaceSlice([\"2\"], at: 1, with: [\"10\", \"20\"]))\n    }\n\n    func testMergeIntoEmpty() {\n        let first = ArrayModification.replaceSlice([], at: 10, with: [\"a\", \"b\", \"c\"])\n\n        let m1 = ArrayModification<String>.replaceSlice([\"a\", \"b\", \"c\"], at: 10, with: [])\n        XCTAssert(first.merged(with: m1) == .collapsedToNoChange)\n    }\n\n    func testMergeIntoNonEmpty() {\n        func x(_ n: Int) -> [String] { return Array(repeating: \"x\", count: n) }\n\n        let first = ArrayModification(replacing: x(10), at: 10, with: [\"a\", \"b\", \"c\"])!\n        // final range of first: 10..<13\n\n        let m1 = ArrayModification(replacing: [\"x\", \"x\", \"x\", \"x\", \"x\"], at: 1, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m1!) == .disjunctOrderedBefore)\n\n        let m2 = ArrayModification(replacing: [\"x\", \"x\", \"x\", \"x\", \"x\"], at: 5, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m2!) == .collapsedTo(.replaceSlice(x(15), at: 5, with: [\"1\", \"2\", \"a\", \"b\", \"c\"])))\n\n        let m3 = ArrayModification(replacing: [\"x\", \"x\", \"x\", \"x\", \"x\", \"a\"], at: 5, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m3!) == .collapsedTo(.replaceSlice(x(15), at: 5, with: [\"1\", \"2\", \"b\", \"c\"])))\n\n        let m4 = ArrayModification(replacing: [\"x\", \"a\", \"b\", \"c\", \"x\", \"x\"], at: 9, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m4!) == .collapsedTo(.replaceSlice(x(13), at: 9, with: [\"1\", \"2\"])))\n\n        let m5 = ArrayModification(replacing: [], at: 10, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m5!) == .collapsedTo(.replaceSlice(x(10), at: 10, with: [\"1\", \"2\", \"a\", \"b\", \"c\"])))\n\n        let m6 = ArrayModification(replacing: [\"a\"], at: 10, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m6!) == .collapsedTo(.replaceSlice(x(10), at: 10, with: [\"1\", \"2\", \"b\", \"c\"])))\n\n        let m7 = ArrayModification(replacing: [\"a\", \"b\", \"c\"], at: 10, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m7!) == .collapsedTo(.replaceSlice(x(10), at: 10, with: [\"1\", \"2\"])))\n\n        let m8 = ArrayModification(replacing: [\"a\", \"b\", \"c\", \"x\"], at: 10, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m8!) == .collapsedTo(.replaceSlice(x(11), at: 10, with: [\"1\", \"2\"])))\n\n        let m9 = ArrayModification(replacing: [\"b\"], at: 11, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m9!) == .collapsedTo(.replaceSlice(x(10), at: 10, with: [\"a\", \"1\", \"2\", \"c\"])))\n\n        let m10 = ArrayModification(replacing: [\"b\", \"c\", \"x\", \"x\"], at: 11, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m10!) == .collapsedTo(.replaceSlice(x(12), at: 10, with: [\"a\", \"1\", \"2\"])))\n\n        let m11 = ArrayModification(replacing: [\"b\", \"c\", \"x\", \"x\", \"x\", \"x\", \"x\", \"x\", \"x\"], at: 11, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m11!) == .collapsedTo(.replaceSlice(x(17), at: 10, with: [\"a\", \"1\", \"2\"])))\n\n        let m12 = ArrayModification(replacing: [], at: 13, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m12!) == .collapsedTo(.replaceSlice(x(10), at: 10, with: [\"a\", \"b\", \"c\", \"1\", \"2\"])))\n\n        let m13 = ArrayModification(replacing: [\"x\"], at: 13, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m13!) == .collapsedTo(.replaceSlice(x(11), at: 10, with: [\"a\", \"b\", \"c\", \"1\", \"2\"])))\n\n        let m14 = ArrayModification(replacing: [], at: 14, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m14!) == .disjunctOrderedAfter)\n        \n        let m15 = ArrayModification(replacing: x(6), at: 25, with: [\"1\", \"2\"])\n        XCTAssert(first.merged(with: m15!) == .disjunctOrderedAfter)\n    }\n\n    func testRemovingEqualChanges() {\n        typealias M = ArrayModification<String>\n\n        XCTAssertEqual(M.insert(\"foo\", at: 1).removingEqualChanges(), [M.insert(\"foo\", at: 1)])\n\n        XCTAssertEqual(M.remove(\"foo\", at: 1).removingEqualChanges(), [M.remove(\"foo\", at: 1)])\n\n        XCTAssertEqual(M.replace(\"foo\", at: 1, with: \"bar\").removingEqualChanges(), [M.replace(\"foo\", at: 1, with: \"bar\")])\n        XCTAssertEqual(M.replace(\"foo\", at: 1, with: \"foo\").removingEqualChanges(), [])\n\n        XCTAssertEqual(M.replaceSlice([\"foo\"], at: 1, with: [\"bar\"]).removingEqualChanges(),\n                       [M.replace(\"foo\", at: 1, with: \"bar\")])\n        XCTAssertEqual(M.replaceSlice([\"foo\", \"bar\"], at: 1, with: [\"bar\", \"foo\"]).removingEqualChanges(),\n                       [M.replaceSlice([\"foo\", \"bar\"], at: 1, with: [\"bar\", \"foo\"])])\n        XCTAssertEqual(M.replaceSlice([\"foo\", \"bar\", \"baz\"], at: 1, with: [\"baz\", \"bar\", \"foo\"]).removingEqualChanges(),\n                       [M.replace(\"foo\", at: 1, with: \"baz\"), M.replace(\"baz\", at: 3, with: \"foo\")])\n        XCTAssertEqual(M.replaceSlice([\"foo\", \"bar\", \"baz\"], at: 1, with: [\"foo\", \"bar\", \"foo\"]).removingEqualChanges(),\n                       [M.replace(\"baz\", at: 3, with: \"foo\")])\n        XCTAssertEqual(M.replaceSlice([\"foo\", \"bar\", \"baz\"], at: 1, with: [\"foo\", \"bar\", \"baz\"]).removingEqualChanges(),\n                       [])\n    }\n\n    func testEquality() {\n        typealias M = ArrayModification<String>\n\n        XCTAssertTrue(M.insert(\"foo\", at: 1) == M.insert(\"foo\", at: 1))\n        XCTAssertFalse(M.insert(\"foo\", at: 1) != M.insert(\"foo\", at: 1))\n\n        XCTAssertFalse(M.insert(\"foo\", at: 1) == M.insert(\"bar\", at: 1))\n        XCTAssertFalse(M.insert(\"foo\", at: 1) == M.insert(\"foo\", at: 2))\n\n        XCTAssertTrue(M.insert(\"foo\", at: 1) == M.replaceSlice([], at: 1, with: [\"foo\"]))\n    }\n\n    func testIsIdentity() {\n        typealias M = ArrayModification<String>\n\n        XCTAssertFalse(M.insert(\"foo\", at: 1).isIdentity)\n\n        XCTAssertFalse(M.remove(\"foo\", at: 1).isIdentity)\n\n        XCTAssertFalse(M.replace(\"foo\", at: 1, with: \"bar\").isIdentity)\n        XCTAssertTrue(M.replace(\"foo\", at: 1, with: \"foo\").isIdentity)\n\n        XCTAssertFalse(M.replaceSlice([\"foo\", \"bar\"], at: 1, with: [\"bar\", \"foo\"]).isIdentity)\n        XCTAssertFalse(M.replaceSlice([\"foo\", \"bar\"], at: 1, with: [\"foo\", \"foo\"]).isIdentity)\n        XCTAssertTrue(M.replaceSlice([\"foo\", \"bar\"], at: 1, with: [\"foo\", \"bar\"]).isIdentity)\n    }\n\n    func testDescription() {\n        typealias M = ArrayModification<String>\n\n        XCTAssertEqual(M.insert(\"foo\", at: 1).description, \".insert(foo, at: 1)\")\n        XCTAssertEqual(M.remove(\"foo\", at: 1).description, \".remove(foo, at: 1)\")\n        XCTAssertEqual(M.replace(\"foo\", at: 1, with: \"bar\").description, \".replace(foo, at: 1, with: bar)\")\n        XCTAssertEqual(M.replaceSlice([\"foo\", \"bar\"], at: 1, with: [\"bar\", \"foo\"]).description,\n                       \".replaceSlice([foo, bar], at: 1, with: [bar, foo])\")\n\n        XCTAssertEqual(M.insert(\"foo\", at: 1).debugDescription, \".insert(\\\"foo\\\", at: 1)\")\n        XCTAssertEqual(M.remove(\"foo\", at: 1).debugDescription, \".remove(\\\"foo\\\", at: 1)\")\n        XCTAssertEqual(M.replace(\"foo\", at: 1, with: \"bar\").debugDescription, \".replace(\\\"foo\\\", at: 1, with: \\\"bar\\\")\")\n        XCTAssertEqual(M.replaceSlice([\"foo\", \"bar\"], at: 1, with: [\"bar\", \"foo\"]).debugDescription,\n                       \".replaceSlice([\\\"foo\\\", \\\"bar\\\"], at: 1, with: [\\\"bar\\\", \\\"foo\\\"])\")\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayReferenceTests.swift",
    "content": "//\n//  ArrayReferenceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass ArrayReferenceTests: XCTestCase {\n    func testReference() {\n        let a: ArrayVariable<Int> = [1, 2, 3]\n        let b: ArrayVariable<Int> = [10, 20]\n        let c: ArrayVariable<Int> = []\n        let ref = Variable<ArrayVariable<Int>>(a)\n\n        XCTAssertEqual(ref.value.value, [1, 2, 3])\n        a[1] = 4\n        XCTAssertEqual(ref.value.value, [1, 4, 3])\n\n        let unpacked = ref.unpacked()\n\n        XCTAssertEqual(unpacked.isBuffered, false)\n        XCTAssertEqual(unpacked.count, 3)\n        XCTAssertEqual(unpacked[0], 1)\n        XCTAssertEqual(Array(unpacked[0 ..< 3]), [1, 4, 3])\n        XCTAssertEqual(unpacked.value, [1, 4, 3])\n        a[0] = 2\n        XCTAssertEqual(unpacked.value, [2, 4, 3])\n\n        let sink = MockArrayObserver(unpacked)\n\n        sink.expecting([\"begin\", \"3.replace(3, at: 2, with: 6)\", \"end\"]) {\n            a[2] = 6\n        }\n\n        sink.expecting([\"begin\", \"3.replaceSlice([2, 4, 6], at: 0, with: [10, 20])\", \"end\"]) {\n            ref.value = b\n        }\n\n        sink.expecting(\"begin\") {\n            b.apply(.beginTransaction)\n        }\n\n        sink.expectingNothing {\n            ref.apply(.beginTransaction)\n        }\n\n        sink.expecting(\"2.insert(15, at: 1)\") {\n            b.insert(15, at: 1)\n        }\n\n        sink.expecting(\"3.replaceSlice([10, 15, 20], at: 0, with: [])\") {\n            ref.value = c\n        }\n\n        sink.expecting(\"0.insert(100, at: 0)\") {\n            c.append(100)\n        }\n\n        sink.expectingNothing {\n            b.apply(.endTransaction)\n        }\n\n        sink.expecting(\"end\") {\n            ref.apply(.endTransaction)\n        }\n        \n        sink.disconnect()\n\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ArrayVariableTests.swift",
    "content": "//\n//  ArrayVariableTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass ArrayVariableTests: XCTestCase {\n    func testArrayInitialization() {\n        let a0 = ArrayVariable<Int>() // Empty\n        XCTAssertEqual(a0.count, 0)\n\n        let a1 = ArrayVariable([1, 2, 3, 4])\n        XCTAssertEqual(a1.value, [1, 2, 3, 4])\n\n        let a2 = ArrayVariable(1 ... 4)\n        XCTAssertEqual(a2.value, [1, 2, 3, 4])\n\n        let a3 = ArrayVariable(elements: 1, 2, 3, 4)\n        XCTAssertEqual(a3.value, [1, 2, 3, 4])\n\n        let a4: ArrayVariable<Int> = [1, 2, 3, 4] // From array literal\n        XCTAssertEqual(a4.value, [1, 2, 3, 4])\n    }\n\n    func testEquality() {\n        // Equality tests between two ArrayVariables\n        XCTAssertTrue(ArrayVariable([1, 2, 3]).value == ArrayVariable([1, 2, 3]).value)\n        XCTAssertFalse(ArrayVariable([1, 2, 3]).value == ArrayVariable([1, 2]).value)\n\n        // Equality tests between ArrayVariable and an array literal\n        XCTAssertTrue(ArrayVariable([1, 2, 3]).value == [1, 2, 3])\n        XCTAssertFalse(ArrayVariable([1, 2, 3]).value == [1, 2])\n\n        // Equality tests between two different ObservableArrayTypes\n        XCTAssertTrue(ArrayVariable([1, 2, 3]).value == AnyObservableArray(ArrayVariable([1, 2, 3])).value)\n        XCTAssertFalse(ArrayVariable([1, 2, 3]).value == AnyObservableArray(ArrayVariable([1, 2])).value)\n\n        // Equality tests between an ArrayVariable and an Array\n        XCTAssertTrue(ArrayVariable([1, 2, 3]).value == Array([1, 2, 3]))\n        XCTAssertFalse(ArrayVariable([1, 2, 3]).value == Array([1, 2]))\n        XCTAssertTrue(Array([1, 2, 3]) == ArrayVariable([1, 2, 3]).value)\n        XCTAssertFalse(Array([1, 2]) == ArrayVariable([1, 2, 3]).value)\n    }\n\n    func testValueAndCount() {\n        let array: ArrayVariable<Int> = [1, 2, 3]\n\n        XCTAssertEqual(array.value, [1, 2, 3])\n        XCTAssertEqual(array.count, 3)\n\n        array.value = [4, 5]\n\n        XCTAssertEqual(array.value, [4, 5])\n        XCTAssertEqual(array.count, 2)\n\n        array.value = [6]\n\n        XCTAssertEqual(array.value, [6])\n        XCTAssertEqual(array.count, 1)\n    }\n\n    func testIndexing() {\n        let array: ArrayVariable<Int> = [1, 2, 3]\n\n        XCTAssertEqual(array[1], 2)\n\n        array[2] = 10\n\n        XCTAssertEqual(array[2], 10)\n\n        XCTAssert([1, 2, 10].elementsEqual(array.value, by: ==))\n    }\n\n    func testIndexingWithRanges() {\n        let array: ArrayVariable<Int> = [1, 2, 3, 4]\n\n        XCTAssertEqual(array[1..<3], [2, 3])\n\n        array[1..<3] = [20, 30, 40]\n\n        XCTAssertEqual(array.value, [1, 20, 30, 40, 4])\n    }\n\n    func testChangeNotifications() {\n        func tryCase(_ input: [Int], op: (ArrayVariable<Int>) -> (), expectedOutput: [Int], expectedChange: ArrayChange<Int>) {\n            let array = ArrayVariable<Int>(input)\n\n            var changes = [ArrayChange<Int>]()\n            var values = [[Int]]()\n\n            let c1 = array.changes.subscribe { changes.append($0) }\n            defer { c1.disconnect() }\n\n            let c2 = array.anyObservableValue.futureValues.subscribe { values.append($0) }\n            defer { c2.disconnect() }\n\n            op(array)\n\n            XCTAssertEqual(array.value, expectedOutput)\n            XCTAssertEqual(values, [expectedOutput])\n            XCTAssertTrue(changes.count == 1 && changes[0] == expectedChange)\n        }\n\n        tryCase([1, 2, 3], op: { $0[1] = 20 },\n            expectedOutput: [1, 20, 3], expectedChange: ArrayChange(initialCount: 3, modification: .replace(2, at: 1, with: 20)))\n\n        tryCase([1, 2, 3], op: { $0[1..<2] = [20, 30] },\n                expectedOutput: [1, 20, 30, 3], expectedChange: ArrayChange(initialCount: 3, modification: .replaceSlice([2], at: 1, with: [20, 30])))\n\n        tryCase([1, 2, 3], op: { $0.value = [4, 5] },\n                expectedOutput: [4, 5], expectedChange: ArrayChange(initialCount: 3, modification: .replaceSlice([1, 2, 3], at: 0, with: [4, 5])))\n\n        tryCase([1, 2, 3], op: { $0.value = [4, 5] },\n                expectedOutput: [4, 5], expectedChange: ArrayChange(initialCount: 3, modification: .replaceSlice([1, 2, 3], at: 0, with: [4, 5])))\n\n        tryCase([1, 2, 3], op: { $0.replaceSubrange(0..<2, with: [5, 6, 7]) },\n                expectedOutput: [5, 6, 7, 3], expectedChange: ArrayChange(initialCount: 3, modification: .replaceSlice([1, 2], at: 0, with: [5, 6, 7])))\n\n        tryCase([1, 2, 3], op: { $0.append(10) },\n                expectedOutput: [1, 2, 3, 10], expectedChange: ArrayChange(initialCount: 3, modification: .insert(10, at: 3)))\n\n        tryCase([1, 2, 3], op: { $0.insert(10, at: 2) },\n                expectedOutput: [1, 2, 10, 3], expectedChange: ArrayChange(initialCount: 3, modification: .insert(10, at: 2)))\n\n        tryCase([1, 2, 3], op: { $0.remove(at: 1) },\n                expectedOutput: [1, 3], expectedChange: ArrayChange(initialCount: 3, modification: .remove(2, at: 1)))\n\n        tryCase([1, 2, 3], op: { $0.removeFirst() },\n                expectedOutput: [2, 3], expectedChange: ArrayChange(initialCount: 3, modification: .remove(1, at: 0)))\n\n        tryCase([1, 2, 3], op: { $0.removeLast() },\n                expectedOutput: [1, 2], expectedChange: ArrayChange(initialCount: 3, modification: .remove(3, at: 2)))\n\n        tryCase([1, 2, 3], op: { $0.removeAll() },\n                expectedOutput: [], expectedChange: ArrayChange(initialCount: 3, modification: .replaceSlice([1, 2, 3], at: 0, with: [])))\n\n    }\n}\n\n"
  },
  {
    "path": "Tests/GlueKitTests/Bookshelf.swift",
    "content": "//\n//  Bookshelf.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport GlueKit\nimport XCTest\n\n// Let's suppose we're writing an app for maintaining a catalogue for your books.\n// Here is what the model could look like.\n\nprivate class Author: Hashable {\n    let name: Variable<String>\n    let yearOfBirth: Variable<Int>\n\n    init(name: String, yearOfBirth: Int) {\n        self.name = .init(name)\n        self.yearOfBirth = .init(yearOfBirth)\n    }\n\n    var hashValue: Int { return name.value.hashValue }\n    static func == (a: Author, b: Author) -> Bool {\n        return a.name.value == b.name.value && a.yearOfBirth.value == b.yearOfBirth.value\n    }\n}\n\nprivate class Book: Hashable {\n    let title: Variable<String>\n    let authors: SetVariable<Author>\n    let publicationYear: Variable<Int>\n    let pages: Variable<Int>\n\n    init(title: String, authors: Set<Author>, publicationYear: Int, pages: Int) {\n        self.title = .init(title)\n        self.authors = SetVariable(authors)\n        self.publicationYear = .init(pages)\n        self.pages = .init(pages)\n    }\n\n    var hashValue: Int { return title.value.hashValue }\n    static func == (a: Book, b: Book) -> Bool {\n        return (a.title.value == b.title.value\n            && a.authors.value == b.authors.value\n            && a.publicationYear.value == b.publicationYear.value\n            && a.pages.value == b.pages.value)\n    }\n}\n\nprivate class Bookshelf {\n    let location: Variable<String>\n    let books: ArrayVariable<Book>\n\n    init(location: String, books: [Book] = []) {\n        self.location = .init(location)\n        self.books = .init(books)\n    }\n}\n\nprivate struct Fixture {\n    let stephenson = Author(name: \"Neal Stephenson\", yearOfBirth: 1959)\n    let pratchett = Author(name: \"Terry Pratchett\", yearOfBirth: 1948)\n    let gaiman = Author(name: \"Neil Gaiman\", yearOfBirth: 1960)\n    let knuth = Author(name: \"Donald E. Knuth\", yearOfBirth: 1938)\n\n    lazy var colourOfMagic: Book = .init(title: \"The Colour of Magic\", authors: [self.pratchett], publicationYear: 1983, pages: 206)\n    lazy var smallGods: Book = .init(title: \"Small Gods\", authors: [self.pratchett], publicationYear: 1992, pages: 284)\n    lazy var seveneves: Book = .init(title: \"Seveneves\", authors: [self.stephenson], publicationYear: 2015, pages: 880)\n    lazy var goodOmens: Book = .init(title: \"Good Omens\", authors: [self.pratchett, self.gaiman], publicationYear: 1990, pages: 288)\n    lazy var americanGods: Book = .init(title: \"American Gods\", authors: [self.gaiman], publicationYear: 2001, pages: 465)\n    lazy var cryptonomicon: Book = .init(title: \"Cryptonomicon\", authors: [self.stephenson], publicationYear: 1999, pages: 918)\n    lazy var anathem: Book = .init(title: \"Anathem\", authors: [self.stephenson], publicationYear: 2008, pages: 928)\n    lazy var texBook: Book = .init(title: \"The TeXBook\", authors: [self.knuth], publicationYear: 1984, pages: 483)\n    lazy var taocp1: Book = .init(title: \"The Art of Computer Programming vol. 1: Fundamental Algorithms. 3rd ed.\", authors: [self.knuth], publicationYear: 1997, pages: 650)\n\n    lazy var topShelf: Bookshelf = .init(location: \"Top\", books: [self.colourOfMagic, self.smallGods, self.seveneves, self.goodOmens, self.americanGods])\n    lazy var bottomShelf: Bookshelf = .init(location: \"Bottom\", books: [self.cryptonomicon, self.anathem, self.texBook, self.taocp1])\n    lazy var shelves: ArrayVariable<Bookshelf> = [self.topShelf, self.bottomShelf]\n}\n\nclass BookshelfTests: XCTestCase {\n\n    func testAllTitles() {\n        var f = Fixture()\n        // Let's get an array of the title of each book in the library.\n        let allTitles = f.shelves.flatMap{$0.books}.map{$0.title}\n        XCTAssertEqual(allTitles.value, [\"The Colour of Magic\", \"Small Gods\", \"Seveneves\", \"Good Omens\", \"American Gods\", \"Cryptonomicon\", \"Anathem\", \"The TeXBook\", \"The Art of Computer Programming vol. 1: Fundamental Algorithms. 3rd ed.\"])\n    }\n\n    func testBooksByStephenson() {\n        var f = Fixture()\n        let booksByStephenson = f.shelves.flatMap{$0.books}.filter { book in book.authors.observableContains(f.stephenson) }\n        XCTAssertEqual(booksByStephenson.value, [f.seveneves, f.cryptonomicon, f.anathem])\n    }\n}\n\n\n\n\n\n"
  },
  {
    "path": "Tests/GlueKitTests/BracketingSourceTests.swift",
    "content": "//\n//  BracketingSourceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass BracketingSourceTests: XCTestCase {\n    func testHello() {\n        let source = Signal<Int>()\n\n        var helloCount = 0\n        let bracket = source.bracketed(hello: { helloCount += 1; return 0 },\n                                       goodbye: { return nil })\n\n\n        XCTAssertFalse(source.isConnected)\n\n        let s1 = MockSink<Int>()\n\n        s1.expecting(0) {\n            bracket.add(s1)\n        }\n        XCTAssertTrue(source.isConnected)\n        XCTAssertEqual(helloCount, 1)\n\n        s1.expecting(1) {\n            source.send(1)\n        }\n\n        let s2 = MockSink<Int>()\n        s2.expecting(0) {\n            bracket.add(s2)\n        }\n        XCTAssertEqual(helloCount, 2)\n\n        s1.expecting(2) {\n            s2.expecting(2) {\n                source.send(2)\n            }\n        }\n\n        s1.expectingNothing {\n            _ = bracket.remove(s1)\n        }\n\n        s2.expecting(3) {\n            source.send(3)\n        }\n\n        s2.expectingNothing {\n            _ = bracket.remove(s2)\n        }\n\n        XCTAssertFalse(source.isConnected)\n        XCTAssertEqual(helloCount, 2)\n    }\n\n    func testGoodbye() {\n        let source = Signal<Int>()\n\n        var goodbyeCount = 0\n        let bracket = source.bracketed(hello: { return nil },\n                                       goodbye: { goodbyeCount += 1; return 0 })\n\n\n        XCTAssertFalse(source.isConnected)\n\n        let s1 = MockSink<Int>()\n\n        s1.expectingNothing {\n            bracket.add(s1)\n        }\n        XCTAssertTrue(source.isConnected)\n        XCTAssertEqual(goodbyeCount, 0)\n\n        s1.expecting(1) {\n            source.send(1)\n        }\n\n        let s2 = MockSink<Int>()\n        s2.expectingNothing {\n            bracket.add(s2)\n        }\n        XCTAssertEqual(goodbyeCount, 0)\n\n        s1.expecting(2) {\n            s2.expecting(2) {\n                source.send(2)\n            }\n        }\n\n        s1.expecting(0) {\n            _ = bracket.remove(s1)\n        }\n        XCTAssertEqual(goodbyeCount, 1)\n\n        s2.expecting(3) {\n            source.send(3)\n        }\n\n        s2.expecting(0) {\n            _ = bracket.remove(s2)\n        }        \n        XCTAssertFalse(source.isConnected)\n        XCTAssertEqual(goodbyeCount, 2)\n    }\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/BufferedSourceTests.swift",
    "content": "//\n//  BufferedSourceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nprivate class TestSource: SourceType {\n    typealias Value = Int\n\n    var added = 0\n    var removed = 0\n    var sinks: Set<AnySink<Int>> = []\n\n    init() {}\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Int {\n        added += 1\n        let (inserted, _) = sinks.insert(sink.anySink)\n        precondition(inserted)\n    }\n\n    @discardableResult\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Int {\n        removed += 1\n        let old = sinks.remove(sink.anySink)!\n        return old.opened()!\n    }\n\n    func send(_ value: Int) {\n        for sink in sinks {\n            if sinks.contains(sink) {\n                sink.receive(value)\n            }\n        }\n    }\n}\n\nclass BufferedSourceTests: XCTestCase {\n    func testRetainsInput() {\n        weak var weakSource: TestSource? = nil\n        var buffered: AnySource<Int>? = nil\n        do {\n            let source = TestSource()\n            weakSource = source\n            buffered = source.buffered()\n        }\n\n        XCTAssertNotNil(weakSource)\n        XCTAssertNotNil(buffered)\n\n        buffered = nil\n\n        XCTAssertNil(weakSource)\n    }\n\n    func testSubscribesOnceWhileActive() {\n        let source = TestSource()\n        let buffered = source.buffered()\n\n        XCTAssertEqual(source.added, 0)\n        XCTAssertEqual(source.removed, 0)\n\n        let sink = MockSink<Int>()\n        buffered.add(sink)\n\n        XCTAssertEqual(source.added, 1)\n        XCTAssertEqual(source.removed, 0)\n\n        let sink2 = MockSink<Int>()\n        buffered.add(sink2)\n\n        XCTAssertEqual(source.added, 1)\n        XCTAssertEqual(source.removed, 0)\n\n        buffered.remove(sink)\n\n        XCTAssertEqual(source.added, 1)\n        XCTAssertEqual(source.removed, 0)\n\n        buffered.remove(sink2)\n\n        XCTAssertEqual(source.added, 1)\n        XCTAssertEqual(source.removed, 1)\n\n        withExtendedLifetime(buffered) {}\n    }\n\n    func testReceivesValuesFromSource() {\n        let source = TestSource()\n        let buffered = source.buffered()\n\n        let sink = MockSink<Int>()\n        buffered.add(sink)\n\n        sink.expecting(1) {\n            source.send(1)\n        }\n\n        let sink2 = MockSink<Int>()\n        buffered.add(sink2)\n\n        sink.expecting(2) {\n            sink2.expecting(2) {\n                source.send(2)\n            }\n        }\n\n        buffered.remove(sink)\n\n        sink2.expecting(3) {\n            source.send(3)\n        }\n\n        buffered.remove(sink2)\n\n        sink.expectingNothing {\n            sink2.expectingNothing {\n                source.send(4)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ChangeTests.swift",
    "content": "//\n//  Abstract Observables.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass ChangeTests: XCTestCase {\n    func testDefaultApplied() {\n        let change = TestChange([1, 2])\n        XCTAssertEqual(change.applied(on: 1), 2)\n    }\n\n    func testDefaultMerged() {\n        let change = TestChange([1, 2])\n        let next = TestChange([2, 3])\n        XCTAssertEqual(change.merged(with: next).values, [1, 2, 3])\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ChangesSourceTests.swift",
    "content": "//\n//  ChangesSourceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass ChangesSourceTests: XCTestCase {\n    func testRetainsObservable() {\n        weak var weakObservable: TestObservable? = nil\n        var changes: AnySource<TestChange>? = nil\n        do {\n            let observable = TestObservable(0)\n            weakObservable = observable\n            changes = observable.changes\n        }\n        XCTAssertNotNil(changes)\n        XCTAssertNotNil(weakObservable)\n        changes = nil\n        XCTAssertNil(weakObservable)\n    }\n\n    func testSubscribingToChangesSubscribesToUpdates() {\n        let observable = TestObservable(0)\n        let changes = observable.changes\n\n        let sink = MockSink<TestChange>()\n\n        XCTAssertFalse(observable.isConnected)\n\n        changes.add(sink)\n\n        XCTAssertTrue(observable.isConnected)\n\n        changes.remove(sink)\n\n        XCTAssertFalse(observable.isConnected)\n    }\n\n    func testChangesSendsCompletedChanges() {\n        let observable = TestObservable(0)\n        let changes = observable.changes\n\n        let sink = MockSink<TestChange>()\n\n        changes.add(sink)\n\n        sink.expectingNothing {\n            observable.beginTransaction()\n            observable.value = 1\n            observable.value = 2\n        }\n\n        sink.expecting(TestChange([0, 1, 2])) {\n            observable.endTransaction()\n        }\n\n        changes.remove(sink)\n    }\n\n    func testRemovingASinkDuringATransactionSendsPartialChanges() {\n        let observable = TestObservable(0)\n        let changes = observable.changes\n\n        let sink = MockSink<TestChange>()\n        changes.add(sink)\n        observable.beginTransaction()\n        observable.value = 1\n        observable.value = 2\n        sink.expecting(TestChange([0, 1, 2])) {\n            _ = changes.remove(sink)\n        }\n        observable.value = 3\n        observable.endTransaction()\n    }\n\n    func testDifferentSinksMayReceiveDifferentChanges() {\n        let observable = TestObservable(0)\n        let changes = observable.changes\n\n        let sink1 = MockSink<TestChange>()\n        changes.add(sink1)\n\n        observable.beginTransaction()\n        observable.value = 1\n\n        let sink2 = MockSink<TestChange>()\n        changes.add(sink2)\n\n        observable.value = 2\n\n        sink1.expecting(TestChange([0, 1, 2])) {\n            _ = changes.remove(sink1)\n        }\n\n        observable.value = 3\n\n        sink2.expecting(TestChange([1, 2, 3])) {\n            observable.endTransaction()\n        }\n\n        changes.remove(sink2)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/CombinedObservableTests.swift",
    "content": "//\n//  CombinedObservableTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nclass CombinedObservableTests: XCTestCase {\n    func testCombine_Works() {\n        let a = TestObservableValue(1)\n        let b = TestObservableValue(2)\n\n        let combined = a.combined(b) { a, b in \"[\\(a),\\(b)]\" }\n\n        let mock = MockValueUpdateSink(combined)\n\n        mock.expecting([\"begin\", \"[1,2] -> [3,2]\", \"end\"]) {\n            a.value = 3\n        }\n\n        XCTAssertEqual(combined.value, \"[3,2]\")\n\n        mock.expecting([\"begin\", \"[3,2] -> [3,4]\", \"end\"]) {\n            b.value = 4\n        }\n\n        XCTAssertEqual(combined.value, \"[3,4]\")\n    }\n\n    func testCombineDistinct_WithNestedUpdates() {\n        let a = TestObservableValue(3)\n        let b = TestObservableValue(2)\n        let combined = a.combined(b) { a, b in (a, b) }.distinct(==)\n\n        var r = \"\"\n        let c = combined.values.subscribe { av, bv in\n            r += \" (\\(av)-\\(bv)\"\n            if av > 0 {\n                a.value = av - 1\n            }\n            else if bv > 0 {\n                b.value = bv - 1\n            }\n            r += \")\"\n        }\n\n        XCTAssertEqual(r, \" (3-2) (2-2) (1-2) (0-2) (0-1) (0-0)\")\n        c.disconnect()\n    }\n\n    func testCombineUpToSixObservables() {\n        let a = TestObservableValue(1)\n        let b = TestObservableValue(2)\n        let c = TestObservableValue(3)\n        let d = TestObservableValue(4)\n        let e = TestObservableValue(5)\n        let f = TestObservableValue(6)\n\n        let t2 = a.combined(b)\n        let t3 = a.combined(b, c)\n        let t4 = a.combined(b, c, d)\n        let t5 = a.combined(b, c, d, e)\n        let t6 = a.combined(b, c, d, e, f)\n\n        let c2 = a.combined(b, by: { (a: Int, b: Int) -> Int in a + b })\n        let c3 = a.combined(b, c, by: { (a: Int, b: Int, c: Int) -> Int in a + b + c })\n        let c4 = a.combined(b, c, d, by: { (a: Int, b: Int, c: Int, d: Int) -> Int in a + b + c + d })\n        let c5 = a.combined(b, c, d, e, by: { (a: Int, b: Int, c: Int, d: Int, e: Int) -> Int in a + b + c + d + e })\n        let c6 = a.combined(b, c, d, e, f, by: { (a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) -> Int in a + b + c + d + e + f })\n\n        XCTAssertTrue(t2.value == (1, 2))\n        XCTAssertTrue(t3.value == (1, 2, 3))\n        XCTAssertTrue(t4.value == (1, 2, 3, 4))\n        XCTAssertTrue(t5.value == (1, 2, 3, 4, 5))\n        XCTAssertTrue(t6.value == (1, 2, 3, 4, 5, 6))\n\n        XCTAssertTrue(c2.value == 3)\n        XCTAssertTrue(c3.value == 6)\n        XCTAssertTrue(c4.value == 10)\n        XCTAssertTrue(c5.value == 15)\n        XCTAssertTrue(c6.value == 21)\n    }\n\n    func testEquatableOperators() {\n        let a = TestObservableValue(0)\n        let b = TestObservableValue(0)\n\n        let eq = (a == b)\n        let ne = (a != b)\n\n        XCTAssertTrue(eq.value)\n        XCTAssertFalse(ne.value)\n\n        a.value = 1\n\n        XCTAssertFalse(eq.value)\n        XCTAssertTrue(ne.value)\n    }\n\n    func testComparableOperators() {\n        let a = TestObservableValue(0)\n        let b = TestObservableValue(0)\n\n        let lt = (a < b)\n        let gt = (a > b)\n        let le = (a <= b)\n        let ge = (a >= b)\n        let mi = min(a, b)\n        let ma = max(a, b)\n\n        XCTAssertFalse(lt.value)\n        XCTAssertFalse(gt.value)\n        XCTAssertTrue(le.value)\n        XCTAssertTrue(ge.value)\n        XCTAssertEqual(mi.value, 0)\n        XCTAssertEqual(ma.value, 0)\n\n        a.value = 1\n\n        XCTAssertFalse(lt.value)\n        XCTAssertTrue(gt.value)\n        XCTAssertFalse(le.value)\n        XCTAssertTrue(ge.value)\n        XCTAssertEqual(mi.value, 0)\n        XCTAssertEqual(ma.value, 1)\n\n        b.value = 2\n\n        XCTAssertTrue(lt.value)\n        XCTAssertFalse(gt.value)\n        XCTAssertTrue(le.value)\n        XCTAssertFalse(ge.value)\n        XCTAssertEqual(mi.value, 1)\n        XCTAssertEqual(ma.value, 2)\n\n        a.value = 2\n\n        XCTAssertFalse(lt.value)\n        XCTAssertFalse(gt.value)\n        XCTAssertTrue(le.value)\n        XCTAssertTrue(ge.value)\n        XCTAssertEqual(mi.value, 2)\n        XCTAssertEqual(ma.value, 2)\n    }\n\n    func testBooleanOperators() {\n        let a = TestUpdatableValue(0)\n        let b = TestUpdatableValue(0)\n        let c = TestUpdatableValue(0)\n\n        let bIsBetweenAAndC = a < b && b < c\n        let bIsNotBetweenAAndC = !bIsBetweenAAndC\n        let aIsNotTheGreatest = a < b || a < c\n\n        XCTAssertFalse(bIsBetweenAAndC.value)\n        XCTAssertTrue(bIsNotBetweenAAndC.value)\n        XCTAssertFalse(aIsNotTheGreatest.value)\n\n        a.value = 1\n\n        XCTAssertFalse(bIsBetweenAAndC.value)\n        XCTAssertTrue(bIsNotBetweenAAndC.value)\n        XCTAssertFalse(aIsNotTheGreatest.value)\n\n        b.value = 2\n\n        XCTAssertFalse(bIsBetweenAAndC.value)\n        XCTAssertTrue(bIsNotBetweenAAndC.value)\n        XCTAssertTrue(aIsNotTheGreatest.value)\n\n        c.value = 3\n\n        XCTAssertTrue(bIsBetweenAAndC.value)\n        XCTAssertFalse(bIsNotBetweenAAndC.value)\n        XCTAssertTrue(aIsNotTheGreatest.value)\n    }\n\n    func testIntegerNegation() {\n        let a = TestUpdatableValue(1)\n\n        let n = -a\n\n        XCTAssertEqual(n.value, -1)\n\n        let mock = MockValueUpdateSink(n)\n\n        mock.expecting([\"begin\", \"-1 -> -2\", \"end\"]) {\n            a.value = 2\n        }\n    }\n\n    func testIntegerArithmeticOperators() {\n        let a = TestUpdatableValue(0)\n        let b = TestUpdatableValue(0)\n        let c = TestUpdatableValue(0)\n\n        let e1 = a % AnyObservableValue.constant(10)\n        let e2 = b * c / (a + AnyObservableValue.constant(1))\n        let expression = e1 + e2 - c\n\n        var r = [Int]()\n        let connection = expression.values.subscribe { r.append($0) }\n\n        XCTAssertEqual(r, [0])\n        r = []\n\n        a.value = 1\n\n        // The observable `a` occurs twice in the expression above, so the expression will be evaluated twice.\n        // The first evaluation will only apply the new value to one of the sources.\n        // However, the `values` source reports only full transactions, so such partial updates will not appear there.\n        XCTAssertEqual(r, [1])\n\n        r = []\n\n        b.value = 2\n\n        XCTAssertEqual(r, [1])\n        r = []\n        \n        c.value = 3\n        \n        XCTAssertEqual(r, [1 + 2 * 3 / 2 - 3] as [Int])\n        r = []\n        \n        a.value = 15\n        \n        XCTAssertEqual(r, [5 + 2 * 3 / 16 - 3] as [Int])\n        r = []\n        \n        \n        connection.disconnect()\n    }\n\n    func testFloatingPointArithmeticOperators() {\n        let a = TestUpdatableValue(0.0)\n        let b = TestUpdatableValue(0.0)\n        let c = TestUpdatableValue(0.0)\n\n        let expression = a + b * c / (a + AnyObservableValue.constant(1)) - c\n\n        XCTAssertEqual(expression.value, 0)\n\n        var r: [Double] = []\n        let connection = expression.values.subscribe { r.append($0) }\n\n        XCTAssertEqual(r, [0])\n        r = []\n\n        a.value = 1\n\n        XCTAssertEqual(r, [1])\n\n        r = []\n\n        b.value = 2\n\n        XCTAssertEqual(r, [1])\n        r = []\n\n        c.value = 3\n\n        XCTAssertEqual(r, [1 + 2 * 3 / 2 - 3] as [Double])\n        r = []\n\n        a.value = 15\n\n        XCTAssertEqual(r, [15 + 2 * 3 / 16 - 3] as [Double])\n        r = []\n        \n        connection.disconnect()\n    }\n\n    func testTransactions() {\n        let a = Variable<Int>(0)\n\n        let sum = a + a\n\n        let sink = MockValueUpdateSink(sum)\n\n        sink.expecting([\"begin\", \"0 -> 1\", \"1 -> 2\", \"end\"]) {\n            a.value = 1\n        }\n\n        sink.expecting(\"begin\") {\n            a.apply(.beginTransaction)\n        }\n\n        sink.expecting([\"2 -> 3\", \"3 -> 4\"]) {\n            a.value = 2\n        }\n\n        sink.expecting(\"end\") {\n            a.apply(.endTransaction)\n        }\n\n        sink.disconnect()\n    }\n}\n\n"
  },
  {
    "path": "Tests/GlueKitTests/CombinedUpdatableTests.swift",
    "content": "//\n//  CombinedUpdatableTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\n\nclass CombinedUpdatableTests: XCTestCase {\n    func testCombine_Works() {\n        let a = TestUpdatableValue(0)\n        let b = TestUpdatableValue(1)\n\n        let combined = a.combined(b).map({ (a, b) in 10 * a + b }, inverse: { ($0 / 10, $0 % 10) })\n\n        XCTAssertEqual(combined.value, 1)\n        combined.value = 12\n        XCTAssertEqual(combined.value, 12)\n\n        let changes = combined.changes\n        let mock = TransformedMockSink(changes, { \"\\($0)\" })\n\n        mock.expecting(\"12 -> 32\") {\n            a.value = 3\n        }\n\n        XCTAssertEqual(combined.value, 32)\n\n        mock.expecting(\"32 -> 34\") {\n            b.value = 4\n        }\n\n        XCTAssertEqual(combined.value, 34)\n\n        mock.expecting(\"34 -> 56\") {\n            combined.value = 56\n        }\n        XCTAssertEqual(combined.value, 56)\n        XCTAssertEqual(a.value, 5)\n        XCTAssertEqual(b.value, 6)\n    }\n\n    func testCombine_WithNestedUpdates() {\n        let a = TestUpdatableValue(3)\n        let b = TestUpdatableValue(2)\n        let combined = a.combined(b)\n\n        var r = \"\"\n        let c = combined.values.subscribe { av, bv in\n            r += \" (\\(av)-\\(bv)\"\n            if av > 0 {\n                a.value = av - 1\n            }\n            else if bv > 0 {\n                b.value = bv - 1\n            }\n            r += \")\"\n        }\n\n        XCTAssertEqual(r, \" (3-2) (2-2) (1-2) (0-2) (0-1) (0-0)\")\n        c.disconnect()\n    }\n\n    func testCombineUpToSixUpdatables() {\n        let a = TestUpdatableValue(1)\n        let b = TestUpdatableValue(2)\n        let c = TestUpdatableValue(3)\n        let d = TestUpdatableValue(4)\n        let e = TestUpdatableValue(5)\n        let f = TestUpdatableValue(6)\n\n        let t2 = a.combined(b)\n        let t3 = a.combined(b, c)\n        let t4 = a.combined(b, c, d)\n        let t5 = a.combined(b, c, d, e)\n        let t6 = a.combined(b, c, d, e, f)\n\n        XCTAssertTrue(t2.value == (1, 2))\n        XCTAssertTrue(t3.value == (1, 2, 3))\n        XCTAssertTrue(t4.value == (1, 2, 3, 4))\n        XCTAssertTrue(t5.value == (1, 2, 3, 4, 5))\n        XCTAssertTrue(t6.value == (1, 2, 3, 4, 5, 6))\n\n        t6.value = (6, 5, 4, 3, 2, 1)\n\n        XCTAssertTrue(t2.value == (6, 5))\n        XCTAssertTrue(t3.value == (6, 5, 4))\n        XCTAssertTrue(t4.value == (6, 5, 4, 3))\n        XCTAssertTrue(t5.value == (6, 5, 4, 3, 2))\n        XCTAssertTrue(t6.value == (6, 5, 4, 3, 2, 1))\n\n        t5.value = (2, 4, 6, 8, 10)\n\n        XCTAssertTrue(t2.value == (2, 4))\n        XCTAssertTrue(t3.value == (2, 4, 6))\n        XCTAssertTrue(t4.value == (2, 4, 6, 8))\n        XCTAssertTrue(t5.value == (2, 4, 6, 8, 10))\n        XCTAssertTrue(t6.value == (2, 4, 6, 8, 10, 1))\n\n        t4.value = (3, 5, 7, 11)\n\n        XCTAssertTrue(t2.value == (3, 5))\n        XCTAssertTrue(t3.value == (3, 5, 7))\n        XCTAssertTrue(t4.value == (3, 5, 7, 11))\n        XCTAssertTrue(t5.value == (3, 5, 7, 11, 10))\n        XCTAssertTrue(t6.value == (3, 5, 7, 11, 10, 1))\n\n        t3.value = (-1, -2, -3)\n\n        XCTAssertTrue(t2.value == (-1, -2))\n        XCTAssertTrue(t3.value == (-1, -2, -3))\n        XCTAssertTrue(t4.value == (-1, -2, -3, 11))\n        XCTAssertTrue(t5.value == (-1, -2, -3, 11, 10))\n        XCTAssertTrue(t6.value == (-1, -2, -3, 11, 10, 1))\n\n        t2.value = (10, 20)\n\n        XCTAssertTrue(t2.value == (10, 20))\n        XCTAssertTrue(t3.value == (10, 20, -3))\n        XCTAssertTrue(t4.value == (10, 20, -3, 11))\n        XCTAssertTrue(t5.value == (10, 20, -3, 11, 10))\n        XCTAssertTrue(t6.value == (10, 20, -3, 11, 10, 1))\n\n        a.value = 0\n\n        XCTAssertTrue(t2.value == (0, 20))\n        XCTAssertTrue(t3.value == (0, 20, -3))\n        XCTAssertTrue(t4.value == (0, 20, -3, 11))\n        XCTAssertTrue(t5.value == (0, 20, -3, 11, 10))\n        XCTAssertTrue(t6.value == (0, 20, -3, 11, 10, 1))\n\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ConnectorTests.swift",
    "content": "//\n//  ConnectorTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass TestConnection: Connection {\n    var callback: (() -> ())?\n\n    init(_ callback: @escaping () -> ()) {\n        self.callback = callback\n        super.init()\n    }\n\n    deinit {\n        disconnect()\n    }\n\n    override func disconnect() {\n        guard let callback = self.callback else { return }\n        self.callback = nil\n        callback()\n    }\n}\nclass ConnectorTests: XCTestCase {\n    \n    func test_EmptyConnector() {\n        let connector = Connector()\n        connector.disconnect()\n    }\n\n    func test_ReleasingTheConnectorDisconnectsItsConnections() {\n        var actual: [Int] = []\n        do {\n            let connector = Connector()\n            let c = TestConnection { actual.append(1) }\n            c.putInto(connector)\n\n            XCTAssertEqual(actual, [])\n        }\n        XCTAssertEqual(actual, [1])\n    }\n\n    func test_DisconnectingTheConnectorDisconnectsItsConnections() {\n        var actual: [Int] = []\n\n        do {\n            let connector = Connector()\n            let c = TestConnection { actual.append(1) }\n            c.putInto(connector)\n            XCTAssertEqual(actual, [])\n            connector.disconnect()\n            XCTAssertEqual(actual, [1])\n            withExtendedLifetime(connector) {}\n        }\n        XCTAssertEqual(actual, [1])\n    }\n\n    func test_ConnectorsCanBeRestarted() {\n        var actual: [Int] = []\n\n        do {\n            let connector = Connector()\n            let c1 = TestConnection { actual.append(1) }\n            c1.putInto(connector)\n            XCTAssertEqual(actual, [])\n            connector.disconnect()\n            XCTAssertEqual(actual, [1])\n\n            let c2 = TestConnection { actual.append(2) }\n            c2.putInto(connector)\n            XCTAssertEqual(actual, [1])\n            connector.disconnect()\n            XCTAssertEqual(actual, [1, 2])\n            \n            withExtendedLifetime(connector) {}\n        }\n        XCTAssertEqual(actual, [1, 2])\n    }\n\n    func test_ConnectingASourceToAClosure() {\n        let signal = Signal<Int>()\n        let connector = Connector()\n\n        var expected: [Int] = []\n        var actual: [Int] = []\n        connector.connect(signal) { value in actual.append(value) }\n\n        XCTAssertEqual(actual, expected)\n\n        expected.append(42)\n        signal.send(42)\n        XCTAssertEqual(actual, expected)\n\n        connector.disconnect()\n        signal.send(23)\n        XCTAssertEqual(actual, expected)\n\n        withExtendedLifetime(connector) {}\n    }\n\n    #if false // TODO Compiler crash in Xcode 8.3.2\n    func test_ConnectingAnObservableToAChangeClosure() {\n        let variable = Variable<Int>(0)\n        let connector = Connector()\n\n        var expected: [ValueChange<Int>] = []\n        var actual: [ValueChange<Int>] = []\n\n        connector.connect(variable) { change in actual.append(change) }\n\n        XCTAssertTrue(actual.elementsEqual(expected, by: ==))\n\n        expected.append(.init(from: 0, to: 42))\n        variable.value = 42\n\n        XCTAssertTrue(actual.elementsEqual(expected, by: ==))\n\n        connector.disconnect()\n        variable.value = 23\n\n        XCTAssertTrue(actual.elementsEqual(expected, by: ==))\n\n        withExtendedLifetime(connector) {}\n    }\n    #endif\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/DispatchSourceTests.swift",
    "content": "//\n//  DispatchSourceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\n\nclass DispatchSourceTests: XCTestCase {\n    func testDispatchQueue() {\n        let signal = Signal<Int>()\n\n        let queue = DispatchQueue(label: \"org.attaswift.GlueKit.test\")\n        let semaphore = DispatchSemaphore(value: 1)\n        var r: [Int] = []\n\n        let connection = signal.dispatch(on: queue).subscribe { value in\n            semaphore.wait()\n            r.append(value)\n            semaphore.signal()\n        }\n\n        semaphore.wait()\n        signal.send(1)\n        XCTAssertEqual(r, [])\n        semaphore.signal()\n        queue.sync {\n            XCTAssertEqual(r, [1])\n        }\n\n        connection.disconnect()\n    }\n\n    func testOperationQueue() {\n        let signal = Signal<Int>()\n\n        let queue = OperationQueue()\n        queue.maxConcurrentOperationCount = 1\n        let semaphore = DispatchSemaphore(value: 1)\n        var r: [Int] = []\n\n        let connection = signal.dispatch(on: queue).subscribe { value in\n            XCTAssertEqual(OperationQueue.current, queue)\n            semaphore.wait()\n            r.append(value)\n            semaphore.signal()\n        }\n\n        semaphore.wait()\n        signal.send(1)\n        XCTAssertEqual(r, [])\n        semaphore.signal()\n\n        queue.waitUntilAllOperationsAreFinished()\n        XCTAssertEqual(r, [1])\n\n        queue.addOperation {\n            signal.send(2)\n        }\n\n        queue.waitUntilAllOperationsAreFinished()\n\n        semaphore.wait()\n        XCTAssertEqual(r, [1, 2])\n        semaphore.signal()\n\n        connection.disconnect()\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/DistinctTests.swift",
    "content": "//\n//  DistinctTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-08.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass DistinctTests: XCTestCase {\n    func test_updates_reportsChangesAtTheEndOfTheTransaction() {\n        let test = TestUpdatableValue(0)\n        let distinct = test.distinct()\n\n        let sink = MockValueUpdateSink<Int>()\n        distinct.updates.add(sink)\n\n        sink.expecting(\"begin\") {\n            test.beginTransaction()\n        }\n\n        sink.expectingNothing {\n            test.value = 1\n            test.value = 2\n        }\n\n        sink.expecting([\"0 -> 2\", \"end\"]) {\n            test.endTransaction()\n        }\n\n        distinct.updates.remove(sink)\n    }\n\n    func test_updates_ignoresTransactionsThatDontChangeTheValue() {\n        let test = TestUpdatableValue(0)\n        let distinct = test.distinct()\n\n        let sink = MockValueUpdateSink<Int>()\n        distinct.updates.add(sink)\n\n        sink.expecting(\"begin\") {\n            test.beginTransaction()\n        }\n\n        sink.expectingNothing {\n            test.value = 1\n            test.value = 0\n        }\n\n        sink.expecting([\"end\"]) {\n            test.endTransaction()\n        }\n\n        distinct.updates.remove(sink)\n    }\n\n    func test_updates_subscribersMaySeeDifferentChanges() {\n        let test = TestUpdatableValue(0)\n        let distinct = test.distinct()\n\n        let sink0to2 = MockValueUpdateSink<Int>()\n        distinct.updates.add(sink0to2)\n\n        let sink0to3 = MockValueUpdateSink<Int>()\n        distinct.updates.add(sink0to3)\n\n        sink0to2.expecting(\"begin\") {\n            sink0to3.expecting(\"begin\") {\n                test.beginTransaction()\n            }\n        }\n\n        sink0to2.expectingNothing {\n            sink0to3.expectingNothing {\n                test.value = 1\n            }\n        }\n\n        let sink1to2 = MockValueUpdateSink<Int>()\n        sink1to2.expecting(\"begin\") {\n            distinct.updates.add(sink1to2)\n        }\n\n        let sink1to3 = MockValueUpdateSink<Int>()\n        sink1to3.expecting(\"begin\") {\n            distinct.updates.add(sink1to3)\n        }\n\n        sink0to2.expectingNothing {\n            sink0to3.expectingNothing {\n                sink1to2.expectingNothing {\n                    sink1to3.expectingNothing {\n                        test.value = 2\n                    }\n                }\n            }\n        }\n\n        sink0to2.expecting([\"0 -> 2\", \"end\"]) {\n            distinct.updates.remove(sink0to2)\n        }\n\n        sink1to2.expecting([\"1 -> 2\", \"end\"]) {\n            distinct.updates.remove(sink1to2)\n        }\n\n        sink0to3.expectingNothing {\n            sink1to3.expectingNothing {\n                test.value = 3\n            }\n        }\n\n        sink0to3.expecting([\"0 -> 3\", \"end\"]) {\n            sink1to3.expecting([\"1 -> 3\", \"end\"]) {\n                test.endTransaction()\n            }\n        }\n\n        sink0to3.expectingNothing {\n            distinct.updates.remove(sink0to3)\n        }\n\n        sink1to3.expectingNothing {\n            distinct.updates.remove(sink1to3)\n        }\n    }\n\n    func test_values_defaultEqualityTest() {\n        let test = TestObservableValue(0)\n        let values = test.distinct().values\n\n        let sink = MockSink<Int>()\n\n        sink.expecting(0) {\n            values.add(sink)\n        }\n\n        sink.expectingNothing {\n            test.value = 0\n        }\n\n        sink.expecting(1) {\n            test.value = 1\n        }\n\n        sink.expectingNothing {\n            test.value = 1\n            test.value = 1\n        }\n\n        sink.expecting(2) {\n            test.value = 2\n        }\n\n        values.remove(sink)\n    }\n\n    func test_futureValues_defaultEqualityTest() {\n        let test = TestObservableValue(0)\n        let values = test.distinct().futureValues\n\n        let sink = MockSink<Int>()\n\n        sink.expectingNothing {\n            values.add(sink)\n            test.value = 0\n        }\n\n        sink.expecting(1) {\n            test.value = 1\n        }\n\n        sink.expectingNothing {\n            test.value = 1\n            test.value = 1\n        }\n\n        sink.expecting(2) {\n            test.value = 2\n        }\n        \n        values.remove(sink)\n    }\n\n    func test_values_customEqualityTest() {\n        let test = TestObservableValue(0)\n\n        // This is a really stupid equality test: 1 is never equal to anything, while everything else is the same.\n        // This will only let through changes from/to a 1 value.\n        let distinct = test.distinct { a, b in a != 1 && b != 1 }\n        let values = distinct.values\n\n        let sink = MockSink<Int>()\n\n        sink.expecting(0) {\n            values.add(sink)\n        }\n\n        sink.expectingNothing {\n            test.value = 0\n        }\n\n        sink.expecting(1) {\n            test.value = 1\n        }\n\n        sink.expecting(1) {\n            test.value = 1\n        }\n\n        sink.expecting(1) {\n            test.value = 1\n        }\n\n        sink.expecting(2) {\n            test.value = 2\n        }\n\n        sink.expectingNothing {\n            test.value = 2\n            test.value = 2\n            test.value = 3\n            test.value = 2\n            test.value = 4\n        }\n\n        values.remove(sink)\n    }\n\n    func testDistinct_IsUpdatableWhenCalledOnUpdatables() {\n        let test = TestUpdatableValue(0)\n\n        let d = test.distinct()\n\n        XCTAssertEqual(d.value, 0)\n\n        let mock = MockValueUpdateSink(d)\n\n        mock.expecting([\"begin\", \"0 -> 42\", \"end\"]) {\n            d.value = 42\n        }\n\n        XCTAssertEqual(d.value, 42)\n        XCTAssertEqual(test.value, 42)\n\n        mock.expecting([\"begin\", \"42 -> 23\", \"end\"]) {\n            d.withTransaction {\n                d.value = 23\n            }\n        }\n\n        mock.expecting([\"begin\", \"end\"]) {\n            d.withTransaction {}\n        }\n\n        XCTAssertEqual(d.value, 23)\n        XCTAssertEqual(test.value, 23)\n    }\n}\n\n"
  },
  {
    "path": "Tests/GlueKitTests/DistinctUnionTests.swift",
    "content": "//\n//  DistinctUnionTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-04.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nclass DistinctUnionTests: XCTestCase {\n\n    func test_getters() {\n        let array: ArrayVariable<Int> = [0, 1, 2, 2, 3, 4, 5, 5, 5]\n        let set = array.distinctUnion()\n\n        XCTAssertTrue(set.isBuffered)\n        XCTAssertEqual(set.count, 6)\n        XCTAssertEqual(set.value, Set(0 ..< 6))\n        XCTAssertTrue(set.contains(0))\n        XCTAssertFalse(set.contains(7))\n\n        XCTAssertTrue(set.isSubset(of: Set(0 ..< 100)))\n        XCTAssertTrue(set.isSubset(of: Set(0 ..< 6)))\n        XCTAssertFalse(set.isSubset(of: Set(-5 ..< 5)))\n        XCTAssertFalse(set.isSubset(of: Set(-5 ..< 0)))\n\n        XCTAssertTrue(set.isSuperset(of: Set(0 ..< 4)))\n        XCTAssertTrue(set.isSuperset(of: Set(0 ..< 6)))\n        XCTAssertFalse(set.isSuperset(of: Set(-1 ..< 6)))\n        XCTAssertFalse(set.isSuperset(of: Set(-1 ..< 3)))\n    }\n\n    func test_updates() {\n        let array: ArrayVariable<Int> = [0]\n\n        let set = array.distinctUnion()\n\n        let mock = MockSetObserver(set)\n\n        mock.expecting([\"begin\", \"[]/[1]\", \"end\"]) {\n            array.append(1)\n        }\n\n        mock.expecting([\"begin\", \"[]/[2]\", \"end\"]) {\n            array.append(2)\n        }\n        XCTAssertEqual(set.value, Set([0, 1, 2]))\n\n        mock.expecting([\"begin\", \"end\"]) {\n            array.append(1)\n        }\n        XCTAssertEqual(array.value, [0, 1, 2, 1])\n        XCTAssertEqual(set.value, Set([0, 1, 2]))\n\n        mock.expecting([\"begin\", \"end\"]) {\n            _ = array.remove(at: 3)\n        }\n        XCTAssertEqual(array.value, [0, 1, 2])\n        XCTAssertEqual(set.value, Set([0, 1, 2]))\n\n        mock.expecting([\"begin\", \"[1]/[]\", \"end\"]) {\n            _ = array.remove(at: 1)\n        }\n        XCTAssertEqual(array.value, [0, 2])\n        XCTAssertEqual(set.value, Set([0, 2]))\n\n        mock.expecting([\"begin\", \"[2]/[3]\", \"end\"]) {\n            array[1] = 3\n        }\n        XCTAssertEqual(array.value, [0, 3])\n        XCTAssertEqual(set.value, Set([0, 3]))\n\n        mock.expecting([\"begin\", \"[]/[4, 5, 6]\", \"end\"]) {\n            array.append(contentsOf: [4, 4, 4, 5, 5, 6])\n        }\n        XCTAssertEqual(array.value, [0, 3, 4, 4, 4, 5, 5, 6])\n        XCTAssertEqual(set.value, Set([0, 3, 4, 5, 6]))\n\n        mock.expecting([\"begin\", \"[6]/[]\", \"[4]/[]\", \"[0]/[]\", \"end\"]) {\n            // Remove even values\n            array.withTransaction {\n                for i in (0 ..< array.count).reversed() {\n                    if array[i] & 1 == 0 {\n                        array.remove(at: i)\n                    }\n                }\n            }\n        }\n        XCTAssertEqual(array.value, [3, 5, 5])\n        XCTAssertEqual(set.value, Set([3, 5]))\n\n        mock.expecting([\"begin\", \"[3, 5]/[]\", \"end\"]) {\n            array.removeAll()\n        }\n        XCTAssertEqual(set.value, Set())\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Tests/GlueKitTests/KVOSupportTests.swift",
    "content": "//\n//  KVOSupportTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-03.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nprivate class Fixture: NSObject {\n    var _name: String = \"\"\n    var _count: Int = 0\n    var _optional: String? = nil\n    var _next: Fixture? = nil\n\n    @objc dynamic var name: String {\n        get { return _name }\n        set { _name = newValue }\n    }\n    @objc dynamic var count: Int {\n        get { return _count }\n        set { _count = newValue }\n    }\n    @objc dynamic var optional: String? {\n        get { return _optional }\n        set { _optional = newValue }\n    }\n    @objc dynamic var next: Fixture? {\n        get { return _next }\n        set { _next = newValue }\n    }\n}\n\nprivate class RawKVOObserver: NSObject {\n    let object: NSObject\n    let keyPath: String\n    let sink: (AnyObject) -> Void\n    var observerContext: Int8 = 0\n    var observing: Bool\n\n    init(object: NSObject, keyPath: String, sink: @escaping (AnyObject) -> Void) {\n        self.object = object\n        self.keyPath = keyPath\n        self.sink = sink\n        self.observing = true\n        super.init()\n        object.addObserver(self, forKeyPath: keyPath, options: .new, context: &self.observerContext)\n    }\n\n    deinit {\n        disconnect()\n    }\n\n    func disconnect() {\n        if observing {\n            object.removeObserver(self, forKeyPath: keyPath, context: &self.observerContext)\n            observing = false\n        }\n    }\n\n    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {\n        if context == &self.observerContext {\n            let newValue = change![NSKeyValueChangeKey.newKey]!\n            sink(newValue as AnyObject)\n        }\n        else {\n            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)\n        }\n    }\n}\n\nclass KVOSupportTests: XCTestCase {\n\n    func test_changes_BasicKVOWithIntegers() {\n        let object = Fixture()\n\n        let count = object.observable(for: \\.count)\n\n        var r = [Int]()\n        let c = count.changes.subscribe { r.append($0.new) }\n\n        object.count = 1\n        object.count = 2\n        object.count = 3\n\n        c.disconnect()\n\n        XCTAssertEqual(r, [1, 2, 3])\n    }\n\n    func test_changes_BasicKVOWithStrings() {\n        let object = Fixture()\n\n        var r = [String]()\n        let c = object.observable(for: \\.name).changes.subscribe { r.append($0.new) }\n\n        object.name = \"Alice\"\n        object.name = \"Bob\"\n        object.name = \"Charlie\"\n\n        c.disconnect()\n\n        object.name = \"Daniel\"\n\n        XCTAssertEqual(r, [\"Alice\", \"Bob\", \"Charlie\"])\n    }\n\n    func test_changes_BasicKVOWithOptionals() {\n        let object = Fixture()\n\n        var r = [String?]()\n        let c = object.observable(for: \\.optional).changes.subscribe { r.append($0.new) }\n\n        object.optional = \"Alice\"\n        object.optional = nil\n        object.optional = \"Bob\"\n        object.optional = nil\n        object.optional = nil\n\n        c.disconnect()\n\n        object.optional = \"Daniel\"\n        object.optional = nil\n\n        let expected: [String?] = [\"Alice\", nil, \"Bob\", nil, nil]\n        XCTAssert(r.elementsEqual(expected, by: { $0 == $1 }))\n    }\n\n\n    func test_changes_DisconnectActuallyDisconnects() {\n        let object = Fixture()\n\n        let count = object.observable(for: \\.count)\n\n        var r = [Int]()\n        let c = count.changes.subscribe { r.append($0.new) }\n\n        object.count = 1\n\n        c.disconnect()\n\n        object.count = 2\n        object.count = 3\n\n        XCTAssertEqual(r, [1])\n    }\n\n    func test_changes_SourceRetainsObject() {\n        var source: AnySource<ValueChange<Int>>? = nil\n        weak var weakObject: NSObject? = nil\n\n        do {\n            let object = Fixture()\n            weakObject = object\n\n            source = object.observable(for: \\.count).changes\n        }\n\n        XCTAssertNotNil(weakObject)\n        source = nil\n        XCTAssertNil(weakObject)\n\n        noop(source)\n    }\n\n    func test_changes_ConnectionRetainsObject() {\n        var c: Connection? = nil\n        weak var weakObject: NSObject? = nil\n\n        do {\n            let object = Fixture()\n            weakObject = object\n\n            c = object.observable(for: \\.count).changes.subscribe { _ in }\n        }\n\n        XCTAssertNotNil(weakObject)\n        c?.disconnect()\n        XCTAssertNil(weakObject)\n    }\n\n    //MARK: Reentrant observers\n\n    func test_rawKVO_ReentrantUpdates() {\n        // KVO supports reentrant updates, but it performs them synchronously, always sending the most up to date value.\n\n        let object = Fixture()\n\n        var s = \"\"\n        let observer = RawKVOObserver(object: object, keyPath: \"count\") { any in\n            let i = (any as! NSNumber).intValue\n            s += \" (\\(i)\"\n            if i > 0 {\n                object.count = i - 1\n            }\n            s += \")\"\n        }\n\n        object.count = 3\n\n        // Note deeply nested invocations.\n        XCTAssertEqual(s, \" (3 (2 (1 (0))))\")\n\n        observer.disconnect()\n    }\n\n    func test_changes_ReentrantUpdates1() {\n        // KVO supports reentrant updates, but it performs them synchronously, always sending the most up to date value.\n        // Our observable delays sending changes until the transaction is over,\n        let object = Fixture()\n\n        let count = object.observable(for: \\.count)\n\n        var s = \"\"\n        let c = count.updates.subscribe { update in\n            switch update {\n            case .beginTransaction:\n                s += \"(<)\"\n            case .change(let change):\n                s += \"(\\(change))\"\n                if count.value > 0 {\n                    object.count = count.value - 1\n                }\n            case .endTransaction:\n                s += \"(>)\"\n            }\n        }\n\n        object.count = 3\n\n        XCTAssertEqual(object.count, 0)\n\n        // Contrast this with the previous test.\n        XCTAssertEqual(s, \"(<)(0 -> 3)(3 -> 2)(2 -> 1)(1 -> 0)(>)\")\n\n        c.disconnect()\n    }\n\n    func test_changes_ReentrantUpdates2() {\n        // KVO supports reentrant updates, but it performs them synchronously, always sending the most up to date value.\n        let object = Fixture()\n\n        let count = object.observable(for: \\.count)\n\n        var s = \"\"\n        let c = count.updates.subscribe { update in\n            switch update {\n            case .beginTransaction:\n                s += \"(<)\"\n            case .change(let change):\n                s += \"(\\(change))\"\n            case .endTransaction:\n                s += \"(>)\"\n                if count.value > 0 {\n                    object.count = count.value - 1\n                }\n            }\n        }\n\n        object.count = 3\n\n        XCTAssertEqual(object.count, 0)\n\n        // Contrast this with the previous test.\n        XCTAssertEqual(s, \"(<)(0 -> 3)(>)(<)(3 -> 2)(>)(<)(2 -> 1)(>)(<)(1 -> 0)(>)\")\n        \n        c.disconnect()\n    }\n    \n\n    func test_rawKVO_MutuallyReentrantUpdates() {\n        // KVO supports reentrant updates, but it performs them synchronously, always sending the most up to date value.\n\n        let object = Fixture()\n\n        var s = \"\"\n        let observer1 = RawKVOObserver(object: object, keyPath: \"count\") { any in\n            let i = (any as! NSNumber).intValue\n            s += \" (\\(i)\"\n            if i > 0 {\n                object.count = i - 1\n            }\n            s += \")\"\n        }\n        let observer2 = RawKVOObserver(object: object, keyPath: \"count\") { any in\n            let i = (any as! NSNumber).intValue\n            s += \" (\\(i)\"\n            if i > 0 {\n                object.count = i - 1\n            }\n            s += \")\"\n        }\n\n        object.count = 2\n\n        // Note deeply nested invocations and how observers always receive the latest value (shortening the cascade).\n        XCTAssertEqual(s, \" (2 (1 (0) (0)) (0)) (0)\")\n        \n        observer1.disconnect()\n        observer2.disconnect()\n    }\n\n\n    func test_changes_MutuallyReentrantUpdates() {\n        // KVO supports reentrant updates, but it performs them synchronously, always sending the most up to date value.\n        // However, our changes source will delay notifications until the end of the transaction.\n\n        let object = Fixture()\n\n        let count = object.observable(for: \\.count)\n\n        var s = \"\"\n        let c1 = count.changes.subscribe { c in\n            let i = c.new\n            s += \" (\\(c)\"\n            if i > 0 {\n                object.count = i - 1\n            }\n            s += \")\"\n        }\n        let c2 = count.changes.subscribe { c in\n            let i = c.new\n            s += \" (\\(c)\"\n            if i > 0 {\n                object.count = i - 1\n            }\n            s += \")\"\n        }\n\n        object.count = 2\n\n        // Contrast this with the previous test.\n        XCTAssertEqual(s, \" (0 -> 2 (2 -> 1 (1 -> 0))) (0 -> 0)\")\n\n        c1.disconnect()\n        c2.disconnect()\n    }\n\n    func test_updates_WillChangeStartsATransaction() {\n        let object = Fixture()\n\n        let count = object.observable(for: \\.count)\n        let sink = MockValueUpdateSink<Int>(count)\n\n        sink.expecting(\"begin\") {\n            object.willChangeValue(forKey: \"count\")\n        }\n\n        sink.expectingNothing {\n            object._count += 1\n        }\n\n        sink.expecting([\"0 -> 1\", \"end\"]) {\n            object.didChangeValue(forKey: \"count\")\n        }\n        \n        sink.disconnect()\n    }\n\n    func test_updates_WillChangeStartsATransaction2() {\n        let object = Fixture()\n\n        let count = object.observable(for: \\.count)\n        let sink = MockValueUpdateSink<Int>(count)\n\n        sink.expecting(\"begin\") {\n            object.willChangeValue(forKey: \"count\")\n        }\n\n        sink.expectingNothing {\n            object._count += 1\n        }\n\n        sink.expectingNothing {\n            object.willChangeValue(forKey: \"count\")\n        }\n\n        sink.expectingNothing {\n            object._count += 1\n        }\n\n        sink.expectingNothing() {\n            object.didChangeValue(forKey: \"count\")\n        }\n\n        sink.expecting([\"0 -> 2\", \"end\"]) {\n            object.didChangeValue(forKey: \"count\")\n        }\n\n        sink.disconnect()\n    }\n\n\n    func test_updates_SubscribingAfterWillChange() {\n        let object = Fixture()\n\n        object.willChangeValue(forKey: \"count\")\n\n        let count = object.observable(for: \\.count)\n        let sink = MockValueUpdateSink<Int>()\n\n        // The change that was pending at the time of subscription isn't reported.\n        sink.expectingNothing {\n            count.add(sink)\n            object._count += 1\n            object.didChangeValue(forKey: \"count\")\n        }\n\n        sink.expecting(\"begin\") {\n            object.willChangeValue(forKey: \"count\")\n        }\n\n        sink.expectingNothing {\n            object._count += 1\n        }\n\n        sink.expecting([\"1 -> 2\", \"end\"]) {\n            object.didChangeValue(forKey: \"count\")\n        }\n\n        count.remove(sink)\n    }\n\n    func test_updates_UnsubscribingBeforeDidChange() {\n        let object = Fixture()\n\n        let count = object.observable(for: \\.count)\n        let sink = MockValueUpdateSink<Int>()\n\n        count.add(sink)\n\n        sink.expecting(\"begin\") {\n            object.willChangeValue(forKey: \"count\")\n        }\n\n        sink.expectingNothing {\n            object._count += 1\n        }\n\n        // We get \"end\" due to TransactionState's bracketing, but the change itself isn't reported.\n        sink.expecting(\"end\") {\n            count.remove(sink)\n        }\n\n        sink.expectingNothing {\n            object.didChangeValue(forKey: \"count\")\n        }\n\n        withExtendedLifetime(count) {}\n    }\n\n    func test_updatable_IntegerKey() {\n        let object = Fixture()\n\n        let count = object.updatable(for: \\.count)\n        let sink = MockValueUpdateSink<Int>(count)\n\n        sink.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            count.value = 1\n        }\n\n        // Our KVO-adaptor updatables behave as if they were buffered\n        sink.expecting(\"begin\") {\n            count.apply(.beginTransaction)\n        }\n        sink.expectingNothing {\n            count.apply(ValueChange(from: 1, to: 2))\n            count.apply(ValueChange(from: 2, to: 3))\n        }\n        sink.expecting([\"1 -> 3\", \"end\"]) {\n            count.apply(.endTransaction)\n        }\n\n        // will/didChange gets translated into begin/endTransaction\n        sink.expecting(\"begin\") {\n            object.willChangeValue(forKey: \"count\")\n        }\n        sink.expectingNothing {\n            object._count = 4\n        }\n        sink.expecting([\"3 -> 4\", \"end\"]) {\n            object.didChangeValue(forKey: \"count\")\n        }\n\n        sink.disconnect()\n    }\n\n    func test_updatable_OptionalKey() {\n        let object = Fixture()\n\n        let updatable = object.updatable(for: \\.optional)\n        let sink = MockValueUpdateSink<String?>(updatable)\n\n        sink.expecting([\"begin\", \"nil -> Optional(\\\"foo\\\")\", \"end\"]) {\n            updatable.value = \"foo\"\n        }\n\n        // Our KVO-adaptor updatables behave as if they were buffered\n        sink.expecting(\"begin\") {\n            updatable.apply(.beginTransaction)\n        }\n        sink.expectingNothing {\n            updatable.apply(ValueChange(from: \"foo\", to: nil))\n            updatable.apply(ValueChange(from: nil, to: \"bar\"))\n        }\n        sink.expecting([\"Optional(\\\"foo\\\") -> Optional(\\\"bar\\\")\", \"end\"]) {\n            updatable.apply(.endTransaction)\n        }\n\n        sink.disconnect()\n    }\n\n    func test_observable_keyPath() {\n        let object = Fixture()\n        let next = Fixture()\n        object.next = next\n\n//        let count = object.observable(for: \\.next?.count)\n//\n//        let sink = MockValueUpdateSink<Int>(count)\n//\n//        sink.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n//            next.count = 1\n//        }\n//\n//        sink.expecting([\"begin\", \"1 -> 2\", \"end\"]) {\n//            object.setValue(2, forKeyPath: \"next.count\")\n//        }\n//\n//        sink.expecting(\"begin\") {\n//            next.willChangeValue(forKey: \"count\")\n//        }\n//        sink.expectingNothing {\n//            next._count = 3\n//        }\n//        sink.expecting([\"2 -> 3\", \"end\"]) {\n//            next.didChangeValue(forKey: \"count\")\n//        }\n//\n//        let next2 = Fixture()\n//        next2.count = 4\n//\n//        sink.expecting(\"begin\") {\n//            object.willChangeValue(forKey: \"next\")\n//        }\n//        sink.expectingNothing {\n//            object._next = next2\n//        }\n//        sink.expecting([\"3 -> 4\", \"end\"]) {\n//            object.didChangeValue(forKey: \"next\")\n//        }\n//\n//        sink.disconnect()\n    }\n\n    func test_observable_keyPathNestedTransactions() {\n//        let object = Fixture()\n//        let next = Fixture()\n//        next.count = 1\n//\n//        object.next = next\n//\n//        let next2 = Fixture()\n//        next2.count = 2\n//\n//        let count = object.observable(for: \\.next?.count)\n//\n//        let sink = MockValueUpdateSink<Int>(count)\n//\n//        sink.expecting(\"begin\") {\n//            object.willChangeValue(forKey: \"next\")\n//        }\n//        sink.expectingNothing {\n//            next2.willChangeValue(forKey: \"count\")\n//            object._next = next2\n//            next2._count = 3\n//        }\n//\n//        sink.expecting([\"1 -> 3\", \"end\"]) {\n//            object.didChangeValue(forKey: \"next\")\n//        }\n//        sink.expectingNothing {\n//            next2._count = 4 // Unfortunately, this change never gets reported.\n//            next2.didChangeValue(forKey: \"count\")\n//        }\n//\n//        sink.disconnect()\n    }\n\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/MergedSourceTests.swift",
    "content": "//\n//  MergedSourceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-04.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass MergedSourceTests: XCTestCase {\n\n    func testSimpleMerge() {\n        let s1 = Signal<Int>()\n        let s2 = Signal<Int>()\n\n        let source = s1.merged(with: s2)\n\n        let sink = MockSink<Int>()\n        source.add(sink)\n\n        sink.expecting(11) { s1.send(11) }\n        sink.expecting(21) { s2.send(21) }\n        sink.expecting(12) { s1.send(12) }\n        sink.expecting(13) { s1.send(13) }\n        sink.expecting(22) { s2.send(22) }\n        sink.expecting(23) { s2.send(23) }\n\n        source.remove(sink)\n    }\n\n    func testNaryMerge() {\n        var signals: [Signal<Int>] = []\n        (0 ..< 10).forEach { _ in signals.append(Signal<Int>()) }\n\n        let merge = Signal.merge(signals)\n\n        let sink = MockSink<Int>()\n        merge.add(sink)\n\n        sink.expecting(Array(0 ..< 20)) {\n            for i in 0 ..< 20 {\n                signals[i % signals.count].send(i)\n            }\n        }\n        merge.remove(sink)\n    }\n\n    func testReentrantMerge() {\n        let s1 = Signal<Int>()\n        let s2 = Signal<Int>()\n\n        let source = s1.merged(with: s2)\n\n        var s = \"\"\n        let c = source.subscribe { i in\n            s += \" (\\(i)\"\n            if i > 0 {\n                s2.send(i - 1)\n            }\n            s += \")\"\n        }\n\n        s1.send(3)\n\n        XCTAssertEqual(s, \" (3) (2) (1) (0)\")\n        c.disconnect()\n    }\n\n    func testVariadicMerge() {\n        let s1 = Signal<Int>()\n        let s2 = Signal<Int>()\n        let s3 = Signal<Int>()\n        let s4 = Signal<Int>()\n\n        let merge = Signal.merge(s1, s2, s3, s4)\n\n        let sink = MockSink<Int>()\n        merge.add(sink)\n\n        sink.expecting(1) { s1.send(1) }\n        sink.expecting(2) { s1.send(2) }\n        sink.expecting(3) { s1.send(3) }\n        sink.expecting(4) { s1.send(4) }\n\n        merge.remove(sink)\n    }\n\n    func testMergeChaining() {\n        let s1 = Signal<Int>()\n        let s2 = Signal<Int>()\n        let s3 = Signal<Int>()\n        let s4 = Signal<Int>()\n\n        // This does not chain three merged sources together; it creates a single merged source containing all sources.\n        let merge = s1.merged(with: s2).merged(with: s3).merged(with: s4)\n\n        let sink = MockSink<Int>()\n        merge.add(sink)\n\n        sink.expecting(1) { s1.send(1) }\n        sink.expecting(2) { s1.send(2) }\n        sink.expecting(3) { s1.send(3) }\n        sink.expecting(4) { s1.send(4) }\n\n        merge.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/MockArrayObserver.swift",
    "content": "//\n//  MockArrayObserver.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-06.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\ninternal func describe<Element>(_ update: Update<ArrayChange<Element>>?) -> String {\n    guard let update = update else { return \"nil\" }\n    switch update {\n    case .beginTransaction:\n        return \"begin\"\n    case .change(let change):\n        let mods = change.modifications.map { mod in \"\\(mod)\" }\n        return \"\\(change.initialCount)\\(mods.joined())\"\n    case .endTransaction:\n        return \"end\"\n    }\n}\n\nclass MockArrayObserver<Element>: MockSinkProtocol {\n    typealias Change = ArrayChange<Element>\n\n    let state: MockSinkState<Update<Change>, String>\n\n    init() {\n        state = .init({ describe($0) })\n    }\n\n    init<Source: SourceType>(_ source: Source) where Source.Value == Update<Change> {\n        state = .init({ describe($0) })\n        self.subscribe(to: source)\n    }\n\n    convenience init<Observable: ObservableArrayType>(_ observable: Observable) where Observable.Change == Change {\n        self.init(observable.updates)\n    }\n\n    func receive(_ value: Update<Change>) {\n        state.receive(value)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/MockSetObserver.swift",
    "content": "//\n//  MockSetObserver.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-06.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nfunc describe<Element: Comparable>(_ update: SetUpdate<Element>) -> String {\n    switch update {\n    case .beginTransaction:\n        return \"begin\"\n    case .change(let change):\n        let removed = change.removed.sorted().map { \"\\($0)\" }.joined(separator: \", \")\n        let inserted = change.inserted.sorted().map { \"\\($0)\" }.joined(separator: \", \")\n        return \"[\\(removed)]/[\\(inserted)]\"\n    case .endTransaction:\n        return \"end\"\n    }\n}\n\nclass MockSetObserver<Element: Hashable & Comparable>: MockSinkProtocol {\n    typealias Change = SetChange<Element>\n\n    let state: MockSinkState<SetUpdate<Element>, String>\n\n    init() {\n        state = .init({ describe($0) })\n    }\n\n    init<Source: SourceType>(_ source: Source) where Source.Value == Update<Change> {\n        state = .init({ describe($0) })\n        self.subscribe(to: source)\n    }\n\n    convenience init<Observable: ObservableSetType>(_ observable: Observable) where Observable.Change == Change {\n        self.init(observable.updates)\n    }\n\n    func receive(_ value: Update<Change>) {\n        state.receive(value)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/MockSink.swift",
    "content": "//\n//  MockSink.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nclass MockSinkState<Value, Output: Equatable> {\n    let transform: (Value) -> Output\n    var isExpecting = false\n    var expected: [[Output]] = []\n    var actual: [Output] = []\n    var connection: Connection?\n\n    init(_ transform: @escaping (Value) -> Output) {\n        self.connection = nil\n        self.transform = transform\n    }\n\n    init(_ connection: Connection, _ transform: @escaping (Value) -> Output) {\n        self.connection = connection\n        self.transform = transform\n    }\n\n    deinit {\n        connection?.disconnect()\n    }\n\n    func receive(_ input: Value) {\n        if !isExpecting {\n            XCTFail(\"Sink received unexpected value: \\(input)\")\n        }\n        else {\n            actual.append(transform(input))\n        }\n    }\n\n    func run<R>(file: StaticString, line: UInt, _ body: () throws -> R) rethrows -> R {\n        isExpecting = true\n        defer {\n            switch expected.count {\n            case 0:\n                XCTAssertEqual(actual, [], file: file, line: line)\n            case 1:\n                XCTAssertEqual(actual, expected[0], file: file, line: line)\n            default:\n                XCTAssertTrue(expected.contains(where: { actual == $0 }), \"Unexpected values received: \\(actual)\", file: file, line: line)\n            }\n\n            actual = []\n            expected = []\n            isExpecting = false\n        }\n        return try body()\n    }\n\n    func disconnect() {\n        connection?.disconnect()\n        connection = nil\n    }\n}\n\nprotocol MockSinkProtocol: class, SinkType {\n    associatedtype Output: Equatable\n    var state: MockSinkState<Value, Output> { get }\n}\n\nextension MockSinkProtocol {\n    @discardableResult\n    func expectingNothing<R>(file: StaticString = #file, line: UInt = #line, body: () throws -> R) rethrows -> R {\n        precondition(state.expected.isEmpty)\n        return try state.run(file: file, line: line, body)\n    }\n\n    @discardableResult\n    func expecting<R>(_ value: Output, file: StaticString = #file, line: UInt = #line, body: () throws -> R) rethrows -> R {\n        precondition(state.expected.isEmpty)\n        state.expected = [[value]]\n        return try state.run(file: file, line: line, body)\n    }\n\n    @discardableResult\n    func expecting<R>(_ values: [Output], file: StaticString = #file, line: UInt = #line, body: () throws -> R) rethrows -> R {\n        precondition(state.expected.isEmpty)\n        state.expected = [values]\n        return try state.run(file: file, line: line, body)\n    }\n\n    @discardableResult\n    func expectingOneOf<R>(_ values: [[Output]], file: StaticString = #file, line: UInt = #line, body: () throws -> R) rethrows -> R {\n        precondition(state.expected.isEmpty)\n        state.expected = values\n        return try state.run(file: file, line: line, body)\n    }\n\n\n    func subscribe<Source: SourceType>(to source: Source) where Source.Value == Value {\n        precondition(state.connection == nil)\n        state.connection = source.subscribe { [unowned self] (input: Value) -> Void in self.receive(input) }\n    }\n\n    func disconnect() {\n        state.disconnect()\n    }\n}\n\n\nclass TransformedMockSink<Value, Output: Equatable>: MockSinkProtocol {\n    let state: MockSinkState<Value, Output>\n\n    init(_ transform: @escaping (Value) -> Output) {\n        self.state = .init(transform)\n    }\n\n    init<Source: SourceType>(_ source: Source, _ transform: @escaping (Value) -> Output) where Source.Value == Value {\n        self.state = .init(transform)\n        self.subscribe(to: source)\n    }\n\n    func receive(_ input: Value) {\n        state.receive(input)\n    }\n}\n\nclass MockSink<Value: Equatable>: MockSinkProtocol {\n    let state: MockSinkState<Value, Value>\n\n    init() {\n        self.state = .init({ $0 })\n    }\n\n    init<Source: SourceType>(_ source: Source) where Source.Value == Value {\n        self.state = .init({ $0 })\n        self.subscribe(to: source)\n    }\n\n    func receive(_ input: Value) {\n        state.receive(input)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/MockUpdateSink.swift",
    "content": "//\n//  MockUpdateSink.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\ninternal func describe<Change>(_ update: Update<Change>?) -> String {\n    guard let update = update else { return \"nil\" }\n    switch update {\n    case .beginTransaction: return \"begin\"\n    case .change(let change): return \"\\(change)\"\n    case .endTransaction: return \"end\"\n    }\n}\n\nclass MockUpdateSink<Change: ChangeType>: MockSinkProtocol {\n    let state: MockSinkState<Update<Change>, String>\n\n    init() {\n        state = .init({ describe($0) })\n    }\n\n    init<Source: SourceType>(_ source: Source) where Source.Value == Update<Change> {\n        state = .init({ describe($0) })\n        self.subscribe(to: source)\n    }\n\n    convenience init<Observable: ObservableValueType>(_ observable: Observable) where Observable.Change == Change {\n        self.init(observable.updates)\n    }\n\n    func receive(_ value: Update<Change>) {\n        state.receive(value)\n    }\n}\n\ntypealias MockValueUpdateSink<Value> = MockUpdateSink<ValueChange<Value>>\n\n"
  },
  {
    "path": "Tests/GlueKitTests/NSUserDefaultsSupportTests.swift",
    "content": "//\n//  NSUserDefaultsSupportTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n\nextension UserDefaults {\n    var testValue: Bool {\n        get { return self.bool(forKey: \"TestKey\") }\n        set { self.set(newValue, forKey: \"TestKey\") }\n    }\n}\n\nclass NSUserDefaultsSupportTests: XCTestCase {\n    let key = \"TestKey\"\n    let defaults = UserDefaults.standard\n    var context: UInt8 = 0\n    var notifications: [[NSKeyValueChangeKey: Any]] = []\n\n    override func setUp() {\n        super.setUp()\n        defaults.removeObject(forKey: key)\n    }\n    \n    override func tearDown() {\n        defaults.removeObject(forKey: key)\n        super.tearDown()\n    }\n    \n    func testStandardNotifications() {\n        defaults.addObserver(self, forKeyPath: key, options: [.old, .new], context: &context)\n        defaults.set(true, forKey: key)\n        defaults.removeObserver(self, forKeyPath: key, context: &context)\n        \n        XCTAssertEqual(notifications.count, 1, \"Unexpected notifications: \\(notifications)\")\n    }\n\n    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {\n        if context == &self.context {\n            print(change ?? \"nil\")\n            notifications.append(change!)\n        }\n        else {\n            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)\n        }\n    }\n\n    func testAny() {\n        let updatable = defaults.glue.updatable(forKey: key)\n        XCTAssertNil(updatable.value)\n\n        updatable.value = 42\n\n        XCTAssertEqual(updatable.value as? Int, 42)\n        XCTAssertEqual(defaults.integer(forKey: key), 42)\n\n        updatable.value = \"Foobar\"\n\n        XCTAssertEqual(updatable.value as? String, \"Foobar\")\n        XCTAssertEqual(defaults.string(forKey: key), \"Foobar\")\n\n        let sink = MockValueUpdateSink(updatable)\n\n        sink.expecting([\"begin\", \"Optional(Foobar) -> Optional(23.125)\", \"end\"]) {\n            updatable.value = 23.125\n        }\n\n        sink.expecting([\"begin\", \"Optional(23.125) -> Optional(Barney)\", \"end\"]) {\n            defaults.set(\"Barney\", forKey: key)\n        }\n\n        sink.disconnect()\n    }\n\n    func testBool() {\n        let updatable = defaults.glue.updatable(forKey: key, defaultValue: false)\n        XCTAssertFalse(updatable.value)\n\n        updatable.value = true\n        XCTAssertEqual(updatable.value, true)\n\n        defaults.set(1, forKey: key)\n        XCTAssertEqual(updatable.value, true)\n\n        defaults.set(0, forKey: key)\n        XCTAssertEqual(updatable.value, false)\n\n        defaults.set(1.0, forKey: key)\n        XCTAssertEqual(updatable.value, true)\n\n        defaults.set(\"YES\", forKey: key)\n        XCTAssertEqual(updatable.value, false)\n\n        let sink = MockValueUpdateSink(updatable)\n\n        sink.expecting([\"begin\", \"false -> true\", \"end\"]) {\n            updatable.value = true\n        }\n\n        sink.expecting([\"begin\", \"true -> false\", \"end\"]) {\n            defaults.set(false, forKey: key)\n        }\n        \n        sink.disconnect()\n    }\n\n    func testInt() {\n        let updatable = defaults.glue.updatable(forKey: key, defaultValue: 0)\n        XCTAssertEqual(updatable.value, 0)\n\n        updatable.value = 1\n        XCTAssertEqual(updatable.value, 1)\n\n        defaults.set(2, forKey: key)\n        XCTAssertEqual(updatable.value, 2)\n\n        defaults.set(nil, forKey: key)\n        XCTAssertEqual(updatable.value, 0)\n\n        defaults.set(42.0, forKey: key)\n        XCTAssertEqual(updatable.value, 42)\n\n        defaults.set(true, forKey: key)\n        XCTAssertEqual(updatable.value, 0) // kCFBooleanTrue is not directly convertible to Int\n\n        defaults.set(42.5, forKey: key)\n        XCTAssertEqual(updatable.value, 42)\n\n        defaults.set(\"23\", forKey: key)\n        XCTAssertEqual(updatable.value, 0)\n\n        let sink = MockValueUpdateSink(updatable)\n\n        sink.expecting([\"begin\", \"0 -> 3\", \"end\"]) {\n            updatable.value = 3\n        }\n\n        sink.expecting([\"begin\", \"3 -> 4\", \"end\"]) {\n            defaults.set(4, forKey: key)\n        }\n        \n        sink.disconnect()\n    }\n\n    func testDouble() {\n        let updatable = defaults.glue.updatable(forKey: key, defaultValue: 0.0)\n        XCTAssertEqual(updatable.value, 0)\n\n        updatable.value = 1\n        XCTAssertEqual(updatable.value, 1)\n\n        defaults.set(2, forKey: key)\n        XCTAssertEqual(updatable.value, 2)\n\n        defaults.set(nil, forKey: key)\n        XCTAssertEqual(updatable.value, 0)\n\n        defaults.set(42.0, forKey: key)\n        XCTAssertEqual(updatable.value, 42)\n\n        defaults.set(true, forKey: key)\n        XCTAssertEqual(updatable.value, 0.0) // kCFBooleanTrue is not directly convertible to Int\n\n        defaults.set(42.5, forKey: key)\n        XCTAssertEqual(updatable.value, 42.5)\n\n        defaults.set(\"23\", forKey: key)\n        XCTAssertEqual(updatable.value, 0)\n\n        let sink = MockValueUpdateSink(updatable)\n\n        sink.expecting([\"begin\", \"0.0 -> 3.0\", \"end\"]) {\n            updatable.value = 3\n        }\n\n        sink.expecting([\"begin\", \"3.0 -> 4.0\", \"end\"]) {\n            defaults.set(4, forKey: key)\n        }\n        \n        sink.disconnect()\n    }\n\n    func testString() {\n        let updatable = defaults.glue.updatable(forKey: key, as: (String?).self)\n        XCTAssertEqual(updatable.value, nil)\n\n        updatable.value = \"Foo\"\n        XCTAssertEqual(updatable.value, \"Foo\")\n\n        defaults.set(2, forKey: key)\n        XCTAssertEqual(updatable.value, nil)\n\n        defaults.set(nil, forKey: key)\n        XCTAssertEqual(updatable.value, nil)\n\n        defaults.set(42.0, forKey: key)\n        XCTAssertEqual(updatable.value, nil)\n\n        defaults.set(true, forKey: key)\n        XCTAssertEqual(updatable.value, nil)\n\n        defaults.set(42.5, forKey: key)\n        XCTAssertEqual(updatable.value, nil)\n\n        defaults.set(\"23\", forKey: key)\n        XCTAssertEqual(updatable.value, \"23\")\n\n        let sink = MockValueUpdateSink(updatable)\n\n        sink.expecting([\"begin\", \"Optional(\\\"23\\\") -> Optional(\\\"Fred\\\")\", \"end\"]) {\n            updatable.value = \"Fred\"\n        }\n\n        sink.expecting([\"begin\", \"Optional(\\\"Fred\\\") -> Optional(\\\"Barney\\\")\", \"end\"]) {\n            defaults.set(\"Barney\", forKey: key)\n        }\n        \n        sink.disconnect()\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/NotificationCenterSupportTests.swift",
    "content": "//\n//  NotificationCenterSupportTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-04.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n\nprivate let center = NotificationCenter.default\n\nprivate func post(_ value: Int) { post(\"TestNotification\", value) }\nprivate func post(_ name: String, _ value: Int) {\n    center.post(name: Notification.Name(rawValue: name), object: nil, userInfo: [\"Value\": value])\n}\n\nlet testNotification = NSNotification.Name(\"TestNotification\")\n\nclass NotificationCenterSupportTests: XCTestCase {\n\n    func testSimpleNotification() {\n        var r = [Int]()\n\n        post(1)\n        let c = center.glue.source(forName: testNotification).subscribe { notification in\n            r.append((notification as NSNotification).userInfo![\"Value\"] as! Int)\n        }\n\n        post(2)\n        post(3)\n\n        c.disconnect()\n\n        post(4)\n\n        XCTAssertEqual(r, [2, 3])\n    }\n\n    func testReentrancyInRawNotificationCenter() {\n        // The notification center supports reentrancy but it is synchronous, just like KVO - except it doesn't force \"latest\" values\n\n        var s = \"\"\n        let observer = center.addObserver(forName: testNotification, object: nil, queue: nil) { notification in\n            let value = (notification as NSNotification).userInfo![\"Value\"] as! Int\n            s += \" (\\(value)\"\n            if value > 0 {\n                post(value - 1)\n            }\n            s += \")\"\n        }\n\n        post(3)\n\n        XCTAssertEqual(s, \" (3 (2 (1 (0))))\")\n\n        center.removeObserver(observer)\n    }\n\n    func testReentrancyInGlueKit() {\n        var s = \"\"\n        let c = center.glue.source(forName: testNotification).subscribe { notification in\n            let value = (notification as NSNotification).userInfo![\"Value\"] as! Int\n            s += \" (\\(value)\"\n            if value > 0 {\n                post(value - 1)\n            }\n            s += \")\"\n        }\n\n        post(3)\n\n        // Nicely serialized invocations.\n        XCTAssertEqual(s, \" (3) (2) (1) (0)\")\n\n        c.disconnect()\n    }\n    \n    func testReentrancyCascadeInRawNotificationCenter() {\n        // The notification center supports reentrancy but it is synchronous, just like KVO - except it doesn't force \"latest\" values\n\n        var firstIndex: Int? = nil\n        var receivedValues: [[Int]] = [[], []]\n        var s = \"\"\n        let block: (Int) -> (Notification) -> Void = { index in\n            return { notification in\n                if firstIndex == nil { firstIndex = index }\n                let value = (notification as NSNotification).userInfo![\"Value\"] as! Int\n                receivedValues[index].append(value)\n                s += \" (\\(value)\"\n                if value > 0 {\n                    post(value - 1)\n                }\n                s += \")\"\n            }\n        }\n\n        let observer1 = center.addObserver(forName: testNotification, object: nil, queue: nil, using: block(0))\n        let observer2 = center.addObserver(forName: testNotification, object: nil, queue: nil, using: block(1))\n\n        post(2)\n\n        // Note nested invocations and strange ordering of delivered values.\n        XCTAssertEqual(receivedValues[firstIndex!], [2, 1, 0, 0, 1, 0, 0])\n        XCTAssertEqual(receivedValues[1 - firstIndex!], [0, 1, 0, 2, 0, 1, 0])\n        XCTAssertEqual(s, \" (2 (1 (0) (0)) (1 (0) (0))) (2 (1 (0) (0)) (1 (0) (0)))\")\n\n        center.removeObserver(observer1)\n        center.removeObserver(observer2)\n    }\n\n    func testReentrancyCascadeInGlueKit() {\n        var firstIndex: Int? = nil\n        var receivedValues: [[Int]] = [[], []]\n        var s = \"\"\n        let block: (Int) -> (Notification) -> Void = { index in\n            return { notification in\n                if firstIndex == nil { firstIndex = index }\n                let value = (notification as NSNotification).userInfo![\"Value\"] as! Int\n                receivedValues[index].append(value)\n                s += \" (\\(value)\"\n                if value > 0 {\n                    post(value - 1)\n                }\n                s += \")\"\n            }\n        }\n\n        let source = center.glue.source(forName: testNotification)\n\n        let c1 = source.subscribe(block(0))\n        let c2 = source.subscribe(block(1))\n\n        post(2)\n\n        // Nicely serialized invocations. Values are progressing monotonically and there are no nested calls.\n        // Note though that this wouldn't happen if the source wasn't shared above!\n        XCTAssertEqual(receivedValues[0], [2, 1, 1, 0, 0, 0, 0])\n        XCTAssertEqual(receivedValues[1], [2, 1, 1, 0, 0, 0, 0])\n        XCTAssertEqual(s, \" (2) (2) (1) (1) (1) (1) (0) (0) (0) (0) (0) (0) (0) (0)\")\n\n        c1.disconnect()\n        c2.disconnect()\n    }\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ObservableArrayTests.swift",
    "content": "//\n//  ObservableArrayTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass TestObservableArray<Element>: ObservableArrayType, TransactionalThing {\n    typealias Change = ArrayChange<Element>\n\n    var _signal: TransactionalSignal<ArrayChange<Element>>? = nil\n    var _transactionCount: Int = 0\n    var _value: [Element]\n\n    init(_ value: [Element]) {\n        self._value = value\n    }\n\n    var count: Int {\n        return _value.count\n    }\n\n    subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        return _value[bounds]\n    }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<ArrayChange<Element>> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<ArrayChange<Element>> {\n        return signal.remove(sink)\n    }\n\n    func apply(_ change: ArrayChange<Element>) {\n        if change.isEmpty { return }\n        beginTransaction()\n        _value.apply(change)\n        sendChange(change)\n        endTransaction()\n    }\n}\n\nprivate class TestUpdatableArray<Element>: TestObservableArray<Element>, UpdatableArrayType {\n    var value: [Element] {\n        get { return super.value }\n        set { self.apply(ArrayChange(from: value, to: newValue)) }\n    }\n\n    override subscript(bounds: Range<Int>) -> ArraySlice<Element> {\n        get { return _value[bounds] }\n        set { self.apply(ArrayChange(initialCount: count, modification: .replaceSlice(Array(self[bounds]), at: bounds.lowerBound, with: Array(newValue)))) }\n    }\n\n    subscript(index: Int) -> Element {\n        get { return _value[index] }\n        set { self.apply(ArrayChange(initialCount: count, modification: .replace(self[index], at: index, with: newValue))) }\n    }\n\n    func withTransaction<Result>(_ body: () -> Result) -> Result {\n        beginTransaction()\n        defer { endTransaction() }\n        return body()\n    }\n\n    func apply(_ update: Update<ArrayChange<Element>>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            _value.apply(change)\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n\nclass ObservableArrayTests: XCTestCase {\n    func testDefaultImplementations() {\n        func check<T, A: ObservableArrayType>(isBuffered: Bool = false, make: ([Int]) -> T, convert: (T) -> A, apply: @escaping (T, ArrayChange<Int>) -> Void) where A.Element == Int {\n            let t = make([1, 2, 3])\n            let test = convert(t)\n\n            XCTAssertEqual(test.isBuffered, isBuffered)\n            XCTAssertEqual(test.value, [1, 2, 3])\n            XCTAssertEqual(test.count, 3)\n            XCTAssertEqual(test[0], 1)\n            XCTAssertEqual(test[1], 2)\n            XCTAssertEqual(test[2], 3)\n            XCTAssertFalse(test.isEmpty)\n            XCTAssertEqual(test.first, 1)\n            XCTAssertEqual(test.last, 3)\n\n            let observable = test.anyObservableValue\n            let observableCount = test.observableCount\n\n            XCTAssertEqual(observable.value, [1, 2, 3])\n            XCTAssertEqual(observableCount.value, 3)\n\n            let mock = MockArrayObserver(test)\n            let valueMock = MockValueUpdateSink(observable.map { \"\\($0)\" }) // map is to convert array into something equatable\n            let countMock = MockValueUpdateSink(observableCount)\n\n            mock.expecting([\"begin\", \"3.insert(4, at: 2)\", \"end\"]) {\n                valueMock.expecting([\"begin\", \"[1, 2, 3] -> [1, 2, 4, 3]\", \"end\"]) {\n                    countMock.expecting([\"begin\", \"3 -> 4\", \"end\"]) {\n                        apply(t, ArrayChange<Int>(initialCount: 3, modification: .insert(4, at: 2)))\n                    }\n                }\n            }\n            XCTAssertEqual(test.value, [1, 2, 4, 3])\n            XCTAssertEqual(observable.value, [1, 2, 4, 3])\n            XCTAssertEqual(observableCount.value, 4)\n\n            mock.expecting([\"begin\", \"4.replaceSlice([1, 2, 4, 4], at: 0, with: [])\", \"end\"]) {\n                valueMock.expecting([\"begin\", \"[1, 2, 4, 3] -> []\", \"end\"]) {\n                    countMock.expecting([\"begin\", \"4 -> 0\", \"end\"]) {\n                        apply(t, ArrayChange<Int>(initialCount: 4, modification: .replaceSlice([1, 2, 4, 4], at: 0, with: [])))\n                    }\n                }\n            }\n            XCTAssertEqual(test.value, [])\n            XCTAssertEqual(observable.value, [])\n            XCTAssertEqual(observableCount.value, 0)\n\n            XCTAssertEqual(test.count, 0)\n            XCTAssertTrue(test.isEmpty)\n            XCTAssertEqual(test.first, nil)\n            XCTAssertEqual(test.last, nil)\n\n        }\n\n        check(make: { TestObservableArray($0) }, convert: { $0 }, apply: { $0.apply($1) })\n        check(make: { TestObservableArray($0) }, convert: { $0.anyObservableArray }, apply: { $0.apply($1) })\n        check(make: { TestUpdatableArray($0) }, convert: { $0 }, apply: { $0.apply($1) })\n        check(make: { TestUpdatableArray($0) }, convert: { $0.anyObservableArray }, apply: { $0.apply($1) })\n        check(make: { TestUpdatableArray($0) }, convert: { $0.anyUpdatableArray }, apply: { $0.apply($1) })\n        check(make: { TestUpdatableArray($0) }, convert: { $0.anyUpdatableArray.anyObservableArray }, apply: { $0.apply($1) })\n        check(isBuffered: true, make: { ArrayVariable($0) }, convert: { $0 }, apply: { $0.apply($1) })\n        check(isBuffered: true, make: { ArrayVariable($0) }, convert: { $0.anyObservableArray }, apply: { $0.apply($1) })\n        check(isBuffered: true, make: { ArrayVariable($0) }, convert: { $0.anyUpdatableArray }, apply: { $0.apply($1) })\n        check(isBuffered: true, make: { ArrayVariable($0) }, convert: { $0.anyUpdatableArray.anyObservableArray }, apply: { $0.apply($1) })\n\n        check(isBuffered: true, make: { TestObservableArray($0) }, convert: { $0.buffered() }, apply: { $0.apply($1) })\n        check(isBuffered: true, make: { ArrayVariable($0) }, convert: { $0.buffered() }, apply: { $0.apply($1) })\n    }\n\n    func testConstant() {\n        let test = AnyObservableArray.constant([1, 2, 3])\n        XCTAssertTrue(test.isBuffered)\n        XCTAssertEqual(test.count, 3)\n        XCTAssertEqual(test.value, [1, 2, 3])\n        XCTAssertEqual(test[0], 1)\n        XCTAssertEqual(test[1], 2)\n        XCTAssertEqual(test[2], 3)\n        XCTAssertEqual(test[0 ..< 2], [1, 2])\n\n        let mock = MockArrayObserver(test)\n        mock.expectingNothing {\n            // Whatevs\n        }\n\n        XCTAssertEqual(test.observableCount.value, 3)\n        XCTAssertEqual(test.anyObservableValue.value, [1, 2, 3])\n    }\n\n    func testUpdatable() {\n        func check<A: UpdatableArrayType>(make: ([Int]) -> A) where A.Element == Int {\n            let test = make([1, 2, 3])\n\n            let mock = MockArrayObserver(test)\n\n            mock.expectingNothing {\n                test.apply(ArrayChange(initialCount: test.count))\n            }\n\n            mock.expecting([\"begin\", \"3.remove(1, at: 0).insert(4, at: 1)\", \"end\"]) {\n                var change = ArrayChange<Int>(initialCount: 3)\n                change.add(.insert(4, at: 2))\n                change.add(.remove(1, at: 0))\n                test.apply(change)\n            }\n            XCTAssertEqual(test.value, [2, 4, 3])\n\n            mock.expecting([\"begin\", \"3.replaceSlice([2, 4, 3], at: 0, with: [-1, -2, -3])\", \"end\"]) {\n                test.value = [-1, -2, -3]\n            }\n            XCTAssertEqual(test.value, [-1, -2, -3])\n\n            mock.expecting([\"begin\", \"3.replace(-2, at: 1, with: 2)\", \"end\"]) {\n                test[1] = 2\n            }\n            XCTAssertEqual(test.value, [-1, 2, -3])\n\n            mock.expecting([\"begin\", \"3.replaceSlice([-1, 2], at: 0, with: [1, 2])\", \"end\"]) {\n                test[0 ..< 2] = [1, 2]\n            }\n            XCTAssertEqual(test.value, [1, 2, -3])\n\n            let updatable = test.anyUpdatableValue\n            XCTAssertEqual(updatable.value, [1, 2, -3])\n            let umock = MockValueUpdateSink(updatable.map { \"\\($0)\" }) // The mapping transforms the array into something equatable\n            mock.expecting([\"begin\", \"3.replaceSlice([1, 2, -3], at: 0, with: [0, 1, 2, 3])\", \"end\"]) {\n                umock.expecting([\"begin\", \"[1, 2, -3] -> [0, 1, 2, 3]\", \"end\"]) {\n                    updatable.value = [0, 1, 2, 3]\n                }\n            }\n            XCTAssertEqual(updatable.value, [0, 1, 2, 3])\n            XCTAssertEqual(test.value, [0, 1, 2, 3])\n\n            umock.disconnect()\n\n            mock.expecting([\"begin\", \"4.remove(2, at: 2)\", \"3.insert(10, at: 1)\", \"end\"]) {\n                test.withTransaction {\n                    test.remove(at: 2)\n                    test.insert(10, at: 1)\n                }\n            }\n            XCTAssertEqual(test.value, [0, 10, 1, 3])\n\n            mock.expecting([\"begin\", \"4.replaceSlice([1, 3], at: 2, with: [11, 12, 13])\", \"end\"]) {\n                test.replaceSubrange(2 ..< 4, with: 11 ... 13)\n            }\n            XCTAssertEqual(test.value, [0, 10, 11, 12, 13])\n\n            mock.expecting([\"begin\", \"5.replaceSlice([0], at: 0, with: [8, 9])\", \"end\"]) {\n                test.replaceSubrange(0 ..< 1, with: [8, 9])\n            }\n            XCTAssertEqual(test.value, [8, 9, 10, 11, 12, 13])\n\n            mock.expecting([\"begin\", \"6.insert(14, at: 6)\", \"end\"]) {\n                test.append(14)\n            }\n            XCTAssertEqual(test.value, [8, 9, 10, 11, 12, 13, 14])\n\n            mock.expecting([\"begin\", \"7.replaceSlice([], at: 7, with: [15, 16, 17])\", \"end\"]) {\n                test.append(contentsOf: 15 ... 17)\n            }\n            XCTAssertEqual(test.value, [8, 9, 10, 11, 12, 13, 14, 15, 16, 17])\n\n            mock.expecting([\"begin\", \"10.insert(20, at: 3)\", \"end\"]) {\n                test.insert(20, at: 3)\n            }\n            XCTAssertEqual(test.value, [8, 9, 10, 20, 11, 12, 13, 14, 15, 16, 17])\n\n            mock.expecting([\"begin\", \"11.replaceSlice([], at: 4, with: [21, 22, 23])\", \"end\"]) {\n                test.insert(contentsOf: 21 ... 23, at: 4)\n            }\n            XCTAssertEqual(test.value, [8, 9, 10, 20, 21, 22, 23, 11, 12, 13, 14, 15, 16, 17])\n\n            mock.expecting([\"begin\", \"14.remove(21, at: 4)\", \"end\"]) {\n                XCTAssertEqual(test.remove(at: 4), 21)\n            }\n            XCTAssertEqual(test.value, [8, 9, 10, 20, 22, 23, 11, 12, 13, 14, 15, 16, 17])\n\n            mock.expecting([\"begin\", \"13.replaceSlice([20, 22, 23], at: 3, with: [])\", \"end\"]) {\n                test.removeSubrange(3 ..< 6)\n            }\n            XCTAssertEqual(test.value, [8, 9, 10, 11, 12, 13, 14, 15, 16, 17])\n\n            mock.expecting([\"begin\", \"10.remove(8, at: 0)\", \"end\"]) {\n                XCTAssertEqual(test.removeFirst(), 8)\n            }\n            XCTAssertEqual(test.value, [9, 10, 11, 12, 13, 14, 15, 16, 17])\n\n            mock.expecting([\"begin\", \"9.replaceSlice([9, 10], at: 0, with: [])\", \"end\"]) {\n                test.removeFirst(2)\n            }\n            XCTAssertEqual(test.value, [11, 12, 13, 14, 15, 16, 17])\n\n            mock.expecting([\"begin\", \"7.remove(17, at: 6)\", \"end\"]) {\n                XCTAssertEqual(test.removeLast(), 17)\n            }\n            XCTAssertEqual(test.value, [11, 12, 13, 14, 15, 16])\n\n            mock.expecting([\"begin\", \"6.replaceSlice([14, 15, 16], at: 3, with: [])\", \"end\"]) {\n                test.removeLast(3)\n            }\n            XCTAssertEqual(test.value, [11, 12, 13])\n\n            mock.expecting([\"begin\", \"3.remove(13, at: 2)\", \"2.replace(12, at: 1, with: 20)\", \"end\"]) {\n                test.withTransaction {\n                    test.remove(at: 2)\n                    test[1] = 20\n                }\n            }\n\n            mock.expecting([\"begin\", \"2.replaceSlice([11, 20], at: 0, with: [])\", \"end\"]) {\n                test.removeAll()\n            }\n            XCTAssertEqual(test.value, [])\n        }\n\n        check { TestUpdatableArray<Int>($0) }\n        check { TestUpdatableArray<Int>($0).anyUpdatableArray }\n        check { TestUpdatableArray<Int>($0).anyUpdatableArray.anyUpdatableArray }\n        check { ArrayVariable<Int>($0) }\n        check { ArrayVariable<Int>($0).anyUpdatableArray }\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ObservableSetTests.swift",
    "content": "//\n//  ObservableSetTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass TestObservableSet<Element: Hashable>: _AbstractObservableSet<Element>, TransactionalThing {\n    var _signal: TransactionalSignal<SetChange<Element>>? = nil\n    var _transactionCount: Int = 0\n    private var _value: Set<Element>\n\n    init(_ value: Set<Element>) {\n        self._value = value\n    }\n\n    override var value: Set<Element> { return _value }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n\n    func apply(_ change: Change) {\n        if change.isEmpty { return }\n        beginTransaction()\n        _value.subtract(change.removed)\n        _value.formUnion(change.inserted)\n        sendChange(change)\n        endTransaction()\n    }\n}\n\nprivate class TestObservableSet2<Element: Hashable>: ObservableSetType, TransactionalThing {\n    typealias Change = SetChange<Element>\n\n    var _signal: TransactionalSignal<SetChange<Element>>? = nil\n    var _transactionCount: Int = 0\n    var _value: Set<Element>\n\n    init(_ value: Set<Element>) {\n        self._value = value\n    }\n\n    var value: Set<Element> { return _value }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n\n    func apply(_ change: Change) {\n        if change.isEmpty { return }\n        beginTransaction()\n        _value.subtract(change.removed)\n        _value.formUnion(change.inserted)\n        sendChange(change)\n        endTransaction()\n    }\n}\n\n\nprivate class TestUpdatableSet<Element: Hashable>: _AbstractUpdatableSet<Element>, TransactionalThing {\n    var _signal: TransactionalSignal<SetChange<Element>>? = nil\n    var _transactionCount: Int = 0\n    var _value: Set<Element>\n\n    init(_ value: Set<Element>) {\n        self._value = value\n    }\n\n    override var value: Set<Element> {\n        get { return _value }\n        set { self.apply(SetChange(removed: _value, inserted: newValue)) }\n    }\n\n    override func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    override func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n\n    override func apply(_ update: Update<Change>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            _value.subtract(change.removed)\n            _value.formUnion(change.inserted)\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n\nprivate class TestUpdatableSet2<Element: Hashable>: UpdatableSetType, TransactionalThing {\n    typealias Change = SetChange<Element>\n\n    var _signal: TransactionalSignal<SetChange<Element>>? = nil\n    var _transactionCount: Int = 0\n    var _value: Set<Element>\n\n    init(_ value: Set<Element>) {\n        self._value = value\n    }\n\n    var value: Set<Element> {\n        get { return _value }\n        set { self.apply(SetChange(removed: _value, inserted: newValue)) }\n    }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n\n    func withTransaction<Result>(_ body: () -> Result) -> Result {\n        beginTransaction()\n        defer { endTransaction() }\n        return body()\n    }\n\n    func apply(_ update: Update<Change>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            _value.subtract(change.removed)\n            _value.formUnion(change.inserted)\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n}\n\n\nprivate func describe(_ update: ValueUpdate<Set<Int>>) -> String {\n    switch update {\n    case .beginTransaction:\n        return \"begin\"\n    case .change(let change):\n        let old = change.old.sorted()\n        let new = change.new.sorted()\n        return \"\\(old) -> \\(new)\"\n    case .endTransaction:\n        return \"end\"\n    }\n}\n\nfunc checkObservableSet<T, S: ObservableSetType>(isBuffered: Bool = false, make: (Set<S.Element>) -> T, convert: (T) -> S, apply: @escaping (T, SetChange<S.Element>) -> Void) where S.Element == Int {\n    let t = make([1, 2, 3])\n    let test = convert(t)\n    XCTAssertEqual(test.value, [1, 2, 3])\n    XCTAssertEqual(test.isBuffered, isBuffered)\n    XCTAssertEqual(test.count, 3)\n    XCTAssertFalse(test.isEmpty)\n    XCTAssertTrue(test.contains(2))\n    XCTAssertFalse(test.contains(4))\n    XCTAssertTrue(test.isSubset(of: [1, 2, 3, 4]))\n    XCTAssertFalse(test.isSubset(of: [1, 3, 4]))\n    XCTAssertTrue(test.isSuperset(of: [1, 2]))\n    XCTAssertFalse(test.isSuperset(of: [0, 1]))\n\n    let observableValue = test.anyObservableValue\n    let observableCount = test.observableCount\n\n    XCTAssertEqual(observableValue.value, [1, 2, 3])\n    XCTAssertEqual(observableCount.value, 3)\n\n    let mock = MockSetObserver(test)\n    let vmock = TransformedMockSink<ValueUpdate<Set<Int>>, String>(observableValue.updates, { describe($0) })\n    let cmock = MockValueUpdateSink(observableCount)\n\n    mock.expecting([\"begin\", \"[]/[4]\", \"end\"]) {\n        vmock.expecting([\"begin\", \"[1, 2, 3] -> [1, 2, 3, 4]\", \"end\"]) {\n            cmock.expecting([\"begin\", \"3 -> 4\", \"end\"]) {\n                apply(t, SetChange<Int>(inserted: [4]))\n            }\n        }\n    }\n    XCTAssertTrue(test.contains(4))\n    XCTAssertEqual(test.value, [1, 2, 3, 4])\n\n    mock.expectingNothing {\n        vmock.expectingNothing {\n            cmock.expectingNothing {\n                apply(t, SetChange<Int>())\n            }\n        }\n    }\n    XCTAssertEqual(test.value, [1, 2, 3, 4])\n}\n\nfunc checkUpdatableSet<U: UpdatableSetType>(_ make: (Set<Int>) -> U) where U.Element == Int {\n    do {\n        let test = make([1, 2, 3])\n\n        XCTAssertEqual(test.value, [1, 2, 3])\n\n        let mock = MockSetObserver(test)\n\n        mock.expecting([\"begin\", \"[]/[4]\", \"end\"]) {\n            test.insert(4)\n        }\n        XCTAssertEqual(test.value, [1, 2, 3, 4])\n\n        mock.expectingNothing {\n            test.insert(2)\n        }\n        XCTAssertEqual(test.value, [1, 2, 3, 4])\n\n        mock.expecting([\"begin\", \"[2]/[]\", \"end\"]) {\n            test.remove(2)\n        }\n        XCTAssertEqual(test.value, [1, 3, 4])\n\n        mock.expectingNothing {\n            test.remove(2)\n        }\n\n        mock.expecting([\"begin\", \"[]/[0]\", \"[3]/[]\", \"end\"]) {\n            test.withTransaction {\n                test.insert(0)\n                test.remove(3)\n            }\n        }\n        XCTAssertEqual(test.value, [0, 1, 4])\n\n        mock.expecting([\"begin\", \"[0, 1, 4]/[10, 20, 30]\", \"end\"]) {\n            test.value = [10, 20, 30]\n        }\n        XCTAssertEqual(test.value, [10, 20, 30])\n\n        mock.expecting([\"begin\", \"[10, 20, 30]/[]\", \"end\"]) {\n            test.removeAll()\n        }\n        XCTAssertEqual(test.value, [])\n        mock.expectingNothing {\n            test.removeAll()\n        }\n        XCTAssertEqual(test.value, [])\n\n        mock.expecting([\"begin\", \"[]/[1, 2, 3]\", \"end\"]) {\n            test.formUnion([1, 2, 3])\n        }\n        XCTAssertEqual(test.value, [1, 2, 3])\n        mock.expecting([\"begin\", \"[3]/[]\", \"end\"]) {\n            test.formIntersection([0, 1, 2, 6])\n        }\n        XCTAssertEqual(test.value, [1, 2])\n        mock.expecting([\"begin\", \"[2]/[3, 4]\", \"end\"]) {\n            test.formSymmetricDifference([2, 3, 4])\n        }\n        XCTAssertEqual(test.value, [1, 3, 4])\n        mock.expecting([\"begin\", \"[1, 4]/[]\", \"end\"]) {\n            test.subtract([1, 4, 5])\n        }\n        XCTAssertEqual(test.value, [3])\n\n        let v = test.anyUpdatableValue\n        XCTAssertEqual(v.value, [3])\n\n        mock.expecting([\"begin\", \"[]/[1, 2]\", \"end\"]) {\n            v.value = [1, 2, 3]\n        }\n    }\n\n    // Try again with no observers.\n    do {\n        let test = make([1, 2, 3])\n\n        XCTAssertEqual(test.value, [1, 2, 3])\n\n        test.insert(4)\n        XCTAssertEqual(test.value, [1, 2, 3, 4])\n        test.insert(2)\n        XCTAssertEqual(test.value, [1, 2, 3, 4])\n        test.remove(2)\n        XCTAssertEqual(test.value, [1, 3, 4])\n        test.remove(2)\n        test.withTransaction {\n            test.insert(0)\n            test.remove(3)\n        }\n        XCTAssertEqual(test.value, [0, 1, 4])\n        test.value = [10, 20, 30]\n        XCTAssertEqual(test.value, [10, 20, 30])\n        test.removeAll()\n        XCTAssertEqual(test.value, [])\n        test.removeAll()\n        XCTAssertEqual(test.value, [])\n        test.formUnion([1, 2, 3])\n        XCTAssertEqual(test.value, [1, 2, 3])\n        test.formIntersection([0, 1, 2, 6])\n        XCTAssertEqual(test.value, [1, 2])\n        test.formSymmetricDifference([2, 3, 4])\n        XCTAssertEqual(test.value, [1, 3, 4])\n        test.subtract([1, 4, 5])\n        XCTAssertEqual(test.value, [3])\n    }\n}\n\n\nclass ObservableSetTypeTests: XCTestCase {\n    func testDefaultImplementations() {\n        checkObservableSet(make: { TestObservableSet($0) }, convert: { $0 }, apply: { $0.apply($1) })\n        checkObservableSet(make: { TestObservableSet($0) }, convert: { $0.anyObservableSet }, apply: { $0.apply($1) })\n\n        checkObservableSet(make: { TestObservableSet2($0) }, convert: { $0 }, apply: { $0.apply($1) })\n        checkObservableSet(make: { TestObservableSet2($0) }, convert: { $0.anyObservableSet }, apply: { $0.apply($1) })\n\n        checkObservableSet(make: { TestUpdatableSet($0) }, convert: { $0 }, apply: { $0.apply($1) })\n        checkObservableSet(make: { TestUpdatableSet($0) }, convert: { $0.anyUpdatableSet }, apply: { $0.apply($1) })\n        checkObservableSet(make: { TestUpdatableSet($0) }, convert: { $0.anyObservableSet }, apply: { $0.apply($1) })\n        checkObservableSet(make: { TestUpdatableSet($0) }, convert: { $0.anyUpdatableSet.anyObservableSet }, apply: { $0.apply($1) })\n\n        checkObservableSet(make: { TestUpdatableSet2($0) }, convert: { $0 }, apply: { $0.apply($1) })\n        checkObservableSet(make: { TestUpdatableSet2($0) }, convert: { $0.anyUpdatableSet }, apply: { $0.apply($1) })\n        checkObservableSet(make: { TestUpdatableSet2($0) }, convert: { $0.anyObservableSet }, apply: { $0.apply($1) })\n        checkObservableSet(make: { TestUpdatableSet2($0) }, convert: { $0.anyUpdatableSet.anyObservableSet }, apply: { $0.apply($1) })\n\n        checkObservableSet(isBuffered: true, make: { SetVariable<Int>($0) }, convert: { $0 }, apply: { $0.apply($1) })\n\n        class T {\n            let foo: TestUpdatableSet<Int>\n            init(_ v: Set<Int>) { self.foo = .init(v) }\n        }\n        checkObservableSet(make: { Variable<T>(T($0)).map { $0.foo } }, convert: { $0 }, apply: { $0.apply($1) })\n\n    }\n\n    func testObservableSetConstant() {\n        let constant = AnyObservableSet.constant([1, 2, 3])\n\n        XCTAssertTrue(constant.isBuffered)\n        XCTAssertEqual(constant.count, 3)\n        XCTAssertEqual(constant.value, [1, 2, 3])\n        XCTAssertTrue(constant.contains(2))\n        XCTAssertFalse(constant.contains(0))\n        XCTAssertTrue(constant.isSubset(of: [1, 2, 3, 4]))\n        XCTAssertFalse(constant.isSubset(of: [1, 3, 4]))\n        XCTAssertTrue(constant.isSuperset(of: [1, 2]))\n        XCTAssertFalse(constant.isSuperset(of: [0, 2]))\n\n        let mock = MockSetObserver(constant)\n        mock.expectingNothing {\n            // Well whatever\n        }\n\n        let observable = constant.anyObservableValue\n        XCTAssertEqual(observable.value, [1, 2, 3])\n\n        let observableCount = constant.observableCount\n        XCTAssertEqual(observableCount.value, 3)\n    }\n\n    func testUpdatableDefaultImplementations() {\n        checkUpdatableSet { TestUpdatableSet<Int>($0) }\n        checkUpdatableSet { TestUpdatableSet<Int>($0).anyUpdatableSet }\n        checkUpdatableSet { TestUpdatableSet<Int>($0).anyUpdatableSet.anyUpdatableSet }\n        checkUpdatableSet { TestUpdatableSet2<Int>($0) }\n        checkUpdatableSet { TestUpdatableSet2<Int>($0).anyUpdatableSet }\n        checkUpdatableSet { TestUpdatableSet2<Int>($0).anyUpdatableSet.anyUpdatableSet }\n        checkUpdatableSet { SetVariable<Int>($0) }\n        checkUpdatableSet { SetVariable<Int>($0).anyUpdatableSet }\n\n        class T {\n            let foo: TestUpdatableSet<Int>\n            init(_ v: Set<Int>) { self.foo = .init(v) }\n        }\n        checkUpdatableSet { Variable<T>(T($0)).map { $0.foo } }\n    }\n\n    func testObservableContains() {\n        let test = SetVariable<Int>([1, 2, 3])\n        let containsTwo = test.observableContains(2)\n\n        XCTAssertEqual(containsTwo.value, true)\n\n        let mock = MockValueUpdateSink(containsTwo)\n\n        mock.expecting([\"begin\", \"end\", \"begin\", \"end\"]) {\n            test.insert(5)\n            test.remove(1)\n        }\n        XCTAssertEqual(containsTwo.value, true)\n\n        mock.expecting([\"begin\", \"true -> false\", \"end\"]) {\n            test.remove(2)\n        }\n        XCTAssertEqual(containsTwo.value, false)\n\n        mock.expecting([\"begin\", \"false -> true\", \"end\"]) {\n            test.formUnion([2, 6])\n        }\n        XCTAssertEqual(containsTwo.value, true)\n    }\n}\n\n"
  },
  {
    "path": "Tests/GlueKitTests/ObservableTypeTests.swift",
    "content": "//\n//  ObservableTypeTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-28.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass ObservableTypeTests: XCTestCase {\n    func test_UpdatableType_withTransaction() {\n        let test = TestUpdatable(0)\n\n        let sink = MockUpdateSink<TestChange>()\n        test.updates.add(sink)\n\n        sink.expecting([\"begin\", \"end\"]) {\n            test.withTransaction {}\n        }\n\n        sink.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            test.withTransaction {\n                test.apply(TestChange(from: 0, to: 1))\n            }\n        }\n\n        sink.expecting([\"begin\", \"1 -> 2\", \"2 -> 3\", \"end\"]) {\n            test.withTransaction {\n                test.apply(TestChange(from: 1, to: 2))\n                test.apply(TestChange(from: 2, to: 3))\n            }\n        }\n\n        sink.expecting([\"begin\", \"3 -> 4\", \"end\"]) {\n            test.withTransaction {\n                test.withTransaction {\n                    test.apply(TestChange(from: 3, to: 4))\n                }\n            }\n        }\n\n        test.updates.remove(sink)\n    }\n\n    func test_UpdatableType_applyChange() {\n        let test = TestUpdatable(0)\n\n        let sink = MockUpdateSink<TestChange>()\n        test.updates.add(sink)\n\n        sink.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            test.apply(TestChange([0, 1]))\n        }\n\n        test.updates.remove(sink)\n    }\n\n    #if false // TODO Compiler crash in Xcode 8.3.2\n    func test_Connector_connectObservableToUpdateSink() {\n        let observable = TestObservable(0)\n\n        let connector = Connector()\n\n        var received: [Update<TestChange>] = []\n        connector.connect(observable) { update in received.append(update) }\n\n        observable.value = 1\n        \n        XCTAssertEqual(received.map { \"\\($0)\" }, [\"beginTransaction\", \"change(0 -> 1)\", \"endTransaction\"])\n        received = []\n\n        connector.disconnect()\n\n        observable.value = 2\n\n        XCTAssertEqual(received.map { \"\\($0)\" }, [])\n    }\n    #endif\n\n    #if false // TODO Compiler crash in Xcode 8.3.2\n    func test_Connector_connectObservableToChangeSink() {\n        let observable = TestObservable(0)\n\n        let connector = Connector()\n\n        var received: [TestChange] = []\n        connector.connect(observable) { change in received.append(change) }\n\n        observable.value = 1\n\n        XCTAssertEqual(received.map { \"\\($0)\" }, [\"0 -> 1\"])\n        received = []\n\n        connector.disconnect()\n\n        observable.value = 2\n\n        XCTAssertEqual(received.map { \"\\($0)\" }, [])\n    }\n    #endif\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ObservableValueTests.swift",
    "content": "//\n//  ObservableValueTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-08.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass ObservableValueTests: XCTestCase {\n    func test_anyObservable_fromObservableValue() {\n        let test = TestObservableValue(0)\n\n        let any = test.anyObservableValue\n\n        XCTAssertEqual(any.value, 0)\n\n        let updateSink = MockValueUpdateSink<Int>(any.updates)\n\n        let changeSink = TransformedMockSink<ValueChange<Int>, String>({ \"\\($0.old) -> \\($0.new)\" })\n        changeSink.subscribe(to: any.changes)\n\n        let valuesSink = MockSink<Int>()\n        valuesSink.expecting(0) {\n            valuesSink.subscribe(to: any.values)\n        }\n\n        let futureValuesSink = MockSink<Int>(any.futureValues)\n\n        updateSink.expecting(\"begin\") {\n            test.beginTransaction()\n        }\n        updateSink.expecting(\"0 -> 1\") {\n            test.value = 1\n        }\n\n        updateSink.expecting(\"end\") {\n            changeSink.expecting(\"0 -> 1\") {\n                valuesSink.expecting(1) {\n                    futureValuesSink.expecting(1) {\n                        test.endTransaction()\n                    }\n                }\n            }\n        }\n    }\n\n    func test_anyObservable_fromClosures() {\n        var value = 0\n        let signal = Signal<ValueUpdate<Int>>()\n        let test = AnyObservableValue(getter: { value },\n                                      updates: signal.anySource)\n\n        let any = test.anyObservableValue\n\n        XCTAssertEqual(any.value, 0)\n\n        let updateSink = MockValueUpdateSink<Int>()\n        updateSink.subscribe(to: any.updates)\n\n        let changeSink = TransformedMockSink<ValueChange<Int>, String>({ \"\\($0.old) -> \\($0.new)\" })\n        changeSink.subscribe(to: any.changes)\n\n        let valuesSink = MockSink<Int>()\n        valuesSink.expecting(0) {\n            valuesSink.subscribe(to: any.values)\n        }\n\n        let futureValuesSink = MockSink<Int>(any.futureValues)\n\n        updateSink.expecting(\"begin\") {\n            signal.send(.beginTransaction)\n        }\n        updateSink.expecting(\"0 -> 1\") {\n            value = 1\n            signal.send(.change(ValueChange(from: 0, to: 1)))\n        }\n\n        updateSink.expecting(\"end\") {\n            changeSink.expecting(\"0 -> 1\") {\n                valuesSink.expecting(1) {\n                    futureValuesSink.expecting(1) {\n                        signal.send(.endTransaction)\n                    }\n                }\n            }\n        }\n    }\n\n    func testObservableValueType_values_SendsInitialValue() {\n        let test = TestObservableValue(0)\n\n        var res = [Int]()\n\n        let connection = test.values.subscribe { res.append($0) }\n        XCTAssertEqual(res, [0])\n        test.value = 1\n        test.value = 2\n        connection.disconnect()\n        test.value = 3\n\n        XCTAssertEqual(res, [0, 1, 2])\n    }\n\n    func testObservableValueType_values_SupportsNestedSendsBySerializingThem() {\n        let test = TestObservableValue(0)\n        var s = \"\"\n\n        let c1 = test.values.subscribe { i in\n            s += \" (\\(i)\"\n            if i > 0 {\n                test.value = i - 1\n            }\n            s += \")\"\n        }\n        let c2 = test.values.subscribe { i in\n            s += \" (\\(i)\"\n            if i > 0 {\n                test.value = i - 1\n            }\n            s += \")\"\n        }\n        XCTAssertEqual(s, \" (0) (0)\")\n\n        s = \"\"\n        test.value = 2\n        XCTAssertEqual(s, \" (2) (2) (1) (1) (1) (1) (0) (0) (0) (0) (0) (0) (0) (0)\")\n\n        c1.disconnect()\n        c2.disconnect()\n    }\n\n    func testObservableValueType_constant() {\n        let constant = AnyObservableValue.constant(1)\n\n        XCTAssertEqual(constant.value, 1)\n\n        let sink = MockValueUpdateSink<Int>()\n        constant.add(sink)\n\n        let sink2 = MockValueUpdateSink<Int>()\n        let removed = constant.remove(sink2)\n        XCTAssert(removed === sink2)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/RefListTests.swift",
    "content": "//\n//  RefListTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-08.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\n@testable import GlueKit\n\nprivate final class Fixture: RefListElement {\n    var value: Int\n    var refListLink = RefListLink<Fixture>()\n\n    init(_ value: Int) { self.value = value }\n}\n\nclass RefListTests: XCTestCase {\n    private func verify(_ list: RefList<Fixture>, file: StaticString = #file, line: UInt = #line) {\n        for i in 0 ..< list.count {\n            let element = list[i]\n            XCTAssertEqual(list.index(of: element), i, file: file, line: line)\n        }\n    }\n\n\n    func test_emptyInitializer() {\n        let list = RefList<Fixture>()\n        XCTAssertTrue(list.isEmpty)\n        XCTAssertEqual(Array(list).map { $0.value }, [])\n        verify(list)\n    }\n\n    func test_initializerFromSequence() {\n        let list = RefList<Fixture>((0 ..< 1000).map { Fixture($0) })\n        XCTAssertFalse(list.isEmpty)\n        XCTAssertEqual(Array(list).map { $0.value }, Array(0 ..< 1000))\n        verify(list)\n    }\n\n    func test_basicOperations() {\n        let list = RefList<Fixture>(order: 5)\n\n        // Append even elements.\n        for i in 0 ..< 50 {\n            list.append(Fixture(2 * i))\n            verify(list)\n        }\n        XCTAssertEqual(list.map { $0.value }, (0 ..< 50).map { 2 * $0 })\n\n        // Insert odd elements.\n        for i in 0 ..< 50 {\n            list.insert(Fixture(2 * i + 1), at: 2 * i + 1)\n            verify(list)\n        }\n        XCTAssertEqual(list.map { $0.value }, Array(0 ..< 100))\n\n        // Look up elements.\n        for i in 0 ..< 100 {\n            let element = list[i]\n            XCTAssertEqual(element.value, i)\n        }\n\n        // Remove elements from the start.\n        for i in 0 ..< 50 {\n            XCTAssertEqual(list.remove(at: 0).value, i)\n            verify(list)\n        }\n\n        // Remove elements from the end.\n        for i in (50 ..< 100).reversed() {\n            XCTAssertEqual(list.remove(at: list.count - 1).value, i)\n            verify(list)\n        }\n    }\n\n    func test_remove() {\n        let c = 30\n        for removedIndex in 0 ..< c {\n            let list = RefList<Fixture>(order: 5)\n            let elements = (0 ..< c).map { Fixture($0) }\n            list.append(contentsOf: elements)\n            XCTAssertEqual(list.remove(at: removedIndex).value, removedIndex)\n            verify(list)\n\n            var expected = elements\n            expected.remove(at: removedIndex)\n            XCTAssertTrue(list.elementsEqual(expected, by: ===))\n        }\n    }\n\n    func test_insertCollection() {\n        let c = 30\n        for insertionIndex in 0 ..< c {\n            let list = RefList<Fixture>(order: 5)\n            let origElements = (0 ..< c).map { Fixture($0) }\n            list.append(contentsOf: origElements)\n\n            let insertedElements = (0 ..< 10).map { Fixture(100 + $0) }\n            list.insert(contentsOf: insertedElements, at: insertionIndex)\n            verify(list)\n\n            var expected = origElements\n            expected.insert(contentsOf: insertedElements, at: insertionIndex)\n\n            XCTAssertTrue(list.elementsEqual(expected, by: ===))\n        }\n    }\n\n    func test_removeSubrange() {\n        let c = 30\n        for start in 0 ..< c {\n            for end in start ..< c {\n                let list = RefList<Fixture>(order: 5)\n                let elements = (0 ..< c).map { Fixture($0) }\n                list.append(contentsOf: elements)\n                list.removeSubrange(start ..< end)\n                verify(list)\n\n                var expected = elements\n                expected.removeSubrange(start ..< end)\n                XCTAssertTrue(list.elementsEqual(expected, by: ===))\n            }\n        }\n    }\n\n    func test_replaceSubrange() {\n        let c = 30\n        for start in 0 ..< c {\n            for end in start ..< c {\n                for newRange in [0 ..< 0, 0 ..< 1, 0 ..< 10] {\n                    let list = RefList<Fixture>(order: 5)\n                    let elements = (0 ..< c).map { Fixture($0) }\n                    list.append(contentsOf: elements)\n\n                    let replacement = newRange.map { Fixture(100 + $0) }\n                    list.replaceSubrange(start ..< end, with: replacement)\n                    verify(list)\n\n                    var expected = elements\n                    expected.replaceSubrange(start ..< end, with: replacement)\n                    XCTAssertTrue(list.elementsEqual(expected, by: ===))\n                }\n            }\n        }\n    }\n\n    func test_subscript_setter() {\n        let list = RefList<Fixture>(order: 5)\n        list.append(contentsOf: (0 ..< 30).map { Fixture($0) })\n        for i in 0 ..< 30 {\n            list[i] = Fixture(2 * i)\n            verify(list)\n        }\n        XCTAssertEqual(list.map { $0.value }, (0 ..< 30).map { 2 * $0 })\n    }\n\n    func test_rangeSubscript() {\n        let list = RefList<Fixture>(order: 5)\n        list.append(contentsOf: (0 ..< 30).map { Fixture($0) })\n\n        for start in 0 ..< 30 {\n            for end in start ..< 30 {\n                let slice = list[start ..< end]\n                XCTAssertEqual(slice.map { $0.value }, Array(start ..< end))\n            }\n        }\n\n        \n    }\n\n    func test_leaks() {\n        weak var list: RefList<Fixture>? = nil\n        weak var test: Fixture? = nil\n        do {\n            let l = RefList<Fixture>(order: 5)\n            l.append(contentsOf: (0 ..< 30).map { Fixture($0) })\n            list = l\n            test = l[10]\n        }\n        XCTAssertNil(list)\n        XCTAssertNil(test)\n    }\n\n    func test_forEach() {\n        let list = RefList<Fixture>(order: 5)\n        list.append(contentsOf: (0 ..< 100).map { Fixture($0) })\n\n        var i = 0\n        list.forEach { e in\n            XCTAssertEqual(e.value, i)\n            i += 1\n        }\n        XCTAssertEqual(i, list.count)\n\n        for start in 0 ..< list.count {\n            for end in start ..< list.count {\n                var i = start\n                list.forEach(in: start ..< end) { e in\n                    XCTAssertEqual(e.value, i)\n                    i += 1\n                }\n                XCTAssertEqual(i, end)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SetBufferingTests.swift",
    "content": "//\n//  SetBufferingTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass SetBufferingTests: XCTestCase {\n    func test_connectsImmediately() {\n        let observable = TestObservableSet([1, 2, 3])\n\n        do {\n            let buffered = observable.buffered()\n            XCTAssertTrue(observable.isConnected)\n            withExtendedLifetime(buffered) {}\n        }\n        XCTAssertFalse(observable.isConnected)\n    }\n\n    func test_properties() {\n        let observable = TestObservableSet([1, 2, 3])\n        let buffered = observable.buffered()\n\n        for b in [buffered, buffered.buffered()] {\n            XCTAssertEqual(b.isBuffered, true)\n            XCTAssertEqual(b.count, 3)\n            XCTAssertEqual(b.value, [1, 2, 3])\n            XCTAssertEqual(b.contains(0), false)\n            XCTAssertEqual(b.contains(1), true)\n            XCTAssertEqual(b.isSubset(of: [1, 2, 3, 4]), true)\n            XCTAssertEqual(b.isSubset(of: [2, 3, 4, 5]), false)\n            XCTAssertEqual(b.isSuperset(of: [1, 2]), true)\n            XCTAssertEqual(b.isSuperset(of: [3, 4]), false)\n        }\n\n        observable.apply(SetChange(removed: [3], inserted: [0]))\n        XCTAssertEqual(buffered.value, [0, 1, 2])\n\n    }\n\n    func test_updates() {\n        let observable = TestObservableSet([1, 2, 3])\n        let buffered = observable.buffered()\n\n        let sink = MockSetObserver(buffered)\n\n        sink.expecting([\"begin\", \"[3]/[]\", \"end\"]) {\n            observable.apply(SetChange(removed: [3]))\n        }\n        XCTAssertEqual(buffered.value, [1, 2])\n\n        sink.expecting(\"begin\") {\n            observable.beginTransaction()\n        }\n\n        sink.expectingNothing {\n            observable.apply(SetChange(removed: [2], inserted: [4]))\n        }\n        XCTAssertEqual(buffered.value, [1, 2])\n\n        sink.expectingNothing {\n            observable.apply(SetChange(inserted: [9]))\n        }\n        XCTAssertEqual(buffered.value, [1, 2])\n\n        sink.expecting([\"[2]/[4, 9]\", \"end\"]) {\n            observable.endTransaction()\n        }\n        XCTAssertEqual(buffered.value, [1, 4, 9])\n\n        sink.disconnect()\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SetFilteringTests.swift",
    "content": "//\n//  SetFilteringTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-06.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nclass SetFilteringTests: XCTestCase {\n\n    func test_filter_simplePredicate() {\n        let set = SetVariable<Int>(0 ..< 10)\n        let even = set.filter { $0 & 1 == 0 }\n\n        XCTAssertFalse(even.isBuffered)\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [0, 2, 4, 6, 8])\n        XCTAssertTrue(even.contains(0))\n        XCTAssertFalse(even.contains(1))\n\n        XCTAssertTrue(even.isSubset(of: Set(0 ..< 10)))\n        XCTAssertTrue(even.isSubset(of: Set(-1 ..< 11)))\n        XCTAssertFalse(even.isSubset(of: Set(1 ..< 20)))\n\n        XCTAssertTrue(even.isSuperset(of: []))\n        XCTAssertTrue(even.isSuperset(of: [2, 4, 6]))\n        XCTAssertTrue(even.isSuperset(of: [0, 2, 4, 6, 8]))\n        XCTAssertFalse(even.isSuperset(of: [2, 5, 6]))\n\n        let mock = MockSetObserver(even)\n\n        // Repeat basic tests with an active connection.\n        XCTAssertFalse(even.isBuffered)\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [0, 2, 4, 6, 8])\n        XCTAssertTrue(even.contains(0))\n        XCTAssertFalse(even.contains(1))\n\n        XCTAssertTrue(even.isSubset(of: Set(0 ..< 10)))\n        XCTAssertTrue(even.isSubset(of: Set(-1 ..< 11)))\n        XCTAssertFalse(even.isSubset(of: Set(1 ..< 20)))\n\n        XCTAssertTrue(even.isSuperset(of: []))\n        XCTAssertTrue(even.isSuperset(of: [2, 4, 6]))\n        XCTAssertTrue(even.isSuperset(of: [0, 2, 4, 6, 8]))\n        XCTAssertFalse(even.isSuperset(of: [2, 5, 6]))\n\n        // Now try some modifications\n\n        mock.expecting([\"begin\", \"[]/[10]\", \"end\"]) { set.insert(10) }\n        XCTAssertEqual(even.value, [0, 2, 4, 6, 8, 10])\n\n        mock.expecting([\"begin\", \"end\"]) { set.insert(11) }\n        XCTAssertEqual(even.value, [0, 2, 4, 6, 8, 10])\n\n        mock.expecting([\"begin\", \"end\"]) { set.remove(5) }\n        XCTAssertEqual(even.value, [0, 2, 4, 6, 8, 10])\n\n        mock.expecting([\"begin\", \"[6]/[]\", \"end\"]) { set.remove(6) }\n        XCTAssertEqual(even.value, [0, 2, 4, 8, 10])\n    }\n\n    func test_filter_observableBool() {\n        var f = (0 ..< 15).map { Foo($0) }\n        let set = SetVariable<Foo>(f[0 ..< 10])\n        let even = set.filter { $0.isEven }\n\n        XCTAssertFalse(even.isBuffered)\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [f[0], f[2], f[4], f[6], f[8]])\n        XCTAssertTrue(even.contains(f[0]))\n        XCTAssertFalse(even.contains(f[1]))\n\n        XCTAssertTrue(even.isSubset(of: Set(f)))\n        XCTAssertTrue(even.isSubset(of: Set(f + [Foo(10), Foo(-1)])))\n        XCTAssertFalse(even.isSubset(of: [f[0], f[2], f[5], f[6], f[8]]))\n\n        XCTAssertTrue(even.isSuperset(of: []))\n        XCTAssertTrue(even.isSuperset(of: [f[2], f[4], f[6]]))\n        XCTAssertTrue(even.isSuperset(of: [f[0], f[2], f[4], f[6], f[8]]))\n        XCTAssertFalse(even.isSuperset(of: [f[2], f[5], f[6]]))\n\n        let mock = MockSetObserver<Foo>(even)\n\n        // Repeat basic tests with an active connection.\n        XCTAssertFalse(even.isBuffered)\n        XCTAssertEqual(even.count, 5)\n        XCTAssertEqual(even.value, [f[0], f[2], f[4], f[6], f[8]])\n        XCTAssertTrue(even.contains(f[0]))\n        XCTAssertFalse(even.contains(f[1]))\n\n        XCTAssertTrue(even.isSubset(of: Set(f)))\n        XCTAssertTrue(even.isSubset(of: Set(f + [Foo(10), Foo(-1)])))\n        XCTAssertFalse(even.isSubset(of: [f[0], f[2], f[5], f[6], f[8]]))\n\n        XCTAssertTrue(even.isSuperset(of: []))\n        XCTAssertTrue(even.isSuperset(of: [f[2], f[4], f[6]]))\n        XCTAssertTrue(even.isSuperset(of: [f[0], f[2], f[4], f[6], f[8]]))\n        XCTAssertFalse(even.isSuperset(of: [f[2], f[5], f[6]]))\n\n        // Now try some modifications\n        mock.expecting([\"begin\", \"[]/[10]\", \"end\"]) {\n            set.insert(f[10])\n        }\n        XCTAssertEqual(even.value, [f[0], f[2], f[4], f[6], f[8], f[10]])\n        mock.expecting([\"begin\", \"end\"]) {\n            set.insert(f[11])\n        }\n        XCTAssertEqual(even.value, [f[0], f[2], f[4], f[6], f[8], f[10]])\n        mock.expecting([\"begin\", \"end\"]) {\n            set.remove(f[3])\n        }\n        XCTAssertEqual(even.value, [f[0], f[2], f[4], f[6], f[8], f[10]])\n        mock.expecting([\"begin\", \"[4]/[]\", \"end\"]) {\n            set.remove(f[4])\n        }\n        XCTAssertEqual(even.value, [f[0], f[2], f[6], f[8], f[10]])\n        mock.expecting([\"begin\", \"[]/[11]\", \"end\"]) {\n            f[11].number.value = 10\n        }\n        XCTAssertEqual(even.value, [f[0], f[2], f[6], f[8], f[10], f[11]])\n        mock.expecting([\"begin\", \"[8]/[]\", \"end\"]) {\n            f[8].number.value = 9\n        }\n        XCTAssertEqual(even.value, [f[0], f[2], f[6], f[10], f[11]])\n        mock.expecting([\"begin\", \"end\"]) {\n            f[8].number.value = 7\n        }\n        XCTAssertEqual(even.value, [f[0], f[2], f[6], f[10], f[11]])\n        mock.expecting([\"begin\", \"end\"]) {\n            f[6].number.value = 8\n        }\n        XCTAssertEqual(even.value, [f[0], f[2], f[6], f[10], f[11]])\n    }\n\n    func test_filter_observablePredicate() {\n        let predicate = Variable<(Int) -> Bool> { $0 & 1 == 0 }\n        let set = SetVariable<Int>(0 ..< 10)\n\n        let filtered = set.filter(predicate)\n\n        XCTAssertEqual(filtered.value, [0, 2, 4, 6, 8])\n\n        let mock = MockSetObserver(filtered)\n\n        mock.expecting([\"begin\", \"[]/[10]\", \"end\"]) { set.insert(10) }\n        mock.expecting([\"begin\", \"[6, 8, 10]/[1, 3, 5]\", \"end\"]) { predicate.value = { $0 <= 5 } }\n        mock.expecting([\"begin\", \"[]/[-1]\", \"end\"]) { set.insert(-1) }\n        mock.expecting([\"begin\", \"[0, 2, 4]/[7, 9]\", \"end\"]) { predicate.value = { $0 & 1 == 1 } }\n    }\n\n    func test_filter_observableOptionalPredicate() {\n        let predicate = Variable<Optional<(Int) -> Bool>> { $0 & 1 == 0 }\n        let set = SetVariable<Int>(0 ..< 10)\n\n        let filtered = set.filter(predicate)\n\n        XCTAssertEqual(filtered.value, [0, 2, 4, 6, 8])\n\n        let mock = MockSetObserver(filtered)\n\n        mock.expecting([\"begin\", \"[]/[10]\", \"end\"]) { set.insert(10) }\n        mock.expecting([\"begin\", \"[6, 8, 10]/[1, 3, 5]\", \"end\"]) { predicate.value = { $0 <= 5 } }\n        mock.expecting([\"begin\", \"[]/[-1]\", \"end\"]) { set.insert(-1) }\n        mock.expecting([\"begin\", \"[0, 2, 4]/[7, 9]\", \"end\"]) { predicate.value = { $0 & 1 == 1 } }\n        mock.expecting([\"begin\", \"[]/[0, 2, 4, 6, 8, 10]\", \"end\"]) { predicate.value = nil }\n    }\n}\n\nprivate final class Foo: Hashable, Comparable, ExpressibleByIntegerLiteral, CustomStringConvertible {\n    let id: Int\n    let number: IntVariable\n\n    var isEven: AnyObservableValue<Bool> { return number.map { $0 & 1 == 0 } }\n\n    init(_ number: Int) {\n        self.id = number\n        self.number = .init(number)\n    }\n    convenience init(integerLiteral value: Int) { self.init(value) }\n    var hashValue: Int { return ObjectIdentifier(self).hashValue }\n    var description: String { return \"\\(id)\" }\n    static func == (a: Foo, b: Foo) -> Bool { return a === b }\n    static func < (a: Foo, b: Foo) -> Bool { return a.number.value < b.number.value }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SetFoldingTests.swift",
    "content": "//\n//  SetFoldingTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-09.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass SetFoldingTests: XCTestCase {\n\n    func testSum() {\n        let set = SetVariable<Int>([1, 2, 3])\n        let sum = set.sum()\n\n        XCTAssertEqual(sum.value, 6)\n\n        set.insert(4)\n        XCTAssertEqual(sum.value, 10)\n\n        set.formUnion([5, 6])\n        XCTAssertEqual(sum.value, 21)\n\n        set.remove(1)\n        XCTAssertEqual(sum.value, 20)\n\n        set.subtract([2, 4])\n        XCTAssertEqual(sum.value, 14)\n        \n        set.removeAll()\n        XCTAssertEqual(sum.value, 0)\n    }\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SetMappingTests.swift",
    "content": "//\n//  SetMappingTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-05.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nprivate class Book: Hashable {\n    let title: StringVariable\n    let authors: SetVariable<String>\n    let chapters: ArrayVariable<String>\n\n    init(_ title: String, authors: Set<String> = [], chapters: [String] = []) {\n        self.title = .init(title)\n        self.authors = .init(authors)\n        self.chapters = .init(chapters)\n    }\n\n    var hashValue: Int { return ObjectIdentifier(self).hashValue }\n    static func ==(a: Book, b: Book) -> Bool { return a === b }\n}\n\nclass SetMappingTests: XCTestCase {\n    func test_injectiveMap() {\n        let set = SetVariable<Int>([0, 2, 3])\n        let mappedSet = set.injectiveMap { \"\\($0)\" }\n\n        XCTAssertTrue(mappedSet.isBuffered)\n        XCTAssertEqual(mappedSet.count, 3)\n        XCTAssertEqual(mappedSet.value, Set([\"0\", \"2\", \"3\"]))\n        XCTAssertEqual(mappedSet.contains(\"0\"), true)\n        XCTAssertEqual(mappedSet.contains(\"1\"), false)\n        XCTAssertEqual(mappedSet.isSubset(of: []), false)\n        XCTAssertEqual(mappedSet.isSubset(of: [\"3\", \"4\", \"5\"]), false)\n        XCTAssertEqual(mappedSet.isSubset(of: [\"0\", \"2\", \"3\"]), true)\n        XCTAssertEqual(mappedSet.isSubset(of: [\"0\", \"1\", \"2\", \"3\"]), true)\n        XCTAssertEqual(mappedSet.isSuperset(of: []), true)\n        XCTAssertEqual(mappedSet.isSuperset(of: [\"3\"]), true)\n        XCTAssertEqual(mappedSet.isSuperset(of: [\"0\", \"2\", \"3\"]), true)\n        XCTAssertEqual(mappedSet.isSuperset(of: [\"0\", \"1\", \"2\", \"3\"]), false)\n        XCTAssertEqual(mappedSet.isSuperset(of: [\"1\"]), false)\n\n        let mock = MockSetObserver(mappedSet)\n        mock.expecting([\"begin\", \"[]/[1]\", \"end\"]) {\n            set.insert(1)\n        }\n        XCTAssertEqual(mappedSet.value, Set([\"0\", \"1\", \"2\", \"3\"]))\n        mock.expecting([\"begin\", \"[1, 2]/[]\", \"end\"]) {\n            set.subtract(Set([1, 2]))\n        }\n        XCTAssertEqual(mappedSet.value, Set([\"0\", \"3\"]))\n    }\n\n    func test_map_injectiveValue() {\n        let set = SetVariable<Int>([0, 2, 3])\n        let mappedSet = set.map { \"\\($0)\" }\n\n        XCTAssertFalse(mappedSet.isBuffered)\n        XCTAssertEqual(mappedSet.count, 3)\n        XCTAssertEqual(mappedSet.value, Set([\"0\", \"2\", \"3\"]))\n        XCTAssertEqual(mappedSet.contains(\"0\"), true)\n        XCTAssertEqual(mappedSet.contains(\"1\"), false)\n        XCTAssertEqual(mappedSet.isSubset(of: []), false)\n        XCTAssertEqual(mappedSet.isSubset(of: [\"3\", \"4\", \"5\"]), false)\n        XCTAssertEqual(mappedSet.isSubset(of: [\"0\", \"2\", \"3\"]), true)\n        XCTAssertEqual(mappedSet.isSubset(of: [\"0\", \"1\", \"2\", \"3\"]), true)\n        XCTAssertEqual(mappedSet.isSuperset(of: []), true)\n        XCTAssertEqual(mappedSet.isSuperset(of: [\"3\"]), true)\n        XCTAssertEqual(mappedSet.isSuperset(of: [\"0\", \"2\", \"3\"]), true)\n        XCTAssertEqual(mappedSet.isSuperset(of: [\"0\", \"1\", \"2\", \"3\"]), false)\n        XCTAssertEqual(mappedSet.isSuperset(of: [\"1\"]), false)\n\n        let mock = MockSetObserver(mappedSet)\n        mock.expecting([\"begin\", \"[]/[1]\", \"end\"]) {\n            set.insert(1)\n        }\n        XCTAssertEqual(mappedSet.value, Set([\"0\", \"1\", \"2\", \"3\"]))\n        mock.expecting([\"begin\", \"[1, 2]/[]\", \"end\"]) {\n            set.subtract(Set([1, 2]))\n        }\n        XCTAssertEqual(mappedSet.value, Set([\"0\", \"3\"]))\n    }\n\n    func test_map_noninjectiveValue() {\n        let set = SetVariable<Int>([0, 2, 3, 4, 8, 9])\n        let mappedSet = set.map { $0 / 2 }\n\n        XCTAssertEqual(mappedSet.value, [0, 1, 2, 4])\n\n        let mock = MockSetObserver(mappedSet)\n        mock.expecting([\"begin\", \"end\"]) { set.insert(1) }\n        XCTAssertEqual(mappedSet.value, [0, 1, 2, 4])\n        mock.expecting([\"begin\", \"[2]/[]\", \"end\"]) { set.remove(4) }\n        XCTAssertEqual(mappedSet.value, [0, 1, 4])\n        mock.expecting([\"begin\", \"end\"]) { set.remove(3) }\n        XCTAssertEqual(mappedSet.value, [0, 1, 4])\n    }\n\n    func test_map_valueField() {\n        let b1 = Book(\"foo\")\n        let b2 = Book(\"bar\")\n        let b3 = Book(\"baz\")\n\n        let books: SetVariable<Book> = [b1, b2, b3]\n        let titles = books.map { $0.title }\n\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\"])\n\n        let mock = MockSetObserver(titles)\n\n        let b4 = Book(\"fred\")\n        mock.expecting([\"begin\", \"[]/[fred]\", \"end\"]) {\n            books.insert(b4)\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"bar\", \"baz\", \"fred\"])\n\n        mock.expecting([\"begin\", \"[bar]/[]\", \"end\"]) {\n            books.remove(b2)\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"baz\", \"fred\"])\n\n        mock.expecting([\"begin\", \"[baz]/[bazaar]\", \"end\"]) { b3.title.value = \"bazaar\" }\n        XCTAssertEqual(titles.value, [\"foo\", \"bazaar\", \"fred\"])\n\n        mock.expecting([\"begin\", \"end\"]) { b3.title.value = \"bazaar\" }\n        XCTAssertEqual(titles.value, [\"foo\", \"bazaar\", \"fred\"])\n\n        mock.expectingNothing {\n            b2.title.value = \"xyzzy\" // b2 isn't in books\n        }\n        XCTAssertEqual(titles.value, [\"foo\", \"bazaar\", \"fred\"])\n\n        mock.expecting([\"begin\", \"[foo]/[xyzzy]\", \"end\"]) { b1.title.value = \"xyzzy\" }\n        XCTAssertEqual(titles.value, [\"xyzzy\", \"bazaar\", \"fred\"])\n\n        mock.expecting([\"begin\", \"end\"]) { books.insert(b2) }\n        mock.expecting([\"begin\", \"end\"]) { books.remove(b1) }\n        XCTAssertEqual(titles.value, [\"xyzzy\", \"bazaar\", \"fred\"])\n\n        mock.expecting([\"begin\", \"[xyzzy]/[]\", \"end\"]) { books.remove(b2) }\n        XCTAssertEqual(titles.value, [\"bazaar\", \"fred\"])\n\n        mock.expecting([\"begin\", \"[fred]/[fuzzy]\", \"end\"]) { b4.title.value = \"fuzzy\" }\n        XCTAssertEqual(titles.value, [\"bazaar\", \"fuzzy\"])\n\n        mock.expecting([\"begin\", \"[bazaar]/[]\", \"end\"]) { b3.title.value = \"fuzzy\" }\n        XCTAssertEqual(titles.value, [\"fuzzy\"])\n    }\n\n    func test_flatMap_setField() {\n        let b1 = Book(\"1\", authors: [\"a\", \"b\", \"c\"])\n        let b2 = Book(\"2\", authors: [\"a\"])\n        let b3 = Book(\"3\", authors: [\"b\", \"d\"])\n\n        let books: SetVariable<Book> = [b1, b2, b3]\n        let authors = books.flatMap { $0.authors }\n\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\"])\n\n        let mock = MockSetObserver(authors)\n\n        let b4 = Book(\"4\", authors: [\"b\", \"c\", \"e\"])\n        mock.expecting([\"begin\", \"[]/[e]\", \"end\"]) { books.insert(b4) }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"end\"]) { books.remove(b1) }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[c]/[]\", \"end\"]) { b4.authors.remove(\"c\") }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[]/[c]\", \"end\"]) { b4.authors.insert(\"c\") }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[a]/[f]\", \"end\"]) { b2.authors.value = [\"f\"] }\n        XCTAssertEqual(authors.value, [\"b\", \"c\", \"d\", \"e\", \"f\"])\n\n        mock.expecting([\"begin\", \"[d]/[]\", \"end\"]) { books.remove(b3) }\n        XCTAssertEqual(authors.value, [\"b\", \"c\", \"e\", \"f\"])\n\n        mock.expecting([\"begin\", \"[f]/[]\", \"end\"]) { books.remove(b2) }\n        XCTAssertEqual(authors.value, [\"b\", \"c\", \"e\"])\n    }\n\n    func test_flatMap_arrayField() {\n        let b1 = Book(\"1\", chapters: [\"a\", \"b\", \"c\"])\n        let b2 = Book(\"2\", chapters: [\"a\"])\n        let b3 = Book(\"3\", chapters: [\"b\", \"d\"])\n\n        let books: SetVariable<Book> = [b1, b2, b3]\n        // It isn't very useful to make a set of chapters from several books, but let's do that anyway.\n        let chapters = books.flatMap { $0.chapters }\n\n        XCTAssertEqual(chapters.value, [\"a\", \"b\", \"c\", \"d\"])\n\n        let mock = MockSetObserver(chapters)\n\n        let b4 = Book(\"4\", chapters: [\"b\", \"c\", \"e\"])\n        mock.expecting([\"begin\", \"[]/[e]\", \"end\"]) { books.insert(b4) }\n        XCTAssertEqual(chapters.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"end\"]) { books.remove(b1) }\n        XCTAssertEqual(chapters.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[c]/[]\", \"end\"]) { _ = b4.chapters.remove(at: 1) } // b4.chapters was bce\n        XCTAssertEqual(chapters.value, [\"a\", \"b\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[]/[c]\", \"end\"]) { b4.chapters.insert(\"c\", at: 1) } // b4.chapters was be\n        XCTAssertEqual(chapters.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"end\"]) { b4.chapters.value = [\"e\", \"c\", \"b\"] } // Reordering chapters has no effect on result set\n        XCTAssertEqual(chapters.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[a]/[f]\", \"end\"]) { b2.chapters.value = [\"f\"] }\n        XCTAssertEqual(chapters.value, [\"b\", \"c\", \"d\", \"e\", \"f\"])\n\n        mock.expecting([\"begin\", \"[d]/[]\", \"end\"]) { books.remove(b3) }\n        XCTAssertEqual(chapters.value, [\"b\", \"c\", \"e\", \"f\"])\n\n        mock.expecting([\"begin\", \"[f]/[]\", \"end\"]) { books.remove(b2) }\n        XCTAssertEqual(chapters.value, [\"b\", \"c\", \"e\"])\n    }\n\n    func test_flatMap_sequence() {\n        let b1 = Book(\"1\", authors: [\"a\", \"b\", \"c\"])\n        let b2 = Book(\"2\", authors: [\"a\"])\n        let b3 = Book(\"3\", authors: [\"b\", \"d\"])\n\n        let books: SetVariable<Book> = [b1, b2, b3]\n        // In this variant, we extract the value of the authors field, so that we have a simple flatMap where the\n        // transform closure just returns a sequence. This means that the resulting observable does not track changes\n        // to the values of individual fields, which is normally a bad idea -- but for this test, it spares us from \n        // having to add a sequence-typed property to Book.\n        let authors = books.flatMap { $0.authors.value }\n\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\"])\n\n        let mock = MockSetObserver(authors)\n\n        let b4 = Book(\"4\", authors: [\"b\", \"c\", \"e\"])\n        mock.expecting([\"begin\", \"[]/[e]\", \"end\"]) { books.insert(b4) }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"end\"]) { books.remove(b1) }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[d]/[]\", \"end\"]) { books.remove(b3) }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"e\"])\n\n        mock.expecting([\"begin\", \"[a]/[]\", \"end\"]) { books.remove(b2) }\n        XCTAssertEqual(authors.value, [\"b\", \"c\", \"e\"])\n    }\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SetReferenceTests.swift",
    "content": "//\n//  SetReferenceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass SetReferenceTests: XCTestCase {\n    func testReference() {\n        let a: SetVariable<Int> = [1, 2, 3]\n        let b: SetVariable<Int> = [10, 20]\n        let c: SetVariable<Int> = [7]\n        let ref = Variable<SetVariable<Int>>(a)\n\n        XCTAssertEqual(ref.value.value, Set([1, 2, 3]))\n        a.insert(4)\n        XCTAssertEqual(ref.value.value, Set([1, 2, 3, 4]))\n\n        let unpacked = ref.unpacked()\n\n        XCTAssertEqual(unpacked.isBuffered, false)\n        XCTAssertEqual(unpacked.count, 4)\n        XCTAssertEqual(unpacked.value, Set([1, 2, 3, 4]))\n        XCTAssertEqual(unpacked.contains(0), false)\n        XCTAssertEqual(unpacked.contains(1), true)\n        XCTAssertEqual(unpacked.isSubset(of: [1, 2, 3, 4, 5]), true)\n        XCTAssertEqual(unpacked.isSubset(of: [2, 3, 4, 5, 6]), false)\n        XCTAssertEqual(unpacked.isSuperset(of: [1, 2, 3]), true)\n        XCTAssertEqual(unpacked.isSuperset(of: [3, 4, 5]), false)\n\n        a.remove(2)\n        XCTAssertEqual(unpacked.value, [1, 3, 4])\n\n        let sink = MockSetObserver(unpacked)\n\n        sink.expecting([\"begin\", \"[1]/[]\", \"end\"]) {\n            a.remove(1)\n        }\n\n        sink.expecting([\"begin\", \"[3, 4]/[10, 20]\", \"end\"]) {\n            ref.value = b\n        }\n\n        sink.expecting(\"begin\") {\n            b.apply(.beginTransaction)\n        }\n\n        sink.expectingNothing {\n            ref.apply(.beginTransaction)\n        }\n\n        sink.expecting(\"[]/[15]\") {\n            b.insert(15)\n        }\n\n        sink.expecting(\"[10, 15, 20]/[7]\") {\n            ref.value = c\n        }\n        \n        sink.expecting(\"[]/[8]\") {\n            c.insert(8)\n        }\n        \n        sink.expectingNothing {\n            b.apply(.endTransaction)\n        }\n        \n        sink.expecting(\"end\") {\n            ref.apply(.endTransaction)\n        }\n        \n        sink.disconnect()\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SetSortingTests.swift",
    "content": "//\n//  SetSortingTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-05.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nextension ArrayModification {\n    fileprivate func dumped() -> String {\n        switch self {\n        case .insert(let e, at: let i):\n            return \"insert(\\(e), at: \\(i))\"\n        case .remove(let e, at: let i):\n            return \"remove(\\(e), at: \\(i))\"\n        case .replace(let old, at: let i, with: let new):\n            return \"replace(\\(old), at: \\(i), with: \\(new))\"\n        case .replaceSlice(let old, at: let i, with: let new):\n            let o = old.map { \"\\($0)\" }.joined(separator: \", \")\n            let n = new.map { \"\\($0)\" }.joined(separator: \", \")\n            return \"replaceSlice([\\(o)], at: \\(i), with: [\\(n)])\"\n        }\n    }\n}\n\nextension ArrayChange {\n    fileprivate func dumped() -> String {\n        return modifications.lazy.map { $0.dumped() }.joined(separator: \", \")\n    }\n}\n\nprivate class Book: Hashable, CustomStringConvertible {\n    let title: StringVariable\n\n    init(_ title: String) { self.title = .init(title) }\n\n    var hashValue: Int { return ObjectIdentifier(self).hashValue }\n    var description: String { return \"Book(\\(title.value))\" }\n    static func ==(a: Book, b: Book) -> Bool { return a === b }\n}\n\nclass SetSortingTests: XCTestCase {\n    func test_sortedSetUsingIdentityTransform() {\n        let set = SetVariable<Int>([0, 2, 3, 4, 8, 9])\n        let sortedSet = set.sorted()\n\n        XCTAssertEqual(sortedSet.value, [0, 2, 3, 4, 8, 9])\n        XCTAssertEqual(sortedSet.isBuffered, false)\n        XCTAssertEqual(sortedSet.count, 6)\n        XCTAssertEqual(sortedSet[0], 0)\n        XCTAssertEqual(sortedSet[1], 2)\n        XCTAssertEqual(sortedSet[2 ..< 4], ArraySlice([3, 4]))\n\n        var actualChanges: [String] = []\n        var expectedChanges: [String] = []\n        let connection = sortedSet.changes.subscribe { change in\n            actualChanges.append(change.dumped())\n        }\n\n        set.insert(1)\n        XCTAssertEqual(sortedSet.value, [0, 1, 2, 3, 4, 8, 9])\n        expectedChanges.append(\"insert(1, at: 1)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        set.remove(3)\n        XCTAssertEqual(sortedSet.value, [0, 1, 2, 4, 8, 9])\n        expectedChanges.append(\"remove(3, at: 3)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        set.formUnion([3, 5, 6])\n        XCTAssertEqual(sortedSet.value, [0, 1, 2, 3, 4, 5, 6, 8, 9])\n        expectedChanges.append(\"insert(3, at: 3), replaceSlice([], at: 5, with: [5, 6])\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        connection.disconnect()\n    }\n\n    func test_sortedSetInReverse() {\n        let set = SetVariable<Int>([0, 2, 3, 4, 8, 9])\n        let sortedSet = set.sorted(by: >)\n\n        XCTAssertEqual(sortedSet.value, [9, 8, 4, 3, 2, 0])\n\n        var actualChanges: [String] = []\n        var expectedChanges: [String] = []\n        let connection = sortedSet.changes.subscribe { change in\n            actualChanges.append(change.dumped())\n        }\n\n        set.insert(1)\n        XCTAssertEqual(sortedSet.value, [9, 8, 4, 3, 2, 1, 0])\n        expectedChanges.append(\"insert(1, at: 5)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        set.remove(3)\n        XCTAssertEqual(sortedSet.value, [9, 8, 4, 2, 1, 0])\n        expectedChanges.append(\"remove(3, at: 3)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        set.formUnion([3, 5, 6])\n        XCTAssertEqual(sortedSet.value, [9, 8, 6, 5, 4, 3, 2, 1, 0])\n        expectedChanges.append(\"replaceSlice([], at: 2, with: [6, 5]), insert(3, at: 5)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        connection.disconnect()\n    }\n\n\n    func test_sortedSetUsingNoninjectiveTransform() {\n        let set = SetVariable<Int>([0, 2, 3, 4, 8, 9])\n        let sortedSet = set.sortedMap { $0 / 2 }\n\n        XCTAssertEqual(sortedSet.value, [0, 1, 2, 4])\n\n        var actualChanges: [String] = []\n        var expectedChanges: [String] = []\n        let connection = sortedSet.changes.subscribe { change in\n            actualChanges.append(change.dumped())\n        }\n\n        set.remove(2)\n        XCTAssertEqual(sortedSet.value, [0, 1, 2, 4])\n        XCTAssertEqual(actualChanges, expectedChanges) // No change expected (2 and 3 both mapped to 1).\n\n        set.remove(3)\n        XCTAssertEqual(sortedSet.value, [0, 2, 4])\n        expectedChanges.append(\"remove(1, at: 1)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        set.insert(5)\n        XCTAssertEqual(sortedSet.value, [0, 2, 4])\n        XCTAssertEqual(actualChanges, expectedChanges) // No change expected (4 already mapped to 2).\n\n        connection.disconnect()\n    }\n\n    func test_sortedSetUsingObservableTransform() {\n        let b1 = Book(\"foo\")\n        let b2 = Book(\"bar\")\n        let b3 = Book(\"baz\")\n        let b4 = Book(\"fred\")\n        let books = SetVariable<Book>([b1, b2, b3])\n        let sortedTitles = books.sortedMap {$0.title}\n\n        XCTAssertEqual(sortedTitles.isBuffered, false)\n        XCTAssertEqual(sortedTitles.value, [\"bar\", \"baz\", \"foo\"])\n        XCTAssertEqual(sortedTitles.count, 3)\n        XCTAssertEqual(sortedTitles[0], \"bar\")\n        XCTAssertEqual(sortedTitles[1], \"baz\")\n        XCTAssertEqual(sortedTitles[1 ..< 3], ArraySlice([\"baz\", \"foo\"]))\n\n        var actualChanges: [String] = []\n        var expectedChanges: [String] = []\n        let connection = sortedTitles.changes.subscribe { change in\n            actualChanges.append(change.dumped())\n        }\n\n        books.insert(b4)\n        XCTAssertEqual(sortedTitles.value, [\"bar\", \"baz\", \"foo\", \"fred\"])\n        expectedChanges.append(\"insert(fred, at: 3)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n\n        books.subtract([b3, b4])\n        XCTAssertEqual(sortedTitles.value, [\"bar\", \"foo\"])\n        expectedChanges.append(\"remove(baz, at: 1), remove(fred, at: 2)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        b2.title.value = \"barney\"\n        XCTAssertEqual(sortedTitles.value, [\"barney\", \"foo\"])\n        expectedChanges.append(\"replace(bar, at: 0, with: barney)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        b3.title.value = \"bazaar\"\n        XCTAssertEqual(sortedTitles.value, [\"barney\", \"foo\"])\n        XCTAssertEqual(actualChanges, expectedChanges) // No change expected\n\n        books.formUnion([b3, b4])\n        XCTAssertEqual(sortedTitles.value, [\"barney\", \"bazaar\", \"foo\", \"fred\"])\n        expectedChanges.append(\"insert(bazaar, at: 1), insert(fred, at: 3)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        b3.title.value = \"xyzzy\"\n        XCTAssertEqual(sortedTitles.value, [\"barney\", \"foo\", \"fred\", \"xyzzy\"])\n        expectedChanges.append(\"remove(bazaar, at: 1), insert(xyzzy, at: 3)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        b1.title.value = \"xyzzy\"\n        XCTAssertEqual(sortedTitles.value, [\"barney\", \"fred\", \"xyzzy\"])\n        expectedChanges.append(\"remove(foo, at: 1)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        books.remove(b3)\n        XCTAssertEqual(sortedTitles.value, [\"barney\", \"fred\", \"xyzzy\"])\n        XCTAssertEqual(actualChanges, expectedChanges) // No change expected (xyzzy had a multiplicity of 2).\n\n        books.remove(b1)\n        XCTAssertEqual(sortedTitles.value, [\"barney\", \"fred\"])\n        expectedChanges.append(\"remove(xyzzy, at: 2)\")\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        b2.title.value = \"barney\"\n        XCTAssertEqual(sortedTitles.value, [\"barney\", \"fred\"])\n        XCTAssertEqual(actualChanges, expectedChanges)\n\n        connection.disconnect()\n    }\n\n    func test_sortedSetUsingObservableComparator() {\n        let set = SetVariable(0..<5)\n        let comparator = Variable<(Int, Int) -> Bool>(<)\n\n        let sorted = set.sorted(by: comparator)\n        XCTAssertEqual(sorted.value, [0, 1, 2, 3, 4])\n\n        comparator.value = (>)\n\n        XCTAssertEqual(sorted.value, [4, 3, 2, 1, 0])\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SetVariableTests.swift",
    "content": "//\n//  SetVariableTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nprivate class Foo: Hashable, Comparable, CustomStringConvertible {\n    var i: Int\n\n    init(_ i: Int) { self.i = i }\n\n    var hashValue: Int { return i.hashValue }\n    static func ==(a: Foo, b: Foo) -> Bool { return a.i == b.i }\n    static func <(a: Foo, b: Foo) -> Bool { return a.i < b.i }\n    var description: String { return \"\\(i)\" }\n}\n\nclass SetVariableTests: XCTestCase {\n\n    func testInitialization() {\n        let s1 = SetVariable<Int>()\n        XCTAssertEqual(s1.value, [])\n\n        let s2 = SetVariable<Int>([1, 2, 3])\n        XCTAssertEqual(s2.value, [1, 2, 3])\n\n        let s3 = SetVariable<Int>(Set([1, 2, 3]))\n        XCTAssertEqual(s3.value, [1, 2, 3])\n\n        let s4 = SetVariable<Int>(1 ... 10)\n        XCTAssertEqual(s4.value, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])\n\n        let s5 = SetVariable<Int>(elements: 1, 2, 3)\n        XCTAssertEqual(s5.value, [1, 2, 3])\n    }\n\n    func testUpdate() {\n        let f1 = Foo(1)\n        let f2 = Foo(2)\n        let f3 = Foo(3)\n\n        let set: SetVariable<Foo> = [f1, f2, f3]\n        let mock = MockSetObserver<Foo>(set)\n\n        let f2p = Foo(2)\n        let a = mock.expecting([\"begin\", \"[2]/[2]\", \"end\"]) { set.update(with: f2p) }\n        XCTAssertTrue(a === f2)\n        let b = mock.expecting([\"begin\", \"[2]/[2]\", \"end\"]) { set.update(with: Foo(2)) }\n        XCTAssertTrue(b === f2p)\n        let c = mock.expecting([\"begin\", \"[]/[4]\", \"end\"]) { set.update(with: Foo(4)) }\n        XCTAssertNil(c)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SignalTests.swift",
    "content": "//\n//  SignalTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-11-30.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass SignalTests: XCTestCase {\n\n    //MARK: Test add/remove API\n\n    func test_AddRemove_SinkReceivesValuesWhileAdded() {\n        let signal = Signal<Int>()\n        let sink = MockSink<Int>()\n\n        sink.expectingNothing {\n            signal.send(1)\n        }\n\n        signal.add(sink)\n\n        sink.expecting([2, 3, 4]) {\n            signal.send(2)\n            signal.send(3)\n            signal.send(4)\n        }\n\n        signal.remove(sink)\n\n        sink.expectingNothing {\n            signal.send(5)\n        }\n    }\n\n    func test_AddRemove_SignalRetainsAddedSinks() {\n        let signal = Signal<Int>()\n\n        weak var weakSink: MockSink<Int>? = nil\n\n        do {\n            let sink = MockSink<Int>()\n            weakSink = sink\n\n            signal.add(sink)\n        }\n\n        XCTAssertNotNil(weakSink)\n\n        signal.remove(weakSink!)\n\n        XCTAssertNil(weakSink)\n    }\n\n    //MARK: Test subscribe API\n\n    func test_Connect_DisconnectingTheConnection() {\n        let signal = Signal<Int>()\n\n        var received = [Int]()\n\n        let c = signal.subscribe { received.append($0) }\n\n        signal.send(1)\n        c.disconnect()\n        signal.send(2)\n\n        XCTAssertEqual(received, [1])\n        noop(c)\n    }\n\n    func test_Connect_ReleasingConnectionAutomaticallyDisconnects() {\n        let signal = Signal<Int>()\n        var values = [Int]()\n\n        var c: Connection? = signal.subscribe { values.append($0) }\n        signal.send(1)\n        c = nil\n        signal.send(2)\n\n        XCTAssertEqual(values, [1])\n        noop(c)\n    }\n\n    func test_Connect_DuplicateDisconnect() {\n        let signal = Signal<Int>()\n\n        let c = signal.subscribe { i in }\n\n        // It is OK to call disconnect twice.\n        c.disconnect()\n        c.disconnect()\n    }\n\n    func test_Connect_MultipleConnections() {\n        let signal = Signal<Int>()\n\n        signal.send(1)\n\n        var a = [Int]()\n        let c1 = signal.subscribe { i in a.append(i) }\n\n        signal.send(2)\n\n        var b = [Int]()\n        let c2 = signal.subscribe { i in b.append(i) }\n\n        signal.send(3)\n\n        c1.disconnect()\n\n        signal.send(4)\n\n        c2.disconnect()\n\n        signal.send(5)\n\n        XCTAssertEqual(a, [2, 3])\n        XCTAssertEqual(b, [3, 4])\n    }\n\n    func test_Connect_ConnectionRetainsTheSignal() {\n        var values = [Int]()\n        weak var weakSignal: Signal<Int>? = nil\n        weak var weakConnection: Connection? = nil\n        do {\n            let connection: Connection\n            do {\n                let signal = Signal<Int>()\n                weakSignal = signal\n                connection = signal.subscribe { i in values.append(i) }\n                weakConnection = .some(connection)\n\n                signal.send(1)\n            }\n\n            XCTAssertNotNil(weakSignal)\n            XCTAssertNotNil(weakConnection)\n            withExtendedLifetime(connection) {}\n        }\n        XCTAssertNil(weakSignal)\n        XCTAssertNil(weakConnection)\n        XCTAssertEqual(values, [1])\n    }\n\n    func test_Connect_DisconnectingConnectionReleasesResources() {\n        weak var weakSignal: Signal<Int>? = nil\n        weak var weakResource: NSMutableArray? = nil\n\n        let connection: Connection\n        do {\n            let signal = Signal<Int>()\n            weakSignal = signal\n\n            let resource = NSMutableArray()\n            weakResource = resource\n\n            connection = signal.subscribe { i in\n                resource.add(i)\n            }\n            signal.send(1)\n        }\n\n        XCTAssertNotNil(weakSignal)\n        XCTAssertNotNil(weakResource)\n\n        XCTAssertEqual(weakResource, NSArray(object: 1))\n\n        connection.disconnect()\n\n        XCTAssertNil(weakSignal)\n        XCTAssertNil(weakResource) \n    }\n\n    func test_Connect_SourceDoesNotRetainConnection() {\n        var values = [Int]()\n        weak var weakConnection: Connection? = nil\n        let signal = Signal<Int>()\n        do {\n            let connection = signal.subscribe { values.append($0) }\n            weakConnection = connection\n\n            signal.send(1)\n            noop(connection)\n        }\n\n        signal.send(2)\n        XCTAssertNil(weakConnection)\n\n        XCTAssertEqual(values, [1])\n    }\n\n    //MARK: Test sinks adding and removing connections\n\n    func test_Connect_AddingAConnectionInASink() {\n        let signal = Signal<Int>()\n\n        var v1 = [Int]()\n        var c1: Connection? = nil\n\n        var v2 = [Int]()\n        var c2: Connection? = nil\n\n        signal.send(1)\n\n        c1 = signal.subscribe { i in\n            v1.append(i)\n            if c2 == nil {\n                c2 = signal.subscribe { v2.append($0) }\n            }\n        }\n\n        XCTAssertNil(c2)\n\n        signal.send(2)\n\n        XCTAssertNotNil(c2)\n\n        signal.send(3)\n\n        c1?.disconnect()\n        c2?.disconnect()\n\n        signal.send(4)\n\n        XCTAssertEqual(v1, [2, 3])\n        XCTAssertEqual(v2, [3])\n    }\n\n    func test_Connect_RemovingConnectionWhileItIsBeingTriggered() {\n        let signal = Signal<Int>()\n\n        signal.send(1)\n\n        var r = [Int]()\n\n        var c: Connection? = nil\n        c = signal.subscribe { i in\n            r.append(i)\n            c?.disconnect()\n        }\n\n        signal.send(2)\n        signal.send(3)\n        signal.send(4)\n\n        XCTAssertEqual(r, [2])\n    }\n\n    func test_Connect_RemovingNextConnection() {\n        let signal = Signal<Int>()\n\n        var r = [Int]()\n\n        var c1: Connection? = nil\n        var c2: Connection? = nil\n\n        signal.send(0)\n\n        // We don't know which connection fires first.\n        // After disconnect() returns, the connection must not fire any more -- even if disconnect is called by a sink.\n\n        c1 = signal.subscribe { i in\n            r.append(i)\n            c2?.disconnect()\n            c2 = nil\n        }\n\n        c2 = signal.subscribe { i in\n            r.append(i)\n            c1?.disconnect()\n            c1 = nil\n        }\n\n        XCTAssertTrue(c1 != nil && c2 != nil)\n\n        signal.send(1)\n        XCTAssertTrue((c1 == nil) != (c2 == nil))\n\n        signal.send(2)\n        signal.send(3)\n        XCTAssertTrue((c1 == nil) != (c2 == nil))\n\n        XCTAssertEqual(r, [1, 2, 3])\n    }\n\n\n    func test_Connect_RemovingAndReaddingConnectionsAlternately() {\n        // This is a weaker test of the semantics of subscribe/disconnect nested in sinks.\n        let signal = Signal<Int>()\n\n        var r1 = [Int]()\n        var r2 = [Int]()\n\n        var c1: Connection? = nil\n        var c2: Connection? = nil\n\n        var sink1: ((Int) -> Void)!\n        var sink2: ((Int) -> Void)!\n\n        sink1 = { i in\n            r1.append(i)\n            c1?.disconnect()\n            c2 = signal.subscribe(sink2)\n        }\n\n        sink2 = { i in\n            r2.append(i)\n            c2?.disconnect()\n            c1 = signal.subscribe(sink1)\n        }\n\n        c1 = signal.subscribe(sink1)\n        for i in 1...6 {\n            signal.send(i)\n        }\n\n        XCTAssertEqual(r1, [1, 3, 5])\n        XCTAssertEqual(r2, [2, 4, 6])\n    }\n\n    func test_Connect_SinkDisconnectingThenReconnectingItself() {\n        // This is a weaker test of the semantics of subscribe/disconnect nested in sinks.\n        let signal = Signal<Int>()\n\n        var r = [Int]()\n        var c: Connection? = nil\n        var sink: ((Int) -> Void)!\n\n        sink = { i in\n            r.append(i)\n            c?.disconnect()\n            c = signal.subscribe(sink)\n        }\n        c = signal.subscribe(sink)\n        \n        for i in 1...6 {\n            signal.send(i)\n        }\n\n        c?.disconnect()\n\n        XCTAssertEqual(r, [1, 2, 3, 4, 5, 6])\n    }\n\n    //MARK: Test reentrant sends\n\n    func test_Reentrancy_SinksAreNeverNested() {\n        let signal = Signal<Int>()\n\n        var s = \"\"\n\n        let c = signal.subscribe { i in\n            s += \" (\\(i)\"\n            if i > 0 {\n                signal.send(i - 1) // This send is asynchronous. The value is sent at the end of the outermost send.\n            }\n            s += \")\"\n        }\n\n        signal.send(3)\n        c.disconnect()\n\n        XCTAssertEqual(s, \" (3) (2) (1) (0)\")\n    }\n\n    func test_Reentrancy_SinksReceiveAllValuesSentAfterTheyConnectedEvenWhenReentrant() {\n        var s = \"\"\n        let signal = Signal<Int>()\n\n        // Let's do an exponential cascade of decrements with two sinks:\n        var values1 = [Int]()\n        let c1 = signal.subscribe { i in\n            values1.append(i)\n            s += \" (\\(i)\"\n            if i > 0 {\n                signal.send(i - 1)\n            }\n            s += \")\"\n        }\n\n        var values2 = [Int]()\n        let c2 = signal.subscribe { i in\n            values2.append(i)\n            s += \" (\\(i)\"\n            if i > 0 {\n                signal.send(i - 1)\n            }\n            s += \")\"\n        }\n\n        signal.send(2)\n\n        // There should be no nesting and both sinks should receive all sent values, in correct order.\n        XCTAssertEqual(values1, [2, 1, 1, 0, 0, 0, 0])\n        XCTAssertEqual(values2, [2, 1, 1, 0, 0, 0, 0])\n        XCTAssertEqual(s, \" (2) (2) (1) (1) (1) (1) (0) (0) (0) (0) (0) (0) (0) (0)\")\n        \n        c1.disconnect()\n        c2.disconnect()\n    }\n\n    func test_Reentrancy_SinksDoNotReceiveValuesSentToTheSignalBeforeTheyWereConnected() {\n        let signal = Signal<Int>()\n\n        var values1 = [Int]()\n        var values2 = [Int]()\n\n        var c2: Connection? = nil\n        let c1 = signal.subscribe { i in\n            values1.append(i)\n            if i == 3 && c2 == nil {\n                signal.send(0) // This should not reach c2\n                c2 = signal.subscribe { i in\n                    values2.append(i)\n                }\n            }\n        }\n        signal.send(1)\n        signal.send(2)\n        signal.send(3)\n        signal.send(4)\n        signal.send(5)\n\n        XCTAssertEqual(values1, [1, 2, 3, 0, 4, 5])\n        XCTAssertEqual(values2, [4, 5])\n\n        c1.disconnect()\n        c2?.disconnect()\n    }\n\n    //MARK: sendLater / sendNow\n\n    func test_Reentrancy_SendLaterSendsValueLater() {\n        let signal = Signal<Int>()\n\n        var r = [Int]()\n        let c = signal.subscribe { r.append($0) }\n\n        signal.sendLater(0)\n        signal.sendLater(1)\n        signal.sendLater(2)\n\n        XCTAssertEqual(r, [])\n\n        signal.sendNow()\n\n        XCTAssertEqual(r, [0, 1, 2])\n\n        c.disconnect()\n    }\n\n    func test_Reentrancy_SendLaterDoesntSendValueToSinksConnectedLater() {\n        let signal = Signal<Int>()\n\n        signal.sendLater(0)\n        signal.sendLater(1)\n        signal.sendLater(2)\n\n        var r = [Int]()\n        let c = signal.subscribe { r.append($0) }\n\n        signal.sendLater(3)\n        signal.sendLater(4)\n\n        XCTAssertEqual(r, [])\n\n        signal.sendNow()\n\n        XCTAssertEqual(r, [3, 4])\n\n        c.disconnect()\n    }\n\n    func test_Reentrancy_SendLaterDoesntSendValueToSinksConnectedLaterEvenIfThereAreOtherSinks() {\n        let signal = Signal<Int>()\n\n        var r1 = [Int]()\n        let c1 = signal.subscribe { r1.append($0) }\n\n        signal.sendLater(0)\n        signal.sendLater(1)\n        signal.sendLater(2)\n\n        var r2 = [Int]()\n        let c2 = signal.subscribe { r2.append($0) }\n\n        signal.sendLater(3)\n        signal.sendLater(4)\n\n        XCTAssertEqual(r1, [])\n        XCTAssertEqual(r2, [])\n\n        signal.sendNow()\n\n        XCTAssertEqual(r1, [0, 1, 2, 3, 4])\n        XCTAssertEqual(r2, [3, 4])\n\n        c1.disconnect()\n        c2.disconnect()\n    }\n\n\n    func test_Reentrancy_SendLaterUsingCounter() {\n        let counter = Counter()\n\n        var s = \"\"\n        let c = counter.subscribe { value in\n            s += \" (\\(value)\"\n            if value < 5 {\n                counter.increment()\n            }\n            s += \")\"\n        }\n\n        let v = counter.increment()\n        XCTAssertEqual(v, 1)\n        XCTAssertEqual(s, \" (1) (2) (3) (4) (5)\")\n\n        c.disconnect()\n    }\n}\n\nprivate class Counter: SourceType {\n    typealias Value = Int\n\n    private let lock = Lock()\n    private var counter: Int = 0\n    private var signal = Signal<Int>()\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Int {\n        signal.add(sink)\n    }\n\n    @discardableResult\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Int {\n        return signal.remove(sink)\n    }\n\n    @discardableResult\n    func increment() -> Int {\n        let value: Int = lock.withLock {\n            self.counter += 1\n            let v = self.counter\n            signal.sendLater(v)\n            return v\n        }\n        signal.sendNow()\n        return value\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SimpleSourcesTests.swift",
    "content": "//\n//  SimpleSourcesTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-03.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass SimpleSourcesTests: XCTestCase {\n    \n    func testEmptySource() {\n        let source = AnySource<Int>.empty()\n\n        let sink = MockSink<Int>()\n        source.add(sink)\n\n        sink.expectingNothing {\n            // Ah, uhm, not sure what to test here, really\n        }\n\n        source.remove(sink)\n    }\n\n    func testNeverSource() {\n        let source = AnySource<Int>.never()\n\n        let sink = MockSink<Int>()\n        source.add(sink)\n\n        sink.expectingNothing {\n            // Ah, uhm, not sure what to test here, really\n        }\n\n        source.remove(sink)\n    }\n\n\n    func testJustSource() {\n        let source = AnySource<Int>.just(42)\n\n        let sink = MockSink<Int>()\n\n        _ = sink.expecting(42) {\n            source.add(sink)\n        }\n\n        source.remove(sink)\n    }\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/SourceOperatorTests.swift",
    "content": "//\n//  SourceOperatorTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-03.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass SourceOperatorTests: XCTestCase {\n\n    func testSourceOperatorIsCalledOnEachSinkDuringEachSend() {\n        let signal = Signal<Int>()\n\n        var count = 0\n        let source = signal.transform(Double.self) { input, sink in\n            count += 1\n        }\n        XCTAssertEqual(count, 0)\n\n        let c1 = source.subscribe { _ in }\n        let c2 = source.subscribe { _ in }\n        XCTAssertEqual(count, 0)\n\n        signal.send(10)\n        XCTAssertEqual(count, 2)\n\n        signal.send(20)\n        XCTAssertEqual(count, 4)\n\n        signal.send(30)\n        XCTAssertEqual(count, 6)\n\n        c1.disconnect()\n        c2.disconnect()\n\n        signal.send(40)\n        XCTAssertEqual(count, 6)\n    }\n\n    func testSourceOperatorRetainsSource() {\n        var source: AnySource<Int>? = nil\n        weak var weakSignal: Signal<Int>? = nil\n        do {\n            let signal = Signal<Int>()\n            weakSignal = signal\n\n            source = signal.transform(Int.self) { input, sink in\n                // Noop\n                sink(input)\n            }\n        }\n\n        XCTAssertNotNil(weakSignal)\n\n        source = nil\n        XCTAssertNil(weakSignal)\n\n        noop(source)\n    }\n\n    func testSourceDoesntRetainOperator() {\n        weak var weakResource: NSObject? = nil\n        do {\n            let resource = NSObject()\n            weakResource = resource\n            let source = Signal<Int>().transform(Int.self) { input, sink in\n                noop(resource)\n                sink(input)\n            }\n            XCTAssertNotNil(weakResource)\n            noop(source)\n        }\n\n        XCTAssertNil(weakResource)\n    }\n\n    func testMap() {\n        let signal = Signal<Int>()\n\n        let source = signal.map { i in \"\\(i)\" }\n\n        let sink = MockSink<String>()\n        source.add(sink)\n\n        sink.expecting(\"1\") { signal.send(1) }\n        sink.expecting(\"2\") { signal.send(2) }\n        sink.expecting(\"3\") { signal.send(3) }\n\n        source.remove(sink)\n    }\n\n    func testFilter() {\n        let signal = Signal<Int>()\n        let oddSource = signal.filter { $0 % 2 == 1 }\n\n        let sink = MockSink<Int>()\n        oddSource.add(sink)\n\n        sink.expecting([1, 3, 5, 7, 9]) {\n            (1...10).forEach { signal.send($0) }\n        }\n\n        oddSource.remove(sink)\n    }\n\n    func testOptionalFlatMap() {\n        let signal = Signal<Int>()\n        let source = signal.flatMap { i in i % 2 == 0 ? i / 2 : nil }\n\n        let sink = MockSink<Int>()\n        source.add(sink)\n        sink.expecting([1, 2, 3, 4, 5]) {\n            (1...10).forEach { signal.send($0) }\n        }\n        source.remove(sink)\n    }\n\n    func testArrayFlatMap() {\n        let signal = Signal<Int>()\n        let source = signal.flatMap { (i: Int) -> [Int] in\n            if i > 0 {\n                return (1...i).filter { i % $0 == 0 }\n            }\n            else {\n                return []\n            }\n        }\n        // Source sends all divisors of all numbers sent by its input source.\n\n        let sink = MockSink<Int>()\n        source.add(sink)\n\n        sink.expecting(1) { signal.send(1) }\n        sink.expecting([1, 2]) { signal.send(2) }\n        sink.expecting([1, 3]) { signal.send(3) }\n        sink.expecting([1, 2, 4]) { signal.send(4) }\n        sink.expecting([1, 5]) { signal.send(5) }\n        sink.expecting([1, 2, 3, 6]) { signal.send(6) }\n        sink.expecting([1, 7]) { signal.send(7) }\n        sink.expecting([1, 2, 4, 8]) { signal.send(8) }\n        sink.expecting([1, 3, 9]) { signal.send(9) }\n        sink.expecting([1, 2, 5, 10]) { signal.send(10) }\n\n        source.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/TestChange.swift",
    "content": "//\n//  TestChange.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\ninternal struct TestChange: ChangeType, Equatable, CustomStringConvertible {\n    typealias Value = Int\n\n    var values: [Int]\n\n    init(_ values: [Int]) {\n        self.values = values\n    }\n\n    init(from oldValue: Int, to newValue: Int) {\n        values = [oldValue, newValue]\n    }\n\n    var isEmpty: Bool {\n        return values.isEmpty\n    }\n\n    func apply(on value: inout Int) {\n        XCTAssertEqual(value, values.first!)\n        value = values.last!\n    }\n\n    mutating func merge(with next: TestChange) {\n        XCTAssertEqual(self.values.last!, next.values.first!)\n        values += next.values.dropFirst()\n    }\n\n    func reversed() -> TestChange {\n        return TestChange(values.reversed())\n    }\n\n    public var description: String {\n        return values.map { \"\\($0)\" }.joined(separator: \" -> \")\n    }\n\n    static func ==(left: TestChange, right: TestChange) -> Bool {\n        return left.values == right.values\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/TestObservable.swift",
    "content": "//\n//  TestObservable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass TestObservable: ObservableType, TransactionalThing {\n    typealias Change = TestChange\n    typealias Value = Int\n\n    var _signal: TransactionalSignal<TestChange>? = nil\n    var _transactionCount: Int = 0\n    var _value: Value\n\n    init(_ value: Value) {\n        self._value = value\n    }\n\n    var value: Value {\n        get { return _value }\n        set {\n            let old = _value\n            beginTransaction()\n            _value = newValue\n            sendChange(.init(from: old, to: _value))\n            endTransaction()\n        }\n    }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n}\n\nclass TestObservableValue<Value>: ObservableValueType, TransactionalThing {\n    typealias Change = ValueChange<Value>\n\n    var _signal: TransactionalSignal<ValueChange<Value>>? = nil\n    var _transactionCount: Int = 0\n    var _value: Value\n\n    init(_ value: Value) {\n        self._value = value\n    }\n\n    var value: Value {\n        get { return _value }\n        set {\n            let old = _value\n            beginTransaction()\n            _value = newValue\n            sendChange(.init(from: old, to: _value))\n            endTransaction()\n        }\n    }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/TestUpdatable.swift",
    "content": "//\n//  TestUpdatable.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass TestUpdatable: UpdatableType, TransactionalThing {\n    typealias Change = TestChange\n    typealias Value = Int\n\n    var _signal: TransactionalSignal<TestChange>? = nil\n    var _transactionCount: Int = 0\n    var _value: Value\n\n    init(_ value: Value) {\n        self._value = value\n    }\n\n    var value: Value {\n        get { return _value }\n        set {\n            let old = _value\n            beginTransaction()\n            _value = newValue\n            sendChange(.init(from: old, to: _value))\n            endTransaction()\n        }\n    }\n\n    func apply(_ update: Update<TestChange>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            change.apply(on: &_value)\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n}\n\nclass TestUpdatableValue<Value>: UpdatableValueType, TransactionalThing {\n    typealias Change = ValueChange<Value>\n\n    var _signal: TransactionalSignal<ValueChange<Value>>? = nil\n    var _transactionCount: Int = 0\n    var _value: Value\n\n    init(_ value: Value) {\n        self._value = value\n    }\n\n    var value: Value {\n        get { return _value }\n        set {\n            let old = _value\n            beginTransaction()\n            _value = newValue\n            sendChange(.init(from: old, to: _value))\n            endTransaction()\n        }\n    }\n\n    func apply(_ update: Update<Change>) {\n        switch update {\n        case .beginTransaction:\n            beginTransaction()\n        case .change(let change):\n            change.apply(on: &_value)\n            sendChange(change)\n        case .endTransaction:\n            endTransaction()\n        }\n    }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/TestUtilities.swift",
    "content": "//\n//  TestUtilities.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-03.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport Foundation\n@testable import GlueKit\n\n@inline(never)\nfunc noop<Value>(_ value: Value) {\n}\n\nfunc XCTAssertEqual<E: Equatable>(_ a: @autoclosure () -> [[E]], _ b: @autoclosure () -> [[E]], message: String? = nil, file: StaticString = #file, line: UInt = #line) {\n    let av = a()\n    let bv = b()\n    if !av.elementsEqual(bv, by: ==) {\n        XCTFail(message ?? \"\\(av) is not equal to \\(bv)\", file: file, line: line)\n    }\n}\n\n"
  },
  {
    "path": "Tests/GlueKitTests/TimerSourceTests.swift",
    "content": "//\n//  TimerSourceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-03.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass TimerSourceTests: XCTestCase {\n\n    func testNeverFiringTimer() {\n        let queue = DispatchQueue(label: \"testqueue\", attributes: [])\n\n        var timerTimes = [Date]()\n        let timerSemaphore = DispatchSemaphore(value: 0)\n\n        let source = TimerSource(queue: queue) {\n            timerTimes.append(Date())\n            timerSemaphore.signal()\n            return nil\n        }\n\n        XCTAssertEqual(timerTimes, [])\n\n        var sinkTimes = [Date]()\n        let sinkSemaphore = DispatchSemaphore(value: 0)\n        let connection = source.subscribe {\n            sinkTimes.append(Date())\n            sinkSemaphore.signal()\n        }\n\n        XCTAssertEqual(timerSemaphore.wait(timeout: DispatchTime.now() + 3.0), .success, \"Timer source should call timer closure when it is first connected\")\n\n        XCTAssertEqual(timerTimes.count, 1)\n        XCTAssertEqual(sinkTimes, [])\n\n        connection.disconnect()\n    }\n\n    func testRefreshingTimerSource() {\n        let queue = DispatchQueue(label: \"testqueue\", attributes: [])\n\n        var signal = false\n        var timerTimes = [Date]()\n        let timerSemaphore = DispatchSemaphore(value: 0)\n\n        var triggerDate: Date? = nil\n\n        let source = TimerSource(queue: queue) {\n            timerTimes.append(Date())\n            if let date = triggerDate {\n                triggerDate = nil\n                return date\n            }\n            else {\n                if signal {\n                    timerSemaphore.signal()\n                }\n                return nil\n            }\n        }\n\n        XCTAssertEqual(timerTimes, [])\n\n        var sinkTimes = [Date]()\n        let connection = source.subscribe {\n            sinkTimes.append(Date())\n        }\n        // Timer should have returned nil -> No firing yet\n\n        XCTAssertEqual(sinkTimes, [])\n\n        queue.sync {\n            signal = true\n            triggerDate = Date(timeIntervalSinceNow: 0.1)\n            source.start()\n        }\n\n        // Timer should return non-nil, clear triggerDate  and signal the semaphore.\n\n        XCTAssertEqual(.success, timerSemaphore.wait(timeout: DispatchTime.now() + 3.0))\n\n        XCTAssertEqual(timerTimes.count, 3) // 1: subscribe, 2: start, 3: after first firing\n        XCTAssertEqual(sinkTimes.count, 1) // Should fire only once\n\n        connection.disconnect()\n    }\n\n    func testSimplePeriodicSignal() {\n        let queue = DispatchQueue(label: \"testqueue\", attributes: [])\n        let start = Date().addingTimeInterval(0.2)\n        let interval: TimeInterval = 0.2\n\n        let source = TimerSource(queue: queue, start: start, interval: interval)\n\n        var ticks = [TimeInterval]()\n        var count = 0\n        let sem = DispatchSemaphore(value: 0)\n        let connection = source.subscribe { i in\n            let elapsed = Date().timeIntervalSince(start)\n            ticks.append(elapsed)\n            NSLog(\"tick \\(count) at \\(elapsed)\")\n            count += 1\n            if count >= 3 {\n                sem.signal()\n            }\n        }\n\n        XCTAssertEqual(.success, sem.wait(timeout: DispatchTime.now() + 3.0))\n        connection.disconnect()\n\n        let diffs: [TimeInterval] = ticks.enumerated().map { tick, elapsed in\n            let ideal = TimeInterval(tick) * interval\n            return elapsed - ideal\n        }\n        XCTAssertEqual(diffs.filter { $0 < 0 }, [])\n    }\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/TransactionStateTests.swift",
    "content": "//\n//  TransactionalTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nprivate class TransactionalTestObservable: ObservableValueType, TransactionalThing {\n    typealias Value = Int\n    typealias Change = ValueChange<Int>\n\n    var _signal: TransactionalSignal<ValueChange<Int>>? = nil\n    var _transactionCount: Int = 0\n\n    var _value: Value = 0\n\n    var value: Value {\n        get { return _value }\n        set {\n            beginTransaction()\n            let old = _value\n            _value = newValue\n            sendChange(.init(from: old, to: _value))\n            endTransaction()\n        }\n    }\n\n    func add<Sink: SinkType>(_ sink: Sink) where Sink.Value == Update<Change> {\n        signal.add(sink)\n    }\n\n    func remove<Sink: SinkType>(_ sink: Sink) -> Sink where Sink.Value == Update<Change> {\n        return signal.remove(sink)\n    }\n\n    var activated = 0\n    var deactivated = 0\n\n    func activate() {\n        activated += 1\n    }\n\n    func deactivate() {\n        deactivated += 1\n    }\n}\n\nclass TransactionalTests: XCTestCase {\n    func testUpdatesSourceRemainsTheSame1() {\n        let observable = TransactionalTestObservable()\n        let sink1 = MockValueUpdateSink<Int>()\n        let updates1 = observable.updates\n        updates1.add(sink1)\n\n        let sink2 = MockValueUpdateSink<Int>()\n        let updates2 = observable.updates\n        updates2.add(sink2)\n\n        // We can't compare the sources, but we can check that triggering\n        // a change is reported from both of them.\n\n        sink1.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            sink2.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n                observable.value = 1\n            }\n        }\n\n        updates1.remove(sink1)\n        updates2.remove(sink2)\n    }\n\n    func testUpdatesSourceRemainsTheSame2() {\n        let observable = TransactionalTestObservable()\n        let sink1 = MockValueUpdateSink<Int>()\n\n        observable.updates.add(sink1)\n\n        let sink2 = MockValueUpdateSink<Int>()\n        observable.updates.add(sink2)\n\n        // We can't compare the sources, but we can check that triggering\n        // a change is reported from both of them.\n\n        sink1.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            sink2.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n                observable.value = 1\n            }\n        }\n        observable.updates.remove(sink1)\n        observable.updates.remove(sink2)\n    }\n\n    func testSendIfConnected() {\n        let observable = TransactionalTestObservable()\n\n        // The autoclosure argument should not be called if the observable isn't connected.\n        observable.beginTransaction()\n        observable.sendIfConnected({ XCTFail(); return ValueChange(from: 0, to: 1) }())\n        observable.endTransaction()\n\n        let sink = MockValueUpdateSink<Int>()\n        observable.updates.add(sink)\n\n        sink.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            observable.beginTransaction()\n            observable.sendIfConnected(ValueChange(from: 0, to: 1))\n            observable.endTransaction()\n        }\n\n        observable.updates.remove(sink)\n    }\n\n    func testSendLater() {\n        let observable = TransactionalTestObservable()\n        let sink = MockValueUpdateSink<Int>()\n\n        observable.updates.add(sink)\n\n        sink.expecting(\"begin\") {\n            observable.beginTransaction()\n        }\n\n        observable.signal.sendLater(.change(ValueChange(from: 0, to: 1)))\n\n        sink.expecting(\"0 -> 1\") {\n            observable.signal.sendNow()\n        }\n\n        sink.expecting(\"end\") {\n            observable.endTransaction()\n        }\n\n        observable.updates.remove(sink)\n    }\n\n    func testSendUpdate() {\n        let observable = TransactionalTestObservable()\n        let sink = MockValueUpdateSink<Int>()\n\n        observable.updates.add(sink)\n\n        sink.expecting(\"begin\") {\n            observable.send(.beginTransaction)\n        }\n\n        sink.expecting(\"0 -> 1\") {\n            observable.send(.change(ValueChange(from: 0, to: 1)))\n        }\n\n        sink.expecting(\"end\") {\n            observable.send(.endTransaction)\n        }\n\n        observable.updates.remove(sink)\n    }\n\n    func testSubscribingToOpenTransaction() {\n        let observable = TransactionalTestObservable()\n        let sink = MockValueUpdateSink<Int>()\n\n        observable.beginTransaction()\n\n        sink.expecting(\"begin\") {\n            observable.updates.add(sink)\n        }\n\n        sink.expecting(\"end\") {\n            observable.endTransaction()\n        }\n\n        _ = observable.updates.remove(sink)\n    }\n\n    func testUnsubscribingFromOpenTransaction() {\n        let observable = TransactionalTestObservable()\n        let sink = MockValueUpdateSink<Int>()\n\n        observable.updates.add(sink)\n\n        sink.expecting(\"begin\") {\n            observable.beginTransaction()\n        }\n        sink.expecting(\"end\") {\n            _ = observable.updates.remove(sink)\n        }\n\n        observable.endTransaction()\n    }\n\n    func testPropertiesWithNestedTransactions() {\n        let observable = TransactionalTestObservable()\n\n        XCTAssertEqual(observable.isInTransaction, false)\n        XCTAssertEqual(observable.isConnected, false)\n        XCTAssertEqual(observable.isActive, false)\n\n        // Start an outer transaction.\n        observable.beginTransaction()\n\n        XCTAssertEqual(observable.isInTransaction, true)\n        XCTAssertEqual(observable.isConnected, false)\n        XCTAssertEqual(observable.isActive, true)\n\n        // Start a nested transaction.\n        observable.beginTransaction()\n\n        XCTAssertEqual(observable.isInTransaction, true)\n        XCTAssertEqual(observable.isConnected, false)\n        XCTAssertEqual(observable.isActive, true)\n\n        observable.endTransaction()\n\n        XCTAssertEqual(observable.isInTransaction, true)\n        XCTAssertEqual(observable.isConnected, false)\n        XCTAssertEqual(observable.isActive, true)\n\n        observable.endTransaction()\n\n        XCTAssertEqual(observable.isInTransaction, false)\n        XCTAssertEqual(observable.isConnected, false)\n        XCTAssertEqual(observable.isActive, false)\n\n        let sink = MockValueUpdateSink<Int>()\n        observable.updates.add(sink)\n\n        XCTAssertEqual(observable.isInTransaction, false)\n        XCTAssertEqual(observable.isConnected, true)\n        XCTAssertEqual(observable.isActive, true)\n\n        sink.expecting(\"begin\") {\n            observable.beginTransaction()\n        }\n\n        XCTAssertEqual(observable.isInTransaction, true)\n        XCTAssertEqual(observable.isConnected, true)\n        XCTAssertEqual(observable.isActive, true)\n\n        sink.expecting(\"end\") {\n            observable.endTransaction()\n        }\n\n        XCTAssertEqual(observable.isInTransaction, false)\n        XCTAssertEqual(observable.isConnected, true)\n        XCTAssertEqual(observable.isActive, true)\n\n        observable.updates.remove(sink)\n\n        XCTAssertEqual(observable.isInTransaction, false)\n        XCTAssertEqual(observable.isConnected, false)\n        XCTAssertEqual(observable.isActive, false)\n    }\n\n    func testActivation() {\n        let observable = TransactionalTestObservable()\n        let sink = MockValueUpdateSink<Int>()\n\n        XCTAssertEqual(observable.activated, 0)\n        observable.updates.add(sink)\n        XCTAssertEqual(observable.activated, 1)\n\n        XCTAssertEqual(observable.deactivated, 0)\n        observable.updates.remove(sink)\n        XCTAssertEqual(observable.deactivated, 1)\n    }\n}\n\nclass TestTransactionalSource: TransactionalSource<ValueChange<Int>> {\n    var activated = 0\n    var deactivated = 0\n\n    override func activate() {\n        super.activate()\n        activated += 1\n    }\n\n    override func deactivate() {\n        super.deactivate()\n        deactivated += 1\n    }\n}\n\nclass TransactionSourceTests: XCTestCase {\n    func test() {\n        let source = TestTransactionalSource()\n\n        XCTAssertEqual(source.activated, 0)\n        XCTAssertEqual(source.deactivated, 0)\n\n        let sink = MockValueUpdateSink<Int>()\n        source.add(sink)\n\n        XCTAssertEqual(source.activated, 1)\n        XCTAssertEqual(source.deactivated, 0)\n\n        source.remove(sink)\n\n        XCTAssertEqual(source.activated, 1)\n        XCTAssertEqual(source.deactivated, 1)\n    }\n}\n\n"
  },
  {
    "path": "Tests/GlueKitTests/TwoWayBindingTests.swift",
    "content": "//\n//  UpdatableTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-07.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass UpdatableTests: XCTestCase {\n\n    func test_bind_OneWayBinding() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(100)\n\n        let c = master.subscribe(to: slave)\n\n        XCTAssertEqual(slave.value, 0)\n\n        master.value = 1\n\n        XCTAssertEqual(master.value, 1)\n        XCTAssertEqual(slave.value, 1)\n\n        slave.value = 200\n\n        XCTAssertEqual(master.value, 1, \"Connection should not be a two-way binding\")\n        XCTAssertEqual(slave.value, 200)\n\n        master.value = 2\n\n        XCTAssertEqual(master.value, 2)\n        XCTAssertEqual(slave.value, 2)\n\n        c.disconnect()\n\n        master.value = 3\n\n        XCTAssertEqual(master.value, 3)\n        XCTAssertEqual(slave.value, 2)\n    }\n\n    func test_bind_TwoWayBinding() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(1)\n\n        let c = master.bind(to: slave)\n\n        XCTAssertEqual(master.value, 0) // Slave should get the value of master\n        XCTAssertEqual(slave.value, 0)\n\n        master.value = 1\n\n        XCTAssertEqual(master.value, 1)\n        XCTAssertEqual(slave.value, 1)\n\n        slave.value = 2\n\n        XCTAssertEqual(master.value, 2)\n        XCTAssertEqual(slave.value, 2)\n\n        c.disconnect() // The variables should now be independent again.\n\n        master.value = 3\n\n        XCTAssertEqual(master.value, 3)\n        XCTAssertEqual(slave.value, 2)\n        \n        slave.value = 4\n        \n        XCTAssertEqual(master.value, 3)\n        XCTAssertEqual(slave.value, 4)\n    }\n\n    func test_Connector_bind() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(1)\n\n        let connector = Connector()\n        connector.bind(master, to: slave)\n\n        XCTAssertEqual(master.value, 0) // Slave should get the value of master\n        XCTAssertEqual(slave.value, 0)\n\n        master.value = 1\n\n        XCTAssertEqual(master.value, 1)\n        XCTAssertEqual(slave.value, 1)\n\n        slave.value = 2\n\n        XCTAssertEqual(master.value, 2)\n        XCTAssertEqual(slave.value, 2)\n\n        connector.disconnect() // The variables should now be independent again.\n\n        master.value = 3\n\n        XCTAssertEqual(master.value, 3)\n        XCTAssertEqual(slave.value, 2)\n\n        slave.value = 4\n\n        XCTAssertEqual(master.value, 3)\n        XCTAssertEqual(slave.value, 4)\n    }\n\n    func test_updates_masterTransaction() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(1)\n\n        let msink = MockValueUpdateSink<Int>(master)\n        let ssink = MockValueUpdateSink<Int>(slave)\n\n        let c = msink.expecting([\"begin\", \"end\"]) {\n            ssink.expecting([\"begin\", \"1 -> 0\", \"end\"]) {\n                return master.bind(to: slave)\n            }\n        }\n\n        msink.expecting(\"begin\") {\n            ssink.expecting(\"begin\") {\n                master.apply(.beginTransaction)\n            }\n        }\n\n        msink.expecting(\"0 -> 2\") {\n            ssink.expecting(\"0 -> 2\") {\n                master.value = 2\n            }\n        }\n\n        msink.expecting(\"end\") {\n            ssink.expecting(\"end\") {\n                master.apply(.endTransaction)\n            }\n        }\n\n        msink.expectingNothing {\n            ssink.expectingNothing {\n                c.disconnect()\n            }\n        }\n\n        ssink.disconnect()\n        msink.disconnect()\n    }\n\n    func test_updates_slaveTransaction() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(1)\n\n        let msink = MockValueUpdateSink<Int>(master)\n        let ssink = MockValueUpdateSink<Int>(slave)\n\n        let c = msink.expecting([\"begin\", \"end\"]) {\n            ssink.expecting([\"begin\", \"1 -> 0\", \"end\"]) {\n                return master.bind(to: slave)\n            }\n        }\n\n        msink.expecting(\"begin\") {\n            ssink.expecting(\"begin\") {\n                slave.apply(.beginTransaction)\n            }\n        }\n\n        msink.expecting(\"0 -> 2\") {\n            ssink.expecting(\"0 -> 2\") {\n                slave.value = 2\n            }\n        }\n\n        msink.expecting(\"end\") {\n            ssink.expecting(\"end\") {\n                slave.apply(.endTransaction)\n            }\n        }\n\n        msink.expectingNothing {\n            ssink.expectingNothing {\n                c.disconnect()\n            }\n        }\n        \n        ssink.disconnect()\n        msink.disconnect()\n    }\n\n    #if false // Binding/unbinding during transactions is currently unsupported.\n    func test_updates_bindingDuringMasterTransaction() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(1)\n\n        let sink = MockValueUpdateSink<Int>(slave)\n\n        master.apply(.beginTransaction)\n\n        let c = sink.expecting([\"begin\", \"1 -> 0\"]) {\n            return master.bind(to: slave)\n        }\n\n        sink.expecting(\"0 -> 2\") {\n            master.value = 2\n        }\n\n        sink.expecting(\"end\") {\n            master.apply(.endTransaction)\n        }\n\n        sink.expectingNothing {\n            c.disconnect()\n        }\n        \n        sink.disconnect()\n    }\n\n    func test_updates_bindingDuringSinkTransaction() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(1)\n\n        let sink = MockValueUpdateSink<Int>(slave)\n\n        sink.expecting(\"begin\") {\n            slave.apply(.beginTransaction)\n        }\n\n        let c = sink.expecting([\"1 -> 0\"]) {\n            return master.bind(to: slave)\n        }\n\n        sink.expecting(\"0 -> 2\") {\n            master.value = 2\n        }\n\n        sink.expectingNothing {\n            master.apply(.endTransaction)\n        }\n\n        sink.expectingNothing {\n            c.disconnect()\n        }\n\n        sink.expecting(\"end\") {\n            slave.apply(.endTransaction)\n        }\n        \n        sink.disconnect()\n    }\n\n    func test_updates_unbindingDuringMasterTransaction() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(1)\n\n        let sink = MockValueUpdateSink<Int>(slave)\n\n        let c = sink.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            return master.bind(to: slave)\n        }\n\n        sink.expecting(\"begin\") {\n            master.apply(.beginTransaction)\n        }\n\n        sink.expecting(\"1 -> 2\") {\n            master.value = 2\n        }\n\n        sink.expecting(\"end\") {\n            c.disconnect()\n        }\n\n        sink.expectingNothing {\n            master.apply(.endTransaction)\n        }\n        \n        sink.disconnect()\n    }\n\n    func test_updates_unbindingDuringSinkTransaction() {\n        let master = Variable<Int>(0)\n        let slave = Variable<Int>(1)\n\n        let sink = MockValueUpdateSink<Int>(slave)\n\n        let c = sink.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            return master.bind(to: slave)\n        }\n\n        sink.expecting(\"begin\") {\n            slave.apply(.beginTransaction)\n        }\n\n        sink.expecting(\"1 -> 2\") {\n            master.value = 2\n        }\n\n        sink.expectingNothing {\n            c.disconnect()\n        }\n\n        sink.expectingNothing {\n            master.apply(.endTransaction)\n        }\n\n        sink.expecting(\"end\") {\n            slave.apply(.endTransaction)\n        }\n        \n        sink.disconnect()\n    }\n    #endif\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/TypeHelperTests.swift",
    "content": "//\n//  TypeHelperTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-10.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nprivate class KVOTest: NSObject {\n    @objc dynamic var string: String = \"\"\n    @objc dynamic var bool: Bool = false\n    @objc dynamic var int: Int = 0\n    @objc dynamic var float: Float = 0\n    @objc dynamic var double: Double = 0\n    @objc dynamic var cgFloat: CGFloat = 0\n    @objc dynamic var point: CGPoint = .init(x: 0, y: 0)\n    @objc dynamic var size: CGSize = .init(width: 0, height: 0)\n    @objc dynamic var rect: CGRect = .init(x: 0, y: 0, width: 0, height: 0)\n    @objc dynamic var transform: CGAffineTransform = .identity\n}\n\nclass TypeHelperTests: XCTestCase {\n\n    private func check<V: Equatable>(\n        type: V.Type = V.self,\n        key: String,\n        sourceTx: (AnySource<Any?>) -> AnySource<V>,\n        observableTx: (AnyObservableValue<Any?>) -> AnyObservableValue<V>,\n        updatableTx: (AnyUpdatableValue<Any?>) -> AnyUpdatableValue<V>,\n        getter: (KVOTest) -> V,\n        setter: (KVOTest, V) -> (),\n        value0: V,\n        value1: V,\n        value2: V)\n    {\n        let t = KVOTest()\n        setter(t, value0)\n\n        let source = sourceTx(t.glue.observable(forKeyPath: key).futureValues)\n        let observable = observableTx(t.glue.observable(forKeyPath: key))\n        let updatable = updatableTx(t.glue.updatable(forKey: key))\n\n        XCTAssertEqual(observable.value, value0)\n        XCTAssertEqual(updatable.value, value0)\n\n        let smock = MockSink(source)\n        let omock = MockValueUpdateSink(observable)\n        let umock = MockValueUpdateSink(updatable)\n\n        smock.expecting(value1) {\n            omock.expecting([\"begin\", \"\\(value0) -> \\(value1)\", \"end\"]) {\n                umock.expecting([\"begin\", \"\\(value0) -> \\(value1)\", \"end\"]) {\n                    setter(t, value1)\n                }\n            }\n        }\n        XCTAssertEqual(observable.value, value1)\n        XCTAssertEqual(updatable.value, value1)\n\n        smock.expecting(value2) {\n            omock.expecting([\"begin\", \"\\(value1) -> \\(value2)\", \"end\"]) {\n                umock.expecting([\"begin\", \"\\(value1) -> \\(value2)\", \"end\"]) {\n                    updatable.value = value2\n                }\n            }\n        }\n        XCTAssertEqual(observable.value, value2)\n        XCTAssertEqual(updatable.value, value2)\n        XCTAssertEqual(getter(t), value2)\n    }\n\n    func testForceCasting() {\n        check(key: \"string\",\n              sourceTx: { $0.forceCasted(to: NSString.self) },\n              observableTx: { $0.forceCasted(to: NSString.self) },\n              updatableTx: { $0.forceCasted(to: NSString.self) },\n              getter: { $0.string as NSString },\n              setter: { $0.string = $1 as String },\n              value0: \"foo\",\n              value1: \"bar\",\n              value2: \"baz\")\n        check(key: \"int\",\n              sourceTx: { $0.forceCasted(to: NSNumber.self) },\n              observableTx: { $0.forceCasted(to: NSNumber.self) },\n              updatableTx: { $0.forceCasted(to: NSNumber.self) },\n              getter: { NSNumber(value: $0.int) },\n              setter: { $0.int = $1.intValue },\n              value0: NSNumber(value: 2),\n              value1: NSNumber(value: 3),\n              value2: NSNumber(value: 4))\n    }\n\n    func testString() {\n        check(key: \"string\", sourceTx: { $0.asString }, observableTx: { $0.asString }, updatableTx: { $0.asString },\n              getter: { $0.string },\n              setter: { $0.string = $1 },\n              value0: \"foo\",\n              value1: \"bar\",\n              value2: \"baz\")\n    }\n\n    func testBool() {\n        check(key: \"bool\", sourceTx: { $0.asBool }, observableTx: { $0.asBool }, updatableTx: { $0.asBool },\n              getter: { $0.bool },\n              setter: { $0.bool = $1 },\n              value0: false,\n              value1: true,\n              value2: false)\n    }\n\n    func testInt() {\n        check(key: \"int\", sourceTx: { $0.asInt }, observableTx: { $0.asInt }, updatableTx: { $0.asInt },\n              getter: { $0.int },\n              setter: { $0.int = $1 },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n    }\n\n    func testFloat() {\n        check(key: \"float\", sourceTx: { $0.asFloat }, observableTx: { $0.asFloat }, updatableTx: { $0.asFloat },\n              getter: { $0.float },\n              setter: { $0.float = $1 },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n        check(key: \"int\", sourceTx: { $0.asFloat }, observableTx: { $0.asFloat }, updatableTx: { $0.asFloat },\n              getter: { Float($0.int) },\n              setter: { $0.int = Int($1) },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n        check(key: \"double\", sourceTx: { $0.asFloat }, observableTx: { $0.asFloat }, updatableTx: { $0.asFloat },\n              getter: { Float($0.double) },\n              setter: { $0.double = Double($1) },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n    }\n\n    func testDouble() {\n        check(key: \"double\", sourceTx: { $0.asDouble }, observableTx: { $0.asDouble }, updatableTx: { $0.asDouble },\n              getter: { $0.double },\n              setter: { $0.double = $1 },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n        check(key: \"float\", sourceTx: { $0.asDouble }, observableTx: { $0.asDouble }, updatableTx: { $0.asDouble },\n              getter: { Double($0.float) },\n              setter: { $0.float = Float($1) },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n        check(key: \"int\", sourceTx: { $0.asDouble }, observableTx: { $0.asDouble }, updatableTx: { $0.asDouble },\n              getter: { Double($0.int) },\n              setter: { $0.int = Int($1) },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n    }\n\n    func testCGFloat() {\n        check(key: \"cgFloat\", sourceTx: { $0.asCGFloat }, observableTx: { $0.asCGFloat }, updatableTx: { $0.asCGFloat },\n              getter: { $0.cgFloat },\n              setter: { $0.cgFloat = $1 },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n        check(key: \"int\", sourceTx: { $0.asCGFloat }, observableTx: { $0.asCGFloat }, updatableTx: { $0.asCGFloat },\n              getter: { CGFloat($0.int) },\n              setter: { $0.int = Int($1) },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n        check(key: \"float\", sourceTx: { $0.asCGFloat }, observableTx: { $0.asCGFloat }, updatableTx: { $0.asCGFloat },\n              getter: { CGFloat($0.float) },\n              setter: { $0.float = Float($1) },\n              value0: 1,\n              value1: 2,\n              value2: 3)\n    }\n\n    func testCGPoint() {\n        check(key: \"point\", sourceTx: { $0.asCGPoint }, observableTx: { $0.asCGPoint }, updatableTx: { $0.asCGPoint },\n              getter: { $0.point },\n              setter: { $0.point = $1 },\n              value0: CGPoint(x: 1, y: 2),\n              value1: CGPoint(x: 3, y: 4),\n              value2: CGPoint(x: 5, y: 6))\n    }\n\n    func testCGSize() {\n        check(key: \"size\", sourceTx: { $0.asCGSize }, observableTx: { $0.asCGSize }, updatableTx: { $0.asCGSize },\n              getter: { $0.size },\n              setter: { $0.size = $1 },\n              value0: CGSize(width: 1, height: 2),\n              value1: CGSize(width: 3, height: 4),\n              value2: CGSize(width: 5, height: 6))\n    }\n\n    func testCGRect() {\n        check(key: \"rect\", sourceTx: { $0.asCGRect }, observableTx: { $0.asCGRect }, updatableTx: { $0.asCGRect },\n              getter: { $0.rect },\n              setter: { $0.rect = $1 },\n              value0: CGRect(x: 1, y: 2, width: 3, height: 4),\n              value1: CGRect(x: 5, y: 6, width: 7, height: 8),\n              value2: CGRect(x: 9, y: 10, width: 11, height: 12))\n    }\n\n    func testCGAffineTransform() {\n        check(key: \"transform\",\n              sourceTx: { $0.asCGAffineTransform },\n              observableTx: { $0.asCGAffineTransform },\n              updatableTx: { $0.asCGAffineTransform },\n              getter: { $0.transform },\n              setter: { $0.transform = $1 },\n              value0: CGAffineTransform(rotationAngle: CGFloat.pi / 4),\n              value1: CGAffineTransform(scaleX: 0.4, y: 0.6),\n              value2: CGAffineTransform(translationX: 100, y: 200))\n    }\n\n\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/UpdatableValueTests.swift",
    "content": "//\n//  UpdatableValueTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-27.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass UpdatableValueTests: XCTestCase {\n    func test_anyUpdatable_fromUpdatableValue() {\n        let test = TestUpdatableValue<Int>(0)\n\n        let any = test.anyUpdatableValue\n\n        XCTAssertEqual(any.value, 0)\n\n        let updateSink = MockValueUpdateSink<Int>(any.updates)\n\n        let changeSink = TransformedMockSink<ValueChange<Int>, String>({ \"\\($0.old) -> \\($0.new)\" })\n        changeSink.subscribe(to: any.changes)\n\n        let valuesSink = MockSink<Int>()\n        valuesSink.expecting(0) {\n            valuesSink.subscribe(to: any.values)\n        }\n\n        let futureValuesSink = MockSink<Int>(any.futureValues)\n\n        updateSink.expecting(\"begin\") {\n            test.beginTransaction()\n        }\n        updateSink.expecting(\"0 -> 1\") {\n            test.value = 1\n        }\n\n        updateSink.expecting(\"end\") {\n            changeSink.expecting(\"0 -> 1\") {\n                valuesSink.expecting(1) {\n                    futureValuesSink.expecting(1) {\n                        test.endTransaction()\n                    }\n                }\n            }\n        }\n\n        updateSink.expecting([\"begin\", \"1 -> 2\", \"end\"]) {\n            changeSink.expecting(\"1 -> 2\") {\n                valuesSink.expecting(2) {\n                    futureValuesSink.expecting(2) {\n                        any.value = 2\n                    }\n                }\n            }\n        }\n\n        updateSink.expecting([\"begin\", \"end\"]) {\n            any.withTransaction {}\n        }\n\n        updateSink.expecting([\"begin\", \"2 -> 3\", \"3 -> 4\", \"end\"]) {\n            changeSink.expecting(\"2 -> 4\") {\n                valuesSink.expecting(4) {\n                    futureValuesSink.expecting(4) {\n                        any.withTransaction {\n                            any.value = 3\n                            any.value = 4\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    func test_anyUpdatable_fromClosures() {\n        var value = 0\n        let signal = Signal<ValueUpdate<Int>>()\n        var transactions = 0\n        let begin = {\n            transactions += 1\n            if transactions == 1 {\n                signal.send(.beginTransaction)\n            }\n        }\n        let end = {\n            transactions -= 1\n            if transactions == 0 {\n                signal.send(.endTransaction)\n            }\n        }\n\n        let test = AnyUpdatableValue(\n            getter: { value },\n            apply: { (update: ValueUpdate<Int>) -> Void in\n                switch update {\n                case .beginTransaction: begin()\n                case .change(let change):\n                    value = change.new\n                    signal.send(update)\n                case .endTransaction: end()\n                }\n            },\n            updates: signal.anySource)\n\n        let any = test.anyUpdatableValue\n\n        XCTAssertEqual(any.value, 0)\n\n        let updateSink = MockValueUpdateSink<Int>(any.updates)\n\n        let changeSink = TransformedMockSink<ValueChange<Int>, String>({ \"\\($0.old) -> \\($0.new)\" })\n        changeSink.subscribe(to: any.changes)\n\n        let valuesSink = MockSink<Int>()\n        valuesSink.expecting(0) {\n            valuesSink.subscribe(to: any.values)\n        }\n\n        let futureValuesSink = MockSink<Int>(any.futureValues)\n\n        updateSink.expecting(\"begin\") {\n            begin()\n        }\n        updateSink.expecting(\"0 -> 1\") {\n            test.value = 1\n        }\n\n        updateSink.expecting(\"end\") {\n            changeSink.expecting(\"0 -> 1\") {\n                valuesSink.expecting(1) {\n                    futureValuesSink.expecting(1) {\n                        end()\n                    }\n                }\n            }\n        }\n\n        updateSink.expecting([\"begin\", \"1 -> 2\", \"end\"]) {\n            changeSink.expecting(\"1 -> 2\") {\n                valuesSink.expecting(2) {\n                    futureValuesSink.expecting(2) {\n                        any.value = 2\n                    }\n                }\n            }\n        }\n\n        updateSink.expecting([\"begin\", \"end\"]) {\n            any.withTransaction {}\n        }\n\n        updateSink.expecting([\"begin\", \"2 -> 3\", \"3 -> 4\", \"end\"]) {\n            changeSink.expecting(\"2 -> 4\") {\n                valuesSink.expecting(4) {\n                    futureValuesSink.expecting(4) {\n                        any.withTransaction {\n                            any.value = 3\n                            any.value = 4\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    func test_anyObservable_fromAnyUpdatable() {\n        let test = TestUpdatableValue<Int>(0)\n        let any = test.anyUpdatableValue.anyObservableValue\n\n        XCTAssertEqual(any.value, 0)\n\n        let updateSink = MockValueUpdateSink<Int>(any.updates)\n\n        updateSink.expecting(\"begin\") {\n            test.beginTransaction()\n        }\n        updateSink.expecting(\"0 -> 1\") {\n            test.value = 1\n        }\n\n        updateSink.expecting(\"end\") {\n            test.endTransaction()\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/UpdateTests.swift",
    "content": "//\n//  UpdateTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-26.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass UpdateTests: XCTestCase {\n    func testChangeExtraction() {\n        let change = TestChange([1, 2, 3])\n        let updates: [Update<TestChange>] = [\n            .beginTransaction,\n            .change(change),\n            .endTransaction,\n        ]\n        let expected: [String] = [\"nil\", \"1 -> 2 -> 3\", \"nil\"]\n        let actual = updates.map { update -> String in\n            if let change = update.change {\n                return \"\\(change)\"\n            }\n            else {\n                return \"nil\"\n            }\n        }\n        XCTAssertEqual(actual, expected)\n    }\n\n    func testFilter() {\n        let change = TestChange([1, 2, 3])\n        let updates: [Update<TestChange>] = [\n            .beginTransaction,\n            .change(change),\n            .endTransaction,\n            ]\n        let expected1: [String] = [\"begin\", \"1 -> 2 -> 3\", \"end\"]\n        let actual1 = updates.map { describe($0.filter { _ in true }) }\n        XCTAssertEqual(actual1, expected1)\n\n        let expected2: [String] = [\"begin\", \"nil\", \"end\"]\n        let actual2 = updates.map { describe($0.filter { _ in false }) }\n        XCTAssertEqual(actual2, expected2)\n    }\n\n    func testMap() {\n        let change = TestChange([1, 2, 3])\n        let updates: [Update<TestChange>] = [\n            .beginTransaction,\n            .change(change),\n            .endTransaction,\n            ]\n\n        let expected: [String] = [\"begin\", \"2 -> 4 -> 6\", \"end\"]\n        let actual = updates.map { describe($0.map { TestChange($0.values.map { 2 * $0 }) }) }\n        XCTAssertEqual(actual, expected)\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ValueBufferingTests.swift",
    "content": "//\n//  BufferedValueTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-28.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass BufferedValueTests: XCTestCase {\n\n    func test_connectsImmediately() {\n        let observable = TestObservableValue(0)\n\n        do {\n            let buffered = observable.buffered()\n            XCTAssertTrue(observable.isConnected)\n            withExtendedLifetime(buffered) {}\n        }\n        XCTAssertFalse(observable.isConnected)\n    }\n\n    func test_isntRetainedByObservable() {\n        let observable = TestObservableValue(0)\n        weak var weakSink: MockValueUpdateSink<Int>? = nil\n        do {\n            let buffered = observable.buffered()\n            let sink = MockValueUpdateSink<Int>()\n            weakSink = sink\n            sink.subscribe(to: buffered.updates)\n            withExtendedLifetime(buffered) {}\n        }\n        // If the sink is still alive, the buffered observable wasn't deallocated.\n        XCTAssertNil(weakSink, \"Possible retain cycle\")\n    }\n\n    func test_updates() {\n        let observable = TestObservableValue(0)\n        let buffered = observable.buffered()\n\n        XCTAssertEqual(buffered.value, 0)\n        observable.value = 1\n        XCTAssertEqual(buffered.value, 1)\n\n        let sink = MockValueUpdateSink(buffered)\n\n        sink.expecting([\"begin\", \"1 -> 2\", \"end\"]) {\n            observable.value = 2\n        }\n\n        sink.expecting(\"begin\") {\n            observable.beginTransaction()\n        }\n\n        sink.expectingNothing {\n            observable.value = 3\n        }\n\n        sink.expectingNothing {\n            observable.value = 4\n        }\n\n        sink.expecting([\"2 -> 4\", \"end\"]) {\n            observable.endTransaction()\n        }\n\n        sink.disconnect()\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ValueChangeTests.swift",
    "content": "//\n//  ValueChangeTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-10-27.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass ValueChangeTests: XCTestCase {\n\n    func test() {\n        let change = ValueChange<Int>(from: 1, to: 2)\n        XCTAssertEqual(change.old, 1)\n        XCTAssertEqual(change.new, 2)\n        XCTAssertFalse(change.isEmpty)\n\n        var value = 1\n        change.apply(on: &value)\n        XCTAssertEqual(value, 2)\n\n        XCTAssertEqual(change.applied(on: 1), 2)\n\n        var m = ValueChange(from: 0, to: 1)\n        m.merge(with: change)\n        XCTAssertEqual(m.old, 0)\n        XCTAssertEqual(m.new, 2)\n\n        let m2 = ValueChange(from: 0, to: 1).merged(with: change)\n        XCTAssertEqual(m2.old, 0)\n        XCTAssertEqual(m2.new, 2)\n\n        let reversed = change.reversed()\n        XCTAssertEqual(reversed.old, 2)\n        XCTAssertEqual(reversed.new, 1)\n\n        let transformed = change.map { 2 * $0 }\n        XCTAssertEqual(transformed.old, 2)\n        XCTAssertEqual(transformed.new, 4)\n\n        XCTAssertTrue(change == ValueChange(from: 1, to: 2))\n        XCTAssertFalse(change == ValueChange(from: 0, to: 2))\n        XCTAssertFalse(change == ValueChange(from: 1, to: 4))\n\n        XCTAssertFalse(change != ValueChange(from: 1, to: 2))\n        XCTAssertTrue(change != ValueChange(from: 0, to: 2))\n        XCTAssertTrue(change != ValueChange(from: 1, to: 4))\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ValueMappingTests.swift",
    "content": "//\n//  SelectOperatorTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-06.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nprivate class Book {\n    let title: Variable<String>\n    let authors: SetVariable<String>\n    let chapters: ArrayVariable<String>\n\n    init(_ title: String, authors: Set<String> = [], chapters: [String] = []) {\n        self.title = .init(title)\n        self.authors = .init(authors)\n        self.chapters = .init(chapters)\n    }\n}\n\nclass ValueMappingTests: XCTestCase {\n    func test_value() {\n        let book = Book(\"foo\")\n\n        let title = book.title.map { $0.uppercased() }\n\n        XCTAssertEqual(title.value, \"FOO\")\n\n        let mock = MockValueUpdateSink(title)\n\n        mock.expecting([\"begin\", \"FOO -> BAR\", \"end\"]) {\n            book.title.value = \"bar\"\n        }\n        XCTAssertEqual(title.value, \"BAR\")\n    }\n\n    func test_updatableValue() {\n        let book = Book(\"foo\")\n\n        // This is a simple mapping that ignores that a book's title is itself observable.\n        let title = book.title.map({ $0.uppercased() }, inverse: { $0.lowercased() })\n\n        XCTAssertEqual(title.value, \"FOO\")\n\n        let mock = MockValueUpdateSink(title)\n\n        mock.expecting([\"begin\", \"FOO -> BAR\", \"end\"]) {\n            book.title.value = \"bar\"\n        }\n        XCTAssertEqual(title.value, \"BAR\")\n\n        mock.expecting([\"begin\", \"BAR -> BAZ\", \"end\"]) {\n            title.value = \"BAZ\"\n        }\n        XCTAssertEqual(title.value, \"BAZ\")\n        XCTAssertEqual(book.title.value, \"baz\")\n    }\n\n    func test_sourceField() {\n        let b1 = Book(\"foo\")\n        let v = Variable<Book>(b1)\n        let titleChanges = v.map { $0.title.changes }\n\n        var expected: [ValueChange<String>] = []\n        var actual: [ValueChange<String>] = []\n        let connection = titleChanges.subscribe { change in actual.append(change) }\n        func expect(_ change: ValueChange<String>? = nil, file: StaticString = #file, line: UInt = #line, body: () -> ()) {\n            if let change = change {\n                expected.append(change)\n            }\n            body()\n            if !expected.elementsEqual(actual, by: ==) {\n                XCTFail(\"\\(actual) is not equal to \\(expected)\", file: file, line: line)\n            }\n            expected = []\n            actual = []\n        }\n\n        expect(ValueChange(from: \"foo\", to: \"bar\")) {\n            b1.title.value = \"bar\"\n        }\n        let b2 = Book(\"fred\")\n        expect() {\n            v.value = b2\n        }\n        expect(ValueChange(from: \"fred\", to: \"barney\")) {\n            b2.title.value = \"barney\"\n        }\n        connection.disconnect()\n    }\n\n    func test_valueField() {\n        let book = Book(\"book\")\n\n        let v = Variable<Book>(book)\n        let title = v.map{ $0.title.map { $0.uppercased() } } // The title is updatable; uppercasing it makes it observable only.\n\n        XCTAssertEqual(title.value, \"BOOK\")\n\n        let mock = MockValueUpdateSink(title)\n\n        mock.expecting([\"begin\", \"BOOK -> UPDATED\", \"end\"]) {\n            book.title.value = \"updated\"\n        }\n        XCTAssertEqual(title.value, \"UPDATED\")\n\n        let book2 = Book(\"other\")\n        mock.expecting([\"begin\", \"UPDATED -> OTHER\", \"end\"]) {\n            v.value = book2\n        }\n        XCTAssertEqual(title.value, \"OTHER\")\n    }\n\n    func test_updatableField() {\n        let book = Book(\"book\")\n\n        let v = Variable<Book>(book)\n        let title = v.map{$0.title}\n\n        XCTAssertEqual(title.value, \"book\")\n\n        let mock = MockValueUpdateSink(title)\n\n        mock.expecting([\"begin\", \"book -> updated\", \"end\"]) {\n            title.value = \"updated\"\n        }\n        XCTAssertEqual(title.value, \"updated\")\n        XCTAssertEqual(book.title.value, \"updated\")\n\n        let book2 = Book(\"other\")\n        mock.expecting([\"begin\", \"updated -> other\", \"end\"]) {\n            v.value = book2\n        }\n        XCTAssertEqual(title.value, \"other\")\n    }\n\n    func test_arrayField() {\n        let book = Book(\"book\", chapters: [\"a\", \"b\", \"c\"])\n        let v = Variable<Book>(book)\n        let chapters = v.map{ $0.chapters.map { $0.uppercased() } } // Uppercasing is there to remove updatability.\n\n        XCTAssertEqual(chapters.isBuffered, false)\n        XCTAssertEqual(chapters.count, 3)\n        XCTAssertEqual(chapters.observableCount.value, 3)\n        XCTAssertEqual(chapters.value, [\"A\", \"B\", \"C\"])\n        XCTAssertEqual(chapters[0], \"A\")\n        XCTAssertEqual(chapters[1 ..< 3], [\"B\", \"C\"])\n\n        let mock = MockArrayObserver(chapters)\n\n        mock.expecting([\"begin\", \"3.insert(D, at: 3)\", \"end\"]) {\n            book.chapters.append(\"d\")\n        }\n        XCTAssertEqual(chapters.value, [\"A\", \"B\", \"C\", \"D\"])\n\n        let book2 = Book(\"other\", chapters: [\"10\", \"11\"])\n        mock.expecting([\"begin\", \"4.replaceSlice([A, B, C, D], at: 0, with: [10, 11])\", \"end\"]) {\n            v.value = book2\n        }\n        XCTAssertEqual(chapters.value, [\"10\", \"11\"])\n    }\n\n    func test_updatableArrayField() {\n        let book = Book(\"book\", chapters: [\"1\", \"2\", \"3\"])\n        let v = Variable<Book>(book)\n        let chapters = v.map{$0.chapters}\n\n        XCTAssertEqual(chapters.isBuffered, true)\n        XCTAssertEqual(chapters.count, 3)\n        XCTAssertEqual(chapters.observableCount.value, 3)\n        XCTAssertEqual(chapters.value, [\"1\", \"2\", \"3\"])\n        XCTAssertEqual(chapters[0], \"1\")\n        XCTAssertEqual(chapters[1 ..< 3], [\"2\", \"3\"])\n\n        let mock = MockArrayObserver(chapters)\n\n        mock.expecting([\"begin\", \"3.insert(4, at: 3)\", \"end\"]) {\n            book.chapters.append(\"4\")\n        }\n        XCTAssertEqual(chapters.value, [\"1\", \"2\", \"3\", \"4\"])\n\n        mock.expecting([\"begin\", \"4.remove(3, at: 2)\", \"end\"]) {\n            _ = chapters.remove(at: 2)\n        }\n        XCTAssertEqual(chapters.value, [\"1\", \"2\", \"4\"])\n        XCTAssertEqual(book.chapters.value, [\"1\", \"2\", \"4\"])\n\n        let book2 = Book(\"other\", chapters: [\"10\", \"11\"])\n        mock.expecting([\"begin\", \"3.replaceSlice([1, 2, 4], at: 0, with: [10, 11])\", \"end\"]) {\n            v.value = book2\n        }\n        XCTAssertEqual(chapters.value, [\"10\", \"11\"])\n\n        mock.expecting([\"begin\", \"2.replace(10, at: 0, with: 20)\", \"end\"]) {\n            chapters[0] = \"20\"\n        }\n        XCTAssertEqual(chapters.value, [\"20\", \"11\"])\n        XCTAssertEqual(book2.chapters.value, [\"20\", \"11\"])\n\n        mock.expecting([\"begin\", \"2.insert(25, at: 1)\", \"end\"]) {\n            chapters.insert(\"25\", at: 1)\n        }\n        XCTAssertEqual(chapters.value, [\"20\", \"25\", \"11\"])\n        XCTAssertEqual(book2.chapters.value, [\"20\", \"25\", \"11\"])\n\n        mock.expecting([\"begin\", \"3.replaceSlice([25, 11], at: 1, with: [21, 22])\", \"end\"]) {\n            chapters[1 ..< 3] = [\"21\", \"22\"]\n        }\n        XCTAssertEqual(chapters.value, [\"20\", \"21\", \"22\"])\n        XCTAssertEqual(book2.chapters.value, [\"20\", \"21\", \"22\"])\n\n        mock.expecting([\"begin\", \"3.replaceSlice([20, 21, 22], at: 0, with: [foo, bar])\", \"end\"]) {\n            chapters.value = [\"foo\", \"bar\"]\n        }\n        XCTAssertEqual(chapters.value, [\"foo\", \"bar\"])\n        XCTAssertEqual(book2.chapters.value, [\"foo\", \"bar\"])\n    }\n\n    func test_setField() {\n        let book = Book(\"book\", authors: [\"a\", \"b\", \"c\"])\n        let v = Variable<Book>(book)\n        let authors = v.map { $0.authors.map { $0.uppercased() } } // Uppercased to lose updatability.\n\n        XCTAssertEqual(authors.isBuffered, false)\n        XCTAssertEqual(authors.count, 3)\n        XCTAssertEqual(authors.observableCount.value, 3)\n        XCTAssertEqual(authors.value, [\"A\", \"B\", \"C\"])\n        XCTAssertEqual(authors.contains(\"A\"), true)\n        XCTAssertEqual(authors.contains(\"0\"), false)\n        XCTAssertEqual(authors.isSubset(of: [\"A\", \"B\", \"C\"]), true)\n        XCTAssertEqual(authors.isSubset(of: [\"A\", \"B\", \"C\", \"D\"]), true)\n        XCTAssertEqual(authors.isSubset(of: [\"B\", \"C\", \"D\"]), false)\n        XCTAssertEqual(authors.isSuperset(of: [\"A\", \"B\", \"C\"]), true)\n        XCTAssertEqual(authors.isSuperset(of: [\"B\", \"C\"]), true)\n        XCTAssertEqual(authors.isSuperset(of: [\"C\", \"D\"]), false)\n\n        let mock = MockSetObserver(authors)\n        mock.expecting([\"begin\", \"[]/[D]\", \"end\"]) {\n            book.authors.insert(\"d\")\n        }\n        XCTAssertEqual(authors.value, [\"A\", \"B\", \"C\", \"D\"])\n        mock.expecting([\"begin\", \"[B]/[]\", \"end\"]) {\n            book.authors.remove(\"b\")\n        }\n        XCTAssertEqual(authors.value, [\"A\", \"C\", \"D\"])\n\n        mock.expecting([\"begin\", \"[A, C, D]/[BARNEY, FRED]\", \"end\"]) {\n            v.value = Book(\"other\", authors: [\"fred\", \"barney\"])\n        }\n        XCTAssertEqual(authors.value, [\"FRED\", \"BARNEY\"])\n    }\n\n    func test_updatableSetField() {\n        let book = Book(\"book\", authors: [\"a\", \"b\", \"c\"])\n        let v = Variable<Book>(book)\n        let authors = v.map{$0.authors}\n\n        XCTAssertEqual(authors.isBuffered, true)\n        XCTAssertEqual(authors.count, 3)\n        XCTAssertEqual(authors.observableCount.value, 3)\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\"])\n        XCTAssertEqual(authors.contains(\"a\"), true)\n        XCTAssertEqual(authors.contains(\"0\"), false)\n        XCTAssertEqual(authors.isSubset(of: [\"a\", \"b\", \"c\"]), true)\n        XCTAssertEqual(authors.isSubset(of: [\"a\", \"b\", \"c\", \"d\"]), true)\n        XCTAssertEqual(authors.isSubset(of: [\"b\", \"c\", \"d\"]), false)\n        XCTAssertEqual(authors.isSuperset(of: [\"a\", \"b\", \"c\"]), true)\n        XCTAssertEqual(authors.isSuperset(of: [\"b\", \"c\"]), true)\n        XCTAssertEqual(authors.isSuperset(of: [\"c\", \"d\"]), false)\n\n        let mock = MockSetObserver(authors)\n        mock.expecting([\"begin\", \"[]/[d]\", \"end\"]) {\n            book.authors.insert(\"d\")\n        }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\"])\n        mock.expecting([\"begin\", \"[b]/[]\", \"end\"]) {\n            book.authors.remove(\"b\")\n        }\n        XCTAssertEqual(authors.value, [\"a\", \"c\", \"d\"])\n\n        mock.expecting([\"begin\", \"[]/[e]\", \"end\"]) {\n            authors.insert(\"e\")\n        }\n        XCTAssertEqual(authors.value, [\"a\", \"c\", \"d\", \"e\"])\n        XCTAssertEqual(book.authors.value, [\"a\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[c]/[]\", \"end\"]) {\n            authors.remove(\"c\")\n        }\n        XCTAssertEqual(authors.value, [\"a\", \"d\", \"e\"])\n        XCTAssertEqual(book.authors.value, [\"a\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[]/[b, c]\", \"end\"]) {\n            authors.apply(SetChange(removed: [], inserted: [\"b\", \"c\"]))\n        }\n        XCTAssertEqual(authors.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n        XCTAssertEqual(book.authors.value, [\"a\", \"b\", \"c\", \"d\", \"e\"])\n\n        mock.expecting([\"begin\", \"[a, b, c, d, e]/[bar, foo]\", \"end\"]) {\n            authors.value = [\"foo\", \"bar\"]\n        }\n        XCTAssertEqual(authors.value, [\"foo\", \"bar\"])\n        XCTAssertEqual(book.authors.value, [\"foo\", \"bar\"])\n\n        mock.expecting([\"begin\", \"[bar, foo]/[barney, fred]\", \"end\"]) {\n            v.value = Book(\"other\", authors: [\"fred\", \"barney\"])\n        }\n        XCTAssertEqual(authors.value, [\"fred\", \"barney\"])\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/ValueReferenceTests.swift",
    "content": "//\n//  ValueReferenceTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2016-11-02.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\nimport GlueKit\n\nclass ValueReferenceTests: XCTestCase {\n    func testReference() {\n        let a = Variable<Int>(0)\n        let b = Variable<Int>(10)\n        let c = Variable<Int>(20)\n        let ref = Variable<AnyObservableValue<Int>>(a.anyObservableValue)\n\n        XCTAssertEqual(ref.value.value, 0)\n        a.value = 1\n        XCTAssertEqual(ref.value.value, 1)\n\n        let unpacked = ref.unpacked()\n\n        XCTAssertEqual(unpacked.value, 1)\n        a.value = 2\n        XCTAssertEqual(unpacked.value, 2)\n\n        let sink = MockValueUpdateSink(unpacked)\n\n        sink.expecting([\"begin\", \"2 -> 3\", \"end\"]) {\n            a.value = 3\n        }\n\n        sink.expecting([\"begin\", \"3 -> 10\", \"end\"]) {\n            ref.value = b.anyObservableValue\n        }\n\n        sink.expecting([\"begin\", \"10 -> 11\", \"end\"]) {\n            b.value = 11\n        }\n\n        sink.expecting(\"begin\") {\n            b.apply(.beginTransaction)\n        }\n\n        sink.expectingNothing {\n            ref.apply(.beginTransaction)\n        }\n\n        sink.expecting(\"11 -> 12\") {\n            b.value = 12\n        }\n\n        sink.expecting(\"12 -> 20\") {\n            ref.value = c.anyObservableValue\n        }\n\n        sink.expecting(\"20 -> 21\") {\n            c.value = 21\n        }\n\n        sink.expectingNothing {\n            b.apply(.endTransaction)\n        }\n\n        sink.expecting(\"end\") {\n            ref.apply(.endTransaction)\n        }\n\n        sink.disconnect()\n    }\n\n    func testDerivedObservable() {\n        let a = Variable<Int>(0)\n        let double = a.map { 2 * $0 }\n\n        let ref = Variable<AnyObservableValue<Int>>(a.anyObservableValue)\n\n        let sink = MockValueUpdateSink(ref.unpacked())\n\n        sink.expecting([\"begin\", \"0 -> 1\", \"end\"]) {\n            a.value = 1\n        }\n\n        sink.expecting([\"begin\", \"1 -> 2\", \"end\"]) {\n            ref.value = double.anyObservableValue\n        }\n\n        sink.expecting([\"begin\", \"2 -> 4\", \"end\"]) {\n            a.value = 2\n        }\n\n        sink.disconnect()\n    }\n}\n"
  },
  {
    "path": "Tests/GlueKitTests/VariableTests.swift",
    "content": "//\n//  VariableTests.swift\n//  GlueKit\n//\n//  Created by Károly Lőrentey on 2015-12-01.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport XCTest\n@testable import GlueKit\n\nclass VariableTests: XCTestCase {\n    func test_values() {\n        let v = Variable<Int>(0)\n\n        var r = [Int]()\n        let c = v.values.subscribe { value in r.append(value) }\n\n        XCTAssertEqual(r, [0], \"The values source should trigger immediately with the current value of the variable\")\n\n        v.value = 1\n        XCTAssertEqual(r, [0, 1])\n\n        v.value = 2\n        XCTAssertEqual(r, [0, 1, 2])\n\n        v.value = 2\n        XCTAssertEqual(r, [0, 1, 2, 2])\n\n        v.withTransaction {\n            v.value = 3\n            v.value = 3\n        }\n        XCTAssertEqual(r, [0, 1, 2, 2, 3])\n\n        v.apply(ValueChange(from: 3, to: 4))\n        XCTAssertEqual(r, [0, 1, 2, 2, 3, 4])\n        \n        c.disconnect()\n    }\n\n    func test_futureValues() {\n        let v = Variable<Int>(0)\n\n        var r = [Int]()\n        let c = v.futureValues.subscribe { value in r.append(value) }\n\n        XCTAssertEqual(r, [], \"The future values source should not trigger with the current value of the variable\")\n\n        v.value = 1\n        XCTAssertEqual(r, [1])\n\n        v.value = 2\n        XCTAssertEqual(r, [1, 2])\n\n        v.value = 2\n        XCTAssertEqual(r, [1, 2, 2])\n\n        v.withTransaction {\n            v.value = 3\n            v.value = 3\n        }\n        XCTAssertEqual(r, [1, 2, 2, 3])\n\n        v.apply(ValueChange(from: 3, to: 4))\n        XCTAssertEqual(r, [1, 2, 2, 3, 4])\n\n        c.disconnect()\n    }\n\n    func test_updates_NestedUpdates() {\n        let v = Variable<Int>(3)\n\n        var s = \"\"\n        let c = v.updates.subscribe { update in\n            s += \" (\\(describe(update))\"\n            if let new = update.change?.new, new > 0 {\n                // This is OK as long as it doesn't lead to infinite updates.\n                // The value is updated immediately, but the source is triggered later, at the end of the outermost update.\n                v.value -= 1\n            }\n            s += \")\"\n        }\n        XCTAssertEqual(s, \"\")\n\n        s = \"\"\n        v.value = 2\n        XCTAssertEqual(s, \" (begin) (3 -> 2) (2 -> 1) (1 -> 0) (end)\")\n\n        c.disconnect()\n    }\n\n    func test_values_NestedUpdates() {\n        let v = Variable<Int>(3)\n\n        var s = \"\"\n        let c = v.values.subscribe { i in\n            s += \" (\\(i)\"\n            if i > 0 {\n                // This is OK as long as it doesn't lead to infinite updates.\n                // The value is updated immediately, but the source is triggered later, at the end of the outermost update.\n                v.value -= 1\n            }\n            s += \")\"\n        }\n        XCTAssertEqual(s, \" (3) (2) (1) (0)\") // No nesting, all updates are received\n\n        s = \"\"\n        v.value = 1\n        XCTAssertEqual(s, \" (1) (0)\")\n\n        c.disconnect()\n    }\n\n    func test_futureValues_NestedUpdates() {\n        let v = Variable<Int>(0)\n\n        var s = \"\"\n        let c = v.futureValues.subscribe { i in\n            s += \" (\\(i)\"\n            if i > 0 {\n                // This is OK as long as it doesn't lead to infinite updates.\n                // The value is updated immediately, but the source is triggered later, at the end of the outermost update.\n                v.value -= 1\n            }\n            s += \")\"\n        }\n\n        XCTAssertEqual(s, \"\")\n\n        v.value = 3\n        XCTAssertEqual(s, \" (3) (2) (1) (0)\") // No nesting, all updates are received\n\n        s = \"\"\n        v.value = 1\n        XCTAssertEqual(s, \" (1) (0)\")\n\n        c.disconnect()\n    }\n\n\n    func test_values_ReentrantSinks() {\n        let v = Variable<Int>(0)\n\n        var s = String()\n        let c1 = v.values.subscribe { i in\n            s += \" (\\(i)\"\n            if i > 0 {\n                v.value = i - 1\n            }\n            s += \")\"\n        }\n        let c2 = v.values.subscribe { i in\n            s += \" (\\(i)\"\n            if i > 0 {\n                v.value = i - 1\n            }\n            s += \")\"\n        }\n\n        XCTAssertEqual(s, \" (0) (0)\")\n\n        s = \"\"\n        v.value = 2\n\n        XCTAssertEqual(s, \" (2) (2) (1) (1) (1) (1) (0) (0) (0) (0) (0) (0) (0) (0)\")\n\n        c1.disconnect()\n        c2.disconnect()\n    }\n\n    func testExerciseVariables() {\n        func check<V: UpdatableValueType>(_ v: V, _ a: V.Value, _ b: V.Value, _ c: V.Value)\n        where V.Value: Equatable {\n            check(v, a, b, c, ==)\n        }\n\n        func check<V: UpdatableValueType>(_ v: V, _ a: V.Value, _ b: V.Value, _ c: V.Value, _ eq: @escaping (V.Value, V.Value) -> Bool) {\n\n            XCTAssert(eq(v.value, a))\n            v.value = a\n            XCTAssert(eq(v.value, a))\n            v.value = b\n            XCTAssert(eq(v.value, b))\n            v.withTransaction {\n                v.value = a\n                v.value = c\n            }\n            XCTAssert(eq(v.value, c))\n            v.value = a\n\n            let mock = MockValueUpdateSink(v)\n            mock.expecting([\"begin\", \"\\(a) -> \\(b)\", \"end\"]) {\n                v.value = b\n            }\n            XCTAssert(eq(v.value, b))\n            mock.expecting([\"begin\", \"\\(b) -> \\(a)\", \"\\(a) -> \\(c)\", \"end\"]) {\n                v.withTransaction {\n                    v.value = a\n                    v.value = c\n                }\n            }\n            XCTAssert(eq(v.value, c))\n        }\n\n        check(Variable<Int>(1), 1, 2, 3)\n        check(IntVariable(1), 1, 2, 3)\n\n        check(FloatVariable(1.0), 1.0, 2.0, 3.0)\n        check(BoolVariable(false), false, true, false)\n        check(StringVariable(\"foo\"), \"foo\", \"bar\", \"baz\")\n        check(Variable<Box>(Box(1)), Box(1), Box(2), Box(3))\n\n        let box = Box(1)\n        check(UnownedVariable<Box>(box), Box(1), Box(2), Box(3))\n        check(WeakVariable<Box>(box), Box(1), Box(2), Box(3), ==)\n    }\n\n    func testUnownedVariable() {\n        weak var box: Box? = nil\n        let variable: UnownedVariable<Box>\n        do {\n            let b = Box(1)\n            box = b\n            variable = .init(b)\n            XCTAssertEqual(box, Box(1))\n            XCTAssertEqual(variable.value, Box(1))\n            withExtendedLifetime(b) {}\n        }\n        XCTAssertNil(box, \"An UnownedVariable must not retain its value\")\n        _ = variable // Accessing its value would trap here\n    }\n\n    func testWeakVariable() {\n        weak var box: Box? = nil\n        let variable: WeakVariable<Box>\n        do {\n            let b = Box(1)\n            box = b\n            variable = .init(b)\n            XCTAssertEqual(box, Box(1))\n            XCTAssertEqual(variable.value, Box(1))\n            withExtendedLifetime(b) {}\n        }\n        XCTAssertNil(box)\n        XCTAssertNil(variable.value)\n\n        let nilVariable = WeakVariable<Box>()\n        XCTAssertNil(nilVariable.value)\n    }\n\n\n    func testLiteralExpressibility() {\n        let int: IntVariable = 1\n        XCTAssertEqual(int.value, 1)\n\n        let float: FloatVariable = 2.0\n        XCTAssertEqual(float.value, 2.0)\n\n        let double: DoubleVariable = 2.0\n        XCTAssertEqual(double.value, 2.0)\n\n        let bool: BoolVariable = true\n        XCTAssertEqual(bool.value, true)\n\n        let string1: StringVariable = \"foo\"\n        XCTAssertEqual(string1.value, \"foo\")\n\n        let string2 = StringVariable(unicodeScalarLiteral: \"bar\") // ¯\\_(ツ)_/¯\n        XCTAssertEqual(string2.value, \"bar\")\n\n        let string3 = StringVariable(extendedGraphemeClusterLiteral: \"baz\") // ¯\\_(ツ)_/¯\n        XCTAssertEqual(string3.value, \"baz\")\n\n        let optional: OptionalVariable<Int> = nil\n        XCTAssertEqual(optional.value, nil)\n    }\n}\n\nprivate class Box: Equatable {\n    var value: Int\n    init(_ value: Int) { self.value = value }\n    static func ==(a: Box, b: Box) -> Bool { return a.value == b.value }\n}\n\n"
  },
  {
    "path": "Tests/PerformanceTests/GlueKitPerformanceTests.swift",
    "content": "//\n//  GlueKitPerformanceTests.swift\n//  GlueKitPerformanceTests\n//\n//  Created by Károly Lőrentey on 2015-12-04.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\nimport Foundation\nimport XCTest\nimport GlueKit\n\nprivate struct EmptySink: SinkType {\n    let id: Int\n\n    func receive(_ value: Int) {\n        // Do nothing\n    }\n    var hashValue: Int { return id }\n    static func ==(left: EmptySink, right: EmptySink) -> Bool { return left.id == right.id }\n}\n\nprivate class TestSink: SinkType {\n    var count = 0\n\n    func receive(_ value: Int) {\n        count += 1\n    }\n}\n\nprivate struct RefCountingSink: SinkType {\n    let object: TestSink\n    let id: Int\n\n    func receive(_ value: Int) {\n        // Do nothing\n    }\n    var hashValue: Int { return id }\n    static func ==(left: RefCountingSink, right: RefCountingSink) -> Bool { return left.id == right.id }\n}\n\n\nprivate struct TestMethodSink: SinkType {\n    let object: TestSink\n    let method: (TestSink) -> (Int) -> Void\n    let id: Int\n    func receive(_ value: Int) {\n        method(object)(value)\n    }\n    var hashValue: Int { return ObjectIdentifier(object).hashValue ^ id }\n    static func ==(left: TestMethodSink, right: TestMethodSink) -> Bool { return left.object === right.object && left.id == right.id }\n}\n\nprivate struct TestPartiallyAppliedMethodSink: SinkType {\n    let object: TestSink\n    let method: (Int) -> Void\n    let id: Int\n    func receive(_ value: Int) {\n        method(value)\n    }\n    var hashValue: Int { return ObjectIdentifier(object).hashValue ^ id }\n    static func ==(left: TestPartiallyAppliedMethodSink, right: TestPartiallyAppliedMethodSink) -> Bool {\n        return left.object === right.object && left.id == right.id\n    }\n}\n\nprivate struct HardwiredMethodSink: SinkType {\n    let object: TestSink\n    let id: Int\n    func receive(_ value: Int) {\n        object.receive(value)\n    }\n    var hashValue: Int { return ObjectIdentifier(object).hashValue ^ id }\n    static func ==(left: HardwiredMethodSink, right: HardwiredMethodSink) -> Bool { return left.object === right.object && left.id == right.id }\n}\n\nextension XCTestCase {\n    func measureDelayed(_ body: @escaping () -> ()) {\n        self.measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false, for: body)\n    }\n}\n\nclass SignalSubscriptionTests: XCTestCase {\n\n    func test_subscribe_EmptySink() {\n        let count = 100_000\n\n        self.measureDelayed {\n            let signal = Signal<Int>()\n\n            self.startMeasuring()\n            for i in 0 ..< count {\n                signal.add(EmptySink(id: i))\n            }\n            self.stopMeasuring()\n\n            signal.send(1)\n\n            for i in 0 ..< count {\n                signal.remove(EmptySink(id: i))\n            }\n\n            XCTAssertFalse(signal.isConnected)\n        }\n    }\n\n    func test_subscribe_RefCountingSink() {\n        let count = 100_000\n\n        self.measureDelayed {\n\n            let signal = Signal<Int>()\n\n            let object = TestSink()\n\n            self.startMeasuring()\n            for i in 0 ..< count {\n                signal.add(RefCountingSink(object: object, id: i))\n            }\n            self.stopMeasuring()\n\n            signal.send(1)\n\n            for i in 0 ..< count {\n                signal.remove(RefCountingSink(object: object, id: i))\n            }\n            \n            XCTAssertFalse(signal.isConnected)\n        }\n    }\n\n    func test_subscribe_MethodSink() {\n        let count = 100_000\n\n        self.measureDelayed {\n\n            let signal = Signal<Int>()\n            let object = TestSink()\n\n            self.startMeasuring()\n            for i in 0 ..< count {\n                signal.add(TestMethodSink(object: object, method: TestSink.receive, id: i))\n            }\n            self.stopMeasuring()\n\n            signal.send(1)\n\n            for i in 0 ..< count {\n                signal.remove(TestMethodSink(object: object, method: TestSink.receive, id: i))\n            }\n\n            XCTAssertFalse(signal.isConnected)\n            XCTAssertEqual(object.count, count)\n        }\n    }\n\n    func test_subscribe_PartiallyAppliedMethodSink() {\n        let count = 100_000\n\n        self.measureDelayed {\n\n            let signal = Signal<Int>()\n            let object = TestSink()\n\n            self.startMeasuring()\n            for i in 0 ..< count {\n                signal.add(TestPartiallyAppliedMethodSink(object: object, method: object.receive, id: i))\n            }\n            self.stopMeasuring()\n\n            signal.send(1)\n\n            for i in 0 ..< count {\n                signal.remove(TestPartiallyAppliedMethodSink(object: object, method: object.receive, id: i))\n            }\n\n            XCTAssertFalse(signal.isConnected)\n            XCTAssertEqual(object.count, count)\n        }\n    }\n\n\n    func test_subscribe_HardwiredMethodSink() {\n        let count = 100_000\n\n        self.measureDelayed {\n\n            let signal = Signal<Int>()\n            let object = TestSink()\n\n            self.startMeasuring()\n            for i in 0 ..< count {\n                signal.add(HardwiredMethodSink(object: object, id: i))\n            }\n            self.stopMeasuring()\n\n            signal.send(1)\n\n            for i in 0 ..< count {\n                signal.remove(HardwiredMethodSink(object: object, id: i))\n            }\n\n            XCTAssertFalse(signal.isConnected)\n            //XCTAssertEqual(object.count, count)\n        }\n    }\n\n\n    func test_subscribe_Closures() {\n        let count = 100_000\n\n        self.measureDelayed {\n\n            let signal = Signal<Int>()\n            var received = 0\n            var connections: [Connection] = []\n\n            self.startMeasuring()\n            for _ in 0 ..< count {\n                let c = signal.subscribe { _ in received += 1 }\n                connections.append(c)\n            }\n            self.stopMeasuring()\n\n            signal.send(1)\n\n            for c in connections {\n                c.disconnect()\n            }\n\n            XCTAssertFalse(signal.isConnected)\n            XCTAssertEqual(received, count)\n        }\n    }\n}\n\nclass SignalUnsubscriptionTests: XCTestCase {\n\n    func test_unsubscribe_emptySinks() {\n        let count = 100_000\n\n        self.measureDelayed {\n            let signal = Signal<Int>()\n            for i in 0 ..< count {\n                signal.add(EmptySink(id: i))\n            }\n\n            signal.send(1)\n\n            self.startMeasuring()\n            for i in 0 ..< count {\n                signal.remove(EmptySink(id: i))\n            }\n            self.stopMeasuring()\n\n            XCTAssertFalse(signal.isConnected)\n        }\n    }\n}\n\nclass SignalSendTests: XCTestCase {\n\n    func test_send_toSink() {\n        let iterations = 200_000\n\n        measureDelayed {\n            let signal = Signal<Int>()\n            let sink = TestSink()\n            signal.add(sink)\n            self.startMeasuring()\n            for i in 1...iterations {\n                signal.send(i)\n            }\n            self.stopMeasuring()\n            signal.remove(sink)\n            XCTAssertEqual(sink.count, iterations)\n        }\n    }\n\n    func test_send_toClosure() {\n        // Sending to a closure should take roughly the same time as sending to a sink.\n        let iterations = 200_000\n\n        self.measureDelayed {\n            var count = 0\n            let signal = Signal<Int>()\n            let c = signal.subscribe { i in count += 1 }\n\n            self.startMeasuring()\n            for i in 1...iterations {\n                signal.send(i)\n            }\n            self.stopMeasuring()\n\n            c.disconnect()\n            XCTAssertEqual(count, iterations)\n        }\n    }\n\n    func testConcurrentSendPerformance() {\n        let queueCount = 4\n        let iterations = 30000\n\n        self.measureDelayed {\n            var count = 0\n            let signal = Signal<Int>()\n            let c = signal.subscribe { i in count += 1 }\n\n            let queues = (1...queueCount).map { i in DispatchQueue(label: \"org.attaswift.GlueKit.testQueue \\(i)\") }\n\n            let group = DispatchGroup()\n            self.startMeasuring()\n            for q in queues {\n                q.async(group: group) {\n                    for i in 1...iterations {\n                        signal.send(i)\n                    }\n                }\n            }\n            group.wait()\n            self.stopMeasuring()\n\n            c.disconnect()\n            XCTAssertEqual(count, iterations * queueCount)\n        }\n    }\n\n    func testChainedSendPerformance() {\n        // Chain 1000 signals together, then send a bunch of numbers through the chain.\n        var connections: [Connection] = []\n        let start = Signal<Int>()\n        var end = start\n        (1...1000).forEach { _ in\n            let new = Signal<Int>()\n            connections.append(end.subscribe(new.send))\n            end = new\n        }\n\n        let count = 100\n        self.measureDelayed {\n            var r = [Int]()\n            r.reserveCapacity(1000)\n            let c = end.subscribe { i in r.append(i) }\n\n            for i in 1...10 {\n                start.send(i)\n            }\n            r.removeAll(keepingCapacity: true)\n\n            self.startMeasuring()\n            for i in 1...count {\n                start.send(i)\n            }\n            self.stopMeasuring()\n\n            c.disconnect()\n            XCTAssertEqual(r.count, count)\n        }\n    }\n}\n"
  },
  {
    "path": "Tests/PerformanceTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "jazzy.sh",
    "content": "#!/bin/sh\n\njazzy \\\n    --clean \\\n    --author \"Károly Lőrentey\" \\\n    --author_url \"https://twitter.com/lorentey\" \\\n    --github_url https://github.com/lorentey/GlueKit \\\n    --github-file-prefix https://github.com/lorentey/GlueKit/tree/master \\\n    --module-version 1.0.0-alpha.1 \\\n    --xcodebuild-arguments -scheme,GlueKit \\\n    --module GlueKit \\\n    --root-url https://lorentey.github.io/GlueKit/reference/ \\\n    --output jazzy/output \\\n    --swift-version 2.1.1\n\n#--template-directory jazzy/templates \\\n"
  },
  {
    "path": "version.xcconfig",
    "content": "//\n//  version.xcconfig\n//\n//  Created by Károly Lőrentey on 2016-03-08.\n//  Copyright © 2015–2017 Károly Lőrentey.\n//\n\n// Increment the build number whenever you modify the version string.\nVERSION_STRING = 0.2.0\nBUILD_NUMBER = 2\n\nPROJECT_NAME = GlueKit\nBUNDLE_IDENTIFIER_BASE = org.attaswift.$(PROJECT_NAME)\n\nIPHONEOS_DEPLOYMENT_TARGET = 9.3\nMACOSX_DEPLOYMENT_TARGET = 10.11\nWATCHOS_DEPLOYMENT_TARGET = 3.0\nTVOS_DEPLOYMENT_TARGET = 10.0\n\nAPPLICATION_EXTENSION_API_ONLY = YES\n"
  }
]