Skip to content

Commit

Permalink
Async variants.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matasx committed Dec 9, 2024
1 parent 34180e3 commit 2d8ce9c
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 22 deletions.
2 changes: 0 additions & 2 deletions Modules/GenHTTP.Modules.I18n/Parsers/LanguageParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public static CultureInfo[] ParseFromLanguage(string? language)

try
{

var actualCount = 0;
var start = 0;
int commaIndex;
Expand Down Expand Up @@ -95,7 +94,6 @@ public static CultureInfo[] ParseFromLanguage(string? language)
rentedArray[actualCount++] = (languagePart.ToString(), qValue);
}
}

} while (commaIndex >= 0);

if (actualCount == 0)
Expand Down
30 changes: 20 additions & 10 deletions Modules/GenHTTP.Modules.I18n/Provider/LocalizationConcern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ public sealed class LocalizationConcern : IConcern
public IHandler Content { get; }

private readonly CultureInfo _defaultCulture;
private readonly CultureSelectorDelegate _cultureSelector;
private readonly CultureFilterDelegate _cultureFilter;
private readonly CultureSetterDelegate _cultureSetter;
private readonly CultureSelectorCombinedAsyncDelegate _cultureSelector;
private readonly CultureFilterAsyncDelegate _cultureFilter;
private readonly CultureSetterAsyncDelegate _cultureSetter;

#endregion

Expand All @@ -22,9 +22,9 @@ public sealed class LocalizationConcern : IConcern
public LocalizationConcern(
IHandler content,
CultureInfo defaultCulture,
CultureSelectorDelegate cultureSelector,
CultureFilterDelegate cultureFilter,
CultureSetterDelegate cultureSetter
CultureSelectorCombinedAsyncDelegate cultureSelector,
CultureFilterAsyncDelegate cultureFilter,
CultureSetterAsyncDelegate cultureSetter
)
{
Content = content;
Expand All @@ -40,13 +40,23 @@ CultureSetterDelegate cultureSetter

#region Functionality

private async ValueTask<CultureInfo?> ResolveCultureInfoAsync(IRequest request)
{
await foreach (var candidate in _cultureSelector(request))
{
if (await _cultureFilter(request, candidate))
{
return candidate;
}
}
return null;
}

public async ValueTask<IResponse?> HandleAsync(IRequest request)
{
var culture = (_cultureSelector(request) ?? [])
.FirstOrDefault(c => _cultureFilter(request, c))
?? _defaultCulture;
var culture = await ResolveCultureInfoAsync(request) ?? _defaultCulture;

_cultureSetter(request, culture);
await _cultureSetter(request, culture);

return await Content.HandleAsync(request);
}
Expand Down
52 changes: 42 additions & 10 deletions Modules/GenHTTP.Modules.I18n/Provider/LocalizationConcernBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ public sealed class LocalizationConcernBuilder : IConcernBuilder

private CultureInfo _defaultCulture = CultureInfo.CurrentCulture;

private readonly List<CultureSelectorDelegate> _cultureSelectors = [];
private CultureFilterDelegate _cultureFilter = (_, _) => true;
private readonly List<CultureSetterDelegate> _cultureSetters = [];
private readonly List<CultureSelectorAsyncDelegate> _cultureSelectors = [];
private CultureFilterAsyncDelegate _cultureFilter = (_, _) => ValueTask.FromResult(true);
private readonly List<CultureSetterAsyncDelegate> _cultureSetters = [];

#endregion

Expand Down Expand Up @@ -46,13 +46,19 @@ public LocalizationConcernBuilder FromHeader(string headerName = "Accept-Languag
});

public LocalizationConcernBuilder FromLanguage(Func<IRequest, string?> languageSelector)
=> FromRequest(request =>
=> FromLanguage(request => ValueTask.FromResult(languageSelector(request)));

public LocalizationConcernBuilder FromLanguage(Func<IRequest, ValueTask<string?>> languageSelector)
=> FromRequest(async request =>
{
var language = languageSelector(request);
var language = await languageSelector(request);
return CultureInfoParser.ParseFromLanguage(language);
});

public LocalizationConcernBuilder FromRequest(CultureSelectorDelegate cultureSelector)
public LocalizationConcernBuilder FromRequest(CultureSelectorDelegate cultureSelector)
=> FromRequest(request => ValueTask.FromResult(cultureSelector(request)));

public LocalizationConcernBuilder FromRequest(CultureSelectorAsyncDelegate cultureSelector)
{
_cultureSelectors.Add(cultureSelector);
return this;
Expand All @@ -71,7 +77,13 @@ public LocalizationConcernBuilder Supports(params CultureInfo[] supportedCulture
public LocalizationConcernBuilder Supports(Predicate<CultureInfo> culturePredicate)
=> Supports((_, culture) => culturePredicate(culture));

public LocalizationConcernBuilder Supports(Func<CultureInfo, ValueTask<bool>> culturePredicate)
=> Supports((_, culture) => culturePredicate(culture));

public LocalizationConcernBuilder Supports(CultureFilterDelegate cultureFilter)
=> Supports((request, culture) => ValueTask.FromResult(cultureFilter(request, culture)));

public LocalizationConcernBuilder Supports(CultureFilterAsyncDelegate cultureFilter)
{
_cultureFilter = cultureFilter;
return this;
Expand Down Expand Up @@ -100,10 +112,20 @@ public LocalizationConcernBuilder Setter(bool currentCulture = false, bool curre
return this;
}

public LocalizationConcernBuilder Setter(Func<CultureInfo, ValueTask> cultureSetter)
=> Setter((_, culture) => cultureSetter(culture));

public LocalizationConcernBuilder Setter(Action<CultureInfo> cultureSetter)
=> Setter((_, culture) => cultureSetter(culture));

public LocalizationConcernBuilder Setter(CultureSetterDelegate cultureSetter)
=> Setter((request, culture) =>
{
cultureSetter(request, culture);
return ValueTask.CompletedTask;
});

public LocalizationConcernBuilder Setter(CultureSetterAsyncDelegate cultureSetter)
{
_cultureSetters.Add(cultureSetter);
return this;
Expand Down Expand Up @@ -146,14 +168,24 @@ public IConcern Build(IHandler content)

#region Composite functions

private IEnumerable<CultureInfo> CultureSelector(IRequest request)
=> _cultureSelectors.SelectMany(selector => selector(request));
private async IAsyncEnumerable<CultureInfo> CultureSelector(IRequest request)
{
foreach (var selector in _cultureSelectors)
{
var cultures = await selector(request);
foreach (var culture in cultures)
{
yield return culture;
}
}
}


private void CultureSetter(IRequest request, CultureInfo cultureInfo)
private async ValueTask CultureSetter(IRequest request, CultureInfo cultureInfo)
{
foreach (var setter in _cultureSetters)
{
setter(request, cultureInfo);
await setter(request, cultureInfo);
}
}

Expand Down
29 changes: 29 additions & 0 deletions Modules/GenHTTP.Modules.I18n/Provider/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,35 @@

namespace GenHTTP.Modules.I18n.Provider;

/// <summary>
/// Delegate to extract the cultures for a given request.
/// </summary>
/// <param name="request">The request to extract cultures for.</param>
/// <returns>An enumerable of CultureInfo objects representing the extracted cultures.</returns>
public delegate IAsyncEnumerable<CultureInfo> CultureSelectorCombinedAsyncDelegate(IRequest request);

/// <summary>
/// Delegate to extract the cultures for a given request.
/// </summary>
/// <param name="request">The request to extract cultures for.</param>
/// <returns>An enumerable of CultureInfo objects representing the extracted cultures.</returns>
public delegate ValueTask<IEnumerable<CultureInfo>> CultureSelectorAsyncDelegate(IRequest request);

/// <summary>
/// Delegate to set the culture for a given request.
/// </summary>
/// <param name="request">The request to set the culture for.</param>
/// <param name="cultureInfo">The CultureInfo object representing the culture to be set.</param>
public delegate ValueTask CultureSetterAsyncDelegate(IRequest request, CultureInfo cultureInfo);

/// <summary>
/// Delegate to filter the cultures for a given request.
/// </summary>
/// <param name="request">The request to filter cultures for.</param>
/// <param name="cultureInfo">The CultureInfo object representing the culture to be filtered.</param>
/// <returns>True if the culture is valid for the request, otherwise false.</returns>
public delegate ValueTask<bool> CultureFilterAsyncDelegate(IRequest request, CultureInfo cultureInfo);

/// <summary>
/// Delegate to extract the cultures for a given request.
/// </summary>
Expand Down

0 comments on commit 2d8ce9c

Please sign in to comment.