public function process(Query $query, $rows)
    {
        $meta = [
            'hasPrevious' => false,
            'previousCursor' => null,
            'hasNext' => false,
            'nextCursor' => null,
        ];

        if ($this->shouldLtrim($query, $rows)) {
            $type = $query->direction()->forward() ? 'previous' : 'next';
            $meta['has' . ucfirst($type)] = true;
            $meta[$type . 'Cursor'] = $this->makeCursor(
                $query,
                $this->offset($rows, (int)$query->exclusive())
            );
            $rows = $this->slice($rows, 1);
        }
        if ($this->shouldRtrim($query, $rows)) {
            $type = $query->direction()->backward() ? 'previous' : 'next';
            $meta['has' . ucfirst($type)] = true;
            $meta[$type . 'Cursor'] = $this->makeCursor(
                $query,
                $this->offset($rows, $query->limit() - $query->exclusive())
            );
            $rows = $this->slice($rows, 0, $query->limit());
        }

        // If we are not using UNION ALL, boolean values are not defined.
        if (!$query->selectOrUnionAll() instanceof UnionAll) {
            $meta[$query->direction()->forward() ? 'hasPrevious' : 'hasNext'] = null;
        }

        return $this->invokeFormatter($this->shouldReverse($query) ? $this->reverse($rows) : $rows, $meta, $query);
    }