from typing import Optional, Sequence, Union, Set, Iterable

__all__ = ['DerObject', 'DerInteger', 'DerOctetString', 'DerNull',
           'DerSequence', 'DerObjectId', 'DerBitString', 'DerSetOf']

# TODO: Make the encoded DerObjects their own type, so that DerSequence and
# DerSetOf can check their contents better

class BytesIO_EOF:
    def __init__(self, initial_bytes: bytes) -> None: ...
    def set_bookmark(self) -> None: ...
    def data_since_bookmark(self) -> bytes: ...
    def remaining_data(self) -> int: ...
    def read(self, length: int) -> bytes: ...
    def read_byte(self) -> bytes: ...

class DerObject:
    payload: bytes
    def __init__(self, asn1Id: Optional[int]=None, payload: Optional[bytes]=..., implicit: Optional[int]=None,
                 constructed: Optional[bool]=False, explicit: Optional[int]=None) -> None: ...
    def encode(self) -> bytes: ...
    def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObject: ...

class DerInteger(DerObject):
    value: int
    def __init__(self, value: Optional[int]= 0, implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ...
    def encode(self) -> bytes: ...
    def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerInteger: ...

class DerSequence(DerObject):
    def __init__(self, startSeq: Optional[Sequence[Union[int, DerInteger, DerObject]]]=None, implicit: Optional[int]=None) -> None: ...
    def __delitem__(self, n: int) -> None: ...
    def __getitem__(self, n: int) -> None: ...
    def __setitem__(self, key: int, value: DerObject) -> None: ...
    def __setslice__(self, i: int, j: int, sequence: Sequence) -> None: ...
    def __delslice__(self, i: int, j: int) -> None: ...
    def __getslice__(self, i: int, j: int) -> DerSequence: ...
    def __len__(self) -> int: ...
    def __iadd__(self, item: DerObject) -> DerSequence: ...
    def append(self, item: DerObject) -> DerSequence: ...
    def hasInts(self, only_non_negative: Optional[bool]=True) -> int: ...
    def hasOnlyInts(self, only_non_negative: Optional[bool]=True) -> bool: ...
    def encode(self) -> bytes: ...
    def decode(self, der_encoded: bytes, strict: Optional[bool]=False, nr_elements: Optional[int]=None, only_ints_expected: Optional[bool]=False) -> DerSequence: ...

class DerOctetString(DerObject):
    payload: bytes
    def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None) -> None: ...

class DerNull(DerObject):
    def __init__(self) -> None: ...

class DerObjectId(DerObject):
    value: str
    def __init__(self, value: Optional[str]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ...
    def encode(self) -> bytes: ...
    def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObjectId: ...

class DerBitString(DerObject):
    value: bytes
    def __init__(self, value: Optional[bytes]=..., implicit: Optional[int]=None, explicit: Optional[int]=None) -> None: ...
    def encode(self) -> bytes: ...
    def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerBitString: ...

DerSetElement = Union[bytes, int]

class DerSetOf(DerObject):
    def __init__(self, startSet: Optional[Set[DerSetElement]]=None, implicit: Optional[int]=None) -> None: ...
    def __getitem__(self, n: int) -> DerSetElement: ...
    def __iter__(self) -> Iterable: ...
    def __len__(self) -> int: ...
    def add(self, elem: DerSetElement) -> None: ...
    def decode(self, der_encoded: bytes, strict: Optional[bool]=False) -> DerObject: ...
    def encode(self) -> bytes: ...
