------------------------------------------ implement zero-copy reader ------------------------------------------ Next implements Reader.
(n int)
| 148 | |
| 149 | // Next implements Reader. |
| 150 | func (b *UnsafeLinkBuffer) Next(n int) (p []byte, err error) { |
| 151 | if n <= 0 { |
| 152 | return |
| 153 | } |
| 154 | // check whether enough or not. |
| 155 | if b.Len() < n { |
| 156 | return p, fmt.Errorf("link buffer next[%d] not enough", n) |
| 157 | } |
| 158 | b.recalLen(-n) // re-cal length |
| 159 | |
| 160 | // single node |
| 161 | if b.isSingleNode(n) { |
| 162 | b.read.setFlag(flagReadExposed) |
| 163 | return b.read.Next(n), nil |
| 164 | } |
| 165 | // multiple nodes |
| 166 | var pIdx int |
| 167 | if block1k < n && n <= mallocMax { |
| 168 | p = malloc(n, n) |
| 169 | b.caches = append(b.caches, p) |
| 170 | } else { |
| 171 | p = dirtmake.Bytes(n, n) |
| 172 | } |
| 173 | var l int |
| 174 | for ack := n; ack > 0; ack = ack - l { |
| 175 | l = b.read.Len() |
| 176 | if l >= ack { |
| 177 | pIdx += copy(p[pIdx:], b.read.Next(ack)) |
| 178 | break |
| 179 | } else if l > 0 { |
| 180 | pIdx += copy(p[pIdx:], b.read.Next(l)) |
| 181 | } |
| 182 | b.read = b.read.next |
| 183 | } |
| 184 | _ = pIdx |
| 185 | return p, nil |
| 186 | } |
| 187 | |
| 188 | // Peek does not have an independent lifecycle, and there is no signal to |
| 189 | // indicate that Peek content can be released, so Peek will not introduce mcache for now. |