public static function parseSchema(array $arr) {
        $result = [];

        foreach ($arr as $key => $value) {
            if (is_int($key)) {
                if (is_string($value)) {
                    // This is a short param value.
                    $param = static::parseShortParam($value);
                    $name = $param['name'];
                    $result[$name] = $param;
                } else {
                    throw new \InvalidArgumentException("Schema at position $key is not a valid param.", 500);
                }
            } else {
                // The parameter is defined in the key.
                $param = static::parseShortParam($key, $value);
                $name = $param['name'];

                if (is_array($value)) {
                    // The value describes a bit more about the schema.
                    switch ($param['type']) {
                        case 'array':
                            if (isset($value['items'])) {
                                // The value includes array schema information.
                                $param = array_replace($param, $value);
                            } elseif (isset($value['type'])) {
                                // The value is a long-form schema.
                                $param['items'] = $value;
                            } else {
                                // The value is another shorthand schema.
                                $param['items'] = [
                                    'type' => 'object',
                                    'required' => true,
                                    'properties' => static::parseSchema($value)
                                ];
                            }
                            break;
                        case 'object':
                            // The value is a schema of the object.
                            if (isset($value['properties'])) {
                                $param['properties'] = static::parseSchema($value['properties']);
                            } else {
                                $param['properties'] = static::parseSchema($value);
                            }
                            break;
                        default:
                            $param = array_replace($param, $value);
                            break;
                    }
                } elseif (is_string($value)) {
                    if ($param['type'] === 'array') {
                        // Check to see if the value is the item type in the array.
                        if (isset(self::$types[$value])) {
                            $arrType = self::$types[$value];
                        } elseif (($index = array_search($value, self::$types)) !== false) {
                            $arrType = self::$types[$index];
                        }

                        if (isset($arrType)) {
                            $param['items'] = ['type' => $arrType, 'required' => true];
                        } else {
                            $param['description'] = $value;
                        }
                    } else {
                        // The value is the schema description.
                        $param['description'] = $value;
                    }
                }

                $result[$name] = $param;
            }
        }

        return $result;
    }