package server import ( "io" "math/bits" "encoding/binary" ) // the protocol requires us to send the level as a gzipped flat array. but our // level representation is close to run length encoding that can be achieved // with DEFLATE. it is thus significantly more CPU efficient to, instead of // expanding out the RLE and compressing it with the generic compressor, // translate it directly into DEFLATE func deflateRuns( wr io.Writer, runs []blockData, changes []blockData, levelSize uint32) (length uint32, err error) { bw := bitsWriter {wr: wr} bw.Write(0b011, 3) // BFINAL, fixed huffman writeCode(&bw, 0xff & (levelSize >> 24)) writeCode(&bw, 0xff & (levelSize >> 16)) writeCode(&bw, 0xff & (levelSize >> 8)) err = writeCode(&bw, 0xff & levelSize) if err != nil { return } for i, data := range runs { var nextPos uint32 if i < len(runs) - 1 { nextPos = runs[i + 1].Pos } else { nextPos = levelSize } curPos := data.Pos for len(changes) > 0 { ch := changes[0] if ch.Pos >= nextPos { break } changes = changes[1:] writeRun(&bw, byte(data.Block), ch.Pos - curPos) err = writeRun(&bw, byte(ch.Block), 1) if err != nil { return } curPos = ch.Pos + 1 } if curPos < nextPos { err = writeRun(&bw, byte(data.Block), nextPos - curPos) if err != nil { return } } } writeCode(&bw, 256) return levelSize + 4, bw.Close() } var lengthExtraBits = [...]uint8{ /* 257 */ 0, 0, 0, /* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, /* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, /* 280 */ 4, 5, 5, 5, 5, 0, } var lengthBase = [...]uint32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 255, } var lengthCodes = [...]uint32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, } func writeRun(bw *bitsWriter, value byte, totalLen uint32) error { var err error for totalLen > 0 { len := min(totalLen, 258) if len < 4 { for i := 0; i < int(len); i++ { err = writeCode(bw, uint32(value)) } } else { writeCode(bw, uint32(value)) writeLength(bw, len - 1) err = bw.Write(0b00000, 5) // distance: 1 } totalLen -= len } return err } func writeLength(bw *bitsWriter, length uint32) error { length -= 3 code := lengthCodes[length] writeCode(bw, 257 + code) return bw.Write(length - lengthBase[code], lengthExtraBits[code]) } func writeCode(bw *bitsWriter, v uint32) error { var code uint32 var size uint8 switch { case v < 144: // size 8, 000110000 .. 10111111 code = v + 48 size = 8 case v < 256: // size 9, 110010000 .. 111111111 code = v + 400 - 144 size = 9 case v < 280: // size 7, 0000000 .. 0010111 code = v - 256 size = 7 case v < 288: // size 8, 11000000 .. 11000111 code = v + 192 - 280 size = 8 default: panic("code value out of range") } code = bits.Reverse32(code << (32 - size)) return bw.Write(code, size) } type bitsWriter struct { wr io.Writer buf uint64 nbuf byte } func (bw *bitsWriter) Write(v uint32, n uint8) error { if 64 - bw.nbuf < n { err := bw.writeBuf() if err != nil { return err } } bw.buf |= uint64(v & ((1<>= nbytes * 8 bw.nbuf -= nbytes * 8 return err } func (bw *bitsWriter) Close() error { if bw.nbuf > 0 { bw.Write(0, 8 - (bw.nbuf % 8)) } return bw.writeBuf() } func writePointlessGzipHeader(wr io.Writer) error { var header = [10]byte { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, } _, err := wr.Write(header[:]) return err } func writePointlessGzipTrailer(wr io.Writer, length uint32) error { var trailer [8]byte binary.LittleEndian.PutUint32(trailer[0:], 0xffffffff) binary.LittleEndian.PutUint32(trailer[4:], length) _, err := wr.Write(trailer[:]) return err }