# HG changeset patch
# User Ilya Etingof <etingof@gmail.com>
# Date 1570091332 -7200
#      Thu Oct 03 10:28:52 2019 +0200
# Node ID 443dbff02dab80c3b34004f5465bb16aed346c40
# Parent  a9aad6c2985da05a97e87e6ea2b96291dbb1c78e
Reuse `SingleItemDecoder` object in `StreamingDecoder`

Try to reuse `SingleItemDecoder` object to leverage its caches.

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
@@ -1118,8 +1118,6 @@
                      tagSet=None, length=None, state=None,
                      decodeFun=None, substrateFun=None,
                      **options):
-        # head = popSubstream(substrate, length)
-
         if asn1Spec is None:
             asn1Object = self.protoComponent.clone(tagSet=tagSet)
 
@@ -1900,17 +1898,16 @@
          1 2 3
     """
 
-    SINGLE_ITEM_DECODER = SingleItemDecoder
+    SINGLE_ITEM_DECODER = SingleItemDecoder()
 
     def __init__(self, substrate, asn1Spec=None, **kwargs):
         self._substrate = asSeekableStream(substrate)
         self._asn1Spec = asn1Spec
         self._options = kwargs
-        self._decoder = self.SINGLE_ITEM_DECODER()
 
     def __iter__(self):
         while True:
-            for asn1Object in self._decoder(
+            for asn1Object in self.SINGLE_ITEM_DECODER(
                     self._substrate, self._asn1Spec, **self._options):
                 yield asn1Object
 
diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py
--- a/pyasn1/codec/ber/encoder.py
+++ b/pyasn1/codec/ber/encoder.py
@@ -846,12 +846,11 @@
 
 
 class Encoder(object):
-    SINGLE_ITEM_ENCODER = SingleItemEncoder
+    SINGLE_ITEM_ENCODER = SingleItemEncoder()
 
     @classmethod
     def __call__(cls, pyObject, asn1Spec=None, **options):
-        singleItemEncoder = cls.SINGLE_ITEM_ENCODER()
-        return singleItemEncoder(pyObject, asn1Spec=asn1Spec, **options)
+        return cls.SINGLE_ITEM_ENCODER(pyObject, asn1Spec=asn1Spec, **options)
 
 
 #: Turns ASN.1 object into BER octet stream.
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
@@ -80,7 +80,7 @@
 class StreamingDecoder(decoder.StreamingDecoder):
     __doc__ = decoder.StreamingDecoder.__doc__
 
-    SINGLE_ITEM_DECODER = SingleItemDecoder
+    SINGLE_ITEM_DECODER = SingleItemDecoder()
 
 
 class Decoder(decoder.Decoder):
diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py
--- a/pyasn1/codec/cer/encoder.py
+++ b/pyasn1/codec/cer/encoder.py
@@ -270,7 +270,7 @@
 
 
 class Encoder(encoder.Encoder):
-    SINGLE_ITEM_ENCODER = SingleItemEncoder
+    SINGLE_ITEM_ENCODER = SingleItemEncoder()
 
 
 #: Turns ASN.1 object into CER octet stream.
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
@@ -50,7 +50,7 @@
 class StreamingDecoder(decoder.StreamingDecoder):
     __doc__ = decoder.StreamingDecoder.__doc__
 
-    SINGLE_ITEM_DECODER = SingleItemDecoder
+    SINGLE_ITEM_DECODER = SingleItemDecoder()
 
 
 class Decoder(decoder.Decoder):
diff --git a/pyasn1/codec/der/encoder.py b/pyasn1/codec/der/encoder.py
--- a/pyasn1/codec/der/encoder.py
+++ b/pyasn1/codec/der/encoder.py
@@ -67,7 +67,7 @@
 
 
 class Encoder(encoder.Encoder):
-    SINGLE_ITEM_ENCODER = SingleItemEncoder
+    SINGLE_ITEM_ENCODER = SingleItemEncoder()
 
 
 #: Turns ASN.1 object into DER octet stream.
diff --git a/pyasn1/codec/native/decoder.py b/pyasn1/codec/native/decoder.py
--- a/pyasn1/codec/native/decoder.py
+++ b/pyasn1/codec/native/decoder.py
@@ -181,12 +181,11 @@
 
 
 class Decoder(object):
-    SINGLE_ITEM_DECODER = SingleItemDecoder
+    SINGLE_ITEM_DECODER = SingleItemDecoder()
 
     @classmethod
     def __call__(cls, pyObject, asn1Spec=None, **kwargs):
-        singleItemDecoder = cls.SINGLE_ITEM_DECODER()
-        return singleItemDecoder(pyObject, asn1Spec=asn1Spec, **kwargs)
+        return cls.SINGLE_ITEM_DECODER(pyObject, asn1Spec=asn1Spec, **kwargs)
 
 
 #: Turns Python objects of built-in types into ASN.1 objects.
diff --git a/pyasn1/codec/native/encoder.py b/pyasn1/codec/native/encoder.py
--- a/pyasn1/codec/native/encoder.py
+++ b/pyasn1/codec/native/encoder.py
@@ -225,12 +225,11 @@
 
 
 class Encoder(object):
-    SINGLE_ITEM_ENCODER = SingleItemEncoder
+    SINGLE_ITEM_ENCODER = SingleItemEncoder()
 
     @classmethod
     def __call__(cls, pyObject, asn1Spec=None, **kwargs):
-        singleItemEncoder = cls.SINGLE_ITEM_ENCODER()
-        return singleItemEncoder(pyObject, asn1Spec=asn1Spec, **kwargs)
+        return cls.SINGLE_ITEM_ENCODER(pyObject, asn1Spec=asn1Spec, **kwargs)
 
 
 #: Turns ASN.1 object into a Python built-in type object(s).
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
@@ -1611,11 +1611,11 @@
         substrate = ints2octs((31, 8, 2, 1, 1, 131, 3, 2, 1, 12))
         stream = streaming.asSeekableStream(substrate)
 
-        class StateMachine(decoder.SingleItemDecoder):
+        class SingleItemEncoder(decoder.SingleItemDecoder):
             defaultErrorState = decoder.stDumpRawValue
 
         class StreamingDecoder(decoder.StreamingDecoder):
-            SINGLE_ITEM_DECODER = StateMachine
+            SINGLE_ITEM_DECODER = SingleItemEncoder()
 
         class OneShotDecoder(decoder.Decoder):
             STREAMING_DECODER = StreamingDecoder