RxSwiftの新しいSingle, Maybe, Completableのソースを読んでみた


[RxSwiftに新しく追加されたSingle, Maybe, Completable](http://qiita.com/fu_nya/items/268299d3e8dfd822b146) で新しいUnitsたちを調べるのにRxSwiftはドキュメントがなかったので、ソースを読んで見たメモ。

## 実装ファイル

実装はこちら:point_right_tone1: [RxSwift/PrimitiveSequence.swift](https://github.com/ReactiveX/RxSwift/blob/master/RxSwift/Traits/PrimitiveSequence.swift) 

新しいUnitsは `Traits` というGroupと分類されている。
Traits = 性質という意味。 なるほど。

<img width="303" alt="RxSwift_PrimitiveSequence_swift_at_master_·_ReactiveX_RxSwift.png" src="https://qiita-image-store.s3.amazonaws.com/0/7893/ea69029f-28b1-dc54-4337-3809adac0dd2.png">


## 元となる構造体の定義

まず、`PrimitiveSequence` というstructが定義されていている
このstructにはGenericsで `Trait(性質)` と `Element(要素)` が指定できる。
`Elements` は`Observable`のレスポンスの型になる。

```swift:PrimitiveSequence
/// Observable sequences containing 0 or 1 element.
public struct PrimitiveSequence<Trait, Element> {
    fileprivate let source: Observable<Element>

    init(raw: Observable<Element>) {
        self.source = raw
    }
}
```

## 新しいUnitsの定義

```swift:Units
/// Sequence containing exactly 1 element
public enum SingleTrait { }
/// Represents a push style sequence containing 1 element.
public typealias Single<Element> = PrimitiveSequence<SingleTrait, Element>

/// Sequence containing 0 or 1 elements
public enum MaybeTrait { }
/// Represents a push style sequence containing 0 or 1 element.
public typealias Maybe<Element> = PrimitiveSequence<MaybeTrait, Element>

/// Sequence containing 0 elements
public enum CompletableTrait { }
/// Represents a push style sequence containing 0 elements.
public typealias Completable = PrimitiveSequence<CompletableTrait, Swift.Never>
```

`SingleTrait` 、`MaybeTrait`、`CompletableTrait` とそれぞれの性質を表すenumが定義されてる。
`Single` 、 `Maybe` 、`Completable` が上述の `PrimitiveSequence` の typealiasとして定義されてる。

`Swift.Never`は初めて知った。何も返さないことはVoidじゃなくて `Never` で表すらしい。
([Never - Swift Standard Library | Apple Developer Documentation](https://developer.apple.com/reference/swift/never))

## PrimitiveSequenceTypeのプロトコル定義

```swift:PrimitiveSequenceType
/// Observable sequences containing 0 or 1 element
public protocol PrimitiveSequenceType {
    /// Additional constraints
    associatedtype TraitType
    /// Sequence element type
    associatedtype ElementType

    // Converts `self` to primitive sequence.
    ///
    /// - returns: Observable sequence that represents `self`.
    var primitiveSequence: PrimitiveSequence<TraitType, ElementType> { get }
}

extension PrimitiveSequence: PrimitiveSequenceType {
    /// Additional constraints
    public typealias TraitType = Trait
    /// Sequence element type
    public typealias ElementType = Element

    // Converts `self` to primitive sequence.
    ///
    /// - returns: Observable sequence that represents `self`.
    public var primitiveSequence: PrimitiveSequence<TraitType, ElementType> {
        return self
    }
}
``` 

ここで、`PrimitiveSequenceType` のプロトコルが定義される。
正直ここで Protocolを定義するがよくわかっていない。。。なんでだろ？
今後の似たようなUnitが出てきたにも対応できるように？:thinking: 
ジェネリクスをtypealiasとしておいた方が、 後術のprotocol extensionは書きやすくなる気がする。

## PrimitiveSeaquenceをObservableConvertibleTypeに適合

```swift:PrimitiveSequence
extension PrimitiveSequence: ObservableConvertibleType {
    /// Type of elements in sequence.
    public typealias E = Element

    /// Converts `self` to `Observable` sequence.
    ///
    /// - returns: Observable sequence that represents `self`.
    public func asObservable() -> Observable<E> {
        return source
    }
}
```

`ObservableConvertibleType` に適合させます。
とすることで、`PrimitiveSequence` はObservableにもなれます
狭い川は広くすることはできる。逆は不可。

## 各Unitsごと実装
その後は各性質ごとにEventや、`create`、`subscribe` 等の実装がされる。

```swift:SingleEvent
public enum SingleEvent<Element> {
    /// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)
    case success(Element)

    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
    case error(Swift.Error)
}

```

各性質ごとのfunctionの実装は `PrimitiveSequenceType` のExtensionとして実装される。
where でジェネリクスの型をを指定することによって、適合する場合のみこのextensionが使えるようになる。

```swift:PrimitiveSequenceType(SingleTrait)
extension PrimitiveSequenceType where TraitType == SingleTrait {
    public typealias SingleObserver = (SingleEvent<ElementType>) -> ()

    public func subscribe(_ observer: @escaping (SingleEvent<ElementType>) -> ()) -> Disposable {
        var stopped = false
        return self.primitiveSequence.asObservable().subscribe { event in
            if stopped { return }
            stopped = true

            switch event {
            case .next(let element):
                observer(.success(element))
            case .error(let error):
                observer(.error(error))
            case .completed:
                rxFatalError("Singles can't emit a completion event")
            }
        }
    } 

   // その他の実装は省略
}
```
`Single` の`subscribe` を見てもわかるように、`success` か、`error` しか流れない。
`completed`が流れてくるのは `Single` の仕様的にありえないので、fatalErrorでアプリが落ちる。

## そのほか

そのほかの共通的な `map`、`filter`などのオペレーターは whereなしの `PrimitiveSequenceType` のextensionとして実装。