class TestOptionalGreedyRepeater(unittest.TestCase): def setUp(self): self.c = OptionalGreedyRepeater(UBInt8("foo")) def test_trivial(self): pass def test_empty_parse(self): self.assertEqual(self.c.parse(""), []) def test_parse(self): self.assertEqual(self.c.parse("\x01\x02"), [1, 2]) def test_empty_build(self): self.assertEqual(self.c.build([]), "") def test_build(self): self.assertEqual(self.c.build([1, 2]), "\x01\x02")
class Bitmap(FixedObjectByteArray): classID = 13 _construct = Struct( "", UBInt32("length"), construct.String("items", lambda ctx: ctx.length * 4), # Identically named "String" class -_- ) @classmethod def from_value(cls, obj): return cls(obj.items) def to_value(self): value = self.value length = (len(value) + 3) / 4 value += "\x00" * (length * 4 - len(value)) # padding return Container(items=value, length=length) _int = Struct( "int", UBInt8("_value"), If( lambda ctx: ctx._value > 223, IfThenElse( "", lambda ctx: ctx._value <= 254, Embed( Struct( "", UBInt8("_second_byte"), Value( "_value", lambda ctx: (ctx._value - 224) * 256 + ctx._second_byte), )), Embed(Struct( "", UBInt32("_value"), )))), ) _length_run_coding = Struct( "", Embed(_int), #ERROR? Value("length", lambda ctx: ctx._value), OptionalGreedyRepeater( Struct( "data", Embed(_int), Value("data_code", lambda ctx: ctx._value % 4), Value("run_length", lambda ctx: (ctx._value - ctx.data_code) / 4), Switch( "", lambda ctx: ctx.data_code, { 0: Embed( Struct( "", StrictRepeater( get_run_length, Value("pixels", lambda ctx: "\x00\x00\x00\x00")), )), 1: Embed( Struct( "", Bytes("_b", 1), StrictRepeater( get_run_length, Value("pixels", lambda ctx: ctx._b * 4), ), )), 2: Embed( Struct( "", Bytes("_pixel", 4), StrictRepeater( get_run_length, Value("pixels", lambda ctx: ctx._pixel), ), )), 3: Embed( Struct( "", StrictRepeater( get_run_length, Bytes("pixels", 4), ), )), }), ))) @classmethod def from_byte_array(cls, bytes_): """Decodes a run-length encoded ByteArray and returns a Bitmap. The ByteArray decompresses to a sequence of 32-bit values, which are stored as a byte string. (The specific encoding depends on Form.depth.) """ runs = cls._length_run_coding.parse(bytes_) pixels = (run.pixels for run in runs.data) data = "".join(itertools.chain.from_iterable(pixels)) return cls(data) def compress(self): """Compress to a ByteArray""" raise NotImplementedError
def setUp(self): self.c = OptionalGreedyRepeater(UBInt8("foo"))