Last active
February 16, 2022 12:53
-
-
Save in-async/741d853eb149df133b96cf60518814c4 to your computer and use it in GitHub Desktop.
URI Template Level 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
namespace Commons { | |
public class UriTemplate1 { | |
public static void Expand(TextWriter writer, string template, IDictionary<string, object?> parameters) { | |
if (writer is null) { throw new ArgumentNullException(nameof(writer)); } | |
if (template is null) { throw new ArgumentNullException(nameof(template)); } | |
if (parameters is null) { throw new ArgumentNullException(nameof(parameters)); } | |
IEnumerable<Enclosing> enclosings = template.EnumerateEnclosings('{', '}'); | |
ExpandCore(writer, template, enclosings, parameters); | |
} | |
public static string Expand(string template, IDictionary<string, object?> parameters) { | |
if (template is null) { throw new ArgumentNullException(nameof(template)); } | |
if (parameters is null) { throw new ArgumentNullException(nameof(parameters)); } | |
using StringWriter writer = new(); | |
IEnumerable<Enclosing> enclosings = template.EnumerateEnclosings('{', '}'); | |
ExpandCore(writer, template, enclosings, parameters); | |
return writer.ToString(); | |
} | |
private readonly Enclosing[] _enclosings; | |
public UriTemplate1(string template) { | |
Template = template ?? throw new ArgumentNullException(nameof(template)); | |
_enclosings = template.EnumerateEnclosings('{', '}').ToArray(); | |
} | |
public string Template { get; } | |
public void Expand(TextWriter writer, IDictionary<string, object?> parameters) { | |
if (writer is null) { throw new ArgumentNullException(nameof(writer)); } | |
if (parameters is null) { throw new ArgumentNullException(nameof(parameters)); } | |
ExpandCore(writer, Template, _enclosings, parameters); | |
} | |
public string Expand(IDictionary<string, object?> parameters) { | |
if (parameters is null) { throw new ArgumentNullException(nameof(parameters)); } | |
using StringWriter writer = new(); | |
ExpandCore(writer, Template, _enclosings, parameters); | |
return writer.ToString(); | |
} | |
private static void ExpandCore(TextWriter writer, string template, IEnumerable<Enclosing> enclosings, IDictionary<string, object?> parameters) { | |
int currentIdx = 0; | |
foreach (Enclosing enclosing in enclosings) { | |
writer.Write(template.Substring(currentIdx, enclosing.OpenIndex - currentIdx)); | |
currentIdx = enclosing.CloseIndex + 1; | |
string expr = enclosing.Inner.ToString(); | |
if (parameters.TryGetValue(expr, out object? value)) { | |
if (value is { }) { | |
writer.Write(Uri.EscapeDataString(value.ToString()!)); | |
} | |
} | |
} | |
writer.Write(template.Substring(currentIdx)); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
namespace Commons { | |
public static class StringExtensions { | |
public static IEnumerable<Enclosing> EnumerateEnclosings(this string value, char open, char close) { | |
if (value is null) { throw new ArgumentNullException(nameof(value)); } | |
for (int currentIdx = 0; currentIdx < value.Length;) { | |
int openIdx = value.IndexOf(open, currentIdx); | |
if (openIdx < 0) { break; } | |
int closeIdx = value.IndexOf(close, openIdx + 1); | |
if (closeIdx < 0) { break; } | |
yield return new Enclosing(value, openIdx, closeIdx); | |
currentIdx = closeIdx + 1; | |
} | |
} | |
} | |
public readonly struct Enclosing { | |
public Enclosing(string source, int openIndex, int closeIndex) { | |
Source = source; | |
OpenIndex = openIndex; | |
CloseIndex = closeIndex; | |
} | |
public string Source { get; } | |
public int OpenIndex { get; } | |
public int CloseIndex { get; } | |
public ReadOnlySpan<char> Inner => Source.AsSpan(OpenIndex + 1, CloseIndex - OpenIndex - 1); | |
public ReadOnlySpan<char> Outer => Source.AsSpan(OpenIndex, CloseIndex - OpenIndex + 1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment