Task: Bitwise IO





Java: module BitwiseIO
    {
    class BitReader
        {
        construct(Byte[] bytes)
            {
            this.bits = bytes.toBitArray();
            }

        private Bit[] bits;
        private Int   index;

        Int offset          
            {
            @Override
            Int get()
                {
                return index;
                }

            @Override
            void set(Int offset)
                {
                assert 0 <= offset < size;
                index = offset;
                }
            }

        Int size.get()      
            {
            return bits.size;
            }

        Boolean eof.get()   
            {
            return index >= size;
            }

        Bit readBit()
            {
            return eof ? assert:bounds : bits[index++];
            }

        Byte readByte()
            {
            assert:bounds index + 8 <= size as $"eof (offset={index}, size={size}";
            Int start = index;
            index += 8;
            return bits[start ..< index].toByte();
            }
        }

    class BitWriter
        {
        private Bit[] bits = new Bit[];

        BitWriter writeBit(Bit bit)
            {
            bits.add(bit);
            return this;
            }

        BitWriter writeByte(Byte byte)
            {
            bits.addAll(byte.toBitArray());
            return this;
            }

        Byte[] bytes.get()
            {
            
            
            
            bits += bits.size & 0x7 == 0 ? [] : Byte:0.toBitArray() [bits.size & 0x7 ..< 8];
            return bits.toByteArray();
            }
        }

    @Inject Console console;
    void run()
        {
        Bit[] orig = [0,1,0,1,0,1,1,1,0,1,0,1,0];   

        val out = new BitWriter();
        orig.forEach(bit -> out.writeBit(bit));

        val bytes = out.bytes;
        console.print($"bytes written={bytes}");  

        val in = new BitReader(bytes);
        val test = new Bit[orig.size]((Int i) -> in.readBit());
        assert test == orig;
        }
    }



Python: class BitWriter(object):
    def __init__(self, f):
        self.accumulator = 0
        self.bcount = 0
        self.out = f

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.flush()

    def __del__(self):
        try:
            self.flush()
        except ValueError:   
            pass

    def _writebit(self, bit):
        if self.bcount == 8:
            self.flush()
        if bit > 0:
            self.accumulator |= 1 << 7-self.bcount
        self.bcount += 1

    def writebits(self, bits, n):
        while n > 0:
            self._writebit(bits & 1 << n-1)
            n -= 1

    def flush(self):
        self.out.write(bytearray([self.accumulator]))
        self.accumulator = 0
        self.bcount = 0


class BitReader(object):
    def __init__(self, f):
        self.input = f
        self.accumulator = 0
        self.bcount = 0
        self.read = 0

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

    def _readbit(self):
        if not self.bcount:
            a = self.input.read(1)
            if a:
                self.accumulator = ord(a)
            self.bcount = 8
            self.read = len(a)
        rv = (self.accumulator & (1 << self.bcount-1)) >> self.bcount-1
        self.bcount -= 1
        return rv

    def readbits(self, n):
        v = 0
        while n > 0:
            v = (v << 1) | self._readbit()
            n -= 1
        return v

if __name__ == '__main__':
    import os
    import sys
    
    module_name = os.path.splitext(os.path.basename(__file__))[0]
    bitio = __import__(module_name)

    with open('bitio_test.dat', 'wb') as outfile:
        with bitio.BitWriter(outfile) as writer:
            chars = '12345abcde'
            for ch in chars:
                writer.writebits(ord(ch), 7)

    with open('bitio_test.dat', 'rb') as infile:
        with bitio.BitReader(infile) as reader:
            chars = []
            while True:
                x = reader.readbits(7)
                if not reader.read:  
                    break
                chars.append(chr(x))
            print(''.join(chars))