Skip to content

Commit 403a526

Browse files
committed
WIP(?)
1 parent 10664b7 commit 403a526

8 files changed

+217
-83
lines changed

RecordParser.Test/FixedLengthReaderBuilderTest.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public void Given_factory_method_should_invoke_it_on_parse()
2424
.Map(x => x.Money, 23, 7)
2525
.Build(factory: () => { called++; return (default, date, default); });
2626

27-
var result = reader.Parse("foo bar baz yyyy.MM.dd 0123.45");
27+
var result = reader.Parse("foo bar baz yyyy.MM.dd 0123.45".AsMemory());
2828

2929
called.Should().Be(1);
3030

RecordParser/Builders/Reader/FixedLengthReaderBuilder.cs

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using RecordParser.Engines.Reader;
1+
using AgileObjects.ReadableExpressions;
2+
using RecordParser.Engines.Reader;
23
using RecordParser.Parsers;
34
using RecordParser.Visitors;
45
using System;
@@ -95,12 +96,22 @@ public IFixedLengthReader<T> Build(CultureInfo cultureInfo = null, Func<T> facto
9596
{
9697
var map = MappingReadConfiguration.Merge(list, dic);
9798
var func = ReaderEngine.RecordParserSpanFlat(map, factory);
99+
var func2 = ReaderEngine.RecordParserSpanFlatAOT(map, factory);
98100

99101
func = CultureInfoVisitor.ReplaceCulture(func, cultureInfo);
102+
func2 = CultureInfoVisitor.ReplaceCulture(func2, cultureInfo);
103+
var saf = func2.ToReadableString();
100104

101-
var memory = new SpanReplacerVisitor().Modify(func);
102-
103-
return new FixedLengthReader<T>(func.Compile(true), memory.Compile(true));
105+
try
106+
{
107+
var f1 = func.Compile(true);
108+
var f2 = func2.Compile(true);
109+
return new FixedLengthReader<T>(f1, f2);
110+
}
111+
catch (Exception ex)
112+
{
113+
throw;
114+
}
104115
}
105116
}
106117
}

RecordParser/Engines/ExpressionHelper.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using RecordParser.Visitors;
2+
using System;
23
using System.Linq.Expressions;
34

45
namespace RecordParser.Engines
@@ -15,7 +16,9 @@ public static Expression SpanAsString(Expression span) =>
1516
Expression.Call(span, "ToString", Type.EmptyTypes);
1617

1718
public static Expression Trim(Expression str) =>
18-
Expression.Call(typeof(MemoryExtensions), "Trim", Type.EmptyTypes, str);
19+
str.Type == typeof(ReadOnlySpan<char>)
20+
? Expression.Call(typeof(MemoryExtensions), "Trim", Type.EmptyTypes, str)
21+
: Expression.Call(str, nameof(Foo.Trim), Type.EmptyTypes);
1922

2023
public static Expression Slice(Expression span, Expression start) =>
2124
Expression.Call(span, "Slice", Type.EmptyTypes, start);

RecordParser/Engines/Reader/PrimitiveTypeReaderEngine.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static PrimitiveTypeReaderEngine()
4747
dic = mapping;
4848
}
4949

50-
private static char ToChar(ReadOnlySpan<char> span) => span[0];
50+
public static char ToChar(ReadOnlySpan<char> span) => span[0];
5151

5252
private static void AddMapForReadOnlySpan<T>(
5353
this IDictionary<(Type, Type), Func<Type, Expression, Expression>> dic,

RecordParser/Engines/Reader/ReaderEngine.cs

+50-5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@ public static Expression<FuncSpanArrayT<T>> RecordParserSpanCSV<T>(IEnumerable<M
3434
return result;
3535
}
3636

37+
public static Expression<Func<Foo, T>> RecordParserSpanFlatAOT<T>(IEnumerable<MappingReadConfiguration> mappedColumns, Func<T> factory)
38+
{
39+
// parameters
40+
var line = Expression.Parameter(typeof(Foo), "span");
41+
42+
// variables
43+
var instanceVariable = Expression.Variable(typeof(T), "inst");
44+
45+
var blockThatSetProperties = MountSetProperties(instanceVariable, mappedColumns, (i, mapConfig) =>
46+
{
47+
return Slice(line, Expression.Constant(mapConfig.start), Expression.Constant(mapConfig.length.Value));
48+
}, true);
49+
50+
var body = MountBody(instanceVariable, blockThatSetProperties, mappedColumns, factory);
51+
var result = Expression.Lambda<Func<Foo, T>>(body, line);
52+
53+
return result;
54+
}
55+
3756
public static Expression<FuncSpanT<T>> RecordParserSpanFlat<T>(IEnumerable<MappingReadConfiguration> mappedColumns, Func<T> factory)
3857
{
3958
// parameters
@@ -54,9 +73,9 @@ public static Expression<FuncSpanT<T>> RecordParserSpanFlat<T>(IEnumerable<Mappi
5473
}
5574

5675
private static BlockExpression MountBody<T>(
57-
ParameterExpression instanceVariable,
58-
BlockExpression blockThatSetProperties,
59-
IEnumerable<MappingReadConfiguration> mappedColumns,
76+
ParameterExpression instanceVariable,
77+
BlockExpression blockThatSetProperties,
78+
IEnumerable<MappingReadConfiguration> mappedColumns,
6079
Func<T> factory)
6180
{
6281
var getNewInstance = factory != null
@@ -75,12 +94,15 @@ private static BlockExpression MountBody<T>(
7594
private static BlockExpression MountSetProperties(
7695
ParameterExpression objectParameter,
7796
IEnumerable<MappingReadConfiguration> mappedColumns,
78-
Func<int, MappingReadConfiguration, Expression> getTextValue)
97+
Func<int, MappingReadConfiguration, Expression> getTextValue,
98+
bool AOT = false)
7999
{
80100
var replacer = new ParameterReplacerVisitor(objectParameter);
81101
var assignsExpressions = new List<Expression>();
82102
var i = -1;
83103

104+
Func<Type, Expression, Delegate, Expression> resolve = AOT ? GetValueToBeSetExpressionAOT : GetValueToBeSetExpression;
105+
84106
foreach (var x in mappedColumns)
85107
{
86108
i++;
@@ -95,7 +117,7 @@ private static BlockExpression MountSetProperties(
95117
var isPropertyNullable = nullableUnderlyingType != null;
96118
var propertyUnderlyingType = nullableUnderlyingType ?? propertyType;
97119

98-
Expression valueToBeSetExpression = GetValueToBeSetExpression(
120+
Expression valueToBeSetExpression = resolve(
99121
propertyUnderlyingType,
100122
textValue,
101123
x.fmask);
@@ -137,5 +159,28 @@ private static Expression GetValueToBeSetExpression(Type propertyType, Expressio
137159

138160
throw new InvalidOperationException($"Type '{propertyType.FullName}' does not have a default parse");
139161
}
162+
163+
private static Expression GetValueToBeSetExpressionAOT(Type propertyType, Expression valueText, Delegate func)
164+
{
165+
if (func != null)
166+
{
167+
var fun = Expression.Constant(func);
168+
169+
return Expression.Call(valueText, nameof(Foo.AsCustom), new[] { func.Method.ReturnType }, fun);
170+
}
171+
172+
if (propertyType.IsEnum)
173+
{
174+
return Expression.Call(valueText, nameof(Foo.AsEnum), new[] { propertyType });
175+
}
176+
177+
var methodName = "As" + propertyType.Name;
178+
var method = typeof(Foo).GetMethod(methodName);
179+
180+
if (method == null)
181+
throw new InvalidOperationException($"Type '{propertyType.FullName}' does not have a default parse");
182+
183+
return Expression.Call(valueText, method);
184+
}
140185
}
141186
}

RecordParser/Parsers/FixedLengthReader.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using RecordParser.Visitors;
2+
using System;
23

34
namespace RecordParser.Parsers
45
{
@@ -12,17 +13,17 @@ public interface IFixedLengthReader<T>
1213
internal class FixedLengthReader<T> : IFixedLengthReader<T>
1314
{
1415
private readonly FuncSpanT<T> parser;
15-
private readonly Func<ReadOnlyMemory<char>, T> parser2;
16+
private readonly Func<Foo, T> parser2;
1617

17-
internal FixedLengthReader(FuncSpanT<T> parser, Func<ReadOnlyMemory<char>, T> parser2)
18+
internal FixedLengthReader(FuncSpanT<T> parser, Func<Foo, T> parser2)
1819
{
1920
this.parser = parser;
2021
this.parser2 = parser2;
2122
}
2223

2324
public T Parse(ReadOnlyMemory<char> line)
2425
{
25-
return parser2(line);
26+
return parser2(new Foo(line));
2627
}
2728

2829
public T Parse(ReadOnlySpan<char> line)

RecordParser/RecordParser.csproj

+6-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
</PropertyGroup>
2828

2929
<ItemGroup>
30-
<None Include="..\LICENSE.md" Pack="true" PackagePath="LICENSE.md"/>
30+
<None Include="..\LICENSE.md" Pack="true" PackagePath="LICENSE.md" />
3131
</ItemGroup>
3232

3333
<ItemGroup>
@@ -36,10 +36,11 @@
3636
</AssemblyAttribute>
3737
</ItemGroup>
3838

39-
<PropertyGroup Condition="
40-
( '$(Configuration)' == 'Debug' OR '$(Configuration)' == 'Release') AND
41-
( '$(TargetFramework)' == 'net6.0' OR '$(TargetFramework)' == 'net7.0' OR '$(TargetFramework)' == 'net8.0') AND
42-
( '$(Platform)' == 'AnyCPU') ">
39+
<ItemGroup>
40+
<PackageReference Include="AgileObjects.ReadableExpressions" Version="4.1.1" />
41+
</ItemGroup>
42+
43+
<PropertyGroup Condition="&#xD;&#xA; ( '$(Configuration)' == 'Debug' OR '$(Configuration)' == 'Release') AND&#xD;&#xA; ( '$(TargetFramework)' == 'net6.0' OR '$(TargetFramework)' == 'net7.0' OR '$(TargetFramework)' == 'net8.0') AND&#xD;&#xA; ( '$(Platform)' == 'AnyCPU') ">
4344
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
4445
</PropertyGroup>
4546

0 commit comments

Comments
 (0)