/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ namespace Microsoft.Rest.ClientRuntime { using System.Linq; using System; internal static partial class Extensions { public static T[] SubArray(this T[] array, int offset, int length) { return new ArraySegment(array, offset, length) .ToArray(); } public static T ReadHeaders(this T instance, global::System.Net.Http.Headers.HttpResponseHeaders headers) where T : class { (instance as IHeaderSerializable)?.ReadHeaders(headers); return instance; } internal static bool If(T input, out T output) { if (null == input) { output = default(T); return false; } output = input; return true; } internal static void AddIf(T value, System.Action addMethod) { // if value is present (and it's not just an empty JSON Object) if (null != value && (value as Carbon.Json.JsonObject)?.Keys.Count != 0) { addMethod(value); } } internal static void AddIf(T value, string serializedName, System.Action addMethod) { // if value is present (and it's not just an empty JSON Object) if (null != value && (value as Carbon.Json.JsonObject)?.Keys.Count != 0) { addMethod(serializedName, value); } } /// /// Returns the first header value as a string from an HttpReponseMessage. /// /// the HttpResponseMessage to fetch a header from /// the header name /// the first header value as a string from an HttpReponseMessage. string.empty if there is no header value matching internal static string GetFirstHeader(this System.Net.Http.HttpResponseMessage response, string headerName) => response.Headers.FirstOrDefault(each => string.Equals(headerName, each.Key, System.StringComparison.OrdinalIgnoreCase)).Value?.FirstOrDefault() ?? string.Empty; /// /// Sets the Synchronization Context to null, and returns an IDisposable that when disposed, /// will restore the synchonization context to the original value. /// /// This is used a less-invasive means to ensure that code in the library that doesn't /// need to be continued in the original context doesn't have to have ConfigureAwait(false) /// on every single await /// /// If the SynchronizationContext is null when this is used, the resulting IDisposable /// will not do anything (this prevents excessive re-setting of the SynchronizationContext) /// /// Usage: /// /// using(NoSynchronizationContext) { /// await SomeAsyncOperation(); /// await SomeOtherOperation(); /// } /// /// /// /// An IDisposable that will return the SynchronizationContext to original state internal static System.IDisposable NoSynchronizationContext => System.Threading.SynchronizationContext.Current == null ? Dummy : new NoSyncContext(); /// /// An instance of the Dummy IDispoable. /// /// internal static System.IDisposable Dummy = new DummyDisposable(); /// /// An IDisposable that does absolutely nothing. /// internal class DummyDisposable : System.IDisposable { public void Dispose() { } } /// /// An IDisposable that saves the SynchronizationContext,sets it to null and /// restores it to the original upon Dispose(). /// /// NOTE: This is designed to be less invasive than using .ConfigureAwait(false) /// on every single await in library code (ie, places where we know we don't need /// to continue in the same context as we went async) /// internal class NoSyncContext : System.IDisposable { private System.Threading.SynchronizationContext original = System.Threading.SynchronizationContext.Current; internal NoSyncContext() { System.Threading.SynchronizationContext.SetSynchronizationContext(null); } public void Dispose() => System.Threading.SynchronizationContext.SetSynchronizationContext(original); } } }