         }
     }
 }
+
+// MARK: - Path nodes
+
+private protocol UnboxPathNode {
+    func unboxPathValue(forKey key: String) -> Any?
+}
+
+extension Dictionary: UnboxPathNode {
+    func unboxPathValue(forKey key: String) -> Any? {
+        return self[key as! Key]
+    }
+}
+
+extension Array: UnboxPathNode {
+    func unboxPathValue(forKey key: String) -> Any? {
+        guard let index = Int(key) else {
+            return nil
+        }
+        
+        if index >= self.count {
+            return nil
+        }
+        
+        return self[index]
+    }
+}
+
+#if !os(Linux)
+extension NSDictionary: UnboxPathNode {
+    func unboxPathValue(forKey key: String) -> Any? {
+        return self[key]
+    }
+}
+    
+extension NSArray: UnboxPathNode {
+    func unboxPathValue(forKey key: String) -> Any? {
+        return (self as Array).unboxPathValue(forKey: key)
+    }
+}
+#endif
 
 private extension Unboxer {
     func unbox<R>(path: UnboxPath, transform: UnboxTransform<R>) throws -> R {

    }
}

// MARK: - UnboxingMode

private enum UnboxingMode {
    case dictionary(UnboxableDictionary)
    case array([Any])
    case value(Any)
}

extension UnboxingMode {
    var value: Any {
        switch self {
        case .dictionary(let dictionary):
            return dictionary
        case .array(let array):
            return array
        case .value(let value):
            return value
        }
    }
    
    init(value: Any) {
        if let dictionary = value as? UnboxableDictionary {
            self = .dictionary(dictionary)
        } else if let array = value as? [Any] {
            self = .array(array)
        } else {
            self = .value(value)
        }
    }
}

// MARK: - UnboxContainers

private struct UnboxContainer<T: Unboxable>: UnboxableWithContext {

                let value = try self.dictionary[key].orThrow(UnboxPathError.missingKey(key))
                return try transform(value).orThrow(UnboxPathError.invalidValue(value, key))
            case .keyPath(let keyPath):
                var node: UnboxPathNode = self.dictionary
                let components = keyPath.components(separatedBy: ".")
                let lastKey = components.last
                
                for key in components {
                    guard let nextValue = node.unboxPathValue(forKey: key) else {
                        throw UnboxPathError.missingKey(key)
                    }
                    
                    if key == lastKey {
                        return try transform(nextValue).orThrow(UnboxPathError.invalidValue(nextValue, key))
                    }
                    
                    guard let nextNode = nextValue as? UnboxPathNode else {
                        print(type(of: nextValue))
                        throw UnboxPathError.invalidValue(nextValue, key)
                    }
                    
                    node = nextNode
                }
                
                throw UnboxPathError.emptyKeyPath
            }
        } catch {
            if let publicError = error as? UnboxError {
