// Copyright 2016-2019, Pulumi Corporation using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; namespace Pulumi { /// /// A list of values that can be passed in as the arguments to a . /// The individual values are themselves s. i.e. the individual values /// can be concrete values or s. /// /// differs from a normal in that it is itself /// an . For example, a that accepts an will accept not just a list but an /// of a list. This is important for cases where the /// list from some needs to be passed into another . Or for cases where creating the list invariably produces an because its resultant value is dependent on other s. /// /// This benefit of is also a limitation. Because it represents a /// list of values that may eventually be created, there is no way to simply iterate over, or /// access the elements of the list synchronously. /// /// is designed to be easily used in object and collection /// initializers. For example, a resource that accepts a list of inputs can be written in /// either of these forms: /// /// /// new SomeResource("name", new SomeResourceArgs { /// ListProperty = { Value1, Value2, Value3 }, /// }); /// /// /// or /// /// new SomeResource("name", new SomeResourceArgs { /// ListProperty = new [] { Value1, Value2, Value3 }, /// }); /// /// public sealed class InputList : Input>, IEnumerable, IAsyncEnumerable> { public InputList() : this(Output.Create(ImmutableArray.Empty)) { } private InputList(Output> values) : base(values) { } public void Add(params Input[] inputs) { // Make an Output from the values passed in, mix in with our own Output, and combine // both to produce the final array that we will now point at. _outputValue = Output.Concat(_outputValue, Output.All(inputs)); } /// /// Concatenates the values in this list with the values in , /// returning the concatenated sequence in a new . /// public InputList Concat(InputList other) => Output.Concat(_outputValue, other._outputValue); internal InputList Clone() => new InputList(_outputValue); #region construct from unary public static implicit operator InputList(T value) => ImmutableArray.Create>(value); public static implicit operator InputList(Output value) => ImmutableArray.Create>(value); public static implicit operator InputList(Input value) => ImmutableArray.Create(value); #endregion #region construct from array public static implicit operator InputList(T[] values) => ImmutableArray.CreateRange(values.Select(v => (Input)v)); public static implicit operator InputList(Output[] values) => ImmutableArray.CreateRange(values.Select(v => (Input)v)); public static implicit operator InputList(Input[] values) => ImmutableArray.CreateRange(values); #endregion #region construct from list public static implicit operator InputList(List values) => ImmutableArray.CreateRange(values); public static implicit operator InputList(List> values) => ImmutableArray.CreateRange(values); public static implicit operator InputList(List> values) => ImmutableArray.CreateRange(values); #endregion #region construct from immutable array public static implicit operator InputList(ImmutableArray values) => values.SelectAsArray(v => (Input)v); public static implicit operator InputList(ImmutableArray> values) => values.SelectAsArray(v => (Input)v); public static implicit operator InputList(ImmutableArray> values) => Output.All(values); #endregion #region construct from Output of some list type. public static implicit operator InputList(Output values) => values.Apply(a => ImmutableArray.CreateRange(a)); public static implicit operator InputList(Output> values) => values.Apply(a => ImmutableArray.CreateRange(a)); public static implicit operator InputList(Output> values) => values.Apply(a => ImmutableArray.CreateRange(a)); public static implicit operator InputList(Output> values) => new InputList(values); #endregion #region IEnumerable IEnumerator IEnumerable.GetEnumerator() => throw new NotSupportedException($"A {GetType().FullName} cannot be synchronously enumerated. Use {nameof(GetAsyncEnumerator)} instead."); public async IAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken) { var data = await _outputValue.GetValueAsync().ConfigureAwait(false); foreach (var value in data) { yield return value; } } #endregion } }