-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#13: Use JSON object mapping instead of DOM access
- Loading branch information
Showing
10 changed files
with
203 additions
and
28 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace GamesDoneQuickCalendarFactory.Data; | ||
|
||
public record Event(string title, IEnumerable<GameRun> runs); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System.Text.Json.Serialization; | ||
|
||
namespace GamesDoneQuickCalendarFactory.Data.GDQ; | ||
|
||
public record GdqEvent( | ||
string type, | ||
int id, | ||
string @short, | ||
string name, | ||
string hashtag, | ||
DateTimeOffset datetime, | ||
string timezone, | ||
[property: JsonPropertyName("use_one_step_screening")] | ||
bool useOneStepScreening | ||
); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using System.Text.Json.Serialization; | ||
|
||
// ReSharper disable ClassNeverInstantiated.Global - these are instantiated by deserializers | ||
|
||
namespace GamesDoneQuickCalendarFactory.Data.GDQ; | ||
|
||
public record GdqRuns( | ||
int count, | ||
object? next, | ||
object? previous, | ||
IReadOnlyList<Run> results | ||
); | ||
|
||
/// <param name="displayName">always the same as <paramref name="name"/></param> | ||
/// <param name="description">always <c>""</c></param> | ||
/// <param name="runTime">before a run ends, this is the estimated duration, but after a run ends, this changes to the actual duration</param> | ||
public record Run( | ||
string type, | ||
int id, | ||
string name, | ||
[property: JsonPropertyName("display_name")] string displayName, | ||
string description, | ||
string category, | ||
string console, | ||
IReadOnlyList<Runner> runners, | ||
IReadOnlyList<Person> hosts, | ||
IReadOnlyList<Person> commentators, | ||
[property: JsonPropertyName("starttime")] DateTimeOffset startTime, | ||
[property: JsonPropertyName("endtime")] DateTimeOffset endTime, | ||
int order, | ||
[property: JsonPropertyName("run_time")] string runTime, | ||
[property: JsonPropertyName("setup_time")] TimeSpan setupTime, | ||
[property: JsonPropertyName("anchor_time")] DateTimeOffset? anchorTime, | ||
[property: JsonPropertyName("video_links")] IReadOnlyList<Video> videos | ||
); | ||
|
||
public record Person( | ||
string type, | ||
int id, | ||
string name, | ||
string pronouns | ||
); | ||
|
||
/// <param name="twitter">Handle/username on Twitter</param> | ||
/// <param name="youtube">Handle on YouTube</param> | ||
/// <param name="streamingPlatform">The service that <paramref name="stream"/> is hosted on</param> | ||
public record Runner( | ||
string type, | ||
int id, | ||
string name, | ||
Uri stream, | ||
string twitter, | ||
string youtube, | ||
[property: JsonPropertyName("platform")] StreamingPlatform streamingPlatform, | ||
string pronouns | ||
): Person(type, id, name, pronouns); | ||
|
||
public enum StreamingPlatform { | ||
|
||
TWITCH | ||
|
||
} | ||
|
||
public record Video( | ||
int id, | ||
[property: JsonPropertyName("link_type")] VideoType type, | ||
Uri url | ||
); | ||
|
||
public enum VideoType { | ||
|
||
TWITCH, | ||
YOUTUBE | ||
|
||
} |
2 changes: 1 addition & 1 deletion
2
GamesDoneQuickCalendarFactory/GameRun.cs → ...sDoneQuickCalendarFactory/Data/GameRun.cs
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
69 changes: 69 additions & 0 deletions
69
GamesDoneQuickCalendarFactory/Data/Marshal/ZeroTolerantTimeSpanConverter.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using System.Buffers.Text; | ||
using System.Diagnostics; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
|
||
namespace GamesDoneQuickCalendarFactory.Data.Marshal; | ||
|
||
/// <summary> | ||
/// Copy of <see cref="System.Text.Json.Serialization.Converters.TimeSpanConverter"/> that can handle <c>"0"</c> inputs | ||
/// </summary> | ||
[ExcludeFromCodeCoverage(Justification = "Copied third-party code")] | ||
public class ZeroTolerantTimeSpanConverter: JsonConverter<TimeSpan> { | ||
|
||
public static readonly ZeroTolerantTimeSpanConverter INSTANCE = new(); | ||
|
||
private const int MINIMUM_TIME_SPAN_FORMAT_LENGTH = 1; // 0, changed from 8 by Ben | ||
private const int MAXIMUM_TIME_SPAN_FORMAT_LENGTH = 26; // -dddddddd.hh:mm:ss.fffffff | ||
private const int MAXIMUM_ESCAPED_TIME_SPAN_FORMAT_LENGTH = 6 * MAXIMUM_TIME_SPAN_FORMAT_LENGTH; | ||
|
||
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { | ||
if (reader.TokenType != JsonTokenType.String) { | ||
throw new InvalidOperationException($"Cannot get the value of a token type '{reader.TokenType}' as a string."); | ||
} | ||
|
||
return readCore(ref reader); | ||
} | ||
|
||
private static TimeSpan readCore(ref Utf8JsonReader reader) { | ||
Debug.Assert(reader.TokenType is JsonTokenType.String or JsonTokenType.PropertyName); | ||
|
||
int valueLength = reader.HasValueSequence ? checked((int) reader.ValueSequence.Length) : reader.ValueSpan.Length; | ||
if (valueLength is < MINIMUM_TIME_SPAN_FORMAT_LENGTH or > MAXIMUM_ESCAPED_TIME_SPAN_FORMAT_LENGTH) { | ||
throw new FormatException($"The JSON value is not in a supported {nameof(TimeSpan)} format."); | ||
} | ||
|
||
scoped ReadOnlySpan<byte> source; | ||
if (!reader.HasValueSequence && !reader.ValueIsEscaped) { | ||
source = reader.ValueSpan; | ||
} else { | ||
Span<byte> stackSpan = stackalloc byte[MAXIMUM_ESCAPED_TIME_SPAN_FORMAT_LENGTH]; | ||
int bytesWritten = reader.CopyString(stackSpan); | ||
source = stackSpan[..bytesWritten]; | ||
} | ||
|
||
char firstChar = (char) source[0]; | ||
if (firstChar is < '0' or > '9' && firstChar != '-') { | ||
throw new FormatException($"The JSON value is not in a supported {nameof(TimeSpan)} format."); | ||
} | ||
|
||
bool result = Utf8Parser.TryParse(source, out TimeSpan tmpValue, out int bytesConsumed, 'c'); | ||
|
||
if (!result || source.Length != bytesConsumed) { | ||
throw new FormatException($"The JSON value is not in a supported {nameof(TimeSpan)} format."); | ||
} | ||
|
||
return tmpValue; | ||
} | ||
|
||
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options) { | ||
Span<byte> output = stackalloc byte[MAXIMUM_TIME_SPAN_FORMAT_LENGTH]; | ||
|
||
bool result = Utf8Formatter.TryFormat(value, output, out int bytesWritten, 'c'); | ||
Debug.Assert(result); | ||
|
||
writer.WriteStringValue(output[..bytesWritten]); | ||
} | ||
|
||
} |
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
This file was deleted.
Oops, something went wrong.
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
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