-
Notifications
You must be signed in to change notification settings - Fork 334
Add support for array encoding with @encode(ArrayEncoding.*) decorator #9430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b4f5cd7
ccef568
3486047
25e823a
7958158
5227fce
175f199
b39a7f4
699978e
d0909f3
17ae707
339819f
9cb6c4c
6606677
fbbfaf5
4be7888
b2757da
434bb4a
1e737ab
4013b4a
1ca3af7
759da07
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
|
|
||
| namespace Microsoft.TypeSpec.Generator.Input.Extensions | ||
| { | ||
| public static class ArrayKnownEncodingExtensions | ||
| { | ||
| /// <summary> | ||
| /// Converts a string representation to ArrayKnownEncoding. | ||
| /// </summary> | ||
| public static bool TryParse(string? value, out ArrayKnownEncoding encoding) | ||
| { | ||
| encoding = default; | ||
| if (value == null) return false; | ||
|
|
||
| return value switch | ||
| { | ||
| "ArrayEncoding.commaDelimited" or "commaDelimited" => | ||
| SetEncodingAndReturnTrue(out encoding, ArrayKnownEncoding.CommaDelimited), | ||
| "ArrayEncoding.spaceDelimited" or "spaceDelimited" => | ||
| SetEncodingAndReturnTrue(out encoding, ArrayKnownEncoding.SpaceDelimited), | ||
| "ArrayEncoding.pipeDelimited" or "pipeDelimited" => | ||
| SetEncodingAndReturnTrue(out encoding, ArrayKnownEncoding.PipeDelimited), | ||
| "ArrayEncoding.newlineDelimited" or "newlineDelimited" => | ||
| SetEncodingAndReturnTrue(out encoding, ArrayKnownEncoding.NewlineDelimited), | ||
| _ => false | ||
| }; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Converts ArrayKnownEncoding to SerializationFormat. | ||
| /// </summary> | ||
| public static SerializationFormat ToSerializationFormat(this ArrayKnownEncoding encoding) | ||
| { | ||
| return encoding switch | ||
| { | ||
| ArrayKnownEncoding.CommaDelimited => SerializationFormat.Array_CommaDelimited, | ||
| ArrayKnownEncoding.SpaceDelimited => SerializationFormat.Array_SpaceDelimited, | ||
| ArrayKnownEncoding.PipeDelimited => SerializationFormat.Array_PipeDelimited, | ||
| ArrayKnownEncoding.NewlineDelimited => SerializationFormat.Array_NewlineDelimited, | ||
| _ => throw new ArgumentOutOfRangeException(nameof(encoding), encoding, "Unknown array encoding") | ||
| }; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets the delimiter string for array serialization format. | ||
| /// </summary> | ||
| public static string GetDelimiter(SerializationFormat format) | ||
| { | ||
| return format switch | ||
| { | ||
| SerializationFormat.Array_CommaDelimited => ",", | ||
| SerializationFormat.Array_SpaceDelimited => " ", | ||
| SerializationFormat.Array_PipeDelimited => "|", | ||
| SerializationFormat.Array_NewlineDelimited => "\n", | ||
| _ => throw new ArgumentOutOfRangeException(nameof(format), format, "Unsupported array serialization format") | ||
| }; | ||
| } | ||
|
|
||
| private static bool SetEncodingAndReturnTrue(out ArrayKnownEncoding encoding, ArrayKnownEncoding value) | ||
| { | ||
| encoding = value; | ||
| return true; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| namespace Microsoft.TypeSpec.Generator.Input | ||
| { | ||
| /// <summary> | ||
| /// Represents the known encoding formats for arrays. | ||
| /// </summary> | ||
| public enum ArrayKnownEncoding | ||
| { | ||
| /// <summary> | ||
| /// Comma-delimited array encoding | ||
| /// </summary> | ||
| CommaDelimited, | ||
|
|
||
| /// <summary> | ||
| /// Space-delimited array encoding | ||
| /// </summary> | ||
| SpaceDelimited, | ||
|
|
||
| /// <summary> | ||
| /// Pipe-delimited array encoding | ||
| /// </summary> | ||
| PipeDelimited, | ||
|
|
||
| /// <summary> | ||
| /// Newline-delimited array encoding | ||
| /// </summary> | ||
| NewlineDelimited | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using Microsoft.TypeSpec.Generator.Input.Extensions; | ||
|
|
||
| namespace Microsoft.TypeSpec.Generator.Input | ||
| { | ||
| public class InputModelProperty : InputProperty | ||
|
|
@@ -18,7 +20,8 @@ public InputModelProperty( | |
| bool isHttpMetadata, | ||
| bool isApiVersion, | ||
| InputConstant? defaultValue, | ||
| InputSerializationOptions serializationOptions) | ||
| InputSerializationOptions serializationOptions, | ||
| string? encode = null) | ||
| : base(name, summary, doc, type, isRequired, isReadOnly, access, serializedName, isApiVersion, defaultValue) | ||
| { | ||
| Name = name; | ||
|
|
@@ -30,11 +33,13 @@ public InputModelProperty( | |
| IsDiscriminator = isDiscriminator; | ||
| IsHttpMetadata = isHttpMetadata; | ||
| SerializationOptions = serializationOptions; | ||
| Encode = encode; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should follow the same pattern we use for other encoding formats. We can define a new ArrayKnownEncoding enum and add each of the possible values and then flow this through to a SerializationFormat. See https://github.com/microsoft/typespec/blob/main/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/TypeFactory.cs#L340
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @JoshLove-msft the factory method only accepts an InputType. Should we add a new overload for the factory method for public SerializationFormat GetSerializationFormat(InputProperty input) => input switch
{
InputModelProperty modelProperty => modelProperty.Encode switch
{
ArrayKnownEncoding.PipeDelimited => SerializationFormat.ArrayPipeDelimited,
},
_ => SerializationFormat.Default
};
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the current approach is okay since these encodings are handled in PropertyProvider and we shouldn't need it outside of that scope. That said, we still need to update to use an ArrayKnownEncoding enum instead of a string. |
||
| } | ||
|
|
||
| public bool IsDiscriminator { get; internal set; } | ||
| public InputSerializationOptions? SerializationOptions { get; internal set; } | ||
| public bool IsHttpMetadata { get; internal set; } | ||
| public string? Encode { get; internal set; } | ||
|
|
||
| /// <summary> | ||
| /// Updates the properties of the input model property. | ||
|
|
@@ -117,5 +122,14 @@ public void Update( | |
| SerializationOptions = serializationOptions; | ||
| } | ||
| } | ||
|
|
||
| public ArrayKnownEncoding? GetArrayEncoding() | ||
| { | ||
| if (ArrayKnownEncodingExtensions.TryParse(Encode, out var encoding)) | ||
| { | ||
| return encoding; | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
| using System.ClientModel; | ||
| using System.Collections.Generic; | ||
| using System.Threading.Tasks; | ||
| using Encode._Array; | ||
| using Encode._Array._Property; | ||
| using NUnit.Framework; | ||
|
|
||
| namespace TestProjects.Spector.Tests.Http.Encode.Array | ||
| { | ||
| public class EncodeArrayTests : SpectorTestBase | ||
| { | ||
| [SpectorTest] | ||
| public Task CommaDelimited() => Test(async (host) => | ||
| { | ||
| var testData = new List<string> { "blue", "red", "green" }; | ||
| var body = new CommaDelimitedArrayProperty(testData); | ||
|
|
||
| ClientResult<CommaDelimitedArrayProperty> result = await new ArrayClient(host, null).GetPropertyClient().CommaDelimitedAsync(body); | ||
| Assert.AreEqual(200, result.GetRawResponse().Status); | ||
| Assert.AreEqual(testData, result.Value.Value); | ||
| }); | ||
|
|
||
| [SpectorTest] | ||
| public Task SpaceDelimited() => Test(async (host) => | ||
| { | ||
| var testData = new List<string> { "blue", "red", "green" }; | ||
| var body = new SpaceDelimitedArrayProperty(testData); | ||
|
|
||
| ClientResult<SpaceDelimitedArrayProperty> result = await new ArrayClient(host, null).GetPropertyClient().SpaceDelimitedAsync(body); | ||
| Assert.AreEqual(200, result.GetRawResponse().Status); | ||
| Assert.AreEqual(testData, result.Value.Value); | ||
| }); | ||
|
|
||
| [SpectorTest] | ||
| public Task PipeDelimited() => Test(async (host) => | ||
| { | ||
| var testData = new List<string> { "blue", "red", "green" }; | ||
| var body = new PipeDelimitedArrayProperty(testData); | ||
|
|
||
| ClientResult<PipeDelimitedArrayProperty> result = await new ArrayClient(host, null).GetPropertyClient().PipeDelimitedAsync(body); | ||
| Assert.AreEqual(200, result.GetRawResponse().Status); | ||
| Assert.AreEqual(testData, result.Value.Value); | ||
| }); | ||
|
|
||
| [SpectorTest] | ||
| public Task NewlineDelimited() => Test(async (host) => | ||
| { | ||
| var testData = new List<string> { "blue", "red", "green" }; | ||
| var body = new NewlineDelimitedArrayProperty(testData); | ||
|
|
||
| ClientResult<NewlineDelimitedArrayProperty> result = await new ArrayClient(host, null).GetPropertyClient().NewlineDelimitedAsync(body); | ||
| Assert.AreEqual(200, result.GetRawResponse().Status); | ||
| Assert.AreEqual(testData, result.Value.Value); | ||
| }); | ||
|
|
||
|
|
||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what exactly is this testing? Also, any reason why we put this test in the ModelCustomizationTests suite?