func (r *Reader) ReadOperations(ops chan rsync.Operation, hashOps chan rsync.Operation) error { if r.t != TypeDelta { // This is a program structure issue, so panic. panic(ErrInvalidCall) } var v uint64 var n, at, dataLen int reader := sbuffer.NewBuffer(r.body, 32*1024) loop := true for loop { buff, err := reader.Next(10) if len(buff) == 0 { return nil } if err != nil { if err != io.EOF { return err } loop = false } op := rsync.Operation{ Type: rsync.OpType(buff[0]), } at = 1 switch op.Type { case rsync.OpBlock: v, n = binary.Uvarint(buff[at:]) if n <= 0 { panic(ErrBadVarintRead) } at += n op.BlockIndex = v reader.Used(at) case rsync.OpBlockRange: v, n = binary.Uvarint(buff[at:]) if n <= 0 { panic(ErrBadVarintRead) } at += n op.BlockIndex = v v, n = binary.Uvarint(buff[at:]) if n <= 0 { panic(ErrBadVarintRead) } at += n op.BlockIndexEnd = v reader.Used(at) case rsync.OpHash: fallthrough case rsync.OpData: v, n = binary.Uvarint(buff[at:]) if n <= 0 { panic(ErrBadVarintRead) } at += n dataLen = int(v) if dataLen > maxDataLength { err = ErrDataTooLong(dataLen) panic(err) } reader.Used(at) buff, err := reader.Next(dataLen) if err != nil { if err != io.EOF { return err } loop = false } op.Data = make([]byte, dataLen) copy(op.Data, buff[:dataLen]) reader.Used(dataLen) default: panic("Unreachable.") } if op.Type == rsync.OpHash { hashOps <- op } else { ops <- op } } return nil }
func (r *Reader) ReadAllSignatures() ([]rsync.BlockHash, error) { if r.t != TypeSignature { // This is a program structure issue, so panic. panic(ErrInvalidCall) } bb := make([]rsync.BlockHash, 0, 10) // Approx size of header, which uses varint encoding. leaveTail := 24 var v uint64 var n, at, hashLen int reader := sbuffer.NewBuffer(r.body, 32*1024) loop := true for loop { buff, err := reader.Next(leaveTail) if err != nil { if err != io.EOF { return nil, err } loop = false } if len(buff) == 0 { break } v, n = binary.Uvarint(buff) if n <= 0 { panic(ErrBadVarintRead) } at = n block := rsync.BlockHash{ Index: v, WeakHash: binary.BigEndian.Uint32(buff[at:]), } at += 4 v, n = binary.Uvarint(buff[at:]) if n <= 0 { panic(ErrBadVarintRead) } at += n hashLen = int(v) if hashLen > maxHashLength { err = ErrHashTooLong(hashLen) panic(err) } reader.Used(at) buff, err = reader.Next(hashLen) if err != nil { if err != io.EOF { return nil, err } loop = false } block.StrongHash = make([]byte, hashLen) copy(block.StrongHash, buff[:hashLen]) reader.Used(hashLen) bb = append(bb, block) } return bb, nil }