Skip to content

Commit f7b338c

Browse files
feat: add async APIs for ToonEncoder and ToonDecoder (#19)
1 parent baa7cac commit f7b338c

File tree

3 files changed

+479
-0
lines changed

3 files changed

+479
-0
lines changed

src/ToonFormat/ToonDecoder.cs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using System.Text;
55
using System.Text.Json;
66
using System.Text.Json.Nodes;
7+
using System.Threading;
8+
using System.Threading.Tasks;
79
using ToonFormat;
810
using ToonFormat.Internal.Decode;
911

@@ -194,4 +196,124 @@ public static class ToonDecoder
194196
var text = reader.ReadToEnd();
195197
return Decode<T>(text, options ?? new ToonDecodeOptions());
196198
}
199+
200+
#region Async Methods
201+
202+
/// <summary>
203+
/// Asynchronously decodes a TOON-formatted string into a JsonNode with default options.
204+
/// </summary>
205+
/// <param name="toonString">The TOON-formatted string to decode.</param>
206+
/// <param name="cancellationToken">A token to cancel the operation.</param>
207+
/// <returns>A task that represents the asynchronous operation. The task result contains the decoded JsonNode.</returns>
208+
/// <exception cref="ArgumentNullException">Thrown when toonString is null.</exception>
209+
/// <exception cref="ToonFormatException">Thrown when the TOON format is invalid.</exception>
210+
public static Task<JsonNode?> DecodeAsync(string toonString, CancellationToken cancellationToken = default)
211+
{
212+
return DecodeAsync(toonString, new ToonDecodeOptions(), cancellationToken);
213+
}
214+
215+
/// <summary>
216+
/// Asynchronously decodes a TOON-formatted string into a JsonNode with custom options.
217+
/// </summary>
218+
/// <param name="toonString">The TOON-formatted string to decode.</param>
219+
/// <param name="options">Decoding options to customize parsing behavior.</param>
220+
/// <param name="cancellationToken">A token to cancel the operation.</param>
221+
/// <returns>A task that represents the asynchronous operation. The task result contains the decoded JsonNode.</returns>
222+
/// <exception cref="ArgumentNullException">Thrown when toonString or options is null.</exception>
223+
/// <exception cref="ToonFormatException">Thrown when the TOON format is invalid.</exception>
224+
public static Task<JsonNode?> DecodeAsync(string toonString, ToonDecodeOptions? options, CancellationToken cancellationToken = default)
225+
{
226+
cancellationToken.ThrowIfCancellationRequested();
227+
var result = Decode(toonString, options);
228+
return Task.FromResult(result);
229+
}
230+
231+
/// <summary>
232+
/// Asynchronously decodes a TOON-formatted string into the specified type with default options.
233+
/// </summary>
234+
/// <typeparam name="T">Target type to deserialize into.</typeparam>
235+
/// <param name="toonString">The TOON-formatted string to decode.</param>
236+
/// <param name="cancellationToken">A token to cancel the operation.</param>
237+
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized value.</returns>
238+
public static Task<T?> DecodeAsync<T>(string toonString, CancellationToken cancellationToken = default)
239+
{
240+
return DecodeAsync<T>(toonString, new ToonDecodeOptions(), cancellationToken);
241+
}
242+
243+
/// <summary>
244+
/// Asynchronously decodes a TOON-formatted string into the specified type with custom options.
245+
/// </summary>
246+
/// <typeparam name="T">Target type to deserialize into.</typeparam>
247+
/// <param name="toonString">The TOON-formatted string to decode.</param>
248+
/// <param name="options">Decoding options to customize parsing behavior.</param>
249+
/// <param name="cancellationToken">A token to cancel the operation.</param>
250+
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized value.</returns>
251+
public static Task<T?> DecodeAsync<T>(string toonString, ToonDecodeOptions? options, CancellationToken cancellationToken = default)
252+
{
253+
cancellationToken.ThrowIfCancellationRequested();
254+
var result = Decode<T>(toonString, options);
255+
return Task.FromResult(result);
256+
}
257+
258+
/// <summary>
259+
/// Asynchronously decodes TOON data from a stream (UTF-8) into a JsonNode with default options.
260+
/// </summary>
261+
/// <param name="stream">The input stream to read from.</param>
262+
/// <param name="cancellationToken">A token to cancel the operation.</param>
263+
/// <returns>A task that represents the asynchronous operation. The task result contains the decoded JsonNode.</returns>
264+
public static Task<JsonNode?> DecodeAsync(Stream stream, CancellationToken cancellationToken = default)
265+
{
266+
return DecodeAsync(stream, new ToonDecodeOptions(), cancellationToken);
267+
}
268+
269+
/// <summary>
270+
/// Asynchronously decodes TOON data from a stream (UTF-8) into a JsonNode with custom options.
271+
/// </summary>
272+
/// <param name="stream">The input stream to read from.</param>
273+
/// <param name="options">Decoding options to customize parsing behavior.</param>
274+
/// <param name="cancellationToken">A token to cancel the operation.</param>
275+
/// <returns>A task that represents the asynchronous operation. The task result contains the decoded JsonNode.</returns>
276+
/// <exception cref="ArgumentNullException">Thrown when stream is null.</exception>
277+
public static async Task<JsonNode?> DecodeAsync(Stream stream, ToonDecodeOptions? options, CancellationToken cancellationToken = default)
278+
{
279+
if (stream == null)
280+
throw new ArgumentNullException(nameof(stream));
281+
282+
using var reader = new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, leaveOpen: true);
283+
var text = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
284+
return Decode(text, options ?? new ToonDecodeOptions());
285+
}
286+
287+
/// <summary>
288+
/// Asynchronously decodes TOON data from a stream (UTF-8) into the specified type with default options.
289+
/// </summary>
290+
/// <typeparam name="T">Target type to deserialize into.</typeparam>
291+
/// <param name="stream">The input stream to read from.</param>
292+
/// <param name="cancellationToken">A token to cancel the operation.</param>
293+
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized value.</returns>
294+
public static Task<T?> DecodeAsync<T>(Stream stream, CancellationToken cancellationToken = default)
295+
{
296+
return DecodeAsync<T>(stream, new ToonDecodeOptions(), cancellationToken);
297+
}
298+
299+
/// <summary>
300+
/// Asynchronously decodes TOON data from a stream (UTF-8) into the specified type with custom options.
301+
/// </summary>
302+
/// <typeparam name="T">Target type to deserialize into.</typeparam>
303+
/// <param name="stream">The input stream to read from.</param>
304+
/// <param name="options">Decoding options to customize parsing behavior.</param>
305+
/// <param name="cancellationToken">A token to cancel the operation.</param>
306+
/// <returns>A task that represents the asynchronous operation. The task result contains the deserialized value.</returns>
307+
/// <exception cref="ArgumentNullException">Thrown when stream is null.</exception>
308+
public static async Task<T?> DecodeAsync<T>(Stream stream, ToonDecodeOptions? options, CancellationToken cancellationToken = default)
309+
{
310+
if (stream == null)
311+
throw new ArgumentNullException(nameof(stream));
312+
313+
using var reader = new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, leaveOpen: true);
314+
var text = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
315+
return Decode<T>(text, options ?? new ToonDecodeOptions());
316+
}
317+
318+
#endregion
197319
}

src/ToonFormat/ToonEncoder.cs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.ComponentModel;
44
using System.IO;
55
using System.Text;
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using ToonFormat;
79
using ToonFormat.Internal.Encode;
810

@@ -192,4 +194,97 @@ public static void EncodeToStream<T>(T data, Stream destination, ToonEncodeOptio
192194
var bytes = EncodeToBytes(data, options);
193195
destination.Write(bytes, 0, bytes.Length);
194196
}
197+
198+
#region Async Methods
199+
200+
/// <summary>
201+
/// Asynchronously encodes the specified value into TOON format with default options.
202+
/// </summary>
203+
/// <typeparam name="T">Type of the value to encode.</typeparam>
204+
/// <param name="data">The value to encode.</param>
205+
/// <param name="cancellationToken">A token to cancel the operation.</param>
206+
/// <returns>A task that represents the asynchronous operation. The task result contains the TOON-formatted string.</returns>
207+
public static Task<string> EncodeAsync<T>(T data, CancellationToken cancellationToken = default)
208+
{
209+
return EncodeAsync(data, new ToonEncodeOptions(), cancellationToken);
210+
}
211+
212+
/// <summary>
213+
/// Asynchronously encodes the specified value into TOON format with custom options.
214+
/// </summary>
215+
/// <typeparam name="T">Type of the value to encode.</typeparam>
216+
/// <param name="data">The value to encode.</param>
217+
/// <param name="options">Encoding options to customize the output format.</param>
218+
/// <param name="cancellationToken">A token to cancel the operation.</param>
219+
/// <returns>A task that represents the asynchronous operation. The task result contains the TOON-formatted string.</returns>
220+
/// <exception cref="ArgumentNullException">Thrown when options is null.</exception>
221+
public static Task<string> EncodeAsync<T>(T data, ToonEncodeOptions? options, CancellationToken cancellationToken = default)
222+
{
223+
cancellationToken.ThrowIfCancellationRequested();
224+
var result = Encode(data, options);
225+
return Task.FromResult(result);
226+
}
227+
228+
/// <summary>
229+
/// Asynchronously encodes the specified value into UTF-8 bytes with default options.
230+
/// </summary>
231+
/// <typeparam name="T">Type of the value to encode.</typeparam>
232+
/// <param name="data">The value to encode.</param>
233+
/// <param name="cancellationToken">A token to cancel the operation.</param>
234+
/// <returns>A task that represents the asynchronous operation. The task result contains the UTF-8 encoded TOON bytes.</returns>
235+
public static Task<byte[]> EncodeToBytesAsync<T>(T data, CancellationToken cancellationToken = default)
236+
{
237+
return EncodeToBytesAsync(data, new ToonEncodeOptions(), cancellationToken);
238+
}
239+
240+
/// <summary>
241+
/// Asynchronously encodes the specified value into UTF-8 bytes with custom options.
242+
/// </summary>
243+
/// <typeparam name="T">Type of the value to encode.</typeparam>
244+
/// <param name="data">The value to encode.</param>
245+
/// <param name="options">Encoding options to customize the output format.</param>
246+
/// <param name="cancellationToken">A token to cancel the operation.</param>
247+
/// <returns>A task that represents the asynchronous operation. The task result contains the UTF-8 encoded TOON bytes.</returns>
248+
/// <exception cref="ArgumentNullException">Thrown when options is null.</exception>
249+
public static Task<byte[]> EncodeToBytesAsync<T>(T data, ToonEncodeOptions? options, CancellationToken cancellationToken = default)
250+
{
251+
cancellationToken.ThrowIfCancellationRequested();
252+
var result = EncodeToBytes(data, options);
253+
return Task.FromResult(result);
254+
}
255+
256+
/// <summary>
257+
/// Asynchronously encodes the specified value and writes UTF-8 bytes to the destination stream using default options.
258+
/// </summary>
259+
/// <typeparam name="T">Type of the value to encode.</typeparam>
260+
/// <param name="data">The value to encode.</param>
261+
/// <param name="destination">The destination stream to write to. The stream is not disposed.</param>
262+
/// <param name="cancellationToken">A token to cancel the operation.</param>
263+
/// <returns>A task that represents the asynchronous write operation.</returns>
264+
public static Task EncodeToStreamAsync<T>(T data, Stream destination, CancellationToken cancellationToken = default)
265+
{
266+
return EncodeToStreamAsync(data, destination, new ToonEncodeOptions(), cancellationToken);
267+
}
268+
269+
/// <summary>
270+
/// Asynchronously encodes the specified value and writes UTF-8 bytes to the destination stream using custom options.
271+
/// </summary>
272+
/// <typeparam name="T">Type of the value to encode.</typeparam>
273+
/// <param name="data">The value to encode.</param>
274+
/// <param name="destination">The destination stream to write to. The stream is not disposed.</param>
275+
/// <param name="options">Encoding options to customize the output format.</param>
276+
/// <param name="cancellationToken">A token to cancel the operation.</param>
277+
/// <returns>A task that represents the asynchronous write operation.</returns>
278+
/// <exception cref="ArgumentNullException">Thrown when destination or options is null.</exception>
279+
public static async Task EncodeToStreamAsync<T>(T data, Stream destination, ToonEncodeOptions? options, CancellationToken cancellationToken = default)
280+
{
281+
if (destination == null)
282+
throw new ArgumentNullException(nameof(destination));
283+
284+
cancellationToken.ThrowIfCancellationRequested();
285+
var bytes = EncodeToBytes(data, options);
286+
await destination.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false);
287+
}
288+
289+
#endregion
195290
}

0 commit comments

Comments
 (0)