StreamHeaderAndPayload reads a payload and streams (and optionally compresses) it to the writer. To do so, it requires the (uncompressed) payload length to be known in advance.
(size uint64, r io.Reader, w io.Writer, comp Compression)
| 71 | // StreamHeaderAndPayload reads a payload and streams (and optionally compresses) it to the writer. |
| 72 | // To do so, it requires the (uncompressed) payload length to be known in advance. |
| 73 | func StreamHeaderAndPayload(size uint64, r io.Reader, w io.Writer, comp Compression) error { |
| 74 | sizeBytes := [binary.MaxVarintLen64]byte{} |
| 75 | sizeByteLen := binary.PutUvarint(sizeBytes[:], size) |
| 76 | n, err := w.Write(sizeBytes[:sizeByteLen]) |
| 77 | if err != nil { |
| 78 | return fmt.Errorf("failed to write size bytes: %w", err) |
| 79 | } |
| 80 | if n != sizeByteLen { |
| 81 | return fmt.Errorf("failed to write size bytes fully: %d/%d", n, sizeByteLen) |
| 82 | } |
| 83 | if comp != nil { |
| 84 | compressedWriter := comp.Compress(&noCloseWriter{w: w}) |
| 85 | defer func() { |
| 86 | _ = compressedWriter.Close() |
| 87 | }() |
| 88 | if _, err := io.Copy(compressedWriter, r); err != nil { |
| 89 | return fmt.Errorf("failed to write payload through compressed writer: %w", err) |
| 90 | } |
| 91 | return nil |
| 92 | } else { |
| 93 | if _, err := io.Copy(w, r); err != nil { |
| 94 | return fmt.Errorf("failed to write payload: %w", err) |
| 95 | } |
| 96 | return nil |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | // EncodeResult writes the result code to the output writer. |
| 101 | func EncodeResult(result ResponseCode, w io.Writer) error { |