write.go (1082B)
1 package bitio 2 3 import ( 4 "io" 5 ) 6 7 type Writer interface { 8 io.Writer 9 10 // alignment: 11 // |-1-byte-block-|--------------|--------------|--------------| 12 // |<-offset->|<-------------------width---------------------->| 13 WriteBits(data []byte, width uint) error 14 15 WriteBit(bit bool) error 16 } 17 18 type writer struct { 19 writer io.Writer 20 octet byte 21 width uint 22 } 23 24 func NewWriter(w io.Writer) Writer { 25 return &writer{writer: w} 26 } 27 28 func (w *writer) Write(p []byte) (n int, err error) { 29 if w.width != 0 { 30 return 0, ErrInvalidAlignment 31 } 32 return w.writer.Write(p) 33 } 34 35 func (w *writer) WriteBits(data []byte, width uint) error { 36 length := uint(len(data)) * 8 37 offset := length - width 38 for i := offset; i < length; i++ { 39 oi := i / 8 40 if err := w.WriteBit((data[oi]>>(7-i%8))&0x01 != 0); err != nil { 41 return err 42 } 43 } 44 return nil 45 } 46 47 func (w *writer) WriteBit(bit bool) error { 48 if bit { 49 w.octet |= 0x1 << (7 - w.width) 50 } 51 w.width++ 52 53 if w.width == 8 { 54 if _, err := w.writer.Write([]byte{w.octet}); err != nil { 55 return err 56 } 57 w.octet = 0x00 58 w.width = 0 59 } 60 return nil 61 }