package bitio import ( "io" ) type Writer interface { io.Writer // alignment: // |-1-byte-block-|--------------|--------------|--------------| // |<-offset->|<-------------------width---------------------->| WriteBits(data []byte, width uint) error WriteBit(bit bool) error } type writer struct { writer io.Writer octet byte width uint } func NewWriter(w io.Writer) Writer { return &writer{writer: w} } func (w *writer) Write(p []byte) (n int, err error) { if w.width != 0 { return 0, ErrInvalidAlignment } return w.writer.Write(p) } func (w *writer) WriteBits(data []byte, width uint) error { length := uint(len(data)) * 8 offset := length - width for i := offset; i < length; i++ { oi := i / 8 if err := w.WriteBit((data[oi]>>(7-i%8))&0x01 != 0); err != nil { return err } } return nil } func (w *writer) WriteBit(bit bool) error { if bit { w.octet |= 0x1 << (7 - w.width) } w.width++ if w.width == 8 { if _, err := w.writer.Write([]byte{w.octet}); err != nil { return err } w.octet = 0x00 w.width = 0 } return nil }