/// <summary>
        /// Downloads the manifest for an OCI artifact.
        /// </summary>
        /// <param name="options">Options for the download operation.</param>
        /// <param name="cancellationToken">The cancellation token to use.</param>
        /// <returns>The download manifest result.</returns>
        public virtual async Task <Response <DownloadManifestResult> > DownloadManifestAsync(DownloadManifestOptions options, CancellationToken cancellationToken = default)
        {
            Argument.AssertNotNull(options, nameof(options));

            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryBlobClient)}.{nameof(DownloadManifest)}");
            scope.Start();
            try
            {
                Response <ManifestWrapper> response = await _restClient.GetManifestAsync(_repositoryName, options.Tag ?? options.Digest, ManifestMediaType.OciManifest.ToString(), cancellationToken).ConfigureAwait(false);

                Response rawResponse = response.GetRawResponse();

                rawResponse.Headers.TryGetValue("Docker-Content-Digest", out var digest);

                if (!ValidateDigest(rawResponse.ContentStream, digest))
                {
                    throw _clientDiagnostics.CreateRequestFailedException(rawResponse,
                                                                          new ResponseError(null, "The requested digest does not match the digest of the received manifest."));
                }

                using var document = JsonDocument.Parse(rawResponse.ContentStream);
                var manifest = OciManifest.DeserializeOciManifest(document.RootElement);

                rawResponse.ContentStream.Position = 0;

                return(Response.FromValue(new DownloadManifestResult(digest, manifest, rawResponse.ContentStream), rawResponse));
            }
            catch (Exception e)
            {
                scope.Failed(e);
                throw;
            }
        }
        /// <summary>
        /// Uploads a manifest for an OCI Artifact.
        /// </summary>
        /// <param name="manifest">The manifest to upload.</param>
        /// <param name="options">Options for configuring the upload operation.</param>
        /// <param name="cancellationToken"> The cancellation token to use. </param>
        /// <returns></returns>
        public virtual Response <UploadManifestResult> UploadManifest(OciManifest manifest, UploadManifestOptions options = default, CancellationToken cancellationToken = default)
        {
            Argument.AssertNotNull(manifest, nameof(manifest));

            options ??= new UploadManifestOptions();

            using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryBlobClient)}.{nameof(UploadManifest)}");
            scope.Start();
            try
            {
                Stream manifestStream = SerializeManifest(manifest);
                string manifestDigest = OciBlobDescriptor.ComputeDigest(manifestStream);
                string tagOrDigest    = options.Tag ?? manifestDigest;

                ResponseWithHeaders <ContainerRegistryCreateManifestHeaders> response = _restClient.CreateManifest(_repositoryName, tagOrDigest, manifestStream, ManifestMediaType.OciManifest.ToString(), cancellationToken);

                if (!manifestDigest.Equals(response.Headers.DockerContentDigest, StringComparison.Ordinal))
                {
                    throw _clientDiagnostics.CreateRequestFailedException(response,
                                                                          new ResponseError(null, "The digest in the response does not match the digest of the uploaded manifest."));
                }

                return(Response.FromValue(new UploadManifestResult(response.Headers.DockerContentDigest), response.GetRawResponse()));
            }
            catch (Exception e)
            {
                scope.Failed(e);
                throw;
            }
        }
        private static Stream SerializeManifest(OciManifest manifest)
        {
            MemoryStream   stream     = new();
            Utf8JsonWriter jsonWriter = new(stream);

            ((IUtf8JsonSerializable)manifest).Write(jsonWriter);
            jsonWriter.Flush();

            stream.Position = 0;

            return(stream);
        }
 internal DownloadManifestResult(string digest, OciManifest manifest, Stream manifestStream)
 {
     Digest         = digest;
     Manifest       = manifest;
     ManifestStream = manifestStream;
 }
 private static OciManifest DeserializeManifest(Stream stream)
 {
     using var document = JsonDocument.Parse(stream);
     return(OciManifest.DeserializeOciManifest(document.RootElement));
 }