// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; namespace EpicGames.Horde.Storage { /// /// Reference to another node in storage. This type is similar to , but without a hash. /// public interface IBlobRef { /// /// Accessor for the innermost import /// IBlobRef Innermost { get; } /// /// Flush the referenced data to underlying storage /// ValueTask FlushAsync(CancellationToken cancellationToken = default); /// /// Reads the blob's data /// /// Cancellation token for the operation ValueTask ReadBlobDataAsync(CancellationToken cancellationToken = default); /// /// Attempt to get a path for this blob. /// /// Receives the blob path on success. /// True if a path was available, false if the blob has not yet been flushed to storage. bool TryGetLocator([NotNullWhen(true)] out BlobLocator locator); } /// /// Typed interface to a particular blob handle /// /// Type of the deserialized blob public interface IBlobRef : IBlobRef { /// /// Options for deserializing the blob /// BlobSerializerOptions? SerializerOptions { get; } } /// /// Extension methods for /// public static class BlobRefExtensions { class TypedBlobRef : IBlobRef { readonly IBlobRef _inner; /// public BlobSerializerOptions? SerializerOptions { get; } public IBlobRef Innermost => throw new NotImplementedException(); public TypedBlobRef(IBlobRef inner, BlobSerializerOptions? serializerOptions) { _inner = inner; SerializerOptions = serializerOptions; } public ValueTask FlushAsync(CancellationToken cancellationToken = default) => _inner.FlushAsync(cancellationToken); public ValueTask ReadBlobDataAsync(CancellationToken cancellationToken = default) => _inner.ReadBlobDataAsync(cancellationToken); public bool TryGetLocator([NotNullWhen(true)] out BlobLocator locator) => _inner.TryGetLocator(out locator); } /// /// Create a typed blob reference /// /// Target type /// Blob referfence to wrap /// Options for deserializing the blob public static IBlobRef ForType(this IBlobRef blobRef, BlobSerializerOptions? serializerOptions = null) => new TypedBlobRef(blobRef, serializerOptions); /// /// Gets a path to this blob that can be used to describe blob references over the wire. /// /// Handle to query public static BlobLocator GetLocator(this IBlobRef import) { BlobLocator locator; if (!import.TryGetLocator(out locator)) { throw new InvalidOperationException("Blob has not yet been written to storage"); } return locator; } } }