Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OrderActionsBy should take IComparer<ApiDescription> or second argument IComparer<string> #2001

Open
foriequal0 opened this issue Feb 9, 2021 · 0 comments
Labels
help-wanted A change up for grabs for contributions from the community p2 Medium priority

Comments

@foriequal0
Copy link

foriequal0 commented Feb 9, 2021

Currently it takes Func<ApiDescription, string>, and it is used with .OrderBy(), without StringComparer or CultureInfo. Without them, doc might be rendered in different order between runtime environments, and we can't control it.

I wanted those endpoints to be sorted in this order

GET /accounts/{id}
POST /accounts/{id}
DELETE /accounts/{id}
GET /accounts:byAlt/{alt}

I had to write this code:

// README:
// You might think "Isn't '/' comes before ':' in Ascii?", but you are wrong.
// Default string comparer isn't StringComparer.Ordinal. It uses unicode collation, so ':' comes before '/'.
// I've chosen '\t' since it works empherically. '\0' didn't worked.
// Please read the specification of the Unicode Collation Algorithm and teach me if you can : https://unicode.org/reports/tr10/
var path = action.RelativePath.Replace('/', '\t');
// To put POST, PUT before DELETE.
var ordering = new[] { "GET", "HEAD", "POST", "PUT", "DELETE", "PATCH" };
var index = Array.IndexOf(ordering, action.HttpMethod!.ToUpperInvariant());
// Again, "\t\t" is choosen to not collide with /some/endpoint/0. (who writes such endpoint template?)
return string.Format(CultureInfo.InvariantCulture, "{0}\t\t{1}", action.RelativePath, index);

If we could provide StringComparer.Ordinal to .OrderBy, then it would've been

var ordering = new[] { "GET", "HEAD", "POST", "PUT", "DELETE", "PATCH" };
var index = Array.IndexOf(ordering, action.HttpMethod!.ToUpperInvariant());
return string.Format(CultureInfo.InvariantCulture, "{0}\0{1}", action.RelativePath, index);

But I'd like to remove the funky '\0' with IComparer<ApiDescription>,

class ApiDescriptionComparer : IComparer<ApiDescription> {
  readonly string[] ordering = new[] { "GET", "HEAD", "POST", "PUT", "DELETE", "PATCH" };
  public int Comapre(ApiDescription a, ApiDescription b) {
    var i = a.RelativePath.CompareTo(b.RelativePath, StringComparer.Ordinal);
    if (i != 0) return i;
    
    var ia = Array.IndexOf(ordering, a.HttpMethod!.ToUpperInvariant());
    var ib = Array.IndexOf(ordering, b.HttpMethod!.ToUpperInvariant());
    return ia - ib;
  }
}
@domaindrivendev domaindrivendev added the p2 Medium priority label Feb 12, 2021
@martincostello martincostello added the help-wanted A change up for grabs for contributions from the community label May 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help-wanted A change up for grabs for contributions from the community p2 Medium priority
Projects
None yet
Development

No branches or pull requests

3 participants