         }
         return value
     }
-
-
+    
+    
     public func valueAtPath<T>(path: JSONPath, defaultValue: T) -> T {
         return valueAtPath(path, errorHandler: {_ in return defaultValue })
     }
-
-
+    
+    
     public func valueAtPath<T>(path: JSONPath) throws -> T {
         return try valueAtPath(path, errorHandler: {throw $0})
     }
-
-
+    
+    
     //MARK:- Reader fetching
-
+    
     public func readerAtPath(path: JSONPath, errorHandler: (JSONPathError) throws -> JSONReader = { throw $0 } ) rethrows -> JSONReader {
         let value: Any? = try optionalValueAtPath(path, substituteNSNullWithNil: false, errorHandler: errorHandler)
         guard let object = value else {
             return try errorHandler(.MissingValue(path: path))
         }
-
+        
         return JSONReader(object: object)
     }
 }
 
 
 public func ==(lhs: JSONReader, rhs: JSONReader) -> Bool {
-
+    
     if lhs.isEmpty && rhs.isEmpty {
         return true
     }
-
+    
     if let
         left:  NSArray = lhs.value(),
         right: NSArray = rhs.value() {
             return left == right
     }
-
+    
     if let
         left:  NSDictionary = lhs.value(),
         right: NSDictionary = rhs.value() {
             return left == right
     }
-
+    
     if let
         left:  NSString = lhs.value(),
         right: NSString = rhs.value() {
             return left == right
     }
-
+    
     if let
         left:  NSNull = lhs.value(),
         right: NSNull = rhs.value() {
             return left == right
     }
-
+    
     if let
         left:  NSNumber = lhs.value(),
         right: NSNumber = rhs.value() {
             return left == right
     }
-
+    
     return false
 }
+
+
+//MARK:- Array index additions
+
+extension NSArray {
+    
+    private func absoluteIndexForRelativeIndex(relativeIndex: Int) -> Int? {
+        
+        let count = self.count
+        let shouldInvertIndex = relativeIndex < 0
+        let index = shouldInvertIndex ? count + relativeIndex : relativeIndex
+        
+        let isInRange = index >= 0 && index < count
+        return isInRange ? index : nil
+    }
+    
+}



public final class JSONReader: Equatable {

    //MARK:- Errors

    public enum Error: ErrorType {
        case MissingValue
        case UnexpectedType(expectedType: Any.Type, actualType: Any.Type)
    }


    /// The object to attempt to fetch values from
    public let object: Any?

    public var isEmpty: Bool {
        return object == nil
    }


    //MARK:- Instance life cycle

    convenience public init(data: NSData, allowFragments: Bool = false) throws {
        let options: NSJSONReadingOptions = allowFragments ? [NSJSONReadingOptions.AllowFragments] : []
        let object = try NSJSONSerialization.JSONObjectWithData(data, options: options)
        self.init(object: object)
    }


    public init(object: Any?) {
        self.object = object
    }


    private convenience init() {
        self.init(object: nil)
    }


    //MARK:- Value access

    public func value<T>() -> T? {
        return object as? T
    }


    public func value<T>(errorHandler: (JSONReader.Error) throws -> T) rethrows -> T {
        guard object != nil else {
            let error = Error.MissingValue
            return try errorHandler(error)
        }

        guard let value = object as? T else {
            let error = Error.UnexpectedType(expectedType: T.self, actualType: object.dynamicType)
            return try errorHandler(error)
        }

        return value
    }


    //MARK:- Element access

    public func isValidIndex(relativeIndex: Int) -> Bool {
        return absoluteIndexForRelativeIndex(relativeIndex) != nil
    }


    private func absoluteIndexForRelativeIndex(relativeIndex: Int) -> Int? {
        guard let array = object as? NSArray else {
            return nil
        }

        let count = array.count
        let shouldInvertIndex = relativeIndex < 0
        let index = shouldInvertIndex ? count + relativeIndex : relativeIndex

        let isInRange = index >= 0 && index < count
        return isInRange ? index : nil
    }


    public subscript(relativeIndex: Int) -> JSONReader {
        guard let index = absoluteIndexForRelativeIndex(relativeIndex),
              let collection = object as? NSArray else {
            return JSONReader()
        }

        return JSONReader(object: collection[index])
    }


    public func isValidKey(key: String) -> Bool {
        guard let collection = object as? NSDictionary else {
            return false
        }

        return collection[key] != nil
    }


    public subscript(key: String) -> JSONReader {
        guard let collection = object as? NSDictionary,
              let element = collection[key] else {
            return JSONReader()
        }

        return JSONReader(object: element)
    }
}

//MARK:- JSONPath extension

extension JSONReader {
    
    public enum JSONPathError: ErrorType {
        public typealias JSONPathComponentsStack = [(JSONPath.Component, Any?)]
        case UnexpectedType(path: JSONPath, componentStack: JSONPathComponentsStack, Any.Type)
