StdCopy is a modified version of [io.Copy] to de-multiplex messages from "multiplexedSource" and copy them to destination streams "destOut" and "destErr". StdCopy demultiplexes "multiplexedSource", assuming that it contains two streams, previously multiplexed using a writer created with [NewStdWrit
(destOut, destErr io.Writer, multiplexedSource io.Reader)
| 48 | // The "written" return holds the total number of bytes written to "destOut" |
| 49 | // and "destErr" combined. |
| 50 | func StdCopy(destOut, destErr io.Writer, multiplexedSource io.Reader) (written int64, _ error) { |
| 51 | var ( |
| 52 | buf = make([]byte, startingBufLen) |
| 53 | bufLen = len(buf) |
| 54 | nr, nw int |
| 55 | err error |
| 56 | out io.Writer |
| 57 | frameSize int |
| 58 | ) |
| 59 | |
| 60 | for { |
| 61 | // Make sure we have at least a full header |
| 62 | for nr < stdWriterPrefixLen { |
| 63 | var nr2 int |
| 64 | nr2, err = multiplexedSource.Read(buf[nr:]) |
| 65 | nr += nr2 |
| 66 | if errors.Is(err, io.EOF) { |
| 67 | if nr < stdWriterPrefixLen { |
| 68 | return written, nil |
| 69 | } |
| 70 | break |
| 71 | } |
| 72 | if err != nil { |
| 73 | return 0, err |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | // Check the first byte to know where to write |
| 78 | stream := StdType(buf[stdWriterFdIndex]) |
| 79 | switch stream { |
| 80 | case Stdin: |
| 81 | fallthrough |
| 82 | case Stdout: |
| 83 | // Write on stdout |
| 84 | out = destOut |
| 85 | case Stderr: |
| 86 | // Write on stderr |
| 87 | out = destErr |
| 88 | case Systemerr: |
| 89 | // If we're on Systemerr, we won't write anywhere. |
| 90 | // NB: if this code changes later, make sure you don't try to write |
| 91 | // to outstream if Systemerr is the stream |
| 92 | out = nil |
| 93 | default: |
| 94 | return 0, fmt.Errorf("unrecognized stream: %d", stream) |
| 95 | } |
| 96 | |
| 97 | // Retrieve the size of the frame |
| 98 | frameSize = int(binary.BigEndian.Uint32(buf[stdWriterSizeIndex : stdWriterSizeIndex+4])) |
| 99 | |
| 100 | // Check if the buffer is big enough to read the frame. |
| 101 | // Extend it if necessary. |
| 102 | if frameSize+stdWriterPrefixLen > bufLen { |
| 103 | buf = append(buf, make([]byte, frameSize+stdWriterPrefixLen-bufLen+1)...) |
| 104 | bufLen = len(buf) |
| 105 | } |
| 106 | |
| 107 | // While the amount of bytes read is less than the size of the frame + header, we keep reading |