Skip to content

Respond to data schema improvements #6465

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

Merged
merged 2 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
namespace Elastic.Clients.Elasticsearch;

/// <summary>
/// Represents a time value
/// Represents a duration value.
/// </summary>
[JsonConverter(typeof(TimeConverter))]
public sealed class Time : IComparable<Time>, IEquatable<Time>, IUrlParameter
[JsonConverter(typeof(DurationConverter))]
public sealed class Duration : IComparable<Duration>, IEquatable<Duration>, IUrlParameter
{
private const double MicrosecondsInATick = 0.1; // 10 ticks = 1 microsecond
private const double MillisecondsInADay = MillisecondsInAnHour * 24;
Expand All @@ -40,18 +40,18 @@ public sealed class Time : IComparable<Time>, IEquatable<Time>, IUrlParameter

private static readonly double FLOAT_TOLERANCE = 1e-7; // less than 1 nanosecond

private Time(int specialFactor, bool specialValue)
private Duration(int specialFactor, bool specialValue)
{
if (!specialValue)
throw new ArgumentException("this constructor is only for static TimeValues");

StaticTimeValue = specialFactor;
}

public Time(TimeSpan timeSpan)
public Duration(TimeSpan timeSpan)
: this(timeSpan.TotalMilliseconds) { }

public Time(double milliseconds)
public Duration(double milliseconds)
{
if (Math.Abs(milliseconds - -1) < FLOAT_TOLERANCE)
StaticTimeValue = -1;
Expand All @@ -61,14 +61,14 @@ public Time(double milliseconds)
Reduce(milliseconds);
}

public Time(double factor, TimeUnit interval)
public Duration(double factor, TimeUnit interval)
{
Factor = factor;
Interval = interval;
Milliseconds = GetExactMilliseconds(Factor.Value, Interval.Value);
}

public Time(string timeUnit)
public Duration(string timeUnit)
{
if (timeUnit.IsNullOrEmpty())
throw new ArgumentException("Expression string is empty", nameof(timeUnit));
Expand All @@ -85,17 +85,17 @@ public Time(string timeUnit)

public double? Milliseconds { get; private set; }

public static Time MinusOne { get; } = new Time(-1, true);
public static Duration MinusOne { get; } = new Duration(-1, true);

public static Time Zero { get; } = new Time(0, true);
public static Duration Zero { get; } = new Duration(0, true);

private int? StaticTimeValue { get; }

public static implicit operator Time(TimeSpan span) => new(span);
public static implicit operator Duration(TimeSpan span) => new(span);

public static implicit operator Time(double milliseconds) => new(milliseconds);
public static implicit operator Duration(double milliseconds) => new(milliseconds);

public static implicit operator Time(string expression) => new(expression);
public static implicit operator Duration(string expression) => new(expression);

private void ParseExpression(string timeUnit)
{
Expand Down Expand Up @@ -147,7 +147,7 @@ private void ParseExpression(string timeUnit)
Milliseconds = GetExactMilliseconds(Factor.Value, Interval.Value);
}

public int CompareTo(Time other)
public int CompareTo(Duration other)
{
if (other == null)
return 1;
Expand Down Expand Up @@ -182,21 +182,21 @@ public int CompareTo(Time other)

private static bool IsIntegerGreaterThanZero(double d) => Math.Abs(d % 1) < double.Epsilon;

public static bool operator <(Time left, Time right) => left.CompareTo(right) < 0;
public static bool operator <(Duration left, Duration right) => left.CompareTo(right) < 0;

public static bool operator <=(Time left, Time right) => left.CompareTo(right) < 0 || left.Equals(right);
public static bool operator <=(Duration left, Duration right) => left.CompareTo(right) < 0 || left.Equals(right);

public static bool operator >(Time left, Time right) => left.CompareTo(right) > 0;
public static bool operator >(Duration left, Duration right) => left.CompareTo(right) > 0;

public static bool operator >=(Time left, Time right) => left.CompareTo(right) > 0 || left.Equals(right);
public static bool operator >=(Duration left, Duration right) => left.CompareTo(right) > 0 || left.Equals(right);

public static bool operator ==(Time left, Time right) =>
public static bool operator ==(Duration left, Duration right) =>
ReferenceEquals(left, null) ? right is null : left.Equals(right);

public static bool operator !=(Time left, Time right) => !(left == right);
public static bool operator !=(Duration left, Duration right) => !(left == right);

/// <summary>
/// Converts this instance of <see cref="Time" /> to an instance of <see cref="TimeSpan" />.
/// Converts this instance of <see cref="Duration" /> to an instance of <see cref="TimeSpan" />.
/// For values in <see cref="TimeUnit.Microseconds" /> and <see cref="TimeUnit.Nanoseconds" />, value will be rounded to
/// the nearest Tick.
/// All other values will be rounded to the nearest Millisecond.
Expand All @@ -206,7 +206,7 @@ public int CompareTo(Time other)
/// special time values <see cref="MinusOne" /> and <see cref="Zero" /> do not have a <see cref="TimeSpan" />
/// representation.
/// </para>
/// <para>instance of <see cref="Time" /> has no value for <see cref="Interval" /></para>
/// <para>instance of <see cref="Duration" /> has no value for <see cref="Interval" /></para>
/// </exception>
public TimeSpan ToTimeSpan()
{
Expand Down Expand Up @@ -256,7 +256,7 @@ string IUrlParameter.GetString(ITransportConfiguration config)
return Milliseconds.ToString();
}

public bool Equals(Time other)
public bool Equals(Duration other)
{
if (ReferenceEquals(null, other))
return false;
Expand Down Expand Up @@ -286,7 +286,7 @@ public override bool Equals(object obj)
if (obj.GetType() != GetType())
return false;

return Equals((Time)obj);
return Equals((Duration)obj);
}

public override int GetHashCode() => StaticTimeValue.HasValue
Expand Down Expand Up @@ -392,33 +392,33 @@ private static string ExponentFormat(double d)
}
}

internal sealed class TimeConverter : JsonConverter<Time>
internal sealed class DurationConverter : JsonConverter<Duration>
{
public override Time? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
public override Duration? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var token = reader.TokenType;

switch (token)
{
case JsonTokenType.String:
return new Time(reader.GetString());
return new Duration(reader.GetString());
case JsonTokenType.Number:
var milliseconds = reader.GetInt64();
if (milliseconds == -1)
return Time.MinusOne;
return Duration.MinusOne;
if (milliseconds == 0)
return Time.Zero;
return new Time(milliseconds);
return Duration.Zero;
return new Duration(milliseconds);
default:
return null;
}
}

public override void Write(Utf8JsonWriter writer, Time value, JsonSerializerOptions options)
public override void Write(Utf8JsonWriter writer, Duration value, JsonSerializerOptions options)
{
if (value == Time.MinusOne)
if (value == Duration.MinusOne)
writer.WriteNumberValue(-1);
else if (value == Time.Zero)
else if (value == Duration.Zero)
writer.WriteNumberValue(0);
else if (value.Factor.HasValue && value.Interval.HasValue)
writer.WriteStringValue(value.ToString());
Expand Down
43 changes: 0 additions & 43 deletions src/Elastic.Clients.Elasticsearch/Common/DateTimeUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,3 @@ internal static class DateTimeUtil
{
public static readonly DateTimeOffset UnixEpoch = new(1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero);
}

[JsonConverter(typeof(EpochMillisConverter))]
public readonly struct EpochMillis
{
public static EpochMillis Zero = new(0);

public EpochMillis() => MillisecondsSinceEpoch = 0;

public EpochMillis(long millisecondsSinceEpoch) => MillisecondsSinceEpoch = millisecondsSinceEpoch;

public static EpochMillis Parse(string millisecondsSinceEpoch)
{
if (!long.TryParse(millisecondsSinceEpoch, out var parsedValue))
throw new InvalidOperationException($"Unable to parse value '{millisecondsSinceEpoch}' to epoch milliseconds.");

return new EpochMillis(parsedValue);
}

public long MillisecondsSinceEpoch { get; private init; }

public DateTimeOffset DateTimeOffset => DateTimeUtil.UnixEpoch.AddMilliseconds(MillisecondsSinceEpoch);
}

internal sealed class EpochMillisConverter : JsonConverter<EpochMillis>
{
public override EpochMillis Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var valueAsString = reader.GetString();
return EpochMillis.Parse(valueAsString);
}
else if (reader.TokenType == JsonTokenType.Number)
{
var value = reader.GetInt64();
return new EpochMillis(value);
}

throw new JsonException("Value could not be parsed to EpochMillis");
}

public override void Write(Utf8JsonWriter writer, EpochMillis value, JsonSerializerOptions options) => writer.WriteNumberValue(value.MillisecondsSinceEpoch);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Elastic.Clients.Elasticsearch
[DebuggerDisplay("{DebugDisplay,nq}")]
public sealed class DataStreamName : IEquatable<DataStreamName>, IUrlParameter
{
internal DataStreamName(string index) => Name = index;
internal DataStreamName(string dataStreamName) => Name = dataStreamName;

public string Name { get; }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using Elastic.Transport;

namespace Elastic.Clients.Elasticsearch
{
[JsonConverter(typeof(ScrollIdConverter))]
[DebuggerDisplay("{DebugDisplay,nq}")]
public sealed class ScrollId : IEquatable<ScrollId>, IUrlParameter
{
internal ScrollId(string scrollId) => Id = scrollId;

public string Id { get; }

internal string DebugDisplay => Id;

public static implicit operator ScrollId(string scrollId) => new(scrollId);

public static bool operator ==(ScrollId left, ScrollId right) => Equals(left, right);

public static bool operator !=(ScrollId left, ScrollId right) => !Equals(left, right);

bool IEquatable<ScrollId>.Equals(ScrollId other) => EqualsMarker(other);

private bool EqualsString(string other) => !other.IsNullOrEmpty() && other.Equals(Id, StringComparison.Ordinal);

public override bool Equals(object obj) => obj is string s ? EqualsString(s) : obj is ScrollId i && EqualsMarker(i);

string IUrlParameter.GetString(ITransportConfiguration? settings) => Id;

public override string ToString() => Id ?? string.Empty;

private bool EqualsMarker(ScrollId other)
{
if (other == null)
return false;

return EqualsString(other.Id);
}

private static int TypeHashCode { get; } = typeof(ScrollId).GetHashCode();

public override int GetHashCode()
{
unchecked
{
return (TypeHashCode * 23) ^ (Id.GetHashCode());
}
}
}

internal sealed class ScrollIdConverter : JsonConverter<ScrollId>
{
public override ScrollId? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.String)
throw new JsonException($"Unexpected token '{reader.TokenType}' for DataStreamName");

return reader.GetString();
}

public override void Write(Utf8JsonWriter writer, ScrollId value, JsonSerializerOptions options)
{
if (value is null || value.Id is null)
{
writer.WriteNullValue();
return;
}

writer.WriteStringValue(value.Id);
}
}
}
Loading