# HG changeset patch
# User Jan Pipek <jan.pipek@gmail.com>
# Date 1568368254 -7200
#      Fri Sep 13 11:50:54 2019 +0200
# Node ID 4329c4c1b263de4c6275e5b2d65574d0d38f446b
# Parent  7dec84bf88d88a3f084bd2c03e9733a3eaae3371
Address several pull requests comments + hide asSeekableStream

diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py
--- a/pyasn1/codec/ber/decoder.py
+++ b/pyasn1/codec/ber/decoder.py
@@ -6,7 +6,7 @@
 #
 import os
 import sys
-from io import BytesIO, BufferedReader, IOBase
+from io import BytesIO, BufferedReader, IOBase, DEFAULT_BUFFER_SIZE
 
 from pyasn1 import debug
 from pyasn1 import error
@@ -22,28 +22,31 @@
 from pyasn1.type import useful
 
 
-__all__ = ['decodeStream']
+__all__ = ['decodeStream', 'decode']
 
 LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER)
 
 noValue = base.noValue
 
 
-_MAX_BUFFER_SIZE = 1024
 _PY2 = sys.version_info < (3,)
 
 
-class _CachedStreamWrapper(IOBase):
-    """Wrapper around non-seekable streams."""
+class _CachingStreamWrapper(IOBase):
+    """Wrapper around non-seekable streams.
+
+    Note that the implementation is tied to the decoder,
+    not checking for dangerous arguments for the sake
+    of performance.
+    """
     def __init__(self, raw):
         self._raw = raw
         self._cache = BytesIO()
-        self._marked_position_ = 0
+        self._markedPosition_ = 0
 
     def peek(self, n):
-        pos = self._cache.tell()
         result = self.read(n)
-        self._cache.seek(pos, os.SEEK_SET)
+        self._cache.seek(-len(result), os.SEEK_CUR)
         return result
 
     def seekable(self):
@@ -61,37 +64,32 @@
         return read_from_cache + read_from_raw
 
     @property
-    def _marked_position(self):
+    def _markedPosition(self):
         # This closely corresponds with how _marked_position attribute
         # is manipulated with in Decoder.__call__ and (indefLen)ValueDecoder's
-        return self._marked_position_
-
-    @_marked_position.setter
-    def _marked_position(self, value):
-        self._marked_position_ = value
-        self.seek(value)
-        self.reset()
+        return self._markedPosition_
 
-    def tell(self):
-        return self._cache.tell()
-
-    def reset(self):
-        """Keep the buffered data reasonably large.
+    @_markedPosition.setter
+    def _markedPosition(self, value):
+        self._markedPosition_ = value
+        self.seek(value)
 
-        Whenever we se _marked_position, we know for sure
-        that we will not return back, and thus it is
-        safe to drop all cached data.
-        """
-        if self._cache.tell() > _MAX_BUFFER_SIZE:
+        # Whenever we set _marked_position, we know for sure
+        # that we will not return back, and thus it is
+        # safe to drop all cached data.
+        if self._cache.tell() > DEFAULT_BUFFER_SIZE:
             current = self._cache.read()
             self._cache.seek(0, os.SEEK_SET)
             self._cache.truncate()
             self._cache.write(current)
             self._cache.seek(0, os.SEEK_SET)
-            self._marked_position_ = 0
+            self._markedPosition_ = 0
+
+    def tell(self):
+        return self._cache.tell()
 
 
-def asSeekableStream(substrate):
+def _asSeekableStream(substrate):
     """Convert object to seekable byte-stream.
 
     Parameters
@@ -113,11 +111,11 @@
         return BytesIO(substrate.asOctets())
     try:
         if _PY2 and isinstance(substrate, file):  # Special case (it is not possible to set attributes)
-            return BufferedReader(substrate, _MAX_BUFFER_SIZE)
+            return BufferedReader(substrate)
         elif substrate.seekable():  # Will fail for most invalid types
             return substrate
         else:
-            return _CachedStreamWrapper(substrate)
+            return _CachingStreamWrapper(substrate)
     except AttributeError:
         raise UnsupportedSubstrateError("Cannot convert " + substrate.__class__.__name__ + " to a seekable bit stream.")
 
@@ -839,7 +837,7 @@
                                         containerValue):
 
                                     component = decodeFun(
-                                        asSeekableStream(containerValue[pos].asOctets()),
+                                        _asSeekableStream(containerValue[pos].asOctets()),
                                         asn1Spec=openType, **options
                                     )
 
@@ -847,7 +845,7 @@
 
                             else:
                                 component = decodeFun(
-                                    asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets()),
+                                    _asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets()),
                                     asn1Spec=openType, **options
                                 )
 
@@ -1023,7 +1021,7 @@
                                         containerValue):
 
                                     component = decodeFun(
-                                        asSeekableStream(containerValue[pos].asOctets()),
+                                        _asSeekableStream(containerValue[pos].asOctets()),
                                         asn1Spec=openType, **dict(options, allowEoo=True)
                                     )
 
@@ -1031,7 +1029,7 @@
 
                             else:
                                 component = decodeFun(
-                                    asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets()),
+                                    _asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets()),
                                     asn1Spec=openType, **dict(options, allowEoo=True)
                                 )
 
@@ -1221,7 +1219,7 @@
             isUntagged = tagSet != asn1Spec.tagSet
 
         if isUntagged:
-            fullPosition = substrate._marked_position
+            fullPosition = substrate._markedPosition
             currentPosition = substrate.tell()
 
             substrate.seek(fullPosition, os.SEEK_SET)
@@ -1260,7 +1258,7 @@
 
         else:
             # TODO: Seems not to be tested
-            fullPosition = substrate._marked_position
+            fullPosition = substrate._markedPosition
             currentPosition = substrate.tell()
 
             substrate.seek(fullPosition, os.SEEK_SET)
@@ -1462,7 +1460,7 @@
         tagCache = self.__tagCache
         tagSetCache = self.__tagSetCache
 
-        substrate._marked_position = substrate.tell()
+        substrate._markedPosition = substrate.tell()
 
         while state is not stStop:
 
@@ -1756,7 +1754,7 @@
     """Iterator of objects in a substrate."""
     # TODO: This should become `decode` after API-breaking approved
     try:
-        substrate = asSeekableStream(substrate)
+        substrate = _asSeekableStream(substrate)
     except TypeError:
         raise PyAsn1Error
     while True:
@@ -1820,7 +1818,7 @@
 def decode(substrate, asn1Spec=None, **kwargs):
     # TODO: Temporary solution before merging with upstream
     #   It preserves the original API
-    substrate = asSeekableStream(substrate)
+    substrate = _asSeekableStream(substrate)
     value = _decode(substrate, asn1Spec=asn1Spec, **kwargs)
     return value, substrate.read()
 
diff --git a/pyasn1/codec/cer/decoder.py b/pyasn1/codec/cer/decoder.py
--- a/pyasn1/codec/cer/decoder.py
+++ b/pyasn1/codec/cer/decoder.py
@@ -8,7 +8,7 @@
 
 from pyasn1 import error
 from pyasn1.codec.ber import decoder
-from pyasn1.codec.ber.decoder import asSeekableStream
+from pyasn1.codec.ber.decoder import _asSeekableStream
 from pyasn1.compat.octets import oct2int
 from pyasn1.type import univ
 
@@ -70,7 +70,7 @@
 def decodeStream(substrate, asn1Spec=None, **kwargs):
     """Iterator of objects in a substrate."""
     # TODO: This should become `decode` after API-breaking approved
-    substrate = asSeekableStream(substrate)
+    substrate = _asSeekableStream(substrate)
     while True:
         result = _decode(substrate, asn1Spec, **kwargs)
         if result is None:
@@ -132,6 +132,6 @@
 def decode(substrate, asn1Spec=None, **kwargs):
     # TODO: Temporary solution before merging with upstream
     #   It preserves the original API
-    substrate = asSeekableStream(substrate)
+    substrate = _asSeekableStream(substrate)
     value = _decode(substrate, asn1Spec=asn1Spec, **kwargs)
     return value, substrate.read()
diff --git a/pyasn1/codec/der/decoder.py b/pyasn1/codec/der/decoder.py
--- a/pyasn1/codec/der/decoder.py
+++ b/pyasn1/codec/der/decoder.py
@@ -6,7 +6,7 @@
 #
 from io import BytesIO
 
-from pyasn1.codec.ber.decoder import asSeekableStream
+from pyasn1.codec.ber.decoder import _asSeekableStream
 from pyasn1.codec.cer import decoder
 from pyasn1.type import univ
 
@@ -50,7 +50,7 @@
 def decodeStream(substrate, asn1Spec=None, **kwargs):
     """Iterator of objects in a substrate."""
     # TODO: This should become `decode` after API-breaking approved
-    substrate = asSeekableStream(substrate)
+    substrate = _asSeekableStream(substrate)
     while True:
         result = _decode(substrate, asn1Spec, **kwargs)
         if result is None:
@@ -112,6 +112,6 @@
 def decode(substrate, asn1Spec=None, **kwargs):
     # TODO: Temporary solution before merging with upstream
     #   It preserves the original API
-    substrate = asSeekableStream(substrate)
+    substrate = _asSeekableStream(substrate)
     value = _decode(substrate, asn1Spec=asn1Spec, **kwargs)
     return value, substrate.read()
\ No newline at end of file
diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py
--- a/tests/codec/ber/test_decoder.py
+++ b/tests/codec/ber/test_decoder.py
@@ -1603,7 +1603,7 @@
     def testErrorCondition(self):
         decode = decoder.Decoder(decoder.tagMap, decoder.typeMap)
         substrate = b'abc'
-        stream = decoder.asSeekableStream(substrate)
+        stream = decoder._asSeekableStream(substrate)
 
         try:
             asn1Object = decode(stream)
@@ -1619,7 +1619,7 @@
     def testRawDump(self):
         decode = decoder.Decoder(decoder.tagMap, decoder.typeMap)
         substrate = ints2octs((31, 8, 2, 1, 1, 131, 3, 2, 1, 12))
-        stream = decoder.asSeekableStream(substrate, )
+        stream = decoder._asSeekableStream(substrate, )
 
         decode.defaultErrorState = decoder.stDumpRawValue