Coverage for d7a/dll/parser.py: 91%
46 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-24 08:03 +0200
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-24 08:03 +0200
1#
2# Copyright (c) 2015-2021 University of Antwerp, Aloxy NV.
3#
4# This file is part of pyd7a.
5# See https://github.com/Sub-IoT/pyd7a for further info.
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11# http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19from enum import Enum
21from bitstring import ConstBitStream, ReadError
23from d7a.dll.background_frame import BackgroundFrame
24from d7a.dll.foreground_frame import ForegroundFrame
26class ParseError(Exception): pass
28class FrameType(Enum):
29 FOREGROUND = 0
30 BACKGROUND = 1
32class Parser(object):
34 def __init__(self, frame_type):
35 self.buffer = []
36 self.frame_type = frame_type
38 def parse(self, frame):
39 self.buffer.extend(frame)
40 return self.parse_buffer()
42 def parse_buffer(self):
43 parsed = 0
44 frames = []
46 (frame, info) = self.parse_one_frame_from_buffer()
47 parsed += info["parsed"]
48 frames.append(frame)
49 # TODO loop
50 # while True:
51 # (frame, info) = self.parse_one_frame_from_buffer()
52 # if frame is None: break
53 # parsed += info["parsed"]
54 # frames.append(frame)
56 info["parsed"] = parsed
57 return (self.frame_type, frames, info)
59 def shift_buffer(self, start: int):
60 self.buffer = self.buffer[start:]
61 return self
63 def parse_one_frame_from_buffer(self):
64 retry = True # until we have one or don't have enough
65 errors = []
66 frame = None
67 bits_parsed = 0
68 while retry and len(self.buffer) > 0:
69 try:
70 self.s = ConstBitStream(bytes=self.buffer)
71 if self.frame_type == FrameType.FOREGROUND:
72 frame = ForegroundFrame.parse(self.s)
73 else:
74 frame = BackgroundFrame.parse(self.s)
75 bits_parsed = self.s.pos
76 self.shift_buffer(bits_parsed//8)
77 retry = False # got one, carry on
78 except ReadError as e: # not enough to read, carry on and wait for more
79 retry = False
80 except ParseError as e: # actual problem with current buffer, need to skip
81 errors.append({
82 "error" : e.args[0],
83 "buffer" : list(self.buffer),
84 "pos" : self.s.pos,
85 "skipped" : self.skip_bad_buffer_content()
86 })
88 info = {
89 "parsed" : bits_parsed,
90 "buffer" : len(self.buffer) * 8,
91 "errors" : errors
92 }
93 return (frame, info)