Files
MoShiro/backend/shared/MoShiro.Protocol/Raw/StreamBuilder.cs
T
justme 83e5120377 refactor!: rename the project from Monitor to MoShiro
Namespaces, assemblies, projects and directories, the solution, binaries,
images, systemd units, config paths, environment variables, protocol method
names, the media type and the raw chunk magic all move to MoShiro/moshiro.
Existing data and deployments are not compatible and must be recreated.
Also fix the architecture tests after the solution layout change and make
the update tests independent of their order.
2026-10-07 01:49:04 +08:00

59 lines
1.8 KiB
C#

namespace MoShiro.Protocol;
/// <summary>按 <see cref="StreamSpec"/> 逐行构造一个 <see cref="RawStream"/>(用于测试、模拟器和离线工具,不用于节点热路径)。</summary>
public sealed class StreamBuilder
{
private readonly StreamSpec _spec;
private readonly List<long>[] _values;
private readonly List<bool>[] _valid;
public StreamBuilder(StreamSpec spec)
{
_spec = spec;
_values = new List<long>[spec.Columns.Count];
_valid = new List<bool>[spec.Columns.Count];
for (int i = 0; i < _values.Length; i++)
{
_values[i] = [];
_valid[i] = [];
}
}
public int Count { get; private set; }
/// <summary>添加一行;<c>null</c> 表示缺失值(只允许用于可空列)。</summary>
public StreamBuilder Add(params long?[] row)
{
if (row.Length != _values.Length)
{
throw new ArgumentException($"stream {_spec.Name} expects {_values.Length} values, got {row.Length}", nameof(row));
}
for (int i = 0; i < row.Length; i++)
{
if (row[i] is null && !_spec.Columns[i].Nullable)
{
throw new ArgumentException($"column {_spec.Columns[i].Name} is not nullable", nameof(row));
}
_values[i].Add(row[i] ?? 0);
_valid[i].Add(row[i] is not null);
}
Count++;
return this;
}
public RawStream Build()
{
var columns = new List<RawColumn>(_values.Length);
for (int i = 0; i < _values.Length; i++)
{
ColumnSpec spec = _spec.Columns[i];
columns.Add(new RawColumn(spec.Name, spec.Type, spec.Enc, spec.Nullable, spec.Role, [.. _values[i]], spec.Nullable ? [.. _valid[i]] : null));
}
return new RawStream(_spec.Name, Count, columns);
}
}