大多数pythonic方式实现字节填充算法

时间:2018-04-16 17:04:11

标签: python python-3.x idiomatic bitstuffing

我正在做一些串行协议,并希望在python中实现基本的字节填充算法。我正努力确定最狡猾的方式。

字节填充基本上只是替换任何"保留"具有由转义字节组成的对的字节和以可逆方式转换的原始字节(例如xor' ed)。

到目前为止,我已经采用了5种不同的方法,每种方法都有一些我不喜欢的方法:

1 Via Generator

def stuff1(bits):
    for byte in bits:
        if byte in _EscapeCodes:
            yield PacketCode.Escape
            yield byte ^ 0xFF
        else:
            yield byte

这可能是我最喜欢的,但也许只是因为我对基于产量的发电机着迷。我担心发电机会让它变慢,但它实际上是第二快的发电机。

2简单字节()

def stuff2(bits):
    result = bytes()
    for byte in bits:
        if byte in _EscapeCodes:
            result += bytes([PacketCode.Escape, byte ^ 0xFF])
        else:
            result += bytes([byte])
    return result

不得不创建单个元素数组只是为了抛弃它们,因为我不知道任何"复制一个额外元素"操作。它与最慢的人联系在一起。

3使用字节数组()

def stuff3(bits):
    result = bytearray()
    for byte in bits:
        if byte in _EscapeCodes:
            result.append(PacketCode.Escape)
            result.append(byte ^ 0xFF)
        else:
            result.append(byte)
    return result

似乎比直接bytes()方法更好。实际上比yield生成器慢,并且可以一次执行一个字节(而不是需要中间1个元素集合)。但它感到野蛮。它是包装性能的中间部分。

4 BytesIO()

def stuff4(bits):
    bio = BytesIO()
    for byte in bits:
        if byte in _EscapeCodes:
            bio.write(bytes([PacketCode.Escape, byte ^ 0xFF]))
        else:
            bio.write(bytes([byte]))
    return bio.getbuffer()

我喜欢这里基于流的方法。但令人讨厌的是,它似乎不像write1 API那样可以添加1个字节,所以我必须再次制作那些中间bytes。如果有一个"写单字节",我就喜欢这个。它的关系最慢。

5使用replace()

def stuff5(bits):
    escapeStuffed = bytes(bits).replace(bytes([PacketCode.Escape]), bytes([PacketCode.Escape, PacketCode.Escape ^ 0xFF]))
    stopStuffed = escapeStuffed.replace(bytes([PacketCode.Stop]), bytes([PacketCode.Escape, PacketCode.Stop ^ 0xFF]))
    return stopStuffed.replace(bytes([PacketCode.Start]), bytes([PacketCode.Escape, PacketCode.Start ^ 0xFF]))

这是最快的。但我不喜欢代码读取和中间扫描的方式。

我还尝试使用translate(),但是AFAICT,它只能翻译1:1序列。

0 个答案:

没有答案