from sys import version_info

import gdb

if version_info[0] >= 3:
    xrange = range

ZERO_FIELD = "__0"
FIRST_FIELD = "__1"


def unwrap_unique_or_non_null(unique_or_nonnull):
    # BACKCOMPAT: rust 1.32
    # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
    # BACKCOMPAT: rust 1.60
    # https://github.com/rust-lang/rust/commit/2a91eeac1a2d27dd3de1bf55515d765da20fd86f
    ptr = unique_or_nonnull["pointer"]
    return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ptr.type.fields()[0]]


# GDB 14 has a tag class that indicates that extension methods are ok
# to call.  Use of this tag only requires that printers hide local
# attributes and methods by prefixing them with "_".
if hasattr(gdb, 'ValuePrinter'):
    printer_base = gdb.ValuePrinter
else:
    printer_base = object


class EnumProvider(printer_base):
    def __init__(self, valobj):
        content = valobj[valobj.type.fields()[0]]
        fields = content.type.fields()
        self._empty = len(fields) == 0
        if not self._empty:
            if len(fields) == 1:
                discriminant = 0
            else:
                discriminant = int(content[fields[0]]) + 1
            self._active_variant = content[fields[discriminant]]
            self._name = fields[discriminant].name
            self._full_name = "{}::{}".format(valobj.type.name, self._name)
        else:
            self._full_name = valobj.type.name

    def to_string(self):
        return self._full_name

    def children(self):
        if not self._empty:
            yield self._name, self._active_variant


class StdStringProvider(printer_base):
    def __init__(self, valobj):
        self._valobj = valobj
        vec = valobj["vec"]
        self._length = int(vec["len"])
        self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["inner"]["ptr"])

    def to_string(self):
        return self._data_ptr.lazy_string(encoding="utf-8", length=self._length)

    @staticmethod
    def display_hint():
        return "string"


class StdOsStringProvider(printer_base):
    def __init__(self, valobj):
        self._valobj = valobj
        buf = self._valobj["inner"]["inner"]
        is_windows = "Wtf8Buf" in buf.type.name
        vec = buf[ZERO_FIELD] if is_windows else buf

        self._length = int(vec["len"])
        self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["inner"]["ptr"])

    def to_string(self):
        return self._data_ptr.lazy_string(encoding="utf-8", length=self._length)

    def display_hint(self):
        return "string"


class StdStrProvider(printer_base):
    def __init__(self, valobj):
        self._valobj = valobj
        self._length = int(valobj["length"])
        self._data_ptr = valobj["data_ptr"]

    def to_string(self):
        return self._data_ptr.lazy_string(encoding="utf-8", length=self._length)

    @staticmethod
    def display_hint():
        return "string"


def _enumerate_array_elements(element_ptrs):
    for (i, element_ptr) in enumerate(element_ptrs):
        key = "[{}]".format(i)
        element = element_ptr.dereference()

        try:
            # rust-lang/rust#64343: passing deref expr to `str` allows
            # catching exception on garbage pointer
            str(element)
        except RuntimeError:
            yield key, "inaccessible"

            break

        yield key, element


class StdSliceProvider(printer_base):
    def __init__(self, valobj):
        self._valobj = valobj
        self._length = int(valobj["length"])
        self._data_ptr = valobj["data_ptr"]

    def to_string(self):
        return "{}(size={})".format(self._valobj.type, self._length)

    def children(self):
        return _enumerate_array_elements(
            self._data_ptr + index for index in xrange(self._length)
        )

    @staticmethod
    def display_hint():
        return "array"


class StdVecProvider(printer_base):
    def __init__(self, valobj):
        self._valobj = valobj
        self._length = int(valobj["len"])
        self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["inner"]["ptr"])
        ptr_ty = gdb.Type.pointer(valobj.type.template_argument(0))
        self._data_ptr = self._data_ptr.reinterpret_cast(ptr_ty)

    def to_string(self):
        return "Vec(size={})".format(self._length)

    def children(self):
        return _enumerate_array_elements(
            self._data_ptr + index for index in xrange(self._length)
        )

    @staticmethod
    def display_hint():
        return "array"


class StdVecDequeProvider(printer_base):
    def __init__(self, valobj):
        self._valobj = valobj
        self._head = int(valobj["head"])
        self._size = int(valobj["len"])
        # BACKCOMPAT: rust 1.75
        cap = valobj["buf"]["inner"]["cap"]
        if cap.type.code != gdb.TYPE_CODE_INT:
            cap = cap[ZERO_FIELD]
        self._cap = int(cap)
        self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["inner"]["ptr"])
        ptr_ty = gdb.Type.pointer(valobj.type.template_argument(0))
        self._data_ptr = self._data_ptr.reinterpret_cast(ptr_ty)

    def to_string(self):
        return "VecDeque(size={})".format(self._size)

    def children(self):
        return _enumerate_array_elements(
            (self._data_ptr + ((self._head + index) % self._cap)) for index in xrange(self._size)
        )

    @staticmethod
    def display_hint():
        return "array"


class StdRcProvider(printer_base):
    def __init__(self, valobj, is_atomic=False):
        self._valobj = valobj
        self._is_atomic = is_atomic
        self._ptr = unwrap_unique_or_non_null(valobj["ptr"])
        self._value = self._ptr["data" if is_atomic else "value"]
        self._strong = self._ptr["strong"]["v" if is_atomic else "value"]["value"]
        self._weak = self._ptr["weak"]["v" if is_atomic else "value"]["value"] - 1

    def to_string(self):
        if self._is_atomic:
            return "Arc(strong={}, weak={})".format(int(self._strong), int(self._weak))
        else:
            return "Rc(strong={}, weak={})".format(int(self._strong), int(self._weak))

    def children(self):
        yield "value", self._value
        yield "strong", self._strong
        yield "weak", self._weak


class StdCellProvider(printer_base):
    def __init__(self, valobj):
        self._value = valobj["value"]["value"]

    def to_string(self):
        return "Cell"

    def children(self):
        yield "value", self._value


class StdRefProvider(printer_base):
    def __init__(self, valobj):
        self._value = valobj["value"].dereference()
        self._borrow = valobj["borrow"]["borrow"]["value"]["value"]

    def to_string(self):
        borrow = int(self._borrow)
        if borrow >= 0:
            return "Ref(borrow={})".format(borrow)
        else:
            return "Ref(borrow_mut={})".format(-borrow)

    def children(self):
        yield "*value", self._value
        yield "borrow", self._borrow


class StdRefCellProvider(printer_base):
    def __init__(self, valobj):
        self._value = valobj["value"]["value"]
        self._borrow = valobj["borrow"]["value"]["value"]

    def to_string(self):
        borrow = int(self._borrow)
        if borrow >= 0:
            return "RefCell(borrow={})".format(borrow)
        else:
            return "RefCell(borrow_mut={})".format(-borrow)

    def children(self):
        yield "value", self._value
        yield "borrow", self._borrow


class StdNonZeroNumberProvider(printer_base):
    def __init__(self, valobj):
        fields = valobj.type.fields()
        assert len(fields) == 1
        field = list(fields)[0]

        inner_valobj = valobj[field.name]

        inner_fields = inner_valobj.type.fields()
        assert len(inner_fields) == 1
        inner_field = list(inner_fields)[0]

        self._value = str(inner_valobj[inner_field.name])

    def to_string(self):
        return self._value


# Yields children (in a provider's sense of the word) for a BTreeMap.
def children_of_btree_map(map):
    # Yields each key/value pair in the node and in any child nodes.
    def children_of_node(node_ptr, height):
        def cast_to_internal(node):
            internal_type_name = node.type.target().name.replace("LeafNode", "InternalNode", 1)
            internal_type = gdb.lookup_type(internal_type_name)
            return node.cast(internal_type.pointer())

        if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"):
            # BACKCOMPAT: rust 1.49
            node_ptr = node_ptr["ptr"]
        node_ptr = unwrap_unique_or_non_null(node_ptr)
        leaf = node_ptr.dereference()
        keys = leaf["keys"]
        vals = leaf["vals"]
        edges = cast_to_internal(node_ptr)["edges"] if height > 0 else None
        length = leaf["len"]

        for i in xrange(0, length + 1):
            if height > 0:
                child_ptr = edges[i]["value"]["value"]
                for child in children_of_node(child_ptr, height - 1):
                    yield child
            if i < length:
                # Avoid "Cannot perform pointer math on incomplete type" on zero-sized arrays.
                key_type_size = keys.type.sizeof
                val_type_size = vals.type.sizeof
                key = keys[i]["value"]["value"] if key_type_size > 0 else gdb.parse_and_eval("()")
                val = vals[i]["value"]["value"] if val_type_size > 0 else gdb.parse_and_eval("()")
                yield key, val

    if map["length"] > 0:
        root = map["root"]
        if root.type.name.startswith("core::option::Option<"):
            root = root.cast(gdb.lookup_type(root.type.name[21:-1]))
        node_ptr = root["node"]
        height = root["height"]
        for child in children_of_node(node_ptr, height):
            yield child


class StdBTreeSetProvider(printer_base):
    def __init__(self, valobj):
        self._valobj = valobj

    def to_string(self):
        return "BTreeSet(size={})".format(self._valobj["map"]["length"])

    def children(self):
        inner_map = self._valobj["map"]
        for i, (child, _) in enumerate(children_of_btree_map(inner_map)):
            yield "[{}]".format(i), child

    @staticmethod
    def display_hint():
        return "array"


class StdBTreeMapProvider(printer_base):
    def __init__(self, valobj):
        self._valobj = valobj

    def to_string(self):
        return "BTreeMap(size={})".format(self._valobj["length"])

    def children(self):
        for i, (key, val) in enumerate(children_of_btree_map(self._valobj)):
            yield "key{}".format(i), key
            yield "val{}".format(i), val

    @staticmethod
    def display_hint():
        return "map"


# BACKCOMPAT: rust 1.35
class StdOldHashMapProvider(printer_base):
    def __init__(self, valobj, show_values=True):
        self._valobj = valobj
        self._show_values = show_values

        self._table = self._valobj["table"]
        self._size = int(self._table["size"])
        self._hashes = self._table["hashes"]
        self._hash_uint_type = self._hashes.type
        self._hash_uint_size = self._hashes.type.sizeof
        self._modulo = 2 ** self._hash_uint_size
        self._data_ptr = self._hashes[ZERO_FIELD]["pointer"]

        self._capacity_mask = int(self._table["capacity_mask"])
        self._capacity = (self._capacity_mask + 1) % self._modulo

        marker = self._table["marker"].type
        self._pair_type = marker.template_argument(0)
        self._pair_type_size = self._pair_type.sizeof

        self._valid_indices = []
        for idx in range(self._capacity):
            data_ptr = self._data_ptr.cast(self._hash_uint_type.pointer())
            address = data_ptr + idx
            hash_uint = address.dereference()
            hash_ptr = hash_uint[ZERO_FIELD]["pointer"]
            if int(hash_ptr) != 0:
                self._valid_indices.append(idx)

    def to_string(self):
        if self._show_values:
            return "HashMap(size={})".format(self._size)
        else:
            return "HashSet(size={})".format(self._size)

    def children(self):
        start = int(self._data_ptr) & ~1

        hashes = self._hash_uint_size * self._capacity
        align = self._pair_type_size
        len_rounded_up = (((((hashes + align) % self._modulo - 1) % self._modulo) & ~(
                (align - 1) % self._modulo)) % self._modulo - hashes) % self._modulo

        pairs_offset = hashes + len_rounded_up
        pairs_start = gdb.Value(start + pairs_offset).cast(self._pair_type.pointer())

        for index in range(self._size):
            table_index = self._valid_indices[index]
            idx = table_index & self._capacity_mask
            element = (pairs_start + idx).dereference()
            if self._show_values:
                yield "key{}".format(index), element[ZERO_FIELD]
                yield "val{}".format(index), element[FIRST_FIELD]
            else:
                yield "[{}]".format(index), element[ZERO_FIELD]

    def display_hint(self):
        return "map" if self._show_values else "array"


class StdHashMapProvider(printer_base):
    def __init__(self, valobj, show_values=True):
        self._valobj = valobj
        self._show_values = show_values

        table = self._table()
        table_inner = table["table"]
        capacity = int(table_inner["bucket_mask"]) + 1
        ctrl = table_inner["ctrl"]["pointer"]

        self._size = int(table_inner["items"])
        self._pair_type = table.type.template_argument(0).strip_typedefs()

        self._new_layout = not table_inner.type.has_key("data")
        if self._new_layout:
            self._data_ptr = ctrl.cast(self._pair_type.pointer())
        else:
            self._data_ptr = table_inner["data"]["pointer"]

        self._valid_indices = []
        for idx in range(capacity):
            address = ctrl + idx
            value = address.dereference()
            is_presented = value & 128 == 0
            if is_presented:
                self._valid_indices.append(idx)

    def _table(self):
        if self._show_values:
            hashbrown_hashmap = self._valobj["base"]
        elif self._valobj.type.fields()[0].name == "map":
            # BACKCOMPAT: rust 1.47
            # HashSet wraps std::collections::HashMap, which wraps hashbrown::HashMap
            hashbrown_hashmap = self._valobj["map"]["base"]
        else:
            # HashSet wraps hashbrown::HashSet, which wraps hashbrown::HashMap
            hashbrown_hashmap = self._valobj["base"]["map"]
        return hashbrown_hashmap["table"]

    def to_string(self):
        if self._show_values:
            return "HashMap(size={})".format(self._size)
        else:
            return "HashSet(size={})".format(self._size)

    def children(self):
        pairs_start = self._data_ptr

        for index in range(self._size):
            idx = self._valid_indices[index]
            if self._new_layout:
                idx = -(idx + 1)
            element = (pairs_start + idx).dereference()
            if self._show_values:
                yield "key{}".format(index), element[ZERO_FIELD]
                yield "val{}".format(index), element[FIRST_FIELD]
            else:
                yield "[{}]".format(index), element[ZERO_FIELD]

    def display_hint(self):
        return "map" if self._show_values else "array"
