Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion GitVersion.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
next-version: 1.1.5
next-version: 2.0.0
tag-prefix: '[vV]'
mode: ContinuousDeployment
branches:
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# <img src="https://github.com/CodeShayk/parsley.net/blob/master/Images/ninja-icon-16.png" alt="ninja" style="width:30px;"/> Parsley.Net v1.1.5
# <img src="https://github.com/CodeShayk/parsley.net/blob/master/Images/ninja-icon-16.png" alt="ninja" style="width:30px;"/> Parsley.Net v2.0.0
[![NuGet version](https://badge.fury.io/nu/Parsley.Net.svg)](https://badge.fury.io/nu/Parsley.Net) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/CodeShayk/Parsley.Net/blob/master/LICENSE.md)
[![GitHub Release](https://img.shields.io/github/v/release/CodeShayk/Parsley.Net?logo=github&sort=semver)](https://github.com/CodeShayk/Parsley.Net/releases/latest)
[![master-build](https://github.com/CodeShayk/parsley.net/actions/workflows/Master-Build.yml/badge.svg)](https://github.com/CodeShayk/parsley.net/actions/workflows/Master-Build.yml)
Expand Down Expand Up @@ -48,12 +48,13 @@ If you are having problems, please let me know by [raising a new issue](https://
This project is licensed with the [MIT license](LICENSE).

## Version History
The main branch is now on .NET 9.0.
| Version | Release Notes |
| -------- | --------|
| [`v1.0.0`](https://github.com/CodeShayk/parsley.net/tree/v1.0.0) | [Notes](https://github.com/CodeShayk/Parsley.Net/releases/tag/v1.0.0) |
| [`v1.1.0`](https://github.com/CodeShayk/parsley.net/tree/v1.1.0) | [Notes](https://github.com/CodeShayk/Parsley.Net/releases/tag/v1.1.0) |
The main branch is now on .NET 9.0.

| Version | Release Notes |
| ---------------------------------------------------------------- | -----------------------------------------------------------------------|
| [`v1.1.5`](https://github.com/CodeShayk/parsley.net/tree/v1.1.5) | [Notes](https://github.com/CodeShayk/Parsley.Net/releases/tag/v1.1.5) |
| [`v1.1.0`](https://github.com/CodeShayk/parsley.net/tree/v1.1.0) | [Notes](https://github.com/CodeShayk/Parsley.Net/releases/tag/v1.1.0) |
| [`v1.0.0`](https://github.com/CodeShayk/parsley.net/tree/v1.0.0) | [Notes](https://github.com/CodeShayk/Parsley.Net/releases/tag/v1.0.0) |

## Credits
Thank you for reading. Please fork, explore, contribute and report. Happy Coding !! :)
174 changes: 161 additions & 13 deletions src/Parsley/IParser.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

Expand All @@ -12,14 +15,14 @@ public interface IParser
/// <typeparam name="T"></typeparam>
/// <param name="filepath"></param>
/// <returns></returns>
T[] Parse<T>(string filepath) where T : IFileLine, new();
T[] Parse<T>(string filepath) where T : IFileLine, new();

/// <summary>
/// Parses an array of delimiter seperated strings into an array of objects of type T.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lines"></param>
/// <returns></returns>
/// <returns></returns>
T[] Parse<T>(string[] lines) where T : IFileLine, new();

/// <summary>
Expand All @@ -28,46 +31,191 @@ public interface IParser
/// <typeparam name="T"></typeparam>
/// <param name="bytes"></param>
/// <returns></returns>
T[] Parse<T>(byte[] bytes, Encoding encoding = null) where T : IFileLine, new();
T[] Parse<T>(byte[] bytes, Encoding encoding = null) where T : IFileLine, new();

/// <summary>
/// Parses a stream of delimiter separated records into an array of objects of type T.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stream"></param>
/// <returns></returns>
T[] Parse<T>(Stream stream, Encoding encoding = null) where T : IFileLine, new();
T[] Parse<T>(Stream stream, Encoding encoding = null) where T : IFileLine, new();

/// <summary>
/// Asynchronously parses a file at the specified filepath into an array of objects of type T.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filepath"></param>
/// <returns></returns>
Task<T[]> ParseAsync<T>(string filepath) where T : IFileLine, new();
Task<T[]> ParseAsync<T>(string filepath) where T : IFileLine, new();

/// <summary>
/// Asynchronously parses an array of delimiter separated strings into an array of objects of type T.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lines"></param>
/// <returns></returns>
Task<T[]> ParseAsync<T>(string[] lines) where T : IFileLine, new();
Task<T[]> ParseAsync<T>(string[] lines) where T : IFileLine, new();

/// <summary>
/// Asynchronously parses an array of bytes of delimiter separated records into an array of objects of type T.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bytes"></param>
/// <returns></returns>
Task<T[]> ParseAsync<T>(byte[] bytes, Encoding encoding = null) where T : IFileLine, new();
Task<T[]> ParseAsync<T>(byte[] bytes, Encoding encoding = null) where T : IFileLine, new();

/// <summary>
/// Asynchronously parses a stream of delimiter separated strings into an array of objects of type T.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stream"></param>
/// <returns></returns>
Task<T[]> ParseAsync<T>(Stream stream, Encoding encoding = null) where T : IFileLine, new();

/// <summary>
/// Attempts to parse a file at the specified filepath into an array of objects of type T with explicit result.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filepath"></param>
/// <returns></returns>
Result<T[]> TryParse<T>(string filepath) where T : IFileLine, new();

/// <summary>
/// Attempts to parse a file at the specified filepath into an array of objects of type T with explicit result and options.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filepath"></param>
/// <param name="options"></param>
/// <returns></returns>
Result<T[]> TryParse<T>(string filepath, ParseOptions options) where T : IFileLine, new();

/// <summary>
/// Attempts to parse an array of delimiter separated strings into an array of objects of type T with explicit result.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lines"></param>
/// <returns></returns>
Result<T[]> TryParse<T>(string[] lines) where T : IFileLine, new();

/// <summary>
/// Attempts to parse an array of delimiter separated strings into an array of objects of type T with explicit result and options.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lines"></param>
/// <param name="options"></param>
/// <returns></returns>
Result<T[]> TryParse<T>(string[] lines, ParseOptions options) where T : IFileLine, new();

/// <summary>
/// Attempts to parse an array of bytes of delimiter separated records into an array of objects of type T with explicit result.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bytes"></param>
/// <param name="encoding"></param>
/// <returns></returns>
Result<T[]> TryParse<T>(byte[] bytes, Encoding encoding = null) where T : IFileLine, new();

/// <summary>
/// Attempts to parse an array of bytes of delimiter separated records into an array of objects of type T with explicit result and options.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bytes"></param>
/// <param name="encoding"></param>
/// <param name="options"></param>
/// <returns></returns>
Result<T[]> TryParse<T>(byte[] bytes, Encoding encoding, ParseOptions options) where T : IFileLine, new();

/// <summary>
/// Attempts to parse a stream of delimiter separated records into an array of objects of type T with explicit result.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stream"></param>
/// <param name="encoding"></param>
/// <returns></returns>
Result<T[]> TryParse<T>(Stream stream, Encoding encoding = null) where T : IFileLine, new();

/// <summary>
/// Attempts to parse a stream of delimiter separated records into an array of objects of type T with explicit result and options.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stream"></param>
/// <param name="encoding"></param>
/// <param name="options"></param>
/// <returns></returns>
Result<T[]> TryParse<T>(Stream stream, Encoding encoding, ParseOptions options) where T : IFileLine, new();

/// <summary>
/// Asynchronously attempts to parse a file at the specified filepath into an array of objects of type T with explicit result.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filepath"></param>
/// <returns></returns>
Task<Result<T[]>> TryParseAsync<T>(string filepath) where T : IFileLine, new();

/// <summary>
/// Asynchronously attempts to parse a file at the specified filepath into an array of objects of type T with explicit result and options.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="filepath"></param>
/// <param name="options"></param>
/// <returns></returns>
Task<Result<T[]>> TryParseAsync<T>(string filepath, ParseOptions options) where T : IFileLine, new();

/// <summary>
/// Asynchronously attempts to parse an array of delimiter separated strings into an array of objects of type T with explicit result.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lines"></param>
/// <returns></returns>
Task<Result<T[]>> TryParseAsync<T>(string[] lines) where T : IFileLine, new();

/// <summary>
/// Asynchronously attempts to parse an array of delimiter separated strings into an array of objects of type T with explicit result and options.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lines"></param>
/// <param name="options"></param>
/// <returns></returns>
Task<Result<T[]>> TryParseAsync<T>(string[] lines, ParseOptions options) where T : IFileLine, new();

/// <summary>
/// Asynchronously attempts to parse an array of bytes of delimiter separated records into an array of objects of type T with explicit result.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bytes"></param>
/// <param name="encoding"></param>
/// <returns></returns>
Task<Result<T[]>> TryParseAsync<T>(byte[] bytes, Encoding encoding = null) where T : IFileLine, new();

/// <summary>
/// Asynchronously attempts to parse an array of bytes of delimiter separated records into an array of objects of type T with explicit result and options.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bytes"></param>
/// <param name="encoding"></param>
/// <param name="options"></param>
/// <returns></returns>
Task<Result<T[]>> TryParseAsync<T>(byte[] bytes, Encoding encoding, ParseOptions options) where T : IFileLine, new();

/// <summary>
/// Asynchronously attempts to parse a stream of delimiter separated records into an array of objects of type T with explicit result.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stream"></param>
/// <param name="encoding"></param>
/// <returns></returns>
Task<Result<T[]>> TryParseAsync<T>(Stream stream, Encoding encoding = null) where T : IFileLine, new();

/// <summary>
/// Asynchronously attempts to parse a stream of delimiter separated records into an array of objects of type T with explicit result and options.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stream"></param>
/// <param name="encoding"></param>
/// <param name="options"></param>
/// <returns></returns>
Task<Result<T[]>> TryParseAsync<T>(Stream stream, Encoding encoding, ParseOptions options) where T : IFileLine, new();
}
}
}

56 changes: 56 additions & 0 deletions src/Parsley/ParseOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
namespace parsley
{
/// <summary>
/// Configuration options for parsing delimiter-separated files
/// </summary>
public class ParseOptions
{
/// <summary>
/// Delimiter character to use for parsing. Default is comma (',')
/// </summary>
public char Delimiter { get; set; } = ',';

/// <summary>
/// Whether to skip the first line of the file, assuming it's a header
/// </summary>
public bool SkipHeaderLine { get; set; } = false;

/// <summary>
/// Whether to trim whitespace from field values
/// Default is true for backward compatibility
/// </summary>
public bool TrimFieldValues { get; set; } = true;

/// <summary>
/// Whether to include empty lines in the result (as objects with errors)
/// Default is true to maintain original behavior
/// </summary>
public bool IncludeEmptyLines { get; set; } = true;

/// <summary>
/// Maximum number of errors to collect before stopping (use -1 for unlimited)
/// Default is -1 (unlimited) for backward compatibility
/// </summary>
public int MaxErrors { get; set; } = -1;

/// <summary>
/// Buffer size for streaming operations (number of lines to process at once)
/// </summary>
public int BufferSize { get; set; } = 1024;

/// <summary>
/// Creates a new ParseOptions instance with default values
/// </summary>
public ParseOptions()
{
}

/// <summary>
/// Creates a new ParseOptions instance with specified delimiter
/// </summary>
public ParseOptions(char delimiter)
{
Delimiter = delimiter;
}
}
}
44 changes: 44 additions & 0 deletions src/Parsley/ParseResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace parsley
{
/// <summary>
/// Provides detailed information about a parsing operation result
/// </summary>
public class ParseResult<T> where T : IFileLine
{
public T[] ParsedValues { get; }
public bool HasErrors => GlobalErrors?.Count > 0 || ParsedValues?.Any(v => v.Errors?.Count > 0) == true;
public IList<string> GlobalErrors { get; }
public int TotalRecords { get; }
public int ErrorCount { get; }
public int SuccessCount => TotalRecords - ErrorCount;

public ParseResult(T[] parsedValues, IList<string> globalErrors = null)
{
ParsedValues = parsedValues ?? Array.Empty<T>();
GlobalErrors = globalErrors ?? new List<string>();
TotalRecords = ParsedValues.Length;
ErrorCount = ParsedValues.Count(v => v.Errors != null && v.Errors.Count > 0);
}

public IEnumerable<T> GetSuccessfulRecords() =>
ParsedValues.Where(v => v.Errors == null || v.Errors.Count == 0);

public IEnumerable<T> GetFailedRecords() =>
ParsedValues.Where(v => v.Errors != null && v.Errors.Count > 0);

public IEnumerable<string> GetAllErrors()
{
var errors = new List<string>(GlobalErrors);
foreach (var record in ParsedValues.Where(v => v.Errors != null))
{
errors.AddRange(record.Errors);
}
return errors;
}
}
}

Loading