|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Azure;
namespace Microsoft.DotNet.Helix.Client
{
public static class AsyncEnumerable
{
public static async Task<List<T>> ToListAsync<T>(this IAsyncEnumerable<T> that, CancellationToken cancellationToken)
{
var results = new List<T>();
await foreach (var value in that.WithCancellation(cancellationToken))
{
results.Add(value);
}
return results;
}
}
public class AsyncPageable
{
public static AsyncPageable<T> Create<T>(Func<string, int?, IAsyncEnumerable<Page<T>>> pageFunc)
{
return new FuncAsyncPageable<T>(pageFunc);
}
public class FuncAsyncPageable<T> : AsyncPageable<T>
{
private readonly Func<string, int?, IAsyncEnumerable<Page<T>>> _pageFunc;
public FuncAsyncPageable(Func<string, int?, IAsyncEnumerable<Page<T>>> pageFunc)
{
_pageFunc = pageFunc;
}
public override IAsyncEnumerable<Page<T>> AsPages(string continuationToken = null, int? pageSizeHint = null)
{
return _pageFunc(continuationToken, pageSizeHint);
}
}
}
public class LinkHeader
{
private LinkHeader(string firstPageLink, string prevPageLink, string nextPageLink, string lastPageLink)
{
FirstPageLink = firstPageLink;
PrevPageLink = prevPageLink;
NextPageLink = nextPageLink;
LastPageLink = lastPageLink;
}
public string FirstPageLink { get; }
public string PrevPageLink { get; }
public string NextPageLink { get; }
public string LastPageLink { get; }
public static LinkHeader Parse(IEnumerable<string> header)
{
var links = ParseLinkHeader(header).ToList();
var first = links.FirstOrDefault(t => t.rel == "first").href;
var prev = links.FirstOrDefault(t => t.rel == "prev").href;
var next = links.FirstOrDefault(t => t.rel == "next").href;
var last = links.FirstOrDefault(t => t.rel == "last").href;
return new LinkHeader(first, prev, next, last);
}
private static IEnumerable<(string href, string rel)> ParseLinkHeader(IEnumerable<string> linkHeader)
{
foreach (var header in linkHeader)
{
foreach (var link in ParseLinkHeader(header))
{
yield return link;
}
}
}
private static IEnumerable<(string href, string rel)> ParseLinkHeader(string linkHeader)
{
foreach (var link in linkHeader.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
{
if (ParseLink(link, out var result))
{
yield return result;
}
}
}
private static bool ParseLink(string link, out (string href, string rel) result)
{
result = default;
var parts = link.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 2)
{
return false;
}
var href = parts[0].Trim().TrimStart('<').TrimEnd('>');
var props = new Dictionary<string, string>();
foreach (var prop in parts.Skip(1))
{
if (TryParseProp(prop, out var p))
{
props.Add(p.key, p.value);
}
}
var rel = props["rel"];
result = (href, rel);
return true;
}
private static bool TryParseProp(string value, out (string key, string value) result)
{
result = default;
var equalIdx = value.IndexOf('=');
if (equalIdx < 0)
{
return false;
}
var key = value.Substring(0, equalIdx).Trim();
var v = value.Substring(equalIdx + 1).Trim().Trim('"');
result = (key, v);
return true;
}
}
}
|