Skip to content

Commit

Permalink
draft
Browse files Browse the repository at this point in the history
  • Loading branch information
leandromoh committed Dec 31, 2023
1 parent 52bf3f7 commit 10664b7
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 2 deletions.
4 changes: 3 additions & 1 deletion RecordParser/Builders/Reader/FixedLengthReaderBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ public IFixedLengthReader<T> Build(CultureInfo cultureInfo = null, Func<T> facto

func = CultureInfoVisitor.ReplaceCulture(func, cultureInfo);

return new FixedLengthReader<T>(func.Compile());
var memory = new SpanReplacerVisitor().Modify(func);

return new FixedLengthReader<T>(func.Compile(true), memory.Compile(true));
}
}
}
10 changes: 9 additions & 1 deletion RecordParser/Parsers/FixedLengthReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@ namespace RecordParser.Parsers
public interface IFixedLengthReader<T>
{
T Parse(ReadOnlySpan<char> line);
T Parse(ReadOnlyMemory<char> line);
bool TryParse(ReadOnlySpan<char> line, out T result);
}

internal class FixedLengthReader<T> : IFixedLengthReader<T>
{
private readonly FuncSpanT<T> parser;
private readonly Func<ReadOnlyMemory<char>, T> parser2;

internal FixedLengthReader(FuncSpanT<T> parser)
internal FixedLengthReader(FuncSpanT<T> parser, Func<ReadOnlyMemory<char>, T> parser2)
{
this.parser = parser;
this.parser2 = parser2;
}

public T Parse(ReadOnlyMemory<char> line)
{
return parser2(line);
}

public T Parse(ReadOnlySpan<char> line)
Expand Down
78 changes: 78 additions & 0 deletions RecordParser/Visitors/MemoryVisitor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Linq;
using System.Linq.Expressions;

namespace RecordParser.Visitors
{
internal class SpanReplacerVisitor : ExpressionVisitor
{
private readonly static ParameterExpression memory = Expression.Parameter(typeof(ReadOnlyMemory<char>), "memory");
private readonly static MemberExpression span = Expression.Property(memory, "Span");



public Expression<Func<ReadOnlyMemory<char>, T>> Modify<T>(Expression<FuncSpanT<T>> ex)
{
if (ex is null) return null;

var body = Visit(ex.Body);

body = new StaticMethodVisitor().Visit(body);

var lamb = Expression.Lambda<Func<ReadOnlyMemory<char>, T>>(body, memory);

return lamb;
}



protected override Expression VisitParameter(ParameterExpression node)
{
if (node.Type == typeof(ReadOnlySpan<char>))
return span;

return base.VisitParameter(node);
}

class StaticMethodVisitor : ExpressionVisitor
{
public static string ToString(ReadOnlySpan<char> span) => span.ToString();
public static ReadOnlySpan<char> Trim(ReadOnlySpan<char> span) => span.Trim();
public static ReadOnlySpan<char> Slice1(ReadOnlySpan<char> span, int start) => span.Slice(start);
public static ReadOnlySpan<char> Slice2(ReadOnlySpan<char> span, int start, int count) => span.Slice(start, count);

protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Object?.Type == typeof(ReadOnlySpan<char>))
{
var args = node.Arguments.Prepend(node.Object).ToArray();

if (node.Method.Name == "Slice")
{
Delegate f = node.Arguments.Count == 1
? StaticMethodVisitor.Slice1
: StaticMethodVisitor.Slice2;

return Expression.Call(f.Method, args);
}

if (node.Method.Name == "ToString")
{
var f = StaticMethodVisitor.ToString;

return Expression.Call(f.Method, args);
}

if (node.Method.Name == "Trim")
{
var f = StaticMethodVisitor.Trim;

return Expression.Call(f.Method, args);
}
}

return base.VisitMethodCall(node);
}
}
}
}

0 comments on commit 10664b7

Please sign in to comment.