Show More
@@ -898,6 +898,48 b' class sansiodecoder(object):' | |||||
898 | self._decodedvalues = [] |
|
898 | self._decodedvalues = [] | |
899 | return l |
|
899 | return l | |
900 |
|
900 | |||
|
901 | class bufferingdecoder(object): | |||
|
902 | """A CBOR decoder that buffers undecoded input. | |||
|
903 | ||||
|
904 | This is a glorified wrapper around ``sansiodecoder`` that adds a buffering | |||
|
905 | layer. All input that isn't consumed by ``sansiodecoder`` will be buffered | |||
|
906 | and concatenated with any new input that arrives later. | |||
|
907 | ||||
|
908 | TODO consider adding limits as to the maximum amount of data that can | |||
|
909 | be buffered. | |||
|
910 | """ | |||
|
911 | def __init__(self): | |||
|
912 | self._decoder = sansiodecoder() | |||
|
913 | self._leftover = None | |||
|
914 | ||||
|
915 | def decode(self, b): | |||
|
916 | """Attempt to decode bytes to CBOR values. | |||
|
917 | ||||
|
918 | Returns a tuple with the following fields: | |||
|
919 | ||||
|
920 | * Bool indicating whether new values are available for retrieval. | |||
|
921 | * Integer number of bytes decoded from the new input. | |||
|
922 | * Integer number of bytes wanted to decode the next value. | |||
|
923 | """ | |||
|
924 | ||||
|
925 | if self._leftover: | |||
|
926 | oldlen = len(self._leftover) | |||
|
927 | b = self._leftover + b | |||
|
928 | self._leftover = None | |||
|
929 | else: | |||
|
930 | b = b | |||
|
931 | oldlen = 0 | |||
|
932 | ||||
|
933 | available, readcount, wanted = self._decoder.decode(b) | |||
|
934 | ||||
|
935 | if readcount < len(b): | |||
|
936 | self._leftover = b[readcount:] | |||
|
937 | ||||
|
938 | return available, readcount - oldlen, wanted | |||
|
939 | ||||
|
940 | def getavailable(self): | |||
|
941 | return self._decoder.getavailable() | |||
|
942 | ||||
901 | def decodeall(b): |
|
943 | def decodeall(b): | |
902 | """Decode all CBOR items present in an iterable of bytes. |
|
944 | """Decode all CBOR items present in an iterable of bytes. | |
903 |
|
945 |
@@ -941,6 +941,30 b' class SansIODecoderTests(TestCase):' | |||||
941 | decoder = cborutil.sansiodecoder() |
|
941 | decoder = cborutil.sansiodecoder() | |
942 | self.assertEqual(decoder.decode(b''), (False, 0, 0)) |
|
942 | self.assertEqual(decoder.decode(b''), (False, 0, 0)) | |
943 |
|
943 | |||
|
944 | class BufferingDecoderTests(TestCase): | |||
|
945 | def testsimple(self): | |||
|
946 | source = [ | |||
|
947 | b'foobar', | |||
|
948 | b'x' * 128, | |||
|
949 | {b'foo': b'bar'}, | |||
|
950 | True, | |||
|
951 | False, | |||
|
952 | None, | |||
|
953 | [None for i in range(128)], | |||
|
954 | ] | |||
|
955 | ||||
|
956 | encoded = b''.join(cborutil.streamencode(source)) | |||
|
957 | ||||
|
958 | for step in range(1, 32): | |||
|
959 | decoder = cborutil.bufferingdecoder() | |||
|
960 | start = 0 | |||
|
961 | ||||
|
962 | while start < len(encoded): | |||
|
963 | decoder.decode(encoded[start:start + step]) | |||
|
964 | start += step | |||
|
965 | ||||
|
966 | self.assertEqual(decoder.getavailable(), [source]) | |||
|
967 | ||||
944 | class DecodeallTests(TestCase): |
|
968 | class DecodeallTests(TestCase): | |
945 | def testemptyinput(self): |
|
969 | def testemptyinput(self): | |
946 | self.assertEqual(cborutil.decodeall(b''), []) |
|
970 | self.assertEqual(cborutil.decodeall(b''), []) |
General Comments 0
You need to be logged in to leave comments.
Login now