SimpleTextTemplateは、変数の埋め込みのみに対応したテキストテンプレートエンジンです。
- 文字列をUTF-8バイト列として
IBufferWriter<byte>
に出力します。 {{ <変数>:<format>:<culture> }}
で変数を埋め込みます。(format
とculture
は省略可能){{
と}}
内の先頭と末尾の空白(U+0020)は無視されます。{{
と}}
で囲まれた範囲以外の文字は、そのまま出力されます。
Important
一部のカルチャーではOSによって定数展開が変わります。
dotnet add package SimpleTextTemplate.Generator
dotnet add package SimpleTextTemplate.Generator -s https://pkgs.dev.azure.com/finphie/Main/_packaging/DotNet/nuget/v3/index.json
次の例では、外部のライブラリであるCommunityToolkit.HighPerformanceを参照しています。
using System;
using System.Globalization;
using System.Text;
using CommunityToolkit.HighPerformance.Buffers;
using SimpleTextTemplate;
using var bufferWriter = new ArrayPoolBufferWriter<byte>();
var context = new SampleContext("Hello, World", 1000, new(2000, 1, 1, 0, 0, 0, TimeSpan.Zero));
var writer = TemplateWriter.Create(bufferWriter);
TemplateRenderer.Render(ref writer, "{{ DateTimeOffsetValue:o }}_{{ StringValue }}!", in context);
TemplateRenderer.Render(ref writer, "_{{ ConstantString }}_{{ ConstantInt:N3:ja-JP }}_{{ IntValue }}", in context, CultureInfo.InvariantCulture);
writer.Flush();
// 2000-01-01T00:00:00.0000000+00:00_Hello, World!_Hello_999.000_1000
Console.WriteLine(Encoding.UTF8.GetString(bufferWriter.WrittenSpan));
readonly record struct SampleContext(
string StringValue,
int IntValue,
DateTimeOffset DateTimeOffsetValue)
{
public const string ConstantString = "Hello";
public const int ConstantInt = 999;
}
using System.Runtime.CompilerServices;
using System.Text;
using CommunityToolkit.HighPerformance.Buffers;
using SimpleTextTemplate;
file static class Intercept
{
[InterceptsLocation(1, "...")]
public static void Render0(ref TemplateWriter<ArrayPoolBufferWriter<byte>> writer, string text, in SampleContext context, IFormatProvider? provider = null)
{
writer.WriteValue(Unsafe.AsRef(in context).@DateTimeOffsetValue, "o", CultureInfo.InvariantCulture);
writer.Grow(2
+ Encoding.UTF8.GetMaxByteCount(
Unsafe.AsRef(in context).@StringValue.Length));
writer.DangerousWriteConstantLiteral("_"u8);
writer.DangerousWriteString(Unsafe.AsRef(in context).@StringValue);
writer.DangerousWriteConstantLiteral("!"u8);
}
[InterceptsLocation(1, "...")]
public static void Render1(ref TemplateWriter<ArrayPoolBufferWriter<byte>> writer, string text, in SampleContext context, IFormatProvider? provider = null)
{
writer.Grow(15);
writer.WriteConstantLiteral("_Hello_999.000_"u8);
writer.WriteValue(Unsafe.AsRef(in context).@IntValue, default, CultureInfo.InvariantCulture);
}
}
SimpleTextTemplate(非推奨)
SimpleTextTemplateとSimpleTextTemplate.Contextsへの参照が必要です。
using System;
using System.Text;
using CommunityToolkit.HighPerformance.Buffers;
using SimpleTextTemplate;
var symbols = Context.Create();
symbols.Add("Identifier"u8.ToArray(), "Hello, World!"u8.ToArray());
using var bufferWriter = new ArrayPoolBufferWriter<byte>();
var source = "{{ Identifier }}"u8.ToArray();
var template = Template.Parse(source);
template.Render(bufferWriter, symbols);
// Hello, World!
Console.WriteLine(Encoding.UTF8.GetString(bufferWriter.WrittenSpan));
Method | Mean | Error | Ratio | Gen0 | Allocated |
---|---|---|---|---|---|
SimpleTextTemplate.Generator | 13.53 ns | 0.110 ns | 1.00 | 0.0067 | 56 B |
(Utf8.TryWrite) | 25.12 ns | 0.164 ns | 1.86 | 0.0067 | 56 B |
(InterpolatedStringHandler) | 30.96 ns | 0.357 ns | 2.29 | 0.0105 | 88 B |
(CompositeFormat) | 29.98 ns | 0.468 ns | 2.22 | 0.0105 | 88 B |
Method | Mean | Error | Ratio | Gen0 | Allocated |
---|---|---|---|---|---|
SimpleTextTemplate.Generator | 12.18 ns | 0.051 ns | 1.00 | 0.0048 | 40 B |
(Utf8.TryWrite) | 13.54 ns | 0.234 ns | 1.11 | 0.0048 | 40 B |
(InterpolatedStringHandler) | 32.67 ns | 0.487 ns | 2.68 | 0.0067 | 56 B |
(CompositeFormat) | 28.76 ns | 0.412 ns | 2.36 | 0.0067 | 56 B |
Method | Mean | Error | Ratio | Gen0 | Gen1 | Allocated |
---|---|---|---|---|---|---|
SimpleTextTemplate.Generator | 25.32 ns | 0.062 ns | 1.00 | 0.0057 | - | 48 B |
SimpleTextTemplate | 61.39 ns | 0.530 ns | 2.42 | 0.0057 | - | 48 B |
Scriban | 8,339.53 ns | 46.900 ns | 329.31 | 3.7842 | 0.3662 | 32071 B |
Scriban_Liquid | 6,670.99 ns | 66.825 ns | 263.43 | 4.0131 | 0.3815 | 33602 B |
(Utf8.TryWrite) | 22.73 ns | 0.346 ns | 0.90 | 0.0057 | - | 48 B |
(InterpolatedStringHandler) | 30.22 ns | 0.393 ns | 1.19 | 0.0086 | - | 72 B |
(CompositeFormat) | 27.75 ns | 0.348 ns | 1.10 | 0.0086 | - | 72 B |
Method | Mean | Error | Ratio | Gen0 | Gen1 | Allocated |
---|---|---|---|---|---|---|
SimpleTextTemplate.Generator | 19.00 ns | 0.067 ns | 1.00 | 0.0057 | - | 48 B |
SimpleTextTemplate | 60.97 ns | 0.690 ns | 3.21 | 0.0057 | - | 48 B |
Scriban | 8,600.22 ns | 78.630 ns | 452.65 | 3.7842 | 0.3662 | 32095 B |
Scriban_Liquid | 6,794.65 ns | 98.124 ns | 357.62 | 4.0131 | 0.3967 | 33626 B |
(Utf8.TryWrite) | 17.98 ns | 0.313 ns | 0.95 | 0.0057 | - | 48 B |
(InterpolatedStringHandler) | 34.09 ns | 0.439 ns | 1.79 | 0.0076 | - | 64 B |
(CompositeFormat) | 29.13 ns | 0.352 ns | 1.53 | 0.0076 | - | 64 B |
Note
()で囲まれているメソッドは参考として記載。
.NET 9
finphie
MIT
このプロジェクトでは、次のライブラリ等を使用しています。
- DocumentationAnalyzers
- IDisposableAnalyzers
- Microsoft.CodeAnalysis.Analyzers
- Microsoft.CodeAnalysis.NetAnalyzers
- Microsoft.VisualStudio.Threading.Analyzers
- Roslynator.Analyzers
- Roslynator.Formatting.Analyzers
- StyleCop.Analyzers