SimpleTextTemplateは、変数の埋め込みのみに対応したテキストテンプレートエンジンです。
- 文字列をUTF-8バイト列としてIBufferWriter<byte>に出力します。
- {{ <変数>:<format>:<culture> }}で変数を埋め込みます。(- formatと- cultureは省略可能)
- {{と- }}内の先頭と末尾の空白(U+0020)は無視されます。
- {{と- }}で囲まれた範囲以外の文字は、そのまま出力されます。
Important
一部のカルチャーではOSによって定数展開が変わります。
dotnet add package SimpleTextTemplate.Generatordotnet 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