From 5b4b9fd72b61144f14183b6d732a9ec941b5d9fc Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 13:08:49 -0700 Subject: [PATCH 1/9] Updated version. Removing shared files and then copying them again to fix folder name casing. --- eng/CodeGeneration.targets | 6 +- .../Shared/Autorest/ArmOperationHelpers.cs | 356 ------------------ .../Shared/Autorest/CodeGenClientAttribute.cs | 18 - .../Shared/Autorest/CodeGenMemberAttribute.cs | 35 -- .../Shared/Autorest/CodeGenModelAttribute.cs | 20 - .../Autorest/CodeGenSuppressAttribute.cs | 20 - .../Shared/Autorest/IUtf8JsonSerializable.cs | 14 - .../src/Shared/Autorest/IXmlSerializable.cs | 14 - .../Shared/Autorest/JsonElementExtensions.cs | 97 ----- .../Autorest/ManagementPipelineBuilder.cs | 22 -- .../Shared/Autorest/OperationFinalStateVia.cs | 14 - .../Azure.Core/src/Shared/Autorest/Page.cs | 16 - .../src/Shared/Autorest/PageableHelpers.cs | 81 ---- .../Shared/Autorest/RawRequestUriBuilder.cs | 91 ----- .../Autorest/RequestHeaderExtensions.cs | 53 --- .../Autorest/RequestUriBuilderExtensions.cs | 105 ------ .../Autorest/ResponseHeadersExtensions.cs | 74 ---- .../Shared/Autorest/ResponseWithHeaders.cs | 20 - .../ResponseWithHeaders{T,THeaders}.cs | 25 -- .../Autorest/ResponseWithHeaders{THeaders}.cs | 22 -- .../Shared/Autorest/StringRequestContent.cs | 40 -- .../src/Shared/Autorest/TypeFormatters.cs | 114 ------ .../Shared/Autorest/Utf8JsonRequestContent.cs | 49 --- .../Autorest/Utf8JsonWriterExtensions.cs | 98 ----- .../src/Shared/Autorest/XElementExtensions.cs | 43 --- .../src/Shared/Autorest/XmlWriterContent.cs | 52 --- .../Shared/Autorest/XmlWriterExtensions.cs | 43 --- 27 files changed, 3 insertions(+), 1539 deletions(-) delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/ArmOperationHelpers.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/CodeGenClientAttribute.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/CodeGenMemberAttribute.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/CodeGenModelAttribute.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/CodeGenSuppressAttribute.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/IUtf8JsonSerializable.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/IXmlSerializable.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/JsonElementExtensions.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/ManagementPipelineBuilder.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/OperationFinalStateVia.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/Page.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/PageableHelpers.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/RawRequestUriBuilder.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/RequestHeaderExtensions.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/RequestUriBuilderExtensions.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/ResponseHeadersExtensions.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders{T,THeaders}.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders{THeaders}.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/StringRequestContent.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/TypeFormatters.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/Utf8JsonRequestContent.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/Utf8JsonWriterExtensions.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/XElementExtensions.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/XmlWriterContent.cs delete mode 100644 sdk/core/Azure.Core/src/Shared/Autorest/XmlWriterExtensions.cs diff --git a/eng/CodeGeneration.targets b/eng/CodeGeneration.targets index fecba93175db..937b473ff992 100644 --- a/eng/CodeGeneration.targets +++ b/eng/CodeGeneration.targets @@ -1,9 +1,9 @@ - <_AutoRestVersion>https://github.com/Azure/autorest/releases/download/autorest-3.0.6221/autorest-3.0.6221.tgz - <_AutoRestCoreVersion>3.0.6280 - <_AutoRestCSharpVersion>https://github.com/Azure/autorest.csharp/releases/download/3.0.0-dev.20200415.7/autorest-csharp-v3-3.0.0-dev.20200415.7.tgz + <_AutoRestVersion>https://github.com/Azure/autorest/releases/download/autorest-3.0.6222/autorest-3.0.6222.tgz + <_AutoRestCoreVersion>3.0.6282 + <_AutoRestCSharpVersion>https://github.com/Azure/autorest.csharp/releases/download/3.0.0-dev.20200427.1/autorest-csharp-v3-3.0.0-dev.20200427.1.tgz <_SupportsCodeGeneration Condition="'$(IsClientLibrary)' == 'true'">true <_DefaultInputName Condition="Exists('$(MSBuildProjectDirectory)/autorest.md')">$(MSBuildProjectDirectory)/autorest.md $(_DefaultInputName) diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/ArmOperationHelpers.cs b/sdk/core/Azure.Core/src/Shared/Autorest/ArmOperationHelpers.cs deleted file mode 100644 index d4111418d0a9..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/ArmOperationHelpers.cs +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Linq; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using Azure.Core.Pipeline; - -namespace Azure.Core -{ - /// - /// Helper methods for ARM long-running operations. - /// - internal static class ArmOperationHelpers - { - internal static Operation Create(HttpPipeline pipeline, ClientDiagnostics clientDiagnostics, Response originalResponse, RequestMethod requestMethod, string scopeName, OperationFinalStateVia finalStateVia, Func createOriginalHttpMessage) - { - return Create(pipeline, clientDiagnostics, originalResponse, requestMethod, scopeName, finalStateVia, createOriginalHttpMessage, - (response, token) => response, - (response, token) => new ValueTask(response)); - } - - internal static Operation Create(HttpPipeline pipeline, ClientDiagnostics clientDiagnostics, Response originalResponse, RequestMethod requestMethod, string scopeName, OperationFinalStateVia finalStateVia, - Func createOriginalHttpMessage, Func createFinalResponse, Func> createFinalResponseAsync) where T : notnull - { - using HttpMessage originalHttpMethod = createOriginalHttpMessage(); - string originalUri = originalHttpMethod.Request.Uri.ToString(); - return new ArmOperation(pipeline, clientDiagnostics, originalResponse, originalUri, requestMethod, finalStateVia, scopeName, createFinalResponse, createFinalResponseAsync); - } - - private static readonly string[] s_failureStates = { "failed", "canceled" }; - private static readonly string[] s_terminalStates = { "succeeded", "failed", "canceled" }; - - /// - /// This implements the ARM scenarios for LROs. It is highly recommended to read the ARM spec prior to modifying this code: - /// https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/Addendum.md#asynchronous-operations - /// Other reference documents include: - /// https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-long-running-operation - /// https://github.com/Azure/adx-documentation-pr/blob/master/sdks/LRO/LRO_AzureSDK.md - /// - /// The final result of the LRO. - private class ArmOperation : Operation where T : notnull - { - private readonly HttpPipeline _pipeline; - private readonly ClientDiagnostics _clientDiagnostics; - private readonly string _scopeName; - private readonly Func _createFinalResponse; - private readonly Func> _createFinalResponseAsync; - private readonly RequestMethod _requestMethod; - private readonly string _originalUri; - private readonly OperationFinalStateVia _finalStateVia; - private HeaderFrom _headerFrom; - private string _pollUri = default!; - private bool _originalHasLocation; - private string? _lastKnownLocation; - - private Response _rawResponse; - private T _value = default!; - private bool _hasValue; - private bool _hasCompleted; - private bool _shouldPoll; - - public ArmOperation(HttpPipeline pipeline, ClientDiagnostics clientDiagnostics, Response originalResponse, - string originalUri, RequestMethod requestMethod, OperationFinalStateVia finalStateVia, string scopeName, - Func createFinalResponse, Func> createFinalResponseAsync) - { - _rawResponse = originalResponse; - _requestMethod = requestMethod; - _originalUri = originalUri; - _finalStateVia = finalStateVia; - InitializeScenarioInfo(); - - _pipeline = pipeline; - _clientDiagnostics = clientDiagnostics; - _scopeName = scopeName; - _createFinalResponse = createFinalResponse; - _createFinalResponseAsync = createFinalResponseAsync; - // When the original response has no headers, we do not start polling immediately. - _shouldPoll = _headerFrom != HeaderFrom.None; - } - - public override Response GetRawResponse() => _rawResponse; - - public override ValueTask> WaitForCompletionAsync(CancellationToken cancellationToken = default) => - this.DefaultWaitForCompletionAsync(OperationHelpers.DefaultPollingInterval, cancellationToken); - - public override ValueTask> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken) => - this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken); - - private async ValueTask UpdateStatusAsync(bool async, CancellationToken cancellationToken) - { - if (_hasCompleted) - { - return GetRawResponse(); - } - - if (_shouldPoll) - { - UpdatePollUri(); - _rawResponse = async - ? await GetResponseAsync(_pollUri, cancellationToken).ConfigureAwait(false) - : GetResponse(_pollUri, cancellationToken); - } - _shouldPoll = true; - _hasCompleted = IsTerminalState(out string state); - if (_hasCompleted) - { - Response finalResponse = GetRawResponse(); - if (s_failureStates.Contains(state)) - { - throw _clientDiagnostics.CreateRequestFailedException(finalResponse); - } - - string? finalUri = GetFinalUri(); - if (finalUri != null) - { - finalResponse = async - ? await GetResponseAsync(finalUri, cancellationToken).ConfigureAwait(false) - : GetResponse(finalUri, cancellationToken); - } - switch (finalResponse.Status) - { - case 200: - case 204 when !(_requestMethod == RequestMethod.Put || _requestMethod == RequestMethod.Patch): - { - _value = async - ? await _createFinalResponseAsync(finalResponse, cancellationToken).ConfigureAwait(false) - : _createFinalResponse(finalResponse, cancellationToken); - _rawResponse = finalResponse; - _hasValue = true; - break; - } - default: - throw _clientDiagnostics.CreateRequestFailedException(finalResponse); - } - } - - return GetRawResponse(); - } - - public override async ValueTask UpdateStatusAsync(CancellationToken cancellationToken = default) => await UpdateStatusAsync(async: true, cancellationToken).ConfigureAwait(false); - - public override Response UpdateStatus(CancellationToken cancellationToken = default) => UpdateStatusAsync(async: false, cancellationToken).EnsureCompleted(); - - //TODO: This is currently unused. - public override string Id { get; } = Guid.NewGuid().ToString(); - - public override T Value - { - get - { - if (!HasValue) - { - throw new InvalidOperationException("The operation has not completed yet."); - } - - return _value; - } - } - public override bool HasCompleted => _hasCompleted; - public override bool HasValue => _hasValue; - - private HttpMessage CreateRequest(string link) - { - HttpMessage message = _pipeline.CreateMessage(); - Request request = message.Request; - request.Method = RequestMethod.Get; - request.Uri.Reset(new Uri(link)); - return message; - } - - private async ValueTask GetResponseAsync(string link, CancellationToken cancellationToken = default) - { - if (link == null) - { - throw new ArgumentNullException(nameof(link)); - } - - using DiagnosticScope scope = _clientDiagnostics.CreateScope(_scopeName); - scope.Start(); - try - { - using HttpMessage message = CreateRequest(link); - await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); - return message.Response; - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - private Response GetResponse(string link, CancellationToken cancellationToken = default) - { - if (link == null) - { - throw new ArgumentNullException(nameof(link)); - } - - using DiagnosticScope scope = _clientDiagnostics.CreateScope(_scopeName); - scope.Start(); - try - { - using HttpMessage message = CreateRequest(link); - _pipeline.Send(message, cancellationToken); - return message.Response; - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - private bool IsTerminalState(out string state) - { - Response response = GetRawResponse(); - state = string.Empty; - if (_headerFrom == HeaderFrom.Location) - { - return response.Status != 202; - } - - if (response.Status >= 200 && response.Status <= 204) - { - if (response.ContentStream?.Length > 0) - { - try - { - using JsonDocument document = JsonDocument.Parse(response.ContentStream); - foreach (JsonProperty property in document.RootElement.EnumerateObject()) - { - if ((_headerFrom == HeaderFrom.OperationLocation || - _headerFrom == HeaderFrom.AzureAsyncOperation) && - property.NameEquals("status")) - { - state = property.Value.GetString().ToLowerInvariant(); - return s_terminalStates.Contains(state); - } - - if (_headerFrom == HeaderFrom.None && property.NameEquals("properties")) - { - foreach (JsonProperty innerProperty in property.Value.EnumerateObject()) - { - if (innerProperty.NameEquals("provisioningState")) - { - state = innerProperty.Value.GetString().ToLowerInvariant(); - return s_terminalStates.Contains(state); - } - } - } - } - } - finally - { - // It is required to reset the position of the content after reading as this response may be used for deserialization. - response.ContentStream.Position = 0; - } - } - - // If provisioningState was not found, it defaults to Succeeded. - if (_headerFrom == HeaderFrom.None) - { - return true; - } - } - - throw _clientDiagnostics.CreateRequestFailedException(response); - } - - private enum HeaderFrom - { - None, - OperationLocation, - AzureAsyncOperation, - Location - } - - private void InitializeScenarioInfo() - { - _originalHasLocation = _rawResponse.Headers.Contains("Location"); - - if (_rawResponse.Headers.Contains("Operation-Location")) - { - _headerFrom = HeaderFrom.OperationLocation; - return; - } - - if (_rawResponse.Headers.Contains("Azure-AsyncOperation")) - { - _headerFrom = HeaderFrom.AzureAsyncOperation; - return; - } - - if (_originalHasLocation) - { - _headerFrom = HeaderFrom.Location; - return; - } - - _pollUri = _originalUri; - _headerFrom = HeaderFrom.None; - } - - private void UpdatePollUri() - { - var hasLocation = _rawResponse.Headers.TryGetValue("Location", out string? location); - if (hasLocation) - { - _lastKnownLocation = location; - } - - switch (_headerFrom) - { - case HeaderFrom.OperationLocation when _rawResponse.Headers.TryGetValue("Operation-Location", out string? operationLocation): - _pollUri = operationLocation; - return; - case HeaderFrom.AzureAsyncOperation when _rawResponse.Headers.TryGetValue("Azure-AsyncOperation", out string? azureAsyncOperation): - _pollUri = azureAsyncOperation; - return; - case HeaderFrom.Location when hasLocation: - _pollUri = location!; - return; - } - } - - private string? GetFinalUri() - { - if (_headerFrom == HeaderFrom.OperationLocation || _headerFrom == HeaderFrom.AzureAsyncOperation) - { - if (_requestMethod == RequestMethod.Delete) - { - return null; - } - - if (_requestMethod == RequestMethod.Put || (_originalHasLocation && _finalStateVia == OperationFinalStateVia.OriginalUri)) - { - return _originalUri; - } - - if (_originalHasLocation && _finalStateVia == OperationFinalStateVia.Location) - { - return _lastKnownLocation; - } - } - - return null; - } - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenClientAttribute.cs b/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenClientAttribute.cs deleted file mode 100644 index 08658438d75a..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenClientAttribute.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace Azure.Core -{ - [AttributeUsage(AttributeTargets.Class)] - internal class CodeGenClientAttribute : Attribute - { - public string OriginalName { get; } - - public CodeGenClientAttribute(string originalName) - { - OriginalName = originalName; - } - } -} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenMemberAttribute.cs b/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenMemberAttribute.cs deleted file mode 100644 index 14c0870a293d..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenMemberAttribute.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; - -namespace Azure.Core -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] - internal class CodeGenMemberAttribute : Attribute - { - public string? OriginalName { get; } - - /// - /// For collection properties. When set to true empty collection would be treated as undefined and not serialized. - /// - public bool EmptyAsUndefined { get; set; } - - /// - /// For collection and model properties. Whether the property would always be initialized on creation/deserialization. - /// Requires a parameterless constructor for implementation type. - /// - public bool Initialize { get; set; } - - public CodeGenMemberAttribute() - { - } - - public CodeGenMemberAttribute(string originalName) - { - OriginalName = originalName; - } - } -} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenModelAttribute.cs b/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenModelAttribute.cs deleted file mode 100644 index f1a8d55e3e2e..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenModelAttribute.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; - -namespace Azure.Core -{ - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct)] - internal class CodeGenModelAttribute : Attribute - { - public string OriginalName { get; } - - public CodeGenModelAttribute(string originalName) - { - OriginalName = originalName; - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenSuppressAttribute.cs b/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenSuppressAttribute.cs deleted file mode 100644 index efb2c82f864e..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/CodeGenSuppressAttribute.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; - -namespace Azure.Core -{ - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct, AllowMultiple = true)] - internal class CodeGenSuppressAttribute : Attribute - { - public string Member { get; } - public Type[] Parameters { get; } - - public CodeGenSuppressAttribute(string member, params Type[] parameters) - { - Member = member; - Parameters = parameters; - } - } -} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/IUtf8JsonSerializable.cs b/sdk/core/Azure.Core/src/Shared/Autorest/IUtf8JsonSerializable.cs deleted file mode 100644 index 5653e4609313..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/IUtf8JsonSerializable.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.Text.Json; - -namespace Azure.Core -{ - internal interface IUtf8JsonSerializable - { - void Write(Utf8JsonWriter writer); - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/IXmlSerializable.cs b/sdk/core/Azure.Core/src/Shared/Autorest/IXmlSerializable.cs deleted file mode 100644 index 343b127384d2..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/IXmlSerializable.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.Xml; - -namespace Azure.Core -{ - internal interface IXmlSerializable - { - void Write(XmlWriter writer, string? nameHint); - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/JsonElementExtensions.cs b/sdk/core/Azure.Core/src/Shared/Autorest/JsonElementExtensions.cs deleted file mode 100644 index f7a4dfd57b02..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/JsonElementExtensions.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text.Json; -using System.Xml; - -namespace Azure.Core -{ - internal static class JsonElementExtensions - { - public static object? GetObject(in this JsonElement element) - { - switch (element.ValueKind) - { - case JsonValueKind.String: - return element.GetString(); - case JsonValueKind.Number: - if (element.TryGetInt32(out int intValue)) - { - return intValue; - } - if (element.TryGetInt64(out long longValue)) - { - return longValue; - } - return element.GetDouble(); - case JsonValueKind.True: - return true; - case JsonValueKind.False: - return false; - case JsonValueKind.Undefined: - case JsonValueKind.Null: - return null; - case JsonValueKind.Object: - var dictionary = new Dictionary(); - foreach (JsonProperty jsonProperty in element.EnumerateObject()) - { - dictionary.Add(jsonProperty.Name, jsonProperty.Value.GetObject()); - } - return dictionary; - case JsonValueKind.Array: - var list = new List(); - foreach (JsonElement item in element.EnumerateArray()) - { - list.Add(item.GetObject()); - } - return list.ToArray(); - default: - throw new NotSupportedException("Not supported value kind " + element.ValueKind); - } - } - - public static byte[] GetBytesFromBase64(in this JsonElement element, string format) => format switch - { - "U" => TypeFormatters.FromBase64UrlString(element.GetString()), - _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) - }; - - public static DateTimeOffset GetDateTimeOffset(in this JsonElement element, string format) => format switch - { - "D" => element.GetDateTimeOffset(), - "S" => DateTimeOffset.Parse(element.GetString(), CultureInfo.InvariantCulture), - "R" => DateTimeOffset.Parse(element.GetString(), CultureInfo.InvariantCulture), - "U" => DateTimeOffset.FromUnixTimeSeconds(element.GetInt64()), - _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) - }; - - public static TimeSpan GetTimeSpan(in this JsonElement element, string format) => format switch - { - "P" => XmlConvert.ToTimeSpan(element.GetString()), - "T" => TimeSpan.ParseExact(element.GetString(), "T", CultureInfo.InvariantCulture), - _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) - }; - - public static char GetChar(this in JsonElement element) - { - if (element.ValueKind == JsonValueKind.String) - { - var text = element.GetString(); - if (text == null || text.Length != 1) - { - throw new NotSupportedException($"Cannot convert \"{text}\" to a Char"); - } - return text[0]; - } - else - { - throw new NotSupportedException($"Cannot convert {element.ValueKind} to a Char"); - } - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/ManagementPipelineBuilder.cs b/sdk/core/Azure.Core/src/Shared/Autorest/ManagementPipelineBuilder.cs deleted file mode 100644 index 8c7fabd3f8a0..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/ManagementPipelineBuilder.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text.Json; -using System.Xml; -using Azure.Core.Pipeline; - -namespace Azure.Core -{ - internal static class ManagementPipelineBuilder - { - public static HttpPipeline Build(TokenCredential credential, ClientOptions options) - { - return HttpPipelineBuilder.Build(options, new BearerTokenAuthenticationPolicy(credential, "https://management.azure.com//.default")); - } - } -} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/OperationFinalStateVia.cs b/sdk/core/Azure.Core/src/Shared/Autorest/OperationFinalStateVia.cs deleted file mode 100644 index 6b6c2771e5a1..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/OperationFinalStateVia.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -namespace Azure.Core -{ - internal enum OperationFinalStateVia - { - AzureAsyncOperation, - Location, - OriginalUri - } -} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/Page.cs b/sdk/core/Azure.Core/src/Shared/Autorest/Page.cs deleted file mode 100644 index 1438fdfd5f04..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/Page.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.Collections.Generic; -using System.Linq; - -namespace Azure.Core -{ - internal static class Page - { - public static Page FromValues(IEnumerable values, string continuationToken, Response response) => - Page.FromValues(values.ToList(), continuationToken, response); - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/PageableHelpers.cs b/sdk/core/Azure.Core/src/Shared/Autorest/PageableHelpers.cs deleted file mode 100644 index cf5563728971..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/PageableHelpers.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Azure.Core -{ - internal static class PageableHelpers - { - public static Pageable CreateEnumerable(Func> firstPageFunc, Func> nextPageFunc, int? pageSize = default) where T : notnull - { - return new FuncPageable((continuationToken, pageSizeHint) => firstPageFunc(pageSizeHint), (continuationToken, pageSizeHint) => nextPageFunc(continuationToken, pageSizeHint), pageSize); - } - - public static AsyncPageable CreateAsyncEnumerable(Func>> firstPageFunc, Func>> nextPageFunc, int? pageSize = default) where T : notnull - { - return new FuncAsyncPageable((continuationToken, pageSizeHint) => firstPageFunc(pageSizeHint), (continuationToken, pageSizeHint) => nextPageFunc(continuationToken, pageSizeHint), pageSize); - } - - internal delegate Task> AsyncPageFunc(string? continuationToken = default, int? pageSizeHint = default); - internal delegate Page PageFunc(string? continuationToken = default, int? pageSizeHint = default); - - internal class FuncAsyncPageable : AsyncPageable where T : notnull - { - private readonly AsyncPageFunc _firstPageFunc; - private readonly AsyncPageFunc _nextPageFunc; - private readonly int? _defaultPageSize; - - public FuncAsyncPageable(AsyncPageFunc firstPageFunc, AsyncPageFunc nextPageFunc, int? defaultPageSize = default) - { - _firstPageFunc = firstPageFunc; - _nextPageFunc = nextPageFunc; - _defaultPageSize = defaultPageSize; - } - - public override async IAsyncEnumerable> AsPages(string? continuationToken = default, int? pageSizeHint = default) - { - AsyncPageFunc pageFunc = _firstPageFunc; - int? pageSize = pageSizeHint ?? _defaultPageSize; - do - { - Page pageResponse = await pageFunc(continuationToken, pageSize).ConfigureAwait(false); - yield return pageResponse; - continuationToken = pageResponse.ContinuationToken; - pageFunc = _nextPageFunc; - } while (!string.IsNullOrEmpty(continuationToken)); - } - } - - internal class FuncPageable : Pageable where T : notnull - { - private readonly PageFunc _firstPageFunc; - private readonly PageFunc _nextPageFunc; - private readonly int? _defaultPageSize; - - public FuncPageable(PageFunc firstPageFunc, PageFunc nextPageFunc, int? defaultPageSize = default) - { - _firstPageFunc = firstPageFunc; - _nextPageFunc = nextPageFunc; - _defaultPageSize = defaultPageSize; - } - - public override IEnumerable> AsPages(string? continuationToken = default, int? pageSizeHint = default) - { - PageFunc pageFunc = _firstPageFunc; - int? pageSize = pageSizeHint ?? _defaultPageSize; - do - { - Page pageResponse = pageFunc(continuationToken, pageSize); - yield return pageResponse; - continuationToken = pageResponse.ContinuationToken; - pageFunc = _nextPageFunc; - } while (!string.IsNullOrEmpty(continuationToken)); - } - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/RawRequestUriBuilder.cs b/sdk/core/Azure.Core/src/Shared/Autorest/RawRequestUriBuilder.cs deleted file mode 100644 index 0c800decc945..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/RawRequestUriBuilder.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Globalization; - -namespace Azure.Core -{ - internal class RawRequestUriBuilder: RequestUriBuilder - { - private const string SchemeSeparator = "://"; - private const char HostSeparator = '/'; - private const char PortSeparator = ':'; - private static readonly char[] HostOrPort = new[] {HostSeparator, PortSeparator}; - - private RawWritingPosition _position = RawWritingPosition.Scheme; - - public void AppendRaw(string value, bool escape) - { - while (!string.IsNullOrWhiteSpace(value)) - { - if (_position == RawWritingPosition.Scheme) - { - int separator = value.IndexOf(SchemeSeparator, StringComparison.InvariantCultureIgnoreCase); - if (separator == -1) - { - Scheme += value; - value = string.Empty; - } - else - { - Scheme += value.Substring(0, separator); - - // TODO: Find a better way to map schemes to default ports - Port = string.Equals(Scheme, "https", StringComparison.OrdinalIgnoreCase) ? 443 : 80; - - value = value.Substring(separator + SchemeSeparator.Length); - _position = RawWritingPosition.Host; - } - } - else if (_position == RawWritingPosition.Host) - { - int separator = value.IndexOfAny(HostOrPort); - if (separator == -1) - { - Host += value; - value = string.Empty; - } - else - { - Host += value.Substring(0, separator); - - _position = value[separator] == HostSeparator ? RawWritingPosition.Rest : RawWritingPosition.Port; - - value = value.Substring(separator + 1); - } - } - else if (_position == RawWritingPosition.Port) - { - int separator = value.IndexOf(HostSeparator); - if (separator == -1) - { - Port = int.Parse(value, CultureInfo.InvariantCulture); - value = string.Empty; - } - else - { - Port = int.Parse(value.Substring(0, separator), CultureInfo.InvariantCulture); - value = value.Substring(separator + 1); - _position = RawWritingPosition.Rest; - } - } - else - { - AppendPath(value, escape); - value = string.Empty; - } - } - } - - private enum RawWritingPosition - { - Scheme, - Host, - Port, - Rest - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/RequestHeaderExtensions.cs b/sdk/core/Azure.Core/src/Shared/Autorest/RequestHeaderExtensions.cs deleted file mode 100644 index 085d05082ea3..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/RequestHeaderExtensions.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Globalization; - -namespace Azure.Core -{ - internal static class RequestHeaderExtensions - { - public static void Add(this RequestHeaders headers, string name, bool value) - { - headers.Add(name, TypeFormatters.ToString(value)); - } - - public static void Add(this RequestHeaders headers, string name, float value) - { - headers.Add(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture)); - } - - public static void Add(this RequestHeaders headers, string name, double value) - { - headers.Add(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture)); - } - - public static void Add(this RequestHeaders headers, string name, int value) - { - headers.Add(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture)); - } - - public static void Add(this RequestHeaders headers, string name, DateTimeOffset value, string format) - { - headers.Add(name, TypeFormatters.ToString(value, format)); - } - - public static void Add(this RequestHeaders headers, string name, TimeSpan value, string format) - { - headers.Add(name, TypeFormatters.ToString(value, format)); - } - - public static void Add(this RequestHeaders headers, string name, Guid value) - { - headers.Add(name, value.ToString()); - } - - public static void Add(this RequestHeaders headers, string name, byte[] value) - { - headers.Add(name, Convert.ToBase64String(value)); - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/RequestUriBuilderExtensions.cs b/sdk/core/Azure.Core/src/Shared/Autorest/RequestUriBuilderExtensions.cs deleted file mode 100644 index 46a3e29d7093..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/RequestUriBuilderExtensions.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Xml; - -namespace Azure.Core -{ - internal static class RequestUriBuilderExtensions - { - public static void AppendPath(this RequestUriBuilder builder, bool value, bool escape = false) - { - builder.AppendPath(TypeFormatters.ToString(value), escape); - } - - public static void AppendPath(this RequestUriBuilder builder, float value, bool escape = true) - { - builder.AppendPath(value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); - } - - public static void AppendPath(this RequestUriBuilder builder, double value, bool escape = true) - { - builder.AppendPath(value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); - } - - public static void AppendPath(this RequestUriBuilder builder, int value, bool escape = true) - { - builder.AppendPath(value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); - } - - public static void AppendPath(this RequestUriBuilder builder, byte[] value, bool escape = true) - { - builder.AppendPath(TypeFormatters.ToBase64UrlString(value), escape); - } - - public static void AppendPath(this RequestUriBuilder builder, IEnumerable value, bool escape = true) - { - builder.AppendPath(string.Join(",", value), escape); - } - - public static void AppendPath(this RequestUriBuilder builder, DateTimeOffset value, string format, bool escape = true) - { - builder.AppendPath(TypeFormatters.ToString(value, format), escape); - } - - public static void AppendPath(this RequestUriBuilder builder, TimeSpan value, string format, bool escape = true) - { - builder.AppendPath(TypeFormatters.ToString(value, format), escape); - } - - public static void AppendPath(this RequestUriBuilder builder, Guid value, bool escape = true) - { - builder.AppendPath(value.ToString(), escape); - } - - public static void AppendQuery(this RequestUriBuilder builder, string name, bool value, bool escape = false) - { - builder.AppendQuery(name, TypeFormatters.ToString(value), escape); - } - - public static void AppendQuery(this RequestUriBuilder builder, string name, float value, bool escape = true) - { - builder.AppendQuery(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); - } - - public static void AppendQuery(this RequestUriBuilder builder, string name, DateTimeOffset value, string format, bool escape = true) - { - builder.AppendQuery(name, TypeFormatters.ToString(value, format), escape); - } - - public static void AppendQuery(this RequestUriBuilder builder, string name, TimeSpan value, string format, bool escape = true) - { - builder.AppendQuery(name, TypeFormatters.ToString(value, format), escape); - } - - public static void AppendQuery(this RequestUriBuilder builder, string name, double value, bool escape = true) - { - builder.AppendQuery(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); - } - - public static void AppendQuery(this RequestUriBuilder builder, string name, int value, bool escape = true) - { - builder.AppendQuery(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); - } - - public static void AppendQuery(this RequestUriBuilder builder, string name, TimeSpan value, bool escape = true) - { - builder.AppendQuery(name, XmlConvert.ToString(value), escape); - } - - public static void AppendQuery(this RequestUriBuilder builder, string name, byte[] value, bool escape = true) - { - builder.AppendQuery(name, Convert.ToBase64String(value), escape); - } - - public static void AppendQueryDelimited(this RequestUriBuilder builder, string name, IEnumerable value, string delimiter, bool escape = true) - { - builder.AppendQuery(name, string.Join(delimiter, value), escape); - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/ResponseHeadersExtensions.cs b/sdk/core/Azure.Core/src/Shared/Autorest/ResponseHeadersExtensions.cs deleted file mode 100644 index f54a1b41f743..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/ResponseHeadersExtensions.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Globalization; -using System.Xml; - -namespace Azure.Core -{ - internal static class ResponseHeadersExtensions - { - public static bool TryGetValue(this ResponseHeaders headers, string name, out byte[]? value) - { - if (headers.TryGetValue(name, out string? stringValue)) - { - value = Convert.FromBase64String(stringValue); - return true; - } - - value = null; - return false; - } - - public static bool TryGetValue(this ResponseHeaders headers, string name, out TimeSpan? value) - { - if (headers.TryGetValue(name, out string? stringValue)) - { - value = XmlConvert.ToTimeSpan(stringValue); - return true; - } - - value = null; - return false; - } - - public static bool TryGetValue(this ResponseHeaders headers, string name, out DateTimeOffset? value) - { - if (headers.TryGetValue(name, out string? stringValue)) - { - value = DateTimeOffset.Parse(stringValue, CultureInfo.InvariantCulture); - return true; - } - - value = null; - return false; - } - - public static bool TryGetValue(this ResponseHeaders headers, string name, out T? value) where T : struct - { - if (headers.TryGetValue(name, out string? stringValue)) - { - value = (T)Convert.ChangeType(stringValue, typeof(T), CultureInfo.InvariantCulture); - return true; - } - - value = null; - return false; - } - - public static bool TryGetValue(this ResponseHeaders headers, string name, out T? value) where T : class - { - if (headers.TryGetValue(name, out string? stringValue)) - { - value = (T)Convert.ChangeType(stringValue, typeof(T), CultureInfo.InvariantCulture); - return true; - } - - value = null; - return false; - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders.cs b/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders.cs deleted file mode 100644 index 2a48fb0ebbfb..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -namespace Azure.Core -{ - internal static class ResponseWithHeaders - { - public static ResponseWithHeaders FromValue(T value, THeaders headers, Response rawResponse) - { - return new ResponseWithHeaders(value, headers, rawResponse); - } - - public static ResponseWithHeaders FromValue(THeaders headers, Response rawResponse) - { - return new ResponseWithHeaders(headers, rawResponse); - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders{T,THeaders}.cs b/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders{T,THeaders}.cs deleted file mode 100644 index 5c2036521e2a..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders{T,THeaders}.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -namespace Azure.Core -{ - internal class ResponseWithHeaders : Response - { - private readonly Response _rawResponse; - - public ResponseWithHeaders(T value, THeaders headers, Response rawResponse) - { - _rawResponse = rawResponse; - Value = value; - Headers = headers; - } - - public override Response GetRawResponse() => _rawResponse; - - public override T Value { get; } - - public THeaders Headers { get; } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders{THeaders}.cs b/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders{THeaders}.cs deleted file mode 100644 index 66a788c4a099..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/ResponseWithHeaders{THeaders}.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -namespace Azure.Core -{ - internal class ResponseWithHeaders - { - private readonly Response _rawResponse; - - public ResponseWithHeaders(THeaders headers, Response rawResponse) - { - _rawResponse = rawResponse; - Headers = headers; - } - - public Response GetRawResponse() => _rawResponse; - - public THeaders Headers { get; } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/StringRequestContent.cs b/sdk/core/Azure.Core/src/Shared/Autorest/StringRequestContent.cs deleted file mode 100644 index 8d1bcf33bd9e..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/StringRequestContent.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Azure.Core -{ - internal class StringRequestContent : RequestContent - { - private readonly byte[] _bytes; - - public StringRequestContent(string value) - { - _bytes = Encoding.UTF8.GetBytes(value); - } - - public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) - { - await stream.WriteAsync(_bytes, 0, _bytes.Length, cancellation).ConfigureAwait(false); - } - - public override void WriteTo(Stream stream, CancellationToken cancellation) - { - stream.Write(_bytes, 0, _bytes.Length); - } - - public override bool TryComputeLength(out long length) - { - length = _bytes.Length; - return true; - } - - public override void Dispose() - { - } - } -} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/TypeFormatters.cs b/sdk/core/Azure.Core/src/Shared/Autorest/TypeFormatters.cs deleted file mode 100644 index 069bcc52672f..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/TypeFormatters.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Globalization; -using System.Xml; - -namespace Azure.Core -{ - internal class TypeFormatters - { - public static string DefaultNumberFormat { get; } = "G"; - - public static string ToString(bool value) => value ? "true" : "false"; - - public static string ToString(DateTimeOffset value, string format) => format switch - { - "D" => value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), - "S" when value.Offset == TimeSpan.Zero => value.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture), - "S" => value.ToString("O", CultureInfo.InvariantCulture), - "R" => value.ToString("R", CultureInfo.InvariantCulture), - "U" => value.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture), - _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) - }; - - public static string ToString(TimeSpan value, string format) => format switch - { - "P" => XmlConvert.ToString(value), - "T" => value.ToString("T", CultureInfo.InvariantCulture), - _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) - }; - - public static string ToBase64UrlString(byte[] value) - { - var numWholeOrPartialInputBlocks = checked(value.Length + 2) / 3; - var size = checked(numWholeOrPartialInputBlocks * 4); - var output = new char[size]; - - var numBase64Chars = Convert.ToBase64CharArray(value, 0, value.Length, output, 0); - - // Fix up '+' -> '-' and '/' -> '_'. Drop padding characters. - int i = 0; - for (; i < numBase64Chars; i++) - { - var ch = output[i]; - if (ch == '+') - { - output[i] = '-'; - } - else if (ch == '/') - { - output[i] = '_'; - } - else if (ch == '=') - { - // We've reached a padding character; truncate the remainder. - break; - } - } - - return new string(output, 0, i); - } - - public static byte[] FromBase64UrlString(string value) - { - var paddingCharsToAdd = GetNumBase64PaddingCharsToAddForDecode(value.Length); - - var output = new char[value.Length + paddingCharsToAdd]; - - int i; - for (i = 0; i < value.Length; i++) - { - var ch = value[i]; - if (ch == '-') - { - output[i] = '+'; - } - else if (ch == '_') - { - output[i] = '/'; - } - else - { - output[i] = ch; - } - } - - for (; i < output.Length; i++) - { - output[i] = '='; - } - - return Convert.FromBase64CharArray(output, 0, output.Length); - } - - - private static int GetNumBase64PaddingCharsToAddForDecode(int inputLength) - { - switch (inputLength % 4) - { - case 0: - return 0; - case 2: - return 2; - case 3: - return 1; - default: - throw new InvalidOperationException("Malformed input"); - } - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/Utf8JsonRequestContent.cs b/sdk/core/Azure.Core/src/Shared/Autorest/Utf8JsonRequestContent.cs deleted file mode 100644 index 766e2c4cbf36..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/Utf8JsonRequestContent.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.IO; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - -namespace Azure.Core -{ - internal class Utf8JsonRequestContent: RequestContent - { - private readonly ArrayBufferWriter _writer; - - public Utf8JsonWriter JsonWriter { get; } - - public Utf8JsonRequestContent() - { - _writer = new ArrayBufferWriter(); - JsonWriter = new Utf8JsonWriter(_writer); - } - - public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) - { - await JsonWriter.FlushAsync(cancellation).ConfigureAwait(false); - using var content = Create(_writer.WrittenMemory); - await content.WriteToAsync(stream, cancellation).ConfigureAwait(false); - } - - public override void WriteTo(Stream stream, CancellationToken cancellation) - { - JsonWriter.Flush(); - using var content = Create(_writer.WrittenMemory); - content.WriteTo(stream, cancellation); - } - - public override bool TryComputeLength(out long length) - { - length = JsonWriter.BytesCommitted + JsonWriter.BytesPending; - return true; - } - - public override void Dispose() - { - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/Utf8JsonWriterExtensions.cs b/sdk/core/Azure.Core/src/Shared/Autorest/Utf8JsonWriterExtensions.cs deleted file mode 100644 index a1fc529d01d5..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/Utf8JsonWriterExtensions.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text.Json; - -namespace Azure.Core -{ - internal static class Utf8JsonWriterExtensions - { - public static void WriteStringValue(this Utf8JsonWriter writer, DateTimeOffset value, string format) => - writer.WriteStringValue(TypeFormatters.ToString(value, format)); - - public static void WriteStringValue(this Utf8JsonWriter writer, TimeSpan value, string format) => - writer.WriteStringValue(TypeFormatters.ToString(value, format)); - - public static void WriteStringValue(this Utf8JsonWriter writer, char value) => - writer.WriteStringValue(value.ToString(CultureInfo.InvariantCulture)); - - public static void WriteObjectValue(this Utf8JsonWriter writer, IUtf8JsonSerializable value) - { - value.Write(writer); - } - - public static void WriteBase64StringValue(this Utf8JsonWriter writer, byte[] value, string format) - { - switch (format) - { - case "U": - writer.WriteStringValue(TypeFormatters.ToBase64UrlString(value)); - break; - default: - throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)); - } - } - - public static void WriteObjectValue(this Utf8JsonWriter writer, object value) - { - switch (value) - { - case null: - writer.WriteNullValue(); - break; - case IUtf8JsonSerializable serializable: - writer.WriteObjectValue(serializable); - break; - case byte[] bytes: - writer.WriteStringValue(Convert.ToBase64String(bytes)); - break; - case int i: - writer.WriteNumberValue(i); - break; - case decimal d: - writer.WriteNumberValue(d); - break; - case double d: - writer.WriteNumberValue(d); - break; - case float f: - writer.WriteNumberValue(f); - break; - case string s: - writer.WriteStringValue(s); - break; - case bool b: - writer.WriteBooleanValue(b); - break; - case DateTimeOffset dateTimeOffset: - writer.WriteStringValue(dateTimeOffset,"S"); - break; - case IEnumerable> enumerable: - writer.WriteStartObject(); - foreach (KeyValuePair pair in enumerable) - { - writer.WritePropertyName(pair.Key); - writer.WriteObjectValue(pair.Value); - } - writer.WriteEndObject(); - break; - case IEnumerable objectEnumerable: - writer.WriteStartArray(); - foreach (object item in objectEnumerable) - { - writer.WriteObjectValue(item); - } - writer.WriteEndArray(); - break; - - default: - throw new NotSupportedException("Not supported type " + value.GetType()); - } - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/XElementExtensions.cs b/sdk/core/Azure.Core/src/Shared/Autorest/XElementExtensions.cs deleted file mode 100644 index 09915d57bbe1..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/XElementExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Globalization; -using System.Xml; -using System.Xml.Linq; - -namespace Azure.Core -{ - internal static class XElementExtensions - { - public static byte[] GetBytesFromBase64Value(this XElement element, string format) => format switch - { - "U" => TypeFormatters.FromBase64UrlString(element.Value), - _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) - }; - - public static DateTimeOffset GetDateTimeOffsetValue(this XElement element, string format) => format switch - { - "D" => (DateTimeOffset)element, - "S" => DateTimeOffset.Parse(element.Value, CultureInfo.InvariantCulture), - "R" => DateTimeOffset.Parse(element.Value, CultureInfo.InvariantCulture), - "U" => DateTimeOffset.FromUnixTimeSeconds((long)element), - _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) - }; - - public static TimeSpan GetTimeSpanValue(this XElement element, string format) => format switch - { - "P" => XmlConvert.ToTimeSpan(element.Value), - _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) - }; - - #pragma warning disable CA1801 //Parameter format of method GetObjectValue is never used. Remove the parameter or use it in the method body. - public static object GetObjectValue(this XElement element, string format) - #pragma warning restore - { - return element.Value; - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/XmlWriterContent.cs b/sdk/core/Azure.Core/src/Shared/Autorest/XmlWriterContent.cs deleted file mode 100644 index 25d6a326de6f..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/XmlWriterContent.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Xml; - -namespace Azure.Core -{ - internal class XmlWriterContent : RequestContent - { - private readonly MemoryStream _stream; - public XmlWriterContent() - { - _stream = new MemoryStream(); - XmlWriter = new XmlTextWriter(_stream, Encoding.UTF8); - } - - public XmlWriter XmlWriter { get; } - - public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) - { - XmlWriter.Flush(); - _stream.Position = 0; - using var content = Create(_stream); - await content.WriteToAsync(stream, cancellation).ConfigureAwait(false); - } - - public override void WriteTo(Stream stream, CancellationToken cancellation) - { - XmlWriter.Flush(); - _stream.Position = 0; - using var content = Create(_stream); - content.WriteTo(stream, cancellation); - } - - public override bool TryComputeLength(out long length) - { - XmlWriter.Flush(); - length = _stream.Length; - return true; - } - - public override void Dispose() - { - } - } -} diff --git a/sdk/core/Azure.Core/src/Shared/Autorest/XmlWriterExtensions.cs b/sdk/core/Azure.Core/src/Shared/Autorest/XmlWriterExtensions.cs deleted file mode 100644 index 84cf13f4c976..000000000000 --- a/sdk/core/Azure.Core/src/Shared/Autorest/XmlWriterExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Xml; - -namespace Azure.Core -{ - internal static class XmlWriterExtensions - { - public static void WriteObjectValue(this XmlWriter writer, object value, string? nameHint) - { - switch (value) - { - case IXmlSerializable serializable: - serializable.Write(writer, nameHint); - return; - default: - throw new NotImplementedException(); - } - } - - public static void WriteValue(this XmlWriter writer, DateTimeOffset value, string format) => - writer.WriteValue(TypeFormatters.ToString(value, format)); - - public static void WriteValue(this XmlWriter writer, TimeSpan value, string format) => - writer.WriteValue(TypeFormatters.ToString(value, format)); - - public static void WriteValue(this XmlWriter writer, byte[] value, string format) - { - switch (format) - { - case "U": - writer.WriteValue(TypeFormatters.ToBase64UrlString(value)); - break; - default: - throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)); - } - } - } -} From 2376173680d2218f543c9e681106771341d3e751 Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 13:10:14 -0700 Subject: [PATCH 2/9] Re-added shared files with fixed folder name. --- .../Shared/AutoRest/ArmOperationHelpers.cs | 356 ++++++++++++++++++ .../Shared/AutoRest/CodeGenClientAttribute.cs | 18 + .../Shared/AutoRest/CodeGenMemberAttribute.cs | 35 ++ .../Shared/AutoRest/CodeGenModelAttribute.cs | 20 + .../AutoRest/CodeGenSuppressAttribute.cs | 20 + .../Shared/AutoRest/IUtf8JsonSerializable.cs | 14 + .../src/Shared/AutoRest/IXmlSerializable.cs | 14 + .../Shared/AutoRest/JsonElementExtensions.cs | 97 +++++ .../AutoRest/ManagementPipelineBuilder.cs | 22 ++ .../Shared/AutoRest/OperationFinalStateVia.cs | 14 + .../Azure.Core/src/Shared/AutoRest/Page.cs | 16 + .../src/Shared/AutoRest/PageableHelpers.cs | 81 ++++ .../Shared/AutoRest/RawRequestUriBuilder.cs | 91 +++++ .../AutoRest/RequestHeaderExtensions.cs | 59 +++ .../AutoRest/RequestUriBuilderExtensions.cs | 110 ++++++ .../AutoRest/ResponseHeadersExtensions.cs | 74 ++++ .../Shared/AutoRest/ResponseWithHeaders.cs | 20 + .../ResponseWithHeaders{T,THeaders}.cs | 25 ++ .../AutoRest/ResponseWithHeaders{THeaders}.cs | 22 ++ .../Shared/AutoRest/StringRequestContent.cs | 40 ++ .../src/Shared/AutoRest/TypeFormatters.cs | 114 ++++++ .../Shared/AutoRest/Utf8JsonRequestContent.cs | 49 +++ .../AutoRest/Utf8JsonWriterExtensions.cs | 98 +++++ .../src/Shared/AutoRest/XElementExtensions.cs | 43 +++ .../src/Shared/AutoRest/XmlWriterContent.cs | 52 +++ .../Shared/AutoRest/XmlWriterExtensions.cs | 43 +++ 26 files changed, 1547 insertions(+) create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/ArmOperationHelpers.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenClientAttribute.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenMemberAttribute.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenModelAttribute.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenSuppressAttribute.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/IUtf8JsonSerializable.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/IXmlSerializable.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/JsonElementExtensions.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/ManagementPipelineBuilder.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/OperationFinalStateVia.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/Page.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/PageableHelpers.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/RawRequestUriBuilder.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/RequestHeaderExtensions.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/RequestUriBuilderExtensions.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/ResponseHeadersExtensions.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders{T,THeaders}.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders{THeaders}.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/TypeFormatters.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/Utf8JsonRequestContent.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/Utf8JsonWriterExtensions.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/XElementExtensions.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/XmlWriterContent.cs create mode 100644 sdk/core/Azure.Core/src/Shared/AutoRest/XmlWriterExtensions.cs diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/ArmOperationHelpers.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/ArmOperationHelpers.cs new file mode 100644 index 000000000000..d4111418d0a9 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/ArmOperationHelpers.cs @@ -0,0 +1,356 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core.Pipeline; + +namespace Azure.Core +{ + /// + /// Helper methods for ARM long-running operations. + /// + internal static class ArmOperationHelpers + { + internal static Operation Create(HttpPipeline pipeline, ClientDiagnostics clientDiagnostics, Response originalResponse, RequestMethod requestMethod, string scopeName, OperationFinalStateVia finalStateVia, Func createOriginalHttpMessage) + { + return Create(pipeline, clientDiagnostics, originalResponse, requestMethod, scopeName, finalStateVia, createOriginalHttpMessage, + (response, token) => response, + (response, token) => new ValueTask(response)); + } + + internal static Operation Create(HttpPipeline pipeline, ClientDiagnostics clientDiagnostics, Response originalResponse, RequestMethod requestMethod, string scopeName, OperationFinalStateVia finalStateVia, + Func createOriginalHttpMessage, Func createFinalResponse, Func> createFinalResponseAsync) where T : notnull + { + using HttpMessage originalHttpMethod = createOriginalHttpMessage(); + string originalUri = originalHttpMethod.Request.Uri.ToString(); + return new ArmOperation(pipeline, clientDiagnostics, originalResponse, originalUri, requestMethod, finalStateVia, scopeName, createFinalResponse, createFinalResponseAsync); + } + + private static readonly string[] s_failureStates = { "failed", "canceled" }; + private static readonly string[] s_terminalStates = { "succeeded", "failed", "canceled" }; + + /// + /// This implements the ARM scenarios for LROs. It is highly recommended to read the ARM spec prior to modifying this code: + /// https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/Addendum.md#asynchronous-operations + /// Other reference documents include: + /// https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-long-running-operation + /// https://github.com/Azure/adx-documentation-pr/blob/master/sdks/LRO/LRO_AzureSDK.md + /// + /// The final result of the LRO. + private class ArmOperation : Operation where T : notnull + { + private readonly HttpPipeline _pipeline; + private readonly ClientDiagnostics _clientDiagnostics; + private readonly string _scopeName; + private readonly Func _createFinalResponse; + private readonly Func> _createFinalResponseAsync; + private readonly RequestMethod _requestMethod; + private readonly string _originalUri; + private readonly OperationFinalStateVia _finalStateVia; + private HeaderFrom _headerFrom; + private string _pollUri = default!; + private bool _originalHasLocation; + private string? _lastKnownLocation; + + private Response _rawResponse; + private T _value = default!; + private bool _hasValue; + private bool _hasCompleted; + private bool _shouldPoll; + + public ArmOperation(HttpPipeline pipeline, ClientDiagnostics clientDiagnostics, Response originalResponse, + string originalUri, RequestMethod requestMethod, OperationFinalStateVia finalStateVia, string scopeName, + Func createFinalResponse, Func> createFinalResponseAsync) + { + _rawResponse = originalResponse; + _requestMethod = requestMethod; + _originalUri = originalUri; + _finalStateVia = finalStateVia; + InitializeScenarioInfo(); + + _pipeline = pipeline; + _clientDiagnostics = clientDiagnostics; + _scopeName = scopeName; + _createFinalResponse = createFinalResponse; + _createFinalResponseAsync = createFinalResponseAsync; + // When the original response has no headers, we do not start polling immediately. + _shouldPoll = _headerFrom != HeaderFrom.None; + } + + public override Response GetRawResponse() => _rawResponse; + + public override ValueTask> WaitForCompletionAsync(CancellationToken cancellationToken = default) => + this.DefaultWaitForCompletionAsync(OperationHelpers.DefaultPollingInterval, cancellationToken); + + public override ValueTask> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken) => + this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken); + + private async ValueTask UpdateStatusAsync(bool async, CancellationToken cancellationToken) + { + if (_hasCompleted) + { + return GetRawResponse(); + } + + if (_shouldPoll) + { + UpdatePollUri(); + _rawResponse = async + ? await GetResponseAsync(_pollUri, cancellationToken).ConfigureAwait(false) + : GetResponse(_pollUri, cancellationToken); + } + _shouldPoll = true; + _hasCompleted = IsTerminalState(out string state); + if (_hasCompleted) + { + Response finalResponse = GetRawResponse(); + if (s_failureStates.Contains(state)) + { + throw _clientDiagnostics.CreateRequestFailedException(finalResponse); + } + + string? finalUri = GetFinalUri(); + if (finalUri != null) + { + finalResponse = async + ? await GetResponseAsync(finalUri, cancellationToken).ConfigureAwait(false) + : GetResponse(finalUri, cancellationToken); + } + switch (finalResponse.Status) + { + case 200: + case 204 when !(_requestMethod == RequestMethod.Put || _requestMethod == RequestMethod.Patch): + { + _value = async + ? await _createFinalResponseAsync(finalResponse, cancellationToken).ConfigureAwait(false) + : _createFinalResponse(finalResponse, cancellationToken); + _rawResponse = finalResponse; + _hasValue = true; + break; + } + default: + throw _clientDiagnostics.CreateRequestFailedException(finalResponse); + } + } + + return GetRawResponse(); + } + + public override async ValueTask UpdateStatusAsync(CancellationToken cancellationToken = default) => await UpdateStatusAsync(async: true, cancellationToken).ConfigureAwait(false); + + public override Response UpdateStatus(CancellationToken cancellationToken = default) => UpdateStatusAsync(async: false, cancellationToken).EnsureCompleted(); + + //TODO: This is currently unused. + public override string Id { get; } = Guid.NewGuid().ToString(); + + public override T Value + { + get + { + if (!HasValue) + { + throw new InvalidOperationException("The operation has not completed yet."); + } + + return _value; + } + } + public override bool HasCompleted => _hasCompleted; + public override bool HasValue => _hasValue; + + private HttpMessage CreateRequest(string link) + { + HttpMessage message = _pipeline.CreateMessage(); + Request request = message.Request; + request.Method = RequestMethod.Get; + request.Uri.Reset(new Uri(link)); + return message; + } + + private async ValueTask GetResponseAsync(string link, CancellationToken cancellationToken = default) + { + if (link == null) + { + throw new ArgumentNullException(nameof(link)); + } + + using DiagnosticScope scope = _clientDiagnostics.CreateScope(_scopeName); + scope.Start(); + try + { + using HttpMessage message = CreateRequest(link); + await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); + return message.Response; + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + private Response GetResponse(string link, CancellationToken cancellationToken = default) + { + if (link == null) + { + throw new ArgumentNullException(nameof(link)); + } + + using DiagnosticScope scope = _clientDiagnostics.CreateScope(_scopeName); + scope.Start(); + try + { + using HttpMessage message = CreateRequest(link); + _pipeline.Send(message, cancellationToken); + return message.Response; + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + private bool IsTerminalState(out string state) + { + Response response = GetRawResponse(); + state = string.Empty; + if (_headerFrom == HeaderFrom.Location) + { + return response.Status != 202; + } + + if (response.Status >= 200 && response.Status <= 204) + { + if (response.ContentStream?.Length > 0) + { + try + { + using JsonDocument document = JsonDocument.Parse(response.ContentStream); + foreach (JsonProperty property in document.RootElement.EnumerateObject()) + { + if ((_headerFrom == HeaderFrom.OperationLocation || + _headerFrom == HeaderFrom.AzureAsyncOperation) && + property.NameEquals("status")) + { + state = property.Value.GetString().ToLowerInvariant(); + return s_terminalStates.Contains(state); + } + + if (_headerFrom == HeaderFrom.None && property.NameEquals("properties")) + { + foreach (JsonProperty innerProperty in property.Value.EnumerateObject()) + { + if (innerProperty.NameEquals("provisioningState")) + { + state = innerProperty.Value.GetString().ToLowerInvariant(); + return s_terminalStates.Contains(state); + } + } + } + } + } + finally + { + // It is required to reset the position of the content after reading as this response may be used for deserialization. + response.ContentStream.Position = 0; + } + } + + // If provisioningState was not found, it defaults to Succeeded. + if (_headerFrom == HeaderFrom.None) + { + return true; + } + } + + throw _clientDiagnostics.CreateRequestFailedException(response); + } + + private enum HeaderFrom + { + None, + OperationLocation, + AzureAsyncOperation, + Location + } + + private void InitializeScenarioInfo() + { + _originalHasLocation = _rawResponse.Headers.Contains("Location"); + + if (_rawResponse.Headers.Contains("Operation-Location")) + { + _headerFrom = HeaderFrom.OperationLocation; + return; + } + + if (_rawResponse.Headers.Contains("Azure-AsyncOperation")) + { + _headerFrom = HeaderFrom.AzureAsyncOperation; + return; + } + + if (_originalHasLocation) + { + _headerFrom = HeaderFrom.Location; + return; + } + + _pollUri = _originalUri; + _headerFrom = HeaderFrom.None; + } + + private void UpdatePollUri() + { + var hasLocation = _rawResponse.Headers.TryGetValue("Location", out string? location); + if (hasLocation) + { + _lastKnownLocation = location; + } + + switch (_headerFrom) + { + case HeaderFrom.OperationLocation when _rawResponse.Headers.TryGetValue("Operation-Location", out string? operationLocation): + _pollUri = operationLocation; + return; + case HeaderFrom.AzureAsyncOperation when _rawResponse.Headers.TryGetValue("Azure-AsyncOperation", out string? azureAsyncOperation): + _pollUri = azureAsyncOperation; + return; + case HeaderFrom.Location when hasLocation: + _pollUri = location!; + return; + } + } + + private string? GetFinalUri() + { + if (_headerFrom == HeaderFrom.OperationLocation || _headerFrom == HeaderFrom.AzureAsyncOperation) + { + if (_requestMethod == RequestMethod.Delete) + { + return null; + } + + if (_requestMethod == RequestMethod.Put || (_originalHasLocation && _finalStateVia == OperationFinalStateVia.OriginalUri)) + { + return _originalUri; + } + + if (_originalHasLocation && _finalStateVia == OperationFinalStateVia.Location) + { + return _lastKnownLocation; + } + } + + return null; + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenClientAttribute.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenClientAttribute.cs new file mode 100644 index 000000000000..08658438d75a --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenClientAttribute.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Core +{ + [AttributeUsage(AttributeTargets.Class)] + internal class CodeGenClientAttribute : Attribute + { + public string OriginalName { get; } + + public CodeGenClientAttribute(string originalName) + { + OriginalName = originalName; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenMemberAttribute.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenMemberAttribute.cs new file mode 100644 index 000000000000..14c0870a293d --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenMemberAttribute.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; + +namespace Azure.Core +{ + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] + internal class CodeGenMemberAttribute : Attribute + { + public string? OriginalName { get; } + + /// + /// For collection properties. When set to true empty collection would be treated as undefined and not serialized. + /// + public bool EmptyAsUndefined { get; set; } + + /// + /// For collection and model properties. Whether the property would always be initialized on creation/deserialization. + /// Requires a parameterless constructor for implementation type. + /// + public bool Initialize { get; set; } + + public CodeGenMemberAttribute() + { + } + + public CodeGenMemberAttribute(string originalName) + { + OriginalName = originalName; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenModelAttribute.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenModelAttribute.cs new file mode 100644 index 000000000000..f1a8d55e3e2e --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenModelAttribute.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; + +namespace Azure.Core +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct)] + internal class CodeGenModelAttribute : Attribute + { + public string OriginalName { get; } + + public CodeGenModelAttribute(string originalName) + { + OriginalName = originalName; + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenSuppressAttribute.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenSuppressAttribute.cs new file mode 100644 index 000000000000..efb2c82f864e --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/CodeGenSuppressAttribute.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Core +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct, AllowMultiple = true)] + internal class CodeGenSuppressAttribute : Attribute + { + public string Member { get; } + public Type[] Parameters { get; } + + public CodeGenSuppressAttribute(string member, params Type[] parameters) + { + Member = member; + Parameters = parameters; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/IUtf8JsonSerializable.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/IUtf8JsonSerializable.cs new file mode 100644 index 000000000000..5653e4609313 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/IUtf8JsonSerializable.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System.Text.Json; + +namespace Azure.Core +{ + internal interface IUtf8JsonSerializable + { + void Write(Utf8JsonWriter writer); + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/IXmlSerializable.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/IXmlSerializable.cs new file mode 100644 index 000000000000..343b127384d2 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/IXmlSerializable.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System.Xml; + +namespace Azure.Core +{ + internal interface IXmlSerializable + { + void Write(XmlWriter writer, string? nameHint); + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/JsonElementExtensions.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/JsonElementExtensions.cs new file mode 100644 index 000000000000..f7a4dfd57b02 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/JsonElementExtensions.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.Json; +using System.Xml; + +namespace Azure.Core +{ + internal static class JsonElementExtensions + { + public static object? GetObject(in this JsonElement element) + { + switch (element.ValueKind) + { + case JsonValueKind.String: + return element.GetString(); + case JsonValueKind.Number: + if (element.TryGetInt32(out int intValue)) + { + return intValue; + } + if (element.TryGetInt64(out long longValue)) + { + return longValue; + } + return element.GetDouble(); + case JsonValueKind.True: + return true; + case JsonValueKind.False: + return false; + case JsonValueKind.Undefined: + case JsonValueKind.Null: + return null; + case JsonValueKind.Object: + var dictionary = new Dictionary(); + foreach (JsonProperty jsonProperty in element.EnumerateObject()) + { + dictionary.Add(jsonProperty.Name, jsonProperty.Value.GetObject()); + } + return dictionary; + case JsonValueKind.Array: + var list = new List(); + foreach (JsonElement item in element.EnumerateArray()) + { + list.Add(item.GetObject()); + } + return list.ToArray(); + default: + throw new NotSupportedException("Not supported value kind " + element.ValueKind); + } + } + + public static byte[] GetBytesFromBase64(in this JsonElement element, string format) => format switch + { + "U" => TypeFormatters.FromBase64UrlString(element.GetString()), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static DateTimeOffset GetDateTimeOffset(in this JsonElement element, string format) => format switch + { + "D" => element.GetDateTimeOffset(), + "S" => DateTimeOffset.Parse(element.GetString(), CultureInfo.InvariantCulture), + "R" => DateTimeOffset.Parse(element.GetString(), CultureInfo.InvariantCulture), + "U" => DateTimeOffset.FromUnixTimeSeconds(element.GetInt64()), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static TimeSpan GetTimeSpan(in this JsonElement element, string format) => format switch + { + "P" => XmlConvert.ToTimeSpan(element.GetString()), + "T" => TimeSpan.ParseExact(element.GetString(), "T", CultureInfo.InvariantCulture), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static char GetChar(this in JsonElement element) + { + if (element.ValueKind == JsonValueKind.String) + { + var text = element.GetString(); + if (text == null || text.Length != 1) + { + throw new NotSupportedException($"Cannot convert \"{text}\" to a Char"); + } + return text[0]; + } + else + { + throw new NotSupportedException($"Cannot convert {element.ValueKind} to a Char"); + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/ManagementPipelineBuilder.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/ManagementPipelineBuilder.cs new file mode 100644 index 000000000000..8c7fabd3f8a0 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/ManagementPipelineBuilder.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.Json; +using System.Xml; +using Azure.Core.Pipeline; + +namespace Azure.Core +{ + internal static class ManagementPipelineBuilder + { + public static HttpPipeline Build(TokenCredential credential, ClientOptions options) + { + return HttpPipelineBuilder.Build(options, new BearerTokenAuthenticationPolicy(credential, "https://management.azure.com//.default")); + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/OperationFinalStateVia.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/OperationFinalStateVia.cs new file mode 100644 index 000000000000..6b6c2771e5a1 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/OperationFinalStateVia.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +namespace Azure.Core +{ + internal enum OperationFinalStateVia + { + AzureAsyncOperation, + Location, + OriginalUri + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/Page.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/Page.cs new file mode 100644 index 000000000000..1438fdfd5f04 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/Page.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Core +{ + internal static class Page + { + public static Page FromValues(IEnumerable values, string continuationToken, Response response) => + Page.FromValues(values.ToList(), continuationToken, response); + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/PageableHelpers.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/PageableHelpers.cs new file mode 100644 index 000000000000..cf5563728971 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/PageableHelpers.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Azure.Core +{ + internal static class PageableHelpers + { + public static Pageable CreateEnumerable(Func> firstPageFunc, Func> nextPageFunc, int? pageSize = default) where T : notnull + { + return new FuncPageable((continuationToken, pageSizeHint) => firstPageFunc(pageSizeHint), (continuationToken, pageSizeHint) => nextPageFunc(continuationToken, pageSizeHint), pageSize); + } + + public static AsyncPageable CreateAsyncEnumerable(Func>> firstPageFunc, Func>> nextPageFunc, int? pageSize = default) where T : notnull + { + return new FuncAsyncPageable((continuationToken, pageSizeHint) => firstPageFunc(pageSizeHint), (continuationToken, pageSizeHint) => nextPageFunc(continuationToken, pageSizeHint), pageSize); + } + + internal delegate Task> AsyncPageFunc(string? continuationToken = default, int? pageSizeHint = default); + internal delegate Page PageFunc(string? continuationToken = default, int? pageSizeHint = default); + + internal class FuncAsyncPageable : AsyncPageable where T : notnull + { + private readonly AsyncPageFunc _firstPageFunc; + private readonly AsyncPageFunc _nextPageFunc; + private readonly int? _defaultPageSize; + + public FuncAsyncPageable(AsyncPageFunc firstPageFunc, AsyncPageFunc nextPageFunc, int? defaultPageSize = default) + { + _firstPageFunc = firstPageFunc; + _nextPageFunc = nextPageFunc; + _defaultPageSize = defaultPageSize; + } + + public override async IAsyncEnumerable> AsPages(string? continuationToken = default, int? pageSizeHint = default) + { + AsyncPageFunc pageFunc = _firstPageFunc; + int? pageSize = pageSizeHint ?? _defaultPageSize; + do + { + Page pageResponse = await pageFunc(continuationToken, pageSize).ConfigureAwait(false); + yield return pageResponse; + continuationToken = pageResponse.ContinuationToken; + pageFunc = _nextPageFunc; + } while (!string.IsNullOrEmpty(continuationToken)); + } + } + + internal class FuncPageable : Pageable where T : notnull + { + private readonly PageFunc _firstPageFunc; + private readonly PageFunc _nextPageFunc; + private readonly int? _defaultPageSize; + + public FuncPageable(PageFunc firstPageFunc, PageFunc nextPageFunc, int? defaultPageSize = default) + { + _firstPageFunc = firstPageFunc; + _nextPageFunc = nextPageFunc; + _defaultPageSize = defaultPageSize; + } + + public override IEnumerable> AsPages(string? continuationToken = default, int? pageSizeHint = default) + { + PageFunc pageFunc = _firstPageFunc; + int? pageSize = pageSizeHint ?? _defaultPageSize; + do + { + Page pageResponse = pageFunc(continuationToken, pageSize); + yield return pageResponse; + continuationToken = pageResponse.ContinuationToken; + pageFunc = _nextPageFunc; + } while (!string.IsNullOrEmpty(continuationToken)); + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/RawRequestUriBuilder.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/RawRequestUriBuilder.cs new file mode 100644 index 000000000000..0c800decc945 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/RawRequestUriBuilder.cs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Globalization; + +namespace Azure.Core +{ + internal class RawRequestUriBuilder: RequestUriBuilder + { + private const string SchemeSeparator = "://"; + private const char HostSeparator = '/'; + private const char PortSeparator = ':'; + private static readonly char[] HostOrPort = new[] {HostSeparator, PortSeparator}; + + private RawWritingPosition _position = RawWritingPosition.Scheme; + + public void AppendRaw(string value, bool escape) + { + while (!string.IsNullOrWhiteSpace(value)) + { + if (_position == RawWritingPosition.Scheme) + { + int separator = value.IndexOf(SchemeSeparator, StringComparison.InvariantCultureIgnoreCase); + if (separator == -1) + { + Scheme += value; + value = string.Empty; + } + else + { + Scheme += value.Substring(0, separator); + + // TODO: Find a better way to map schemes to default ports + Port = string.Equals(Scheme, "https", StringComparison.OrdinalIgnoreCase) ? 443 : 80; + + value = value.Substring(separator + SchemeSeparator.Length); + _position = RawWritingPosition.Host; + } + } + else if (_position == RawWritingPosition.Host) + { + int separator = value.IndexOfAny(HostOrPort); + if (separator == -1) + { + Host += value; + value = string.Empty; + } + else + { + Host += value.Substring(0, separator); + + _position = value[separator] == HostSeparator ? RawWritingPosition.Rest : RawWritingPosition.Port; + + value = value.Substring(separator + 1); + } + } + else if (_position == RawWritingPosition.Port) + { + int separator = value.IndexOf(HostSeparator); + if (separator == -1) + { + Port = int.Parse(value, CultureInfo.InvariantCulture); + value = string.Empty; + } + else + { + Port = int.Parse(value.Substring(0, separator), CultureInfo.InvariantCulture); + value = value.Substring(separator + 1); + _position = RawWritingPosition.Rest; + } + } + else + { + AppendPath(value, escape); + value = string.Empty; + } + } + } + + private enum RawWritingPosition + { + Scheme, + Host, + Port, + Rest + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/RequestHeaderExtensions.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/RequestHeaderExtensions.cs new file mode 100644 index 000000000000..5417f05ecc62 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/RequestHeaderExtensions.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace Azure.Core +{ + internal static class RequestHeaderExtensions + { + public static void Add(this RequestHeaders headers, string name, bool value) + { + headers.Add(name, TypeFormatters.ToString(value)); + } + + public static void Add(this RequestHeaders headers, string name, float value) + { + headers.Add(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture)); + } + + public static void Add(this RequestHeaders headers, string name, double value) + { + headers.Add(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture)); + } + + public static void Add(this RequestHeaders headers, string name, int value) + { + headers.Add(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture)); + } + + public static void Add(this RequestHeaders headers, string name, DateTimeOffset value, string format) + { + headers.Add(name, TypeFormatters.ToString(value, format)); + } + + public static void Add(this RequestHeaders headers, string name, TimeSpan value, string format) + { + headers.Add(name, TypeFormatters.ToString(value, format)); + } + + public static void Add(this RequestHeaders headers, string name, Guid value) + { + headers.Add(name, value.ToString()); + } + + public static void Add(this RequestHeaders headers, string name, byte[] value) + { + headers.Add(name, Convert.ToBase64String(value)); + } + + public static void AddDelimited(this RequestHeaders headers, string name, IEnumerable value, string delimiter) + { + headers.Add(name, string.Join(delimiter, value)); + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/RequestUriBuilderExtensions.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/RequestUriBuilderExtensions.cs new file mode 100644 index 000000000000..5b43df070308 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/RequestUriBuilderExtensions.cs @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Xml; + +namespace Azure.Core +{ + internal static class RequestUriBuilderExtensions + { + public static void AppendPath(this RequestUriBuilder builder, bool value, bool escape = false) + { + builder.AppendPath(TypeFormatters.ToString(value), escape); + } + + public static void AppendPath(this RequestUriBuilder builder, float value, bool escape = true) + { + builder.AppendPath(value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); + } + + public static void AppendPath(this RequestUriBuilder builder, double value, bool escape = true) + { + builder.AppendPath(value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); + } + + public static void AppendPath(this RequestUriBuilder builder, int value, bool escape = true) + { + builder.AppendPath(value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); + } + + public static void AppendPath(this RequestUriBuilder builder, byte[] value, bool escape = true) + { + builder.AppendPath(TypeFormatters.ToBase64UrlString(value), escape); + } + + public static void AppendPath(this RequestUriBuilder builder, IEnumerable value, bool escape = true) + { + builder.AppendPath(string.Join(",", value), escape); + } + + public static void AppendPath(this RequestUriBuilder builder, DateTimeOffset value, string format, bool escape = true) + { + builder.AppendPath(TypeFormatters.ToString(value, format), escape); + } + + public static void AppendPath(this RequestUriBuilder builder, TimeSpan value, string format, bool escape = true) + { + builder.AppendPath(TypeFormatters.ToString(value, format), escape); + } + + public static void AppendPath(this RequestUriBuilder builder, Guid value, bool escape = true) + { + builder.AppendPath(value.ToString(), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, bool value, bool escape = false) + { + builder.AppendQuery(name, TypeFormatters.ToString(value), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, float value, bool escape = true) + { + builder.AppendQuery(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, DateTimeOffset value, string format, bool escape = true) + { + builder.AppendQuery(name, TypeFormatters.ToString(value, format), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, TimeSpan value, string format, bool escape = true) + { + builder.AppendQuery(name, TypeFormatters.ToString(value, format), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, double value, bool escape = true) + { + builder.AppendQuery(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, int value, bool escape = true) + { + builder.AppendQuery(name, value.ToString(TypeFormatters.DefaultNumberFormat, CultureInfo.InvariantCulture), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, TimeSpan value, bool escape = true) + { + builder.AppendQuery(name, XmlConvert.ToString(value), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, byte[] value, bool escape = true) + { + builder.AppendQuery(name, Convert.ToBase64String(value), escape); + } + + public static void AppendQuery(this RequestUriBuilder builder, string name, Guid value, bool escape = true) + { + builder.AppendQuery(name, value.ToString(), escape); + } + + public static void AppendQueryDelimited(this RequestUriBuilder builder, string name, IEnumerable value, string delimiter, bool escape = true) + { + builder.AppendQuery(name, string.Join(delimiter, value), escape); + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseHeadersExtensions.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseHeadersExtensions.cs new file mode 100644 index 000000000000..f54a1b41f743 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseHeadersExtensions.cs @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Globalization; +using System.Xml; + +namespace Azure.Core +{ + internal static class ResponseHeadersExtensions + { + public static bool TryGetValue(this ResponseHeaders headers, string name, out byte[]? value) + { + if (headers.TryGetValue(name, out string? stringValue)) + { + value = Convert.FromBase64String(stringValue); + return true; + } + + value = null; + return false; + } + + public static bool TryGetValue(this ResponseHeaders headers, string name, out TimeSpan? value) + { + if (headers.TryGetValue(name, out string? stringValue)) + { + value = XmlConvert.ToTimeSpan(stringValue); + return true; + } + + value = null; + return false; + } + + public static bool TryGetValue(this ResponseHeaders headers, string name, out DateTimeOffset? value) + { + if (headers.TryGetValue(name, out string? stringValue)) + { + value = DateTimeOffset.Parse(stringValue, CultureInfo.InvariantCulture); + return true; + } + + value = null; + return false; + } + + public static bool TryGetValue(this ResponseHeaders headers, string name, out T? value) where T : struct + { + if (headers.TryGetValue(name, out string? stringValue)) + { + value = (T)Convert.ChangeType(stringValue, typeof(T), CultureInfo.InvariantCulture); + return true; + } + + value = null; + return false; + } + + public static bool TryGetValue(this ResponseHeaders headers, string name, out T? value) where T : class + { + if (headers.TryGetValue(name, out string? stringValue)) + { + value = (T)Convert.ChangeType(stringValue, typeof(T), CultureInfo.InvariantCulture); + return true; + } + + value = null; + return false; + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders.cs new file mode 100644 index 000000000000..2a48fb0ebbfb --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +namespace Azure.Core +{ + internal static class ResponseWithHeaders + { + public static ResponseWithHeaders FromValue(T value, THeaders headers, Response rawResponse) + { + return new ResponseWithHeaders(value, headers, rawResponse); + } + + public static ResponseWithHeaders FromValue(THeaders headers, Response rawResponse) + { + return new ResponseWithHeaders(headers, rawResponse); + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders{T,THeaders}.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders{T,THeaders}.cs new file mode 100644 index 000000000000..5c2036521e2a --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders{T,THeaders}.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +namespace Azure.Core +{ + internal class ResponseWithHeaders : Response + { + private readonly Response _rawResponse; + + public ResponseWithHeaders(T value, THeaders headers, Response rawResponse) + { + _rawResponse = rawResponse; + Value = value; + Headers = headers; + } + + public override Response GetRawResponse() => _rawResponse; + + public override T Value { get; } + + public THeaders Headers { get; } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders{THeaders}.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders{THeaders}.cs new file mode 100644 index 000000000000..66a788c4a099 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/ResponseWithHeaders{THeaders}.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +namespace Azure.Core +{ + internal class ResponseWithHeaders + { + private readonly Response _rawResponse; + + public ResponseWithHeaders(THeaders headers, Response rawResponse) + { + _rawResponse = rawResponse; + Headers = headers; + } + + public Response GetRawResponse() => _rawResponse; + + public THeaders Headers { get; } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs new file mode 100644 index 000000000000..b5d98e9b5c08 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Azure.Core +{ + internal class StringRequestContent : RequestContent + { + private readonly byte[] _bytes; + + public StringRequestContent(string value) + { + _bytes = Encoding.UTF8.GetBytes(value); + } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) + { + await stream.WriteAsync(_bytes, 0, _bytes.Length, cancellation); + } + + public override void WriteTo(Stream stream, CancellationToken cancellation) + { + stream.Write(_bytes, 0, _bytes.Length); + } + + public override bool TryComputeLength(out long length) + { + length = _bytes.Length; + return true; + } + + public override void Dispose() + { + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/TypeFormatters.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/TypeFormatters.cs new file mode 100644 index 000000000000..069bcc52672f --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/TypeFormatters.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Globalization; +using System.Xml; + +namespace Azure.Core +{ + internal class TypeFormatters + { + public static string DefaultNumberFormat { get; } = "G"; + + public static string ToString(bool value) => value ? "true" : "false"; + + public static string ToString(DateTimeOffset value, string format) => format switch + { + "D" => value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), + "S" when value.Offset == TimeSpan.Zero => value.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture), + "S" => value.ToString("O", CultureInfo.InvariantCulture), + "R" => value.ToString("R", CultureInfo.InvariantCulture), + "U" => value.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static string ToString(TimeSpan value, string format) => format switch + { + "P" => XmlConvert.ToString(value), + "T" => value.ToString("T", CultureInfo.InvariantCulture), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static string ToBase64UrlString(byte[] value) + { + var numWholeOrPartialInputBlocks = checked(value.Length + 2) / 3; + var size = checked(numWholeOrPartialInputBlocks * 4); + var output = new char[size]; + + var numBase64Chars = Convert.ToBase64CharArray(value, 0, value.Length, output, 0); + + // Fix up '+' -> '-' and '/' -> '_'. Drop padding characters. + int i = 0; + for (; i < numBase64Chars; i++) + { + var ch = output[i]; + if (ch == '+') + { + output[i] = '-'; + } + else if (ch == '/') + { + output[i] = '_'; + } + else if (ch == '=') + { + // We've reached a padding character; truncate the remainder. + break; + } + } + + return new string(output, 0, i); + } + + public static byte[] FromBase64UrlString(string value) + { + var paddingCharsToAdd = GetNumBase64PaddingCharsToAddForDecode(value.Length); + + var output = new char[value.Length + paddingCharsToAdd]; + + int i; + for (i = 0; i < value.Length; i++) + { + var ch = value[i]; + if (ch == '-') + { + output[i] = '+'; + } + else if (ch == '_') + { + output[i] = '/'; + } + else + { + output[i] = ch; + } + } + + for (; i < output.Length; i++) + { + output[i] = '='; + } + + return Convert.FromBase64CharArray(output, 0, output.Length); + } + + + private static int GetNumBase64PaddingCharsToAddForDecode(int inputLength) + { + switch (inputLength % 4) + { + case 0: + return 0; + case 2: + return 2; + case 3: + return 1; + default: + throw new InvalidOperationException("Malformed input"); + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/Utf8JsonRequestContent.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/Utf8JsonRequestContent.cs new file mode 100644 index 000000000000..766e2c4cbf36 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/Utf8JsonRequestContent.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace Azure.Core +{ + internal class Utf8JsonRequestContent: RequestContent + { + private readonly ArrayBufferWriter _writer; + + public Utf8JsonWriter JsonWriter { get; } + + public Utf8JsonRequestContent() + { + _writer = new ArrayBufferWriter(); + JsonWriter = new Utf8JsonWriter(_writer); + } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) + { + await JsonWriter.FlushAsync(cancellation).ConfigureAwait(false); + using var content = Create(_writer.WrittenMemory); + await content.WriteToAsync(stream, cancellation).ConfigureAwait(false); + } + + public override void WriteTo(Stream stream, CancellationToken cancellation) + { + JsonWriter.Flush(); + using var content = Create(_writer.WrittenMemory); + content.WriteTo(stream, cancellation); + } + + public override bool TryComputeLength(out long length) + { + length = JsonWriter.BytesCommitted + JsonWriter.BytesPending; + return true; + } + + public override void Dispose() + { + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/Utf8JsonWriterExtensions.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/Utf8JsonWriterExtensions.cs new file mode 100644 index 000000000000..a1fc529d01d5 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/Utf8JsonWriterExtensions.cs @@ -0,0 +1,98 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.Json; + +namespace Azure.Core +{ + internal static class Utf8JsonWriterExtensions + { + public static void WriteStringValue(this Utf8JsonWriter writer, DateTimeOffset value, string format) => + writer.WriteStringValue(TypeFormatters.ToString(value, format)); + + public static void WriteStringValue(this Utf8JsonWriter writer, TimeSpan value, string format) => + writer.WriteStringValue(TypeFormatters.ToString(value, format)); + + public static void WriteStringValue(this Utf8JsonWriter writer, char value) => + writer.WriteStringValue(value.ToString(CultureInfo.InvariantCulture)); + + public static void WriteObjectValue(this Utf8JsonWriter writer, IUtf8JsonSerializable value) + { + value.Write(writer); + } + + public static void WriteBase64StringValue(this Utf8JsonWriter writer, byte[] value, string format) + { + switch (format) + { + case "U": + writer.WriteStringValue(TypeFormatters.ToBase64UrlString(value)); + break; + default: + throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)); + } + } + + public static void WriteObjectValue(this Utf8JsonWriter writer, object value) + { + switch (value) + { + case null: + writer.WriteNullValue(); + break; + case IUtf8JsonSerializable serializable: + writer.WriteObjectValue(serializable); + break; + case byte[] bytes: + writer.WriteStringValue(Convert.ToBase64String(bytes)); + break; + case int i: + writer.WriteNumberValue(i); + break; + case decimal d: + writer.WriteNumberValue(d); + break; + case double d: + writer.WriteNumberValue(d); + break; + case float f: + writer.WriteNumberValue(f); + break; + case string s: + writer.WriteStringValue(s); + break; + case bool b: + writer.WriteBooleanValue(b); + break; + case DateTimeOffset dateTimeOffset: + writer.WriteStringValue(dateTimeOffset,"S"); + break; + case IEnumerable> enumerable: + writer.WriteStartObject(); + foreach (KeyValuePair pair in enumerable) + { + writer.WritePropertyName(pair.Key); + writer.WriteObjectValue(pair.Value); + } + writer.WriteEndObject(); + break; + case IEnumerable objectEnumerable: + writer.WriteStartArray(); + foreach (object item in objectEnumerable) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + break; + + default: + throw new NotSupportedException("Not supported type " + value.GetType()); + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/XElementExtensions.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/XElementExtensions.cs new file mode 100644 index 000000000000..09915d57bbe1 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/XElementExtensions.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Globalization; +using System.Xml; +using System.Xml.Linq; + +namespace Azure.Core +{ + internal static class XElementExtensions + { + public static byte[] GetBytesFromBase64Value(this XElement element, string format) => format switch + { + "U" => TypeFormatters.FromBase64UrlString(element.Value), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static DateTimeOffset GetDateTimeOffsetValue(this XElement element, string format) => format switch + { + "D" => (DateTimeOffset)element, + "S" => DateTimeOffset.Parse(element.Value, CultureInfo.InvariantCulture), + "R" => DateTimeOffset.Parse(element.Value, CultureInfo.InvariantCulture), + "U" => DateTimeOffset.FromUnixTimeSeconds((long)element), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static TimeSpan GetTimeSpanValue(this XElement element, string format) => format switch + { + "P" => XmlConvert.ToTimeSpan(element.Value), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + #pragma warning disable CA1801 //Parameter format of method GetObjectValue is never used. Remove the parameter or use it in the method body. + public static object GetObjectValue(this XElement element, string format) + #pragma warning restore + { + return element.Value; + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/XmlWriterContent.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/XmlWriterContent.cs new file mode 100644 index 000000000000..25d6a326de6f --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/XmlWriterContent.cs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; + +namespace Azure.Core +{ + internal class XmlWriterContent : RequestContent + { + private readonly MemoryStream _stream; + public XmlWriterContent() + { + _stream = new MemoryStream(); + XmlWriter = new XmlTextWriter(_stream, Encoding.UTF8); + } + + public XmlWriter XmlWriter { get; } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) + { + XmlWriter.Flush(); + _stream.Position = 0; + using var content = Create(_stream); + await content.WriteToAsync(stream, cancellation).ConfigureAwait(false); + } + + public override void WriteTo(Stream stream, CancellationToken cancellation) + { + XmlWriter.Flush(); + _stream.Position = 0; + using var content = Create(_stream); + content.WriteTo(stream, cancellation); + } + + public override bool TryComputeLength(out long length) + { + XmlWriter.Flush(); + length = _stream.Length; + return true; + } + + public override void Dispose() + { + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/XmlWriterExtensions.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/XmlWriterExtensions.cs new file mode 100644 index 000000000000..84cf13f4c976 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/XmlWriterExtensions.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Xml; + +namespace Azure.Core +{ + internal static class XmlWriterExtensions + { + public static void WriteObjectValue(this XmlWriter writer, object value, string? nameHint) + { + switch (value) + { + case IXmlSerializable serializable: + serializable.Write(writer, nameHint); + return; + default: + throw new NotImplementedException(); + } + } + + public static void WriteValue(this XmlWriter writer, DateTimeOffset value, string format) => + writer.WriteValue(TypeFormatters.ToString(value, format)); + + public static void WriteValue(this XmlWriter writer, TimeSpan value, string format) => + writer.WriteValue(TypeFormatters.ToString(value, format)); + + public static void WriteValue(this XmlWriter writer, byte[] value, string format) + { + switch (format) + { + case "U": + writer.WriteValue(TypeFormatters.ToBase64UrlString(value)); + break; + default: + throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)); + } + } + } +} From 0ed58eee7d340c15310fa936278f8bcf258810c6 Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 13:13:39 -0700 Subject: [PATCH 3/9] Regeneration after version update. --- .../src/Generated/Operations/ServiceClient.cs | 1 + .../src/Generated/Operations/ServiceRestClient.cs | 4 +++- .../src/Generated/Operations/DataSourcesClient.cs | 1 + .../src/Generated/Operations/DocumentsClient.cs | 1 + .../src/Generated/Operations/IndexersClient.cs | 1 + .../src/Generated/Operations/IndexesClient.cs | 1 + .../src/Generated/Operations/ServiceClient.cs | 1 + .../src/Generated/Operations/SkillsetsClient.cs | 1 + .../src/Generated/Operations/SynonymMapsClient.cs | 1 + .../src/Generated/Operations/ServiceClient.cs | 1 + .../src/Generated/Operations/TableInternalClient.cs | 1 + .../src/Generated/Operations/MiniSecretClient.cs | 1 + 12 files changed, 14 insertions(+), 1 deletion(-) diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/src/Generated/Operations/ServiceClient.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/src/Generated/Operations/ServiceClient.cs index aa42ab8781cf..af2c390156f1 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/src/Generated/Operations/ServiceClient.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/src/Generated/Operations/ServiceClient.cs @@ -17,6 +17,7 @@ namespace Azure.AI.FormRecognizer { + /// The Service service client. internal partial class ServiceClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/src/Generated/Operations/ServiceRestClient.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/src/Generated/Operations/ServiceRestClient.cs index aef302eae78a..eccd94f9ada0 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/src/Generated/Operations/ServiceRestClient.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/src/Generated/Operations/ServiceRestClient.cs @@ -1233,7 +1233,9 @@ internal HttpMessage CreateListCustomModelsNextPageRequest(string nextLink) var request = message.Request; request.Method = RequestMethod.Get; var uri = new RawRequestUriBuilder(); - uri.AppendRaw(nextLink, false); + uri.AppendRaw(endpoint, false); + uri.AppendRaw("/formrecognizer/v2.0-preview", false); + uri.AppendRawNextLink(nextLink, false); request.Uri = uri; return message; } diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Operations/DataSourcesClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/Operations/DataSourcesClient.cs index 1e21f9350344..ac093e4e4536 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Operations/DataSourcesClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Operations/DataSourcesClient.cs @@ -14,6 +14,7 @@ namespace Azure.Search.Documents { + /// The DataSources service client. internal partial class DataSourcesClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Operations/DocumentsClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/Operations/DocumentsClient.cs index a24239866970..97a1df9e2db2 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Operations/DocumentsClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Operations/DocumentsClient.cs @@ -15,6 +15,7 @@ namespace Azure.Search.Documents { + /// The Documents service client. internal partial class DocumentsClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Operations/IndexersClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/Operations/IndexersClient.cs index 8672830714cf..3f32747df335 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Operations/IndexersClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Operations/IndexersClient.cs @@ -14,6 +14,7 @@ namespace Azure.Search.Documents { + /// The Indexers service client. internal partial class IndexersClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Operations/IndexesClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/Operations/IndexesClient.cs index 35108ffbf327..c597d99bdf88 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Operations/IndexesClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Operations/IndexesClient.cs @@ -14,6 +14,7 @@ namespace Azure.Search.Documents { + /// The Indexes service client. internal partial class IndexesClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Operations/ServiceClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/Operations/ServiceClient.cs index 28f612c587a7..d78e6f4cbdb1 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Operations/ServiceClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Operations/ServiceClient.cs @@ -14,6 +14,7 @@ namespace Azure.Search.Documents { + /// The Service service client. internal partial class ServiceClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Operations/SkillsetsClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/Operations/SkillsetsClient.cs index 5809103494d8..06f23e4d043d 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Operations/SkillsetsClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Operations/SkillsetsClient.cs @@ -14,6 +14,7 @@ namespace Azure.Search.Documents { + /// The Skillsets service client. internal partial class SkillsetsClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/search/Azure.Search.Documents/src/Generated/Operations/SynonymMapsClient.cs b/sdk/search/Azure.Search.Documents/src/Generated/Operations/SynonymMapsClient.cs index ca9a8c02dde6..817302f06dc4 100644 --- a/sdk/search/Azure.Search.Documents/src/Generated/Operations/SynonymMapsClient.cs +++ b/sdk/search/Azure.Search.Documents/src/Generated/Operations/SynonymMapsClient.cs @@ -14,6 +14,7 @@ namespace Azure.Search.Documents { + /// The SynonymMaps service client. internal partial class SynonymMapsClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/tables/Azure.Data.Tables/src/Generated/Operations/ServiceClient.cs b/sdk/tables/Azure.Data.Tables/src/Generated/Operations/ServiceClient.cs index c33a599dae22..2569937d3772 100644 --- a/sdk/tables/Azure.Data.Tables/src/Generated/Operations/ServiceClient.cs +++ b/sdk/tables/Azure.Data.Tables/src/Generated/Operations/ServiceClient.cs @@ -13,6 +13,7 @@ namespace Azure.Data.Tables { + /// The Service service client. internal partial class ServiceClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/tables/Azure.Data.Tables/src/Generated/Operations/TableInternalClient.cs b/sdk/tables/Azure.Data.Tables/src/Generated/Operations/TableInternalClient.cs index 0c96d5f5853c..659fb60f70ea 100644 --- a/sdk/tables/Azure.Data.Tables/src/Generated/Operations/TableInternalClient.cs +++ b/sdk/tables/Azure.Data.Tables/src/Generated/Operations/TableInternalClient.cs @@ -14,6 +14,7 @@ namespace Azure.Data.Tables { + /// The Table service client. internal partial class TableInternalClient { private readonly ClientDiagnostics _clientDiagnostics; diff --git a/sdk/template/Azure.Template/src/Generated/Operations/MiniSecretClient.cs b/sdk/template/Azure.Template/src/Generated/Operations/MiniSecretClient.cs index 716ab1e3f758..80cd32a08820 100644 --- a/sdk/template/Azure.Template/src/Generated/Operations/MiniSecretClient.cs +++ b/sdk/template/Azure.Template/src/Generated/Operations/MiniSecretClient.cs @@ -13,6 +13,7 @@ namespace Azure.Template { + /// The Service service client. public partial class MiniSecretClient { private readonly ClientDiagnostics _clientDiagnostics; From 3211370ce835577ec34e1d34bcec7326e26fda86 Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 13:26:49 -0700 Subject: [PATCH 4/9] Copied wrong version of the file. --- .../Shared/AutoRest/RawRequestUriBuilder.cs | 88 ++++++++++++++++--- 1 file changed, 75 insertions(+), 13 deletions(-) diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/RawRequestUriBuilder.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/RawRequestUriBuilder.cs index 0c800decc945..14dd07e14773 100644 --- a/sdk/core/Azure.Core/src/Shared/AutoRest/RawRequestUriBuilder.cs +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/RawRequestUriBuilder.cs @@ -13,10 +13,23 @@ internal class RawRequestUriBuilder: RequestUriBuilder private const string SchemeSeparator = "://"; private const char HostSeparator = '/'; private const char PortSeparator = ':'; - private static readonly char[] HostOrPort = new[] {HostSeparator, PortSeparator}; + private static readonly char[] HostOrPort = { HostSeparator, PortSeparator }; + private const char QueryBeginSeparator = '?'; + private const char QueryContinueSeparator = '&'; + private const char QueryValueSeparator = '='; private RawWritingPosition _position = RawWritingPosition.Scheme; + private static (string Name, string Value) GetQueryParts(string queryUnparsed) + { + int separatorIndex = queryUnparsed.IndexOf(QueryValueSeparator); + if (separatorIndex == -1) + { + return (queryUnparsed, string.Empty); + } + return (queryUnparsed.Substring(0, separatorIndex), queryUnparsed.Substring(separatorIndex + 1)); + } + public void AppendRaw(string value, bool escape) { while (!string.IsNullOrWhiteSpace(value)) @@ -32,10 +45,8 @@ public void AppendRaw(string value, bool escape) else { Scheme += value.Substring(0, separator); - // TODO: Find a better way to map schemes to default ports Port = string.Equals(Scheme, "https", StringComparison.OrdinalIgnoreCase) ? 443 : 80; - value = value.Substring(separator + SchemeSeparator.Length); _position = RawWritingPosition.Host; } @@ -45,15 +56,22 @@ public void AppendRaw(string value, bool escape) int separator = value.IndexOfAny(HostOrPort); if (separator == -1) { - Host += value; - value = string.Empty; + if (string.IsNullOrEmpty(Path)) + { + Host += value; + value = string.Empty; + } + else + { + // All Host information must be written before Path information + // If Path already has information, we transition to writing Path + _position = RawWritingPosition.Path; + } } else { Host += value.Substring(0, separator); - - _position = value[separator] == HostSeparator ? RawWritingPosition.Rest : RawWritingPosition.Port; - + _position = value[separator] == HostSeparator ? RawWritingPosition.Path : RawWritingPosition.Port; value = value.Substring(separator + 1); } } @@ -69,13 +87,44 @@ public void AppendRaw(string value, bool escape) { Port = int.Parse(value.Substring(0, separator), CultureInfo.InvariantCulture); value = value.Substring(separator + 1); - _position = RawWritingPosition.Rest; } + // Port cannot be split (like Host), so always transition to Path when Port is parsed + _position = RawWritingPosition.Path; } - else + else if (_position == RawWritingPosition.Path) { - AppendPath(value, escape); - value = string.Empty; + int separator = value.IndexOf(QueryBeginSeparator); + if (separator == -1) + { + AppendPath(value, escape); + value = string.Empty; + } + else + { + AppendPath(value.Substring(0, separator), escape); + value = value.Substring(separator + 1); + _position = RawWritingPosition.Query; + } + } + else if (_position == RawWritingPosition.Query) + { + int separator = value.IndexOf(QueryContinueSeparator); + if (separator == 0) + { + value = value.Substring(1); + } + else if (separator == -1) + { + (string queryName, string queryValue) = GetQueryParts(value); + AppendQuery(queryName, queryValue, escape); + value = string.Empty; + } + else + { + (string queryName, string queryValue) = GetQueryParts(value.Substring(0, separator)); + AppendQuery(queryName, queryValue, escape); + value = value.Substring(separator + 1); + } } } } @@ -85,7 +134,20 @@ private enum RawWritingPosition Scheme, Host, Port, - Rest + Path, + Query + } + + public void AppendRawNextLink(string nextLink, bool escape) + { + // If it is an absolute link, we use the nextLink as the entire url + if (nextLink.StartsWith(Uri.UriSchemeHttp, StringComparison.InvariantCultureIgnoreCase)) + { + Reset(new Uri(nextLink)); + return; + } + + AppendPath(nextLink, escape); } } } From 8d5dbb33a6dd79d8b09c407f2fa8aadc890d054d Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 14:40:07 -0700 Subject: [PATCH 5/9] Update generator version and add string request fix. --- eng/CodeGeneration.targets | 2 +- sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/CodeGeneration.targets b/eng/CodeGeneration.targets index 937b473ff992..0749a6f76eb3 100644 --- a/eng/CodeGeneration.targets +++ b/eng/CodeGeneration.targets @@ -3,7 +3,7 @@ <_AutoRestVersion>https://github.com/Azure/autorest/releases/download/autorest-3.0.6222/autorest-3.0.6222.tgz <_AutoRestCoreVersion>3.0.6282 - <_AutoRestCSharpVersion>https://github.com/Azure/autorest.csharp/releases/download/3.0.0-dev.20200427.1/autorest-csharp-v3-3.0.0-dev.20200427.1.tgz + <_AutoRestCSharpVersion>https://github.com/Azure/autorest.csharp/releases/download/3.0.0-dev.20200427.3/autorest-csharp-v3-3.0.0-dev.20200427.3.tgz <_SupportsCodeGeneration Condition="'$(IsClientLibrary)' == 'true'">true <_DefaultInputName Condition="Exists('$(MSBuildProjectDirectory)/autorest.md')">$(MSBuildProjectDirectory)/autorest.md $(_DefaultInputName) diff --git a/sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs b/sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs index b5d98e9b5c08..8d1bcf33bd9e 100644 --- a/sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs +++ b/sdk/core/Azure.Core/src/Shared/AutoRest/StringRequestContent.cs @@ -19,7 +19,7 @@ public StringRequestContent(string value) public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) { - await stream.WriteAsync(_bytes, 0, _bytes.Length, cancellation); + await stream.WriteAsync(_bytes, 0, _bytes.Length, cancellation).ConfigureAwait(false); } public override void WriteTo(Stream stream, CancellationToken cancellation) From 16414778b1ce69184daf62cc694b7bd5aa04b73d Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 14:51:03 -0700 Subject: [PATCH 6/9] Fix path folder casing. --- eng/CodeGeneration.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/CodeGeneration.targets b/eng/CodeGeneration.targets index 0749a6f76eb3..57c209cc9bad 100644 --- a/eng/CodeGeneration.targets +++ b/eng/CodeGeneration.targets @@ -13,7 +13,7 @@ --> <_SharedCodeDirectory>$(MSBuildThisFileDirectory)../sdk/core/Azure.Core/src/Shared/ - <_AutoRestSharedCodeDirectory>$(_SharedCodeDirectory)Autorest/ + <_AutoRestSharedCodeDirectory>$(_SharedCodeDirectory)AutoRest/ <_GenerateCode Condition="'$(_SupportsCodeGeneration)' == 'true' AND '$(AutorestInput)' != ''">true true From 0bbb977423477b2dee80d45761b9536a7a58ac69 Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 14:53:20 -0700 Subject: [PATCH 7/9] Fix casing. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c6fbf341cf3e..1ad48b39636d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -260,7 +260,7 @@ input-file: require: https://github.com/Azure/azure-rest-api-specs/blob/49fc16354df7211f8392c56884a3437138317d1f/specification/azsadmin/resource-manager/storage/readme.md ``` -3. Run `dotnet msbuild /t:GenerateCode` in src directory of the project (e.g. `net\sdk\storage\Azure.Management.Storage\src`). This would run Autorest and generate the code. (NOTE: this step requires Node 13). +3. Run `dotnet msbuild /t:GenerateCode` in src directory of the project (e.g. `net\sdk\storage\Azure.Management.Storage\src`). This would run AutoRest and generate the code. (NOTE: this step requires Node 13). 4. For management plan libraries add `azure-arm: true` setting to `autorest.md` client constructors and options would be auto-generated. For data-plane libraries follow the next two steps. 4. Add a `*ClientOptions` type that inherits from `ClientOptions` and has a service version enum: From 78e5880fcfeeaf92f30a0f44a100da3cf553f331 Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 14:55:36 -0700 Subject: [PATCH 8/9] More casing. --- eng/CodeGeneration.targets | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eng/CodeGeneration.targets b/eng/CodeGeneration.targets index 57c209cc9bad..55c9695c0210 100644 --- a/eng/CodeGeneration.targets +++ b/eng/CodeGeneration.targets @@ -6,22 +6,22 @@ <_AutoRestCSharpVersion>https://github.com/Azure/autorest.csharp/releases/download/3.0.0-dev.20200427.3/autorest-csharp-v3-3.0.0-dev.20200427.3.tgz <_SupportsCodeGeneration Condition="'$(IsClientLibrary)' == 'true'">true <_DefaultInputName Condition="Exists('$(MSBuildProjectDirectory)/autorest.md')">$(MSBuildProjectDirectory)/autorest.md - $(_DefaultInputName) + $(_DefaultInputName) - + <_SharedCodeDirectory>$(MSBuildThisFileDirectory)../sdk/core/Azure.Core/src/Shared/ <_AutoRestSharedCodeDirectory>$(_SharedCodeDirectory)AutoRest/ - <_GenerateCode Condition="'$(_SupportsCodeGeneration)' == 'true' AND '$(AutorestInput)' != ''">true + <_GenerateCode Condition="'$(_SupportsCodeGeneration)' == 'true' AND '$(AutoRestInput)' != ''">true true - + From f2a614529b8e99615ce3e255a45b3125bbba47ba Mon Sep 17 00:00:00 2001 From: Michael Yanni Date: Mon, 27 Apr 2020 14:57:36 -0700 Subject: [PATCH 9/9] Last of casing. Now, it is fixed for the repo. --- sdk/storage/Azure.Storage.Common/swagger/Generator/readme.md | 2 +- tools/Repo-Tasks.psm1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/storage/Azure.Storage.Common/swagger/Generator/readme.md b/sdk/storage/Azure.Storage.Common/swagger/Generator/readme.md index cc05a8a7d76d..8d0f6c9aeba0 100644 --- a/sdk/storage/Azure.Storage.Common/swagger/Generator/readme.md +++ b/sdk/storage/Azure.Storage.Common/swagger/Generator/readme.md @@ -17,7 +17,7 @@ We support a number of extensions including using the vendor prefix `x-az-`: - `x-az-nullable-array`: Allows list to be null. The default value is `false`. - `x-az-internal`: x-ms-external is only allowed on definitions so this does the same for parameters, etc. -### Autorest plugin configuration +### AutoRest plugin configuration The AutoRest example at https://github.com/Azure/autorest-extension-helloworld walks through the following section and the docs at http://azure.github.io/autorest/user/literate-file-formats/configuration.html diff --git a/tools/Repo-Tasks.psm1 b/tools/Repo-Tasks.psm1 index edc69d039264..8b165b37151a 100644 --- a/tools/Repo-Tasks.psm1 +++ b/tools/Repo-Tasks.psm1 @@ -350,7 +350,7 @@ Function Install-VSProjectTemplates .SYNOPSIS Install-VSProjectTemplates will install getting started project templates for -1) Autorest-.NET SDKProject +1) AutoRest-.NET SDKProject 2) .NET SDK Test projectct After executing the cmdlet, restart VS (if already open), create new project