// Package rle implements the run-length encoding scheme discovered in Chaos // Gate .obj files. It may be used for other data too - to be determined. package rle import ( "bufio" "io" "io/ioutil" ) // Expand converts the compressed input data into uncompressed output data. The // output buffer should be of at least the expected size. We will read until // io.EOF is encountered. func Expand(in io.Reader, out []byte) error { buf := bufio.NewReader(in) idx := 0 for { b, err := buf.ReadByte() if err != nil { if err == io.EOF { return nil } return err } if b == 0x00 { // NOP continue } else if b < 0x80 { // repeat the next byte this many times repeat := b value, err := buf.ReadByte() if err != nil { return err } for x := 0; x < int(repeat); x++ { out[idx+x] = value } idx = idx + int(repeat) } else if b == 0x80 { // skip forward in the output by the next byte's value skip, err := buf.ReadByte() if err != nil { return err } idx = idx + int(skip) } else { // Take the next b-0x80 bytes literally lr := io.LimitReader(buf, int64(b-0x80)) literals, err := ioutil.ReadAll(lr) if err != nil { return err } copy(out[idx:], literals) idx = idx + len(literals) } } return nil }