# Path: pdfminer/arcfour.py
# class Arcfour:
#     def __init__(self, key: Sequence[int]) -> None:
#         # because Py3 range is not indexable
#         s = [i for i in range(256)]
#         j = 0
#         klen = len(key)
#         for i in range(256):
#             j = (j + s[i] + key[i % klen]) % 256
#             (s[i], s[j]) = (s[j], s[i])
#         self.s = s
#         (self.i, self.j) = (0, 0)
# 
#     def process(self, data: bytes) -> bytes:
#         (i, j) = (self.i, self.j)
#         s = self.s
#         r = b""
#         for c in iter(data):
#             i = (i + 1) % 256
#             j = (j + s[i]) % 256
#             (s[i], s[j]) = (s[j], s[i])
#             k = s[(s[i] + s[j]) % 256]
#             r += bytes((c ^ k,))
#         (self.i, self.j) = (i, j)
#         return r
# 
#     encrypt = decrypt = process
# 
# Path: pdfminer/ascii85.py
# def asciihexdecode(data: bytes) -> bytes:
#     """
#     ASCIIHexDecode filter: PDFReference v1.4 section 3.3.1
#     For each pair of ASCII hexadecimal digits (0-9 and A-F or a-f), the
#     ASCIIHexDecode filter produces one byte of binary data. All white-space
#     characters are ignored. A right angle bracket character (>) indicates
#     EOD. Any other characters will cause an error. If the filter encounters
#     the EOD marker after reading an odd number of hexadecimal digits, it
#     will behave as if a 0 followed the last digit.
#     """
# 
#     def decode(x: bytes) -> bytes:
#         i = int(x, 16)
#         return bytes((i,))
# 
#     out = b""
#     for x in hex_re.findall(data):
#         out += decode(x)
# 
#     m = trail_re.search(data)
#     if m:
#         out += decode(m.group(1) + b"0")
#     return out
# 
# def ascii85decode(data: bytes) -> bytes:
#     """
#     In ASCII85 encoding, every four bytes are encoded with five ASCII
#     letters, using 85 different types of characters (as 256**4 < 85**5).
#     When the length of the original bytes is not a multiple of 4, a special
#     rule is used for round up.
# 
#     The Adobe's ASCII85 implementation is slightly different from
#     its original in handling the last characters.
# 
#     """
#     n = b = 0
#     out = b""
#     for i in iter(data):
#         c = bytes((i,))
#         if b"!" <= c and c <= b"u":
#             n += 1
#             b = b * 85 + (ord(c) - 33)
#             if n == 5:
#                 out += struct.pack(">L", b)
#                 n = b = 0
#         elif c == b"z":
#             assert n == 0, str(n)
#             out += b"\0\0\0\0"
#         elif c == b"~":
#             if n:
#                 for _ in range(5 - n):
#                     b = b * 85 + 84
#                 out += struct.pack(">L", b)[: n - 1]
#             break
#     return out
# 
# Path: pdfminer/lzw.py
# def lzwdecode(data: bytes) -> bytes:
#     fp = BytesIO(data)
#     s = LZWDecoder(fp).run()
#     return b"".join(s)
# 
# Path: pdfminer/runlength.py
# def rldecode(data: bytes) -> bytes:
#     """
#     RunLength decoder (Adobe version) implementation based on PDF Reference
#     version 1.4 section 3.3.4:
#         The RunLengthDecode filter decodes data that has been encoded in a
#         simple byte-oriented format based on run length. The encoded data
#         is a sequence of runs, where each run consists of a length byte
#         followed by 1 to 128 bytes of data. If the length byte is in the
#         range 0 to 127, the following length + 1 (1 to 128) bytes are
#         copied literally during decompression. If length is in the range
#         129 to 255, the following single byte is to be copied 257 - length
#         (2 to 128) times during decompression. A length value of 128
#         denotes EOD.
#     """
#     decoded = b""
#     i = 0
#     while i < len(data):
#         length = data[i]
#         if length == 128:
#             break
# 
#         if length >= 0 and length < 128:
#             for j in range(i + 1, (i + 1) + (length + 1)):
#                 decoded += bytes((data[j],))
#             i = (i + 1) + (length + 1)
# 
#         if length > 128:
#             run = bytes((data[i + 1],)) * (257 - length)
#             decoded += run
#             i = (i + 1) + 1
# 
#     return decoded


import binascii
from pdfminer.arcfour import Arcfour
from pdfminer.ascii85 import asciihexdecode, ascii85decode
from pdfminer.lzw import lzwdecode
from pdfminer.runlength import rldecode
"""Test of various compression/encoding modules (previously in doctests)
"""



def hex(b):
    """encode('hex')"""
    return binascii.hexlify(b)


def dehex(b):
    """decode('hex')"""
    return binascii.unhexlify(b)


class TestAscii85:
    def test_ascii85decode(self):
        """The sample string is taken from:
        http://en.wikipedia.org/w/index.php?title=Ascii85"""
        assert ascii85decode(b"9jqo^BlbD-BleB1DJ+*+F(f,q") == b"Man is distinguished"
        assert ascii85decode(b"E,9)oF*2M7/c~>") == b"pleasure."

    def test_asciihexdecode(self):
        assert asciihexdecode(b"61 62 2e6364   65") == b"ab.cde"
        assert asciihexdecode(b"61 62 2e6364   657>") == b"ab.cdep"
        assert asciihexdecode(b"7>") == b"p"


class TestArcfour:
    def test(self):

# Path: pdfminer/arcfour.py
# class Arcfour:
#     def __init__(self, key: Sequence[int]) -> None:
#         # because Py3 range is not indexable
#         s = [i for i in range(256)]
#         j = 0
#         klen = len(key)
#         for i in range(256):
#             j = (j + s[i] + key[i % klen]) % 256
#             (s[i], s[j]) = (s[j], s[i])
#         self.s = s
#         (self.i, self.j) = (0, 0)
# 
#     def process(self, data: bytes) -> bytes:
#         (i, j) = (self.i, self.j)
#         s = self.s
#         r = b""
#         for c in iter(data):
#             i = (i + 1) % 256
#             j = (j + s[i]) % 256
#             (s[i], s[j]) = (s[j], s[i])
#             k = s[(s[i] + s[j]) % 256]
#             r += bytes((c ^ k,))
#         (self.i, self.j) = (i, j)
#         return r
# 
#     encrypt = decrypt = process
# 
# Path: pdfminer/ascii85.py
# def asciihexdecode(data: bytes) -> bytes:
#     """
#     ASCIIHexDecode filter: PDFReference v1.4 section 3.3.1
#     For each pair of ASCII hexadecimal digits (0-9 and A-F or a-f), the
#     ASCIIHexDecode filter produces one byte of binary data. All white-space
#     characters are ignored. A right angle bracket character (>) indicates
#     EOD. Any other characters will cause an error. If the filter encounters
#     the EOD marker after reading an odd number of hexadecimal digits, it
#     will behave as if a 0 followed the last digit.
#     """
# 
#     def decode(x: bytes) -> bytes:
#         i = int(x, 16)
#         return bytes((i,))
# 
#     out = b""
#     for x in hex_re.findall(data):
#         out += decode(x)
# 
#     m = trail_re.search(data)
#     if m:
#         out += decode(m.group(1) + b"0")
#     return out
# 
# def ascii85decode(data: bytes) -> bytes:
#     """
#     In ASCII85 encoding, every four bytes are encoded with five ASCII
#     letters, using 85 different types of characters (as 256**4 < 85**5).
#     When the length of the original bytes is not a multiple of 4, a special
#     rule is used for round up.
# 
#     The Adobe's ASCII85 implementation is slightly different from
#     its original in handling the last characters.
# 
#     """
#     n = b = 0
#     out = b""
#     for i in iter(data):
#         c = bytes((i,))
#         if b"!" <= c and c <= b"u":
#             n += 1
#             b = b * 85 + (ord(c) - 33)
#             if n == 5:
#                 out += struct.pack(">L", b)
#                 n = b = 0
#         elif c == b"z":
#             assert n == 0, str(n)
#             out += b"\0\0\0\0"
#         elif c == b"~":
#             if n:
#                 for _ in range(5 - n):
#                     b = b * 85 + 84
#                 out += struct.pack(">L", b)[: n - 1]
#             break
#     return out
# 
# Path: pdfminer/lzw.py
# def lzwdecode(data: bytes) -> bytes:
#     fp = BytesIO(data)
#     s = LZWDecoder(fp).run()
#     return b"".join(s)
# 
# Path: pdfminer/runlength.py
# def rldecode(data: bytes) -> bytes:
#     """
#     RunLength decoder (Adobe version) implementation based on PDF Reference
#     version 1.4 section 3.3.4:
#         The RunLengthDecode filter decodes data that has been encoded in a
#         simple byte-oriented format based on run length. The encoded data
#         is a sequence of runs, where each run consists of a length byte
#         followed by 1 to 128 bytes of data. If the length byte is in the
#         range 0 to 127, the following length + 1 (1 to 128) bytes are
#         copied literally during decompression. If length is in the range
#         129 to 255, the following single byte is to be copied 257 - length
#         (2 to 128) times during decompression. A length value of 128
#         denotes EOD.
#     """
#     decoded = b""
#     i = 0
#     while i < len(data):
#         length = data[i]
#         if length == 128:
#             break
# 
#         if length >= 0 and length < 128:
#             for j in range(i + 1, (i + 1) + (length + 1)):
#                 decoded += bytes((data[j],))
#             i = (i + 1) + (length + 1)
# 
#         if length > 128:
#             run = bytes((data[i + 1],)) * (257 - length)
#             decoded += run
#             i = (i + 1) + 1
# 
#     return decoded


# Path: tests/test_pdfminer_crypto.py
import binascii
from pdfminer.arcfour import Arcfour
from pdfminer.ascii85 import asciihexdecode, ascii85decode
from pdfminer.lzw import lzwdecode
from pdfminer.runlength import rldecode

"""Test of various compression/encoding modules (previously in doctests)
"""



def hex(b):
    """encode('hex')"""
    return binascii.hexlify(b)


def dehex(b):
    """decode('hex')"""
    return binascii.unhexlify(b)


class TestAscii85:
    def test_ascii85decode(self):
        """The sample string is taken from:
        http://en.wikipedia.org/w/index.php?title=Ascii85"""
        assert ascii85decode(b"9jqo^BlbD-BleB1DJ+*+F(f,q") == b"Man is distinguished"
        assert ascii85decode(b"E,9)oF*2M7/c~>") == b"pleasure."

    def test_asciihexdecode(self):
        assert asciihexdecode(b"61 62 2e6364   65") == b"ab.cde"
        assert asciihexdecode(b"61 62 2e6364   657>") == b"ab.cdep"
        assert asciihexdecode(b"7>") == b"p"


class TestArcfour:
    def test(self):

        assert hex(Arcfour(b"Key").process(b"Plaintext")) == b"bbf316e8d940af0ad3"