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

Added Value (variant) Type #27487

Merged
merged 7 commits into from
Mar 12, 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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,111 @@ public BinaryContent() { }
public virtual System.BinaryData? Data { get { throw null; } set { } }
public virtual bool IsReadOnly { get { throw null; } }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct Value
tg-msft marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public Value(System.ArraySegment<byte> segment) { throw null; }
KrzysztofCwalina marked this conversation as resolved.
Show resolved Hide resolved
public Value(System.ArraySegment<char> segment) { throw null; }
public Value(bool value) { throw null; }
public Value(byte value) { throw null; }
public Value(char value) { throw null; }
public Value(System.DateTime value) { throw null; }
public Value(System.DateTimeOffset value) { throw null; }
public Value(double value) { throw null; }
public Value(short value) { throw null; }
public Value(int value) { throw null; }
public Value(long value) { throw null; }
public Value(bool? value) { throw null; }
public Value(byte? value) { throw null; }
public Value(char? value) { throw null; }
public Value(System.DateTimeOffset? value) { throw null; }
public Value(System.DateTime? value) { throw null; }
public Value(double? value) { throw null; }
public Value(short? value) { throw null; }
public Value(int? value) { throw null; }
public Value(long? value) { throw null; }
public Value(sbyte? value) { throw null; }
public Value(float? value) { throw null; }
public Value(ushort? value) { throw null; }
public Value(uint? value) { throw null; }
public Value(ulong? value) { throw null; }
public Value(object? value) { throw null; }
KrzysztofCwalina marked this conversation as resolved.
Show resolved Hide resolved
public Value(sbyte value) { throw null; }
public Value(float value) { throw null; }
public Value(ushort value) { throw null; }
public Value(uint value) { throw null; }
public Value(ulong value) { throw null; }
public System.Type? Type { get { throw null; } }
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public T As<T>() { throw null; }
public static Azure.Value Create<T>(T value) { throw null; }
public static explicit operator System.ArraySegment<byte> (in Azure.Value value) { throw null; }
public static explicit operator System.ArraySegment<char> (in Azure.Value value) { throw null; }
public static explicit operator bool (in Azure.Value value) { throw null; }
public static explicit operator byte (in Azure.Value value) { throw null; }
public static explicit operator char (in Azure.Value value) { throw null; }
public static explicit operator System.DateTime (in Azure.Value value) { throw null; }
public static explicit operator System.DateTimeOffset (in Azure.Value value) { throw null; }
public static explicit operator decimal (in Azure.Value value) { throw null; }
public static explicit operator double (in Azure.Value value) { throw null; }
public static explicit operator short (in Azure.Value value) { throw null; }
public static explicit operator int (in Azure.Value value) { throw null; }
public static explicit operator long (in Azure.Value value) { throw null; }
public static explicit operator bool? (in Azure.Value value) { throw null; }
public static explicit operator byte? (in Azure.Value value) { throw null; }
public static explicit operator char? (in Azure.Value value) { throw null; }
public static explicit operator System.DateTimeOffset? (in Azure.Value value) { throw null; }
public static explicit operator System.DateTime? (in Azure.Value value) { throw null; }
public static explicit operator decimal? (in Azure.Value value) { throw null; }
public static explicit operator double? (in Azure.Value value) { throw null; }
public static explicit operator short? (in Azure.Value value) { throw null; }
public static explicit operator int? (in Azure.Value value) { throw null; }
public static explicit operator long? (in Azure.Value value) { throw null; }
public static explicit operator sbyte? (in Azure.Value value) { throw null; }
public static explicit operator float? (in Azure.Value value) { throw null; }
public static explicit operator ushort? (in Azure.Value value) { throw null; }
public static explicit operator uint? (in Azure.Value value) { throw null; }
public static explicit operator ulong? (in Azure.Value value) { throw null; }
public static explicit operator sbyte (in Azure.Value value) { throw null; }
public static explicit operator float (in Azure.Value value) { throw null; }
public static explicit operator ushort (in Azure.Value value) { throw null; }
public static explicit operator uint (in Azure.Value value) { throw null; }
public static explicit operator ulong (in Azure.Value value) { throw null; }
public static implicit operator Azure.Value (System.ArraySegment<byte> value) { throw null; }
public static implicit operator Azure.Value (System.ArraySegment<char> value) { throw null; }
public static implicit operator Azure.Value (bool value) { throw null; }
public static implicit operator Azure.Value (byte value) { throw null; }
public static implicit operator Azure.Value (char value) { throw null; }
public static implicit operator Azure.Value (System.DateTime value) { throw null; }
public static implicit operator Azure.Value (System.DateTimeOffset value) { throw null; }
public static implicit operator Azure.Value (decimal value) { throw null; }
public static implicit operator Azure.Value (double value) { throw null; }
public static implicit operator Azure.Value (short value) { throw null; }
public static implicit operator Azure.Value (int value) { throw null; }
public static implicit operator Azure.Value (long value) { throw null; }
public static implicit operator Azure.Value (bool? value) { throw null; }
public static implicit operator Azure.Value (byte? value) { throw null; }
public static implicit operator Azure.Value (char? value) { throw null; }
public static implicit operator Azure.Value (System.DateTimeOffset? value) { throw null; }
public static implicit operator Azure.Value (System.DateTime? value) { throw null; }
public static implicit operator Azure.Value (decimal? value) { throw null; }
public static implicit operator Azure.Value (double? value) { throw null; }
public static implicit operator Azure.Value (short? value) { throw null; }
public static implicit operator Azure.Value (int? value) { throw null; }
public static implicit operator Azure.Value (long? value) { throw null; }
public static implicit operator Azure.Value (sbyte? value) { throw null; }
public static implicit operator Azure.Value (float? value) { throw null; }
public static implicit operator Azure.Value (ushort? value) { throw null; }
public static implicit operator Azure.Value (uint? value) { throw null; }
public static implicit operator Azure.Value (ulong? value) { throw null; }
public static implicit operator Azure.Value (sbyte value) { throw null; }
public static implicit operator Azure.Value (float value) { throw null; }
public static implicit operator Azure.Value (ushort value) { throw null; }
public static implicit operator Azure.Value (uint value) { throw null; }
public static implicit operator Azure.Value (ulong value) { throw null; }
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public bool TryGetValue<T>(out T value) { throw null; }
}
}
namespace Azure.Core
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;

namespace Azure {
public readonly partial struct Value
{
private sealed class DateTimeOffsetFlag : TypeFlag<DateTimeOffset>
{
public static DateTimeOffsetFlag Instance { get; } = new();

public override DateTimeOffset To(in Value value)
=> new(new DateTime(value._union.Ticks, DateTimeKind.Utc));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Runtime.InteropServices;

namespace Azure {
public readonly partial struct Value
{
[StructLayout(LayoutKind.Sequential)]
private readonly struct NullableTemplate<T> where T : unmanaged
{
public readonly bool _hasValue;
public readonly T _value;

public NullableTemplate(T value)
{
_value = value;
_hasValue = true;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Diagnostics;

namespace Azure {
public readonly partial struct Value
{
private readonly struct PackedDateTimeOffset
{
// HHHHHMMT TTT...
//
// HHHHH - hour bits 1-31
// MM - minutes flag
// T - ticks bit
// 00 - :00
// 01 - :15
// 10 - :30
// 11 - :45
KrzysztofCwalina marked this conversation as resolved.
Show resolved Hide resolved

// Base local tick time 1800 [DateTime(1800, 1, 1).Ticks]
private const ulong BaseTicks = 567709344000000000;
private const ulong MaxTicks = BaseTicks + TickMask;

// Hours go from -14 to 14. We add 14 to get our number to store.
private const int HourOffset = 14;

private const ulong TickMask = 0b00000001_11111111_11111111_11111111__11111111_11111111_11111111_11111111;
private const ulong MinuteMask = 0b00000110_00000000_00000000_00000000__00000000_00000000_00000000_00000000;
private const ulong HourMask = 0b11111000_00000000_00000000_00000000__00000000_00000000_00000000_00000000;

private const int MinuteShift = 57;
private const int HourShift = 59;

private readonly ulong _data;

private PackedDateTimeOffset(ulong data) => _data = data;

public static bool TryCreate(DateTimeOffset dateTime, TimeSpan offset, out PackedDateTimeOffset packed)
{
bool result = false;
packed = default;

ulong ticks = (ulong)dateTime.Ticks;
if (ticks > BaseTicks && ticks < MaxTicks)
{
ulong data = default;
int minutes = offset.Minutes;
if (minutes % 15 == 0)
{
data = (ulong)(minutes / 15) << MinuteShift;
int hours = offset.Hours + HourOffset;

// Only valid offset hours are -14 to 14
Debug.Assert(hours >= 0 && hours <= 28);
data |= (ulong)hours << HourShift;
data |= ticks - BaseTicks;
packed = new(data);
result = true;
}
}

return result;
}

public DateTimeOffset Extract()
{
TimeSpan offset = new(
(int)(((_data & HourMask) >> HourShift) - HourOffset),
(int)((_data & MinuteMask) >> MinuteShift),
0);
return new((long)((_data & TickMask) + BaseTicks), offset);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;

namespace Azure {
public readonly partial struct Value
{
private sealed class PackedDateTimeOffsetFlag : TypeFlag<DateTimeOffset>
{
public static PackedDateTimeOffsetFlag Instance { get; } = new();

public override DateTimeOffset To(in Value value)
=> value._union.PackedDateTimeOffset.Extract();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Runtime.CompilerServices;

namespace Azure {
public readonly partial struct Value
{
private sealed class StraightCastFlag<T> : TypeFlag<T>
{
public static StraightCastFlag<T> Instance { get; } = new();

public override T To(in Value value)
=> Unsafe.As<Union, T>(ref Unsafe.AsRef(value._union));
}
}
}
33 changes: 33 additions & 0 deletions sdk/core/Azure.Core.Experimental/src/Variant/Value.TypeFlag.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Runtime.CompilerServices;

namespace Azure {
public readonly partial struct Value
{
private abstract class TypeFlag
{
public abstract Type Type
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
}

public abstract object ToObject(in Value value);
}

private abstract class TypeFlag<T> : TypeFlag
{
public sealed override Type Type
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => typeof(T);
}

public override object ToObject(in Value value) => To(value)!;
public abstract T To(in Value value);
}
}
}
28 changes: 28 additions & 0 deletions sdk/core/Azure.Core.Experimental/src/Variant/Value.TypeFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;

namespace Azure {
public readonly partial struct Value
{
private static class TypeFlags
{
internal static readonly StraightCastFlag<bool> Boolean = StraightCastFlag<bool>.Instance;
internal static readonly StraightCastFlag<char> Char = StraightCastFlag<char>.Instance;
internal static readonly StraightCastFlag<byte> Byte = StraightCastFlag<byte>.Instance;
internal static readonly StraightCastFlag<sbyte> SByte = StraightCastFlag<sbyte>.Instance;
internal static readonly StraightCastFlag<short> Int16 = StraightCastFlag<short>.Instance;
internal static readonly StraightCastFlag<ushort> UInt16 = StraightCastFlag<ushort>.Instance;
internal static readonly StraightCastFlag<int> Int32 = StraightCastFlag<int>.Instance;
internal static readonly StraightCastFlag<uint> UInt32 = StraightCastFlag<uint>.Instance;
internal static readonly StraightCastFlag<long> Int64 = StraightCastFlag<long>.Instance;
internal static readonly StraightCastFlag<ulong> UInt64 = StraightCastFlag<ulong>.Instance;
internal static readonly StraightCastFlag<float> Single = StraightCastFlag<float>.Instance;
internal static readonly StraightCastFlag<double> Double = StraightCastFlag<double>.Instance;
internal static readonly StraightCastFlag<DateTime> DateTime = StraightCastFlag<DateTime>.Instance;
internal static readonly DateTimeOffsetFlag DateTimeOffset = DateTimeOffsetFlag.Instance;
internal static readonly PackedDateTimeOffsetFlag PackedDateTimeOffset = PackedDateTimeOffsetFlag.Instance;
}
}
}
31 changes: 31 additions & 0 deletions sdk/core/Azure.Core.Experimental/src/Variant/Value.Union.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Runtime.InteropServices;

namespace Azure {
public readonly partial struct Value
KrzysztofCwalina marked this conversation as resolved.
Show resolved Hide resolved
{
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
private struct Union
{
[FieldOffset(0)] public byte Byte;
[FieldOffset(0)] public sbyte SByte;
[FieldOffset(0)] public char Char;
[FieldOffset(0)] public bool Boolean;
[FieldOffset(0)] public short Int16;
[FieldOffset(0)] public ushort UInt16;
[FieldOffset(0)] public int Int32;
[FieldOffset(0)] public uint UInt32;
[FieldOffset(0)] public long Int64;
[FieldOffset(0)] public long Ticks;
[FieldOffset(0)] public ulong UInt64;
[FieldOffset(0)] public float Single; // 4 bytes
[FieldOffset(0)] public double Double; // 8 bytes
[FieldOffset(0)] public DateTime DateTime; // 8 bytes (ulong)
[FieldOffset(0)] public PackedDateTimeOffset PackedDateTimeOffset;
[FieldOffset(0)] public (int Offset, int Count) Segment;
}
}
}
Loading