示例#1
0
        public StringBuilder ToStringBuilder <T>(ReadOnlySpan <T> value, ValuePresenterLimits limits)
        {
            var builder = new StringBuilder();

            AppendTo(builder, value, limits);
            return(builder);
        }
示例#2
0
        public StringBuilder ToStringBuilder <T>(T value, ValuePresenterLimits limits = default)
        {
            var builder = new StringBuilder();

            AppendTo(builder, value, limits);
            return(builder);
        }
示例#3
0
        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)));
        }
示例#4
0
 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('…');
     }
 }
示例#5
0
        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);
        }
示例#6
0
 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("…");
     }
 }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
        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;
            }
        }
示例#10
0
        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}");
            }
        }
示例#11
0
        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;
            }
        }
示例#12
0
        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);
        }
示例#13
0
        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(" }");
        }
示例#14
0
 public void AppendTo <T>(StringBuilder builder, ReadOnlySpan <T> value, ValuePresenterLimits limits)
 {
     AppendSpanTo(builder, value, depth: 1, limits);
 }
示例#15
0
 public void AppendTo <T>(StringBuilder builder, T value, ValuePresenterLimits limits)
 {
     AppendTo(builder, value, depth: 1, limits);
 }
示例#16
0
        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(" }");
        }