public Chunk(ChunkReader reader, long pos, ChunkHeader header) { _reader = reader; _header = header; BeginPosition = pos; }
async Task <Meter?> ReadMeter(long pos) { Debug.Assert(pos >= 0 && pos % MeterInterval == 0); if (pos == 0) { return new Meter() { ChunkBeginPosition = 0 } } ; _reader.Seek(pos); if (await _reader.ReadAsync(_meter, 0, _meter.Length) != _meter.Length) { return(null); } var res = new Meter(); if (!res.ReadFrom(_meter)) { return(null); } if (res.ChunkBeginPosition > pos) { return(null); } return(res); } async Task <ChunkHeader?> ReadChunkHeader(long pos) { if (!await ReadMetered(pos, _header, 0, _header.Length)) { return(null); } var res = new ChunkHeader(); if (!res.ReadFrom(_header)) { return(null); } if (!res.EndPosition(pos).HasValue) { return(null); } return(res); } async Task <bool> ReadMetered(long pos, byte[] array, int offset, int count) { Debug.Assert(array != null); Debug.Assert(offset >= 0); Debug.Assert(array.Length - offset >= count); if (!(MeteredPosition(pos, count) <= Length)) { return(false); } while (count > 0) { Debug.Assert(IsValidPosition(pos)); if (pos % MeterInterval == 0) { pos += Meter.Size; } _reader.Seek(pos); int n = Math.Min(count, MeterInterval - (int)(pos % MeterInterval)); if (await _reader.ReadAsync(array, offset, n) != n) { return(false); } pos += n; offset += n; count -= n; } return(true); }