|
4 | 4 | "errors" |
5 | 5 | "fmt" |
6 | 6 | "io" |
| 7 | + "math" |
7 | 8 |
|
8 | 9 | blocks "github.com/ipfs/go-block-format" |
9 | 10 | "github.com/ipfs/go-cid" |
@@ -141,6 +142,25 @@ func (br *BlockReader) Next() (blocks.Block, error) { |
141 | 142 | return blocks.NewBlockWithCid(data, c) |
142 | 143 | } |
143 | 144 |
|
| 145 | +// NextReader returns a CID, io.Reader and length of what should be the next block |
| 146 | +// the CID itself is not verified, and the reader is limited to the size of the block |
| 147 | +// The user of this function HAS TO consume all of the bytes in the returned reader before using any other function |
| 148 | +// on the BlockReader. |
| 149 | +// The returned length might be larger than MaxAllowedSectionSize, it is up to the user to check before loading the data into memory. |
| 150 | +func (br *BlockReader) NextReader() (cid.Cid, io.Reader, uint64, error) { |
| 151 | + // we pass Math.MaxInt64 as io.LimitReader doesn't support uint64 |
| 152 | + // and we want unlimited size, as it is for the user of the function to read blocks of data without OOMing |
| 153 | + c, length, err := util.ReadNodeHeader(br.r, br.opts.ZeroLengthSectionAsEOF, math.MaxInt64) |
| 154 | + if err != nil { |
| 155 | + return cid.Undef, nil, 0, err |
| 156 | + } |
| 157 | + limitReader := io.LimitReader(br.r, int64(length)) |
| 158 | + |
| 159 | + ss := uint64(c.ByteLen()) + length |
| 160 | + br.offset += uint64(varint.UvarintSize(ss)) + ss |
| 161 | + return c, limitReader, length, nil |
| 162 | +} |
| 163 | + |
144 | 164 | // BlockMetadata contains metadata about a block's section in a CAR file/stream. |
145 | 165 | // |
146 | 166 | // There are two offsets for the block section which will be the same if the |
@@ -171,26 +191,14 @@ type BlockMetadata struct { |
171 | 191 | // If the underlying reader used by the BlockReader is actually a ReadSeeker, this method will attempt to |
172 | 192 | // seek over the underlying data rather than reading it into memory. |
173 | 193 | func (br *BlockReader) SkipNext() (*BlockMetadata, error) { |
174 | | - sectionSize, err := util.LdReadSize(br.r, br.opts.ZeroLengthSectionAsEOF, br.opts.MaxAllowedSectionSize) |
| 194 | + c, blockSize, err := util.ReadNodeHeader(br.r, br.opts.ZeroLengthSectionAsEOF, br.opts.MaxAllowedSectionSize) |
175 | 195 | if err != nil { |
176 | 196 | return nil, err |
177 | 197 | } |
178 | | - if sectionSize == 0 { |
179 | | - _, _, err := cid.CidFromBytes([]byte{}) // generate zero-byte CID error |
180 | | - if err == nil { |
181 | | - panic("expected zero-byte CID error") |
182 | | - } |
183 | | - return nil, err |
184 | | - } |
185 | | - |
| 198 | + cidSize := uint64(c.ByteLen()) |
| 199 | + sectionSize := blockSize + cidSize |
186 | 200 | lenSize := uint64(varint.UvarintSize(sectionSize)) |
187 | 201 |
|
188 | | - cidSize, c, err := cid.CidFromReader(io.LimitReader(br.r, int64(sectionSize))) |
189 | | - if err != nil { |
190 | | - return nil, err |
191 | | - } |
192 | | - |
193 | | - blockSize := sectionSize - uint64(cidSize) |
194 | 202 | blockOffset := br.offset |
195 | 203 |
|
196 | 204 | // move our reader forward; either by seeking or slurping |
|
0 commit comments