/// <summary> /// Compute a cache manifest from runtime data. /// </summary> /// <param name="version">The version of the cache</param> /// <param name="graphicsApi">The graphics api used by the cache</param> /// <param name="hashType">The hash type of the cache</param> /// <param name="entries">The entries in the cache</param> /// <returns>The cache manifest from runtime data</returns> public static byte[] ComputeManifest(ulong version, CacheGraphicsApi graphicsApi, CacheHashType hashType, HashSet <Hash128> entries) { if (hashType != CacheHashType.XxHash128) { throw new NotImplementedException($"{hashType}"); } CacheManifestHeader manifestHeader = new CacheManifestHeader(version, graphicsApi, hashType); byte[] data = new byte[Unsafe.SizeOf <CacheManifestHeader>() + entries.Count * Unsafe.SizeOf <Hash128>()]; // CacheManifestHeader has the same size as a Hash128. Span <Hash128> dataSpan = MemoryMarshal.Cast <byte, Hash128>(data.AsSpan()).Slice(1); int i = 0; foreach (Hash128 hash in entries) { dataSpan[i++] = hash; } manifestHeader.UpdateChecksum(data.AsSpan(Unsafe.SizeOf <CacheManifestHeader>())); MemoryMarshal.Write(data, ref manifestHeader); return(data); }
/// <summary> /// Save the manifest file. /// </summary> private void SaveManifest() { CacheManifestHeader manifestHeader = new CacheManifestHeader(_version, _graphicsApi, _hashType); byte[] data; lock (_hashTable) { data = new byte[Unsafe.SizeOf <CacheManifestHeader>() + _hashTable.Count * Unsafe.SizeOf <Hash128>()]; // CacheManifestHeader has the same size as a Hash128. Span <Hash128> dataSpan = MemoryMarshal.Cast <byte, Hash128>(data.AsSpan()).Slice(1); int i = 0; foreach (Hash128 hash in _hashTable) { dataSpan[i++] = hash; } } manifestHeader.UpdateChecksum(data.AsSpan().Slice(Unsafe.SizeOf <CacheManifestHeader>())); MemoryMarshal.Write(data, ref manifestHeader); File.WriteAllBytes(GetManifestPath(), data); }