public StringBuilder ToStringBuilder <T>(ReadOnlySpan <T> value, ValuePresenterLimits limits) { var builder = new StringBuilder(); AppendTo(builder, value, limits); return(builder); }
public StringBuilder ToStringBuilder <T>(T value, ValuePresenterLimits limits = default) { var builder = new StringBuilder(); AppendTo(builder, value, limits); return(builder); }
private string Present <T>(T value, ValuePresenterLimits limits) { var bytes = (Span <byte>) stackalloc byte[256]; new Utf8ValuePresenter() .Present(bytes, VariantValue.From(value), limits, out var byteCount); return(Encoding.UTF8.GetString(bytes.Slice(0, byteCount))); }
public void AppendStringTo(StringBuilder builder, string value, ValuePresenterLimits limits) { if (value.Length <= limits.MaxValueLength) { builder.Append(value); } else { builder.Append(value, 0, limits.MaxValueLength - 1); builder.Append('…'); } }
private void AppendString(Span <byte> output, string value, ValuePresenterLimits limits, out int byteCount) { if (value.Length > limits.MaxValueLength) { byteCount = limits.MaxValueLength - 1; CharBreakingUtf8Encoder.Encode(value.AsSpan().Slice(0, byteCount), output); byteCount += AppendEllipsis(output, byteCount); return; } byteCount = Encoding.UTF8.GetBytes(value, output); }
public void AppendStringTo(StringBuilder builder, string value, ValuePresenterLimits limits) { if (limits.MaxValueLength == null || value.Length <= limits.MaxValueLength) { builder.Append(value); } else { builder.Append(value, 0, limits.MaxValueLength.Value - 1); builder.Append("…"); } }
private void AppendEnumerable <T>( Span <byte> output, IEnumerable <T> enumerable, int depth, ValuePresenterLimits limits, out int byteCount ) { if (depth > limits.MaxDepth) { output[0] = (byte)'{'; byteCount = 1 + AppendEllipsis(output, 1); output[byteCount] = (byte)'}'; byteCount += 1; return; } byteCount = Append(output, '{', ' ', 0); var index = 0; foreach (var item in enumerable) { if (index > 0) { byteCount += Append(output, ',', ' ', byteCount); } if (index > limits.MaxEnumerableItemCount - 1) { byteCount += AppendEllipsis(output, byteCount); break; } AppendValue( output.Slice(byteCount), item, depth + 1, limits.WithMaxEnumerableItemCount(1), out var itemByteCount ); byteCount += itemByteCount; index += 1; } byteCount += Append(output, ' ', '}', byteCount); }
public void GetMaxOutputByteCount_MatchesActualMaximumLength() { var limits = new ValuePresenterLimits( maxValueLength: 10, maxEnumerableItemCount: 3 ); var presented = Present( Enumerable.Range(0, 10) .Select(_ => Enumerable.Range(0, 10).Select(_ => "1234567890+").ToList()) .ToList(), limits ); var calculatedLength = new Utf8ValuePresenter() .GetMaxOutputByteCount(limits); Assert.Equal(Encoding.UTF8.GetByteCount(presented), calculatedLength); }
private void AppendValue <T>(Span <byte> output, T value, int depth, ValuePresenterLimits limits, out int byteCount) { if (value == null) { output[0] = (byte)'n'; output[1] = (byte)'u'; output[2] = (byte)'l'; output[3] = (byte)'l'; byteCount = 4; return; } switch (value) { case int i: AppendNumber(output, i, out byteCount); break; case ICollection <int> c: AppendEnumerable(output, c, depth, limits, out byteCount); break; case ICollection c: AppendEnumerable(output, c.Cast <object>(), depth, limits, out byteCount); break; case DateTime date: AppendString(output, date.ToString("dd.MM.yyyy HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture), limits, out byteCount); break; case DateTimeOffset date: AppendString(output, date.ToString("dd.MM.yyyy HH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture), limits, out byteCount); break; case IFormattable f: AppendString(output, f.ToString(null, CultureInfo.InvariantCulture) ?? "", limits, out byteCount); break; default: AppendString(output, value.ToString() ?? "", limits, out byteCount); break; } }
public void Present(Span <byte> output, VariantValue value, ValuePresenterLimits limits, out int byteCount) { switch (value.Kind) { case VariantKind.Int32: AppendNumber(output, value.AsInt32Unchecked(), out byteCount); return; case VariantKind.Int64: Utf8Formatter.TryFormat(value.AsInt64Unchecked(), output, out byteCount); return; case VariantKind.Object: AppendValue(output, value.AsObjectUnchecked(), depth: 1, limits, out byteCount); return; default: throw new NotSupportedException($"Unsupported variant kind: {value.Kind}"); } }
private void AppendTo <T>(StringBuilder builder, T value, int depth, ValuePresenterLimits limits) { if (value == null) { builder.Append("null"); return; } if (depth > limits.MaxDepth) { builder.Append("…"); return; } switch (value) { case ICollection <int> c: AppendEnumerableTo(builder, c, depth, limits); break; case ICollection c: AppendEnumerableTo(builder, c.Cast <object>(), depth, limits); break; case DateTime date: AppendStringTo(builder, date.ToString("dd.MM.yyyy HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture), limits); break; case DateTimeOffset date: AppendStringTo(builder, date.ToString("dd.MM.yyyy HH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture), limits); break; case IFormattable f: AppendStringTo(builder, f.ToString(null, CultureInfo.InvariantCulture) ?? "", limits); break; default: AppendStringTo(builder, value.ToString() ?? "", limits); break; } }
public int GetMaxOutputByteCount(ValuePresenterLimits limits) { if (limits.MaxDepth > 2) { throw new NotSupportedException("Output length calculation can only be done for depth <= 2."); } // maximum length is this (depending on item and sequence limits): // { { longestitem…, … }, { longestitem…, … }, … } const int ellipsis = Utf8Ellipsis.Length; const int bracesAndEllipsis = 2 // {␣ + ellipsis + 2; // ␣} return(( bracesAndEllipsis + +(limits.MaxValueLength - 1) + ellipsis + 2 // ,␣ (before last … inside) + 2 // ,␣ (before next item outside) ) * limits.MaxEnumerableItemCount + bracesAndEllipsis); }
public void AppendEnumerableTo <T>(StringBuilder builder, IEnumerable <T> enumerable, int depth, ValuePresenterLimits limits) { builder.Append("{ "); var index = 0; foreach (var item in enumerable) { if (index > 0) { builder.Append(", "); } if (index > limits.MaxEnumerableItemCount) { builder.Append('…'); break; } AppendTo(builder, item, depth + 1, limits); index += 1; } builder.Append(" }"); }
public void AppendTo <T>(StringBuilder builder, ReadOnlySpan <T> value, ValuePresenterLimits limits) { AppendSpanTo(builder, value, depth: 1, limits); }
public void AppendTo <T>(StringBuilder builder, T value, ValuePresenterLimits limits) { AppendTo(builder, value, depth: 1, limits); }
private void AppendSpanTo <T>(StringBuilder builder, ReadOnlySpan <T> value, int depth, ValuePresenterLimits limits) { builder.Append("{ "); var index = 0; foreach (var item in value) { if (index > 0) { builder.Append(", "); } if (index > limits.MaxEnumerableItemCount) { builder.Append('…'); break; } AppendTo(builder, item, depth + 1, limits); index += 1; } builder.Append(" }"); }