async ValueTask ReadChunks(long chunkTableOffset, int chunkCount) { if (ChunkReader is null) { throw new InvalidOperationException(); } var chunkTable = new byte[(chunkCount + 1) * (4 + sizeof(long))]; if (await ChunkReader.ReadAtAsync(chunkTableOffset, chunkTable).ConfigureAwait(false) != chunkTable.Length) { return; } _chunks = Enumerable.Range(0, chunkCount + 1).Select(i => new Chunk { Name = (i < chunkCount) ? Encoding.ASCII.GetString(chunkTable, 12 * i, 4) : null, Position = NetBitConverter.ToInt64(chunkTable, 12 * i + 4) }).ToArray(); for (int i = 0; i < chunkCount; i++) { _chunks[i].Length = _chunks[i + 1].Position - _chunks[i].Position; } FanOut = await ReadFanOutAsync().ConfigureAwait(false); }
protected override async ValueTask <(GitIdType IdType, int ChunkCount, long ChunkTableOffset)> ReadHeaderAsync() { if (ChunkReader is null) { throw new InvalidOperationException(); } var headerBuffer = new byte[8]; if (await ChunkReader.ReadAtAsync(0, headerBuffer).ConfigureAwait(false) != headerBuffer.Length) { return(GitIdType.None, 0, -1); } if (!"CGPH\x01".Select(x => (byte)x).SequenceEqual(headerBuffer.Take(5))) { return(GitIdType.None, 0, -1); } var idType = (GitIdType)headerBuffer[5]; int chunkCount = headerBuffer[6]; int baseCommitGraphs = headerBuffer[7]; if (baseCommitGraphs <= 0) { _baseCommitGraphs = -1; } else { _baseCommitGraphs = baseCommitGraphs; } return(idType, chunkCount, headerBuffer.Length); }
protected ValueTask <int> ReadFromChunkAsync(string chunkType, long position, byte[] buffer, int length) { if (_chunks == null || ChunkReader == null) { return(new ValueTask <int>(0)); } else if (length <= 0) { throw new ArgumentOutOfRangeException(nameof(length)); } Chunk?ch = null; foreach (var c in _chunks) { if (c.Name == chunkType) { ch = c; break; } } if (ch == null) { return(new ValueTask <int>(0)); } int requested = (int)Math.Min(length, ch.Value.Length - position); if (requested <= 0) { return(new ValueTask <int>(0)); } return(ChunkReader.ReadAtAsync(ch.Value.Position + position, buffer, requested)); }
async ValueTask <bool> GetHasBitmap() { if (ChunkReader is null) { return(false); } byte[] multiPackId = new byte[Repository.InternalConfig.IdType.HashLength()]; if (multiPackId.Length != (await ChunkReader.ReadAtAsync(AfterChunkPosition, multiPackId).ConfigureAwait(false))) { return(false); } GitId id = new GitId(Repository.InternalConfig.IdType, multiPackId); _multiPackBitmapPath = Path.Combine(_dir, $"multi-pack-index-{id}.bitmap"); return(File.Exists(_multiPackBitmapPath)); }