<commit_before>//
//  Observable+MapTo.swift
//  Meow
//
//  Copyright © 2017年 喵喵喵的伙伴. All rights reserved.
//

import RxSwift
import SwiftyJSON

enum MeowError: String {
    case badCast, badData
}

extension MeowError: Swift.Error { }

extension Observable {
    func mapTo <T: JSONConvertible>(type: T.Type) -> Observable<T> {
        return map {
            (element) -> T in
            
            guard let json = element as? JSON else {
                throw MeowError.badData
            }
            guard let model = T.fromJSON(json) else {
                throw MeowError.badCast
            }
            return model
        }
    }
    
    func mapTo<T: JSONConvertible>(arrayOf type: T.Type) -> Observable<[T]> {
        return self.map {
            (element) -> [T] in
            guard let array = element as? [AnyObject], let jsonArray = array as? [JSON] else {
                throw MeowError.badData
            }
            
            do {
                let models = try jsonArray.map {
                    (jsonElement) -> T in
                    guard let model = T.fromJSON(jsonElement) else {
                        throw MeowError.badCast
                    }
                    return model
                }
            
                return models
            }<commit_msg>Use flatMap for better nil filtering<commit_after>//
//  Observable+MapTo.swift
//  Meow
//
//  Copyright © 2017年 喵喵喵的伙伴. All rights reserved.
//

import RxSwift
import SwiftyJSON

enum MeowError: String {
    case badCast, badData
}

extension MeowError: Swift.Error { }

extension Observable {
    func mapTo <T: JSONConvertible>(type: T.Type) -> Observable<T> {
        return map {
            (element) -> T in
            
            guard let json = element as? JSON else {
                throw MeowError.badData
            }
            guard let model = T.fromJSON(json) else {
                throw MeowError.badCast
            }
            return model
        }
    }
    
    func mapTo<T: JSONConvertible>(arrayOf type: T.Type) -> Observable<[T]> {
        return self.map {
            (element) -> [T] in
            guard let array = element as? [AnyObject], let jsonArray = array as? [JSON] else {
                throw MeowError.badData
            }
            
            return jsonArray.flatMap {
                (jsonElement) -> T? in
                T.fromJSON(jsonElement)
            }
{'fraction_non_alphanumeric': 0.08859721082854799, 'fraction_numerical': 0.003281378178835111, 'mean_word_length': 1.36108422071636, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2331173', 'n_tokens_mistral': 718, 'n_tokens_neox': 673, 'n_words': 188}