Converts Weld object to Python object.

        Args:
            obj: Result of Weld computation that needs to be decoded
            restype: Type of Weld computation result
            raw_ptr: Boolean indicating whether obj needs to be extracted
                     from WeldValue or not

        Returns:
            Python object representing result of the Weld computation

def decode(self, obj, restype, raw_ptr=False):
        """Converts Weld object to Python object.

        Args:
            obj: Result of Weld computation that needs to be decoded
            restype: Type of Weld computation result
            raw_ptr: Boolean indicating whether obj needs to be extracted
                     from WeldValue or not

        Returns:
            Python object representing result of the Weld computation
        """
        if raw_ptr:
            data = obj
        else:
            data = cweld.WeldValue(obj).data()
        result = ctypes.cast(data, ctypes.POINTER(restype.ctype_class)).contents

        if restype == WeldInt16():
            data = cweld.WeldValue(obj).data()
            result = ctypes.cast(data, ctypes.POINTER(c_int16)).contents.value
            return result
        elif restype == WeldInt():
            data = cweld.WeldValue(obj).data()
            result = ctypes.cast(data, ctypes.POINTER(c_int)).contents.value
            return result
        elif restype == WeldLong():
            data = cweld.WeldValue(obj).data()
            result = ctypes.cast(data, ctypes.POINTER(c_long)).contents.value
            return result
        elif restype == WeldFloat():
            data = cweld.WeldValue(obj).data()
            result = ctypes.cast(data, ctypes.POINTER(c_float)).contents.value
            return np.float32(result)
        elif restype == WeldDouble():
            data = cweld.WeldValue(obj).data()
            result = ctypes.cast(data, ctypes.POINTER(c_double)).contents.value
            return float(result)
        elif restype == WeldBit():
            data = cweld.WeldValue(obj).data()
            result = ctypes.cast(data, ctypes.POINTER(c_bool)).contents.value
            return bool(result)

        # Obj is a WeldVec(WeldInt()).ctype_class, which is a subclass of
        # ctypes._structure
        if restype == WeldVec(WeldBit()):
            weld_to_numpy = self.utils.weld_to_numpy_bool_arr
        elif restype == WeldVec(WeldInt16()):
            weld_to_numpy = self.utils.weld_to_numpy_int16_arr
        elif restype == WeldVec(WeldInt()):
            weld_to_numpy = self.utils.weld_to_numpy_int_arr
        elif restype == WeldVec(WeldLong()):
            weld_to_numpy = self.utils.weld_to_numpy_long_arr
        elif restype == WeldVec(WeldFloat()):
            weld_to_numpy = self.utils.weld_to_numpy_float_arr
        elif restype == WeldVec(WeldDouble()):
            weld_to_numpy = self.utils.weld_to_numpy_double_arr
        elif restype == WeldVec(WeldVec(WeldChar())):
            weld_to_numpy = self.utils.weld_to_numpy_char_arr_arr
        elif restype == WeldVec(WeldVec(WeldInt16())):
            weld_to_numpy = self.utils.weld_to_numpy_int16_arr_arr
        elif restype == WeldVec(WeldVec(WeldInt())):
            weld_to_numpy = self.utils.weld_to_numpy_int_arr_arr
        elif restype == WeldVec(WeldVec(WeldLong())):
            weld_to_numpy = self.utils.weld_to_numpy_long_arr_arr
        elif restype == WeldVec(WeldVec(WeldFloat())):
            weld_to_numpy = self.utils.weld_to_numpy_float_arr_arr
        elif restype == WeldVec(WeldVec(WeldDouble())):
            weld_to_numpy = self.utils.weld_to_numpy_double_arr_arr
        elif restype == WeldVec(WeldVec(WeldBit())):
            weld_to_numpy = self.utils.weld_to_numpy_bool_arr_arr
        elif isinstance(restype, WeldStruct):
            ret_vecs = []
            # Iterate through all fields in the struct, and recursively call
            # decode.
            for field_type in restype.field_types:
                ret_vec = self.decode(data, field_type, raw_ptr=True)
                data += sizeof(field_type.ctype_class())
                ret_vecs.append(ret_vec)
            return tuple(ret_vecs)
        else:
            raise Exception("Unable to decode; invalid return type")

        weld_to_numpy.restype = py_object
        weld_to_numpy.argtypes = [restype.ctype_class]

        ret_vec = weld_to_numpy(result)
        return ret_vec