feat(content): add physical blob aliases to pak writer
This commit is contained in:
parent
86fadf8661
commit
0dee14765b
3 changed files with 183 additions and 2 deletions
|
|
@ -170,6 +170,13 @@ public sealed class PakReader : IDisposable {
|
|||
return (long)_toc[index].Offset;
|
||||
}
|
||||
|
||||
/// <summary>Returns the immutable TOC receipt for alias/layout assertions in tests.</summary>
|
||||
public PakTocEntry GetTocEntryForTest(ulong key) {
|
||||
int index = BinarySearch(key);
|
||||
if (index < 0) throw new KeyNotFoundException($"pak key 0x{key:X16} not found");
|
||||
return _toc[index];
|
||||
}
|
||||
|
||||
/// <summary>O(n) linear scan, used only to cross-check the binary search in tests.</summary>
|
||||
public bool DebugLinearScanContainsKey(ulong key) {
|
||||
for (int i = 0; i < _toc.Length; i++) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ public sealed class PakWriter : IDisposable {
|
|||
private readonly PakHeader _headerTemplate;
|
||||
private readonly List<PakTocEntry> _tocEntries = new();
|
||||
private readonly HashSet<ulong> _seenKeys = new();
|
||||
private readonly Dictionary<ulong, PakTocEntry> _receiptByKey = new();
|
||||
private bool _finished;
|
||||
|
||||
public PakWriter(string path, PakHeader headerTemplate) {
|
||||
|
|
@ -56,12 +57,37 @@ public sealed class PakWriter : IDisposable {
|
|||
_stream.Write(bytes);
|
||||
PadToAlignment();
|
||||
|
||||
_tocEntries.Add(new PakTocEntry {
|
||||
var receipt = new PakTocEntry {
|
||||
Key = key,
|
||||
Offset = (ulong)offset,
|
||||
Length = (uint)bytes.Length,
|
||||
Crc32 = Content.Pak.Crc32.Compute(bytes),
|
||||
});
|
||||
};
|
||||
_tocEntries.Add(receipt);
|
||||
_receiptByKey.Add(key, receipt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a second independently addressable key for an existing physical
|
||||
/// blob. The alias receives a normal TOC row with the source blob's exact
|
||||
/// offset, length, and CRC; no payload bytes are written again.
|
||||
/// </summary>
|
||||
public void AddAlias(ulong aliasKey, ulong existingKey) {
|
||||
ThrowIfFinished();
|
||||
if (aliasKey == existingKey) {
|
||||
throw new ArgumentException("an alias key must differ from its source key", nameof(aliasKey));
|
||||
}
|
||||
if (!_receiptByKey.TryGetValue(existingKey, out var source)) {
|
||||
throw new KeyNotFoundException($"source pak key 0x{existingKey:X16} has not been written");
|
||||
}
|
||||
if (!_seenKeys.Add(aliasKey)) {
|
||||
throw new ArgumentException($"duplicate pak key 0x{aliasKey:X16}", nameof(aliasKey));
|
||||
}
|
||||
|
||||
var alias = source;
|
||||
alias.Key = aliasKey;
|
||||
_tocEntries.Add(alias);
|
||||
_receiptByKey.Add(aliasKey, alias);
|
||||
}
|
||||
|
||||
/// <summary>Writes the sorted TOC and finalizes the header. Must be called exactly once.</summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue