Skip to content

Commit

Permalink
feat: add stringenum
Browse files Browse the repository at this point in the history
  • Loading branch information
JamieMagee committed Aug 8, 2022
1 parent 05c3225 commit f1f4604
Show file tree
Hide file tree
Showing 34 changed files with 331 additions and 160 deletions.
18 changes: 18 additions & 0 deletions src/Octokit.Webhooks/Converter/StringEnumConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Octokit.Webhooks.Converter;

using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Octokit.Webhooks.Extensions;

internal sealed class StringEnumConverter<TEnum> : JsonConverter<StringEnum<TEnum>>
where TEnum : struct
{
public override StringEnum<TEnum> Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) => new(reader.GetString()!);

public override void Write(Utf8JsonWriter writer, StringEnum<TEnum> value, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, value.StringValue, options);
}
104 changes: 104 additions & 0 deletions src/Octokit.Webhooks/Extensions/StringEnum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
namespace Octokit.Webhooks.Extensions;

using System;
using System.Globalization;
using System.Linq;
using System.Runtime.Serialization;
using JetBrains.Annotations;

[PublicAPI]
public sealed record StringEnum<TEnum>
where TEnum : struct
{
private TEnum? parsedValue;

public StringEnum(string stringValue)
{
this.StringValue = stringValue;
this.parsedValue = null;
}

public StringEnum(TEnum parsedValue)
{
if (!Enum.IsDefined(typeof(TEnum), parsedValue))
{
throw GetArgumentException(parsedValue.ToString());
}

this.StringValue = ToEnumString(parsedValue);
this.parsedValue = parsedValue;
}

public string StringValue { get; }

public TEnum Value => this.parsedValue ??= this.ParseValue();

public static implicit operator StringEnum<TEnum>(string value) => new(value);

public static implicit operator StringEnum<TEnum>(TEnum parsedValue) => new(parsedValue);

public bool TryParse(out TEnum value)
{
if (this.parsedValue is not null)
{
value = this.parsedValue.Value;
return true;
}

try
{
value = ToEnum(this.StringValue);
this.parsedValue = value;
return true;
}
catch (ArgumentException)
{
value = default;
return false;
}
}

private static ArgumentException GetArgumentException(string? value) => new(string.Format(
CultureInfo.InvariantCulture,
"Value '{0}' is not a valid '{1}' enum value.",
value,
typeof(TEnum).Name));

private TEnum ParseValue()
{
if (this.TryParse(out var value))
{
return value;
}

throw GetArgumentException(this.StringValue);
}

private static string ToEnumString(TEnum type)
{
var enumType = typeof(TEnum);
var name = Enum.GetName(enumType, type);
if (name is not null)
{
var enumMemberAttribute = ((EnumMemberAttribute[])enumType.GetField(name)!.GetCustomAttributes(typeof(EnumMemberAttribute), true)).Single();
return enumMemberAttribute.Value!;
}

throw new ArgumentException(type.ToString());
}

private static TEnum ToEnum(string str)
{
var enumType = typeof(TEnum);
foreach (var name in Enum.GetNames(enumType))
{
var enumMemberAttribute = ((EnumMemberAttribute[])enumType.GetField(name)!.GetCustomAttributes(typeof(EnumMemberAttribute), true)).Single();
if (enumMemberAttribute.Value == str)
{
return (TEnum)Enum.Parse(enumType, name);
}
}

throw new ArgumentException(str);
}
}
3 changes: 0 additions & 3 deletions src/Octokit.Webhooks/Models/ActiveLockReason.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
namespace Octokit.Webhooks.Models;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using JetBrains.Annotations;

[PublicAPI]
[JsonConverter(typeof(JsonStringEnumMemberConverterWithFallback))]
public enum ActiveLockReason
{
Unknown = -1,
[EnumMember(Value = "resolved")]
Resolved,
[EnumMember(Value = "off-topic")]
Expand Down
4 changes: 3 additions & 1 deletion src/Octokit.Webhooks/Models/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Octokit.Webhooks.Models;
using System.Text.Json.Serialization;
using JetBrains.Annotations;
using Octokit.Webhooks.Converter;
using Octokit.Webhooks.Extensions;

[PublicAPI]
public sealed record App
Expand Down Expand Up @@ -45,5 +46,6 @@ public sealed record App
public AppPermissions? Permissions { get; init; }

[JsonPropertyName("events")]
public IEnumerable<AppEvent>? Events { get; init; }
[JsonConverter(typeof(StringEnum<AppEvent>))]
public IEnumerable<StringEnum<AppEvent>>? Events { get; init; }
}
3 changes: 0 additions & 3 deletions src/Octokit.Webhooks/Models/AppEvent.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
namespace Octokit.Webhooks.Models;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using JetBrains.Annotations;

[PublicAPI]
[JsonConverter(typeof(JsonStringEnumMemberConverterWithFallback))]
public enum AppEvent
{
Unknown = -1,
[EnumMember(Value = "*")]
All,
[EnumMember(Value = "branch_protection_rule")]
Expand Down
107 changes: 72 additions & 35 deletions src/Octokit.Webhooks/Models/AppPermissions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,112 +2,149 @@

using System.Text.Json.Serialization;
using JetBrains.Annotations;
using Octokit.Webhooks.Converter;
using Octokit.Webhooks.Extensions;

[PublicAPI]
public sealed record AppPermissions
{
[JsonPropertyName("actions")]
public AppPermissionsLevel? Actions { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Actions { get; init; }

[JsonPropertyName("administration")]
public AppPermissionsLevel? Administration { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Administration { get; init; }

[JsonPropertyName("checks")]
public AppPermissionsLevel? Checks { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Checks { get; init; }

[JsonPropertyName("content_references")]
public AppPermissionsLevel? ContentReferences { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? ContentReferences { get; init; }

[JsonPropertyName("contents")]
public AppPermissionsLevel? Contents { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Contents { get; init; }

[JsonPropertyName("deployments")]
public AppPermissionsLevel? Deployments { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Deployments { get; init; }

[JsonPropertyName("discussions")]
public AppPermissionsLevel? Discussions { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Discussions { get; init; }

[JsonPropertyName("emails")]
public AppPermissionsLevel? Emails { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Emails { get; init; }

[JsonPropertyName("environments")]
public AppPermissionsLevel? Environments { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Environments { get; init; }

[JsonPropertyName("issues")]
public AppPermissionsLevel? Issues { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Issues { get; init; }

[JsonPropertyName("members")]
public AppPermissionsLevel? Members { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Members { get; init; }

[JsonPropertyName("merge_queues")]
public AppPermissionsLevel? MergeQueues { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? MergeQueues { get; init; }

[JsonPropertyName("metadata")]
public AppPermissionsLevel? Metadata { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Metadata { get; init; }

[JsonPropertyName("organization_administration")]
public AppPermissionsLevel? OrganizationAdministration { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? OrganizationAdministration { get; init; }

[JsonPropertyName("organization_hooks")]
public AppPermissionsLevel? OrganizationHooks { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? OrganizationHooks { get; init; }

[JsonPropertyName("organization_packages")]
public AppPermissionsLevel? OrganizationPackages { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? OrganizationPackages { get; init; }

[JsonPropertyName("organization_plan")]
public AppPermissionsLevel? OrganizationPlan { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? OrganizationPlan { get; init; }

[JsonPropertyName("organization_projects")]
public AppPermissionsLevel? OrganizationProjects { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? OrganizationProjects { get; init; }

[JsonPropertyName("organization_secrets")]
public AppPermissionsLevel? OrganizationSecrets { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? OrganizationSecrets { get; init; }

[JsonPropertyName("organization_self_hosted_runners")]
public AppPermissionsLevel? OrganizationSelfHostedRunners { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? OrganizationSelfHostedRunners { get; init; }

[JsonPropertyName("organization_user_blocking")]
public AppPermissionsLevel? OrganizationUserBlocking { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? OrganizationUserBlocking { get; init; }

[JsonPropertyName("packages")]
public AppPermissionsLevel? Packages { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Packages { get; init; }

[JsonPropertyName("pages")]
public AppPermissionsLevel? Pages { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Pages { get; init; }

[JsonPropertyName("pull_requests")]
public AppPermissionsLevel? PullRequests { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? PullRequests { get; init; }

[JsonPropertyName("repository_hooks")]
public AppPermissionsLevel? RepositoryHooks { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? RepositoryHooks { get; init; }

[JsonPropertyName("repository_projects")]
public AppPermissionsLevel? RepositoryProjects { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? RepositoryProjects { get; init; }

[JsonPropertyName("secret_scanning_alerts")]
public AppPermissionsLevel? SecretScanningAlerts { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? SecretScanningAlerts { get; init; }

[JsonPropertyName("secrets")]
public AppPermissionsLevel? Secrets { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Secrets { get; init; }

[JsonPropertyName("security_events")]
public AppPermissionsLevel? SecurityEvents { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? SecurityEvents { get; init; }

[JsonPropertyName("security_scanning_alert")]
public AppPermissionsLevel? SecurityScanningAlert { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? SecurityScanningAlert { get; init; }

[JsonPropertyName("single_file")]
public AppPermissionsLevel? SingleFile { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? SingleFile { get; init; }

[JsonPropertyName("statuses")]
public AppPermissionsLevel? Statuses { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Statuses { get; init; }

[JsonPropertyName("team_discussions")]
public AppPermissionsLevel? TeamDiscussions { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? TeamDiscussions { get; init; }

[JsonPropertyName("vulnerability_alerts")]
public AppPermissionsLevel? VulnerabilityAlerts { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? VulnerabilityAlerts { get; init; }

[JsonPropertyName("workflows")]
public AppPermissionsLevel? Workflows { get; init; }
[JsonConverter(typeof(StringEnumConverter<AppPermissionsLevel>))]
public StringEnum<AppPermissionsLevel>? Workflows { get; init; }
}
3 changes: 0 additions & 3 deletions src/Octokit.Webhooks/Models/AppPermissionsLevel.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
namespace Octokit.Webhooks.Models;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using JetBrains.Annotations;

[PublicAPI]
[JsonConverter(typeof(JsonStringEnumMemberConverterWithFallback))]
public enum AppPermissionsLevel
{
Unknown = -1,
[EnumMember(Value = "read")]
Read,
[EnumMember(Value = "write")]
Expand Down
3 changes: 0 additions & 3 deletions src/Octokit.Webhooks/Models/AuthorAssociation.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
namespace Octokit.Webhooks.Models;

using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using JetBrains.Annotations;

[PublicAPI]
[JsonConverter(typeof(JsonStringEnumMemberConverterWithFallback))]
public enum AuthorAssociation
{
Unknown = -1,
[EnumMember(Value = "COLLABORATOR")]
Collaborator,
[EnumMember(Value = "CONTRIBUTOR")]
Expand Down
Loading

0 comments on commit f1f4604

Please sign in to comment.