[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/Krusen/BencodeNET/master/BencodeNET/Objects/BString.cs [Back]  [Original]

using System;
using System.IO;
using System.IO.Pipelines;
using System.Text;

namespace BencodeNET.Objects
{
    /// 
    /// Represents a bencoded string, i.e. a byte-string.
    /// It isn't necessarily human-readable.
    /// 
    /// 
    /// The underlying value is a  array.
    /// 
    public sealed class BString : BObject, IComparable
    {
        /// 
        /// The maximum number of digits that can be handled as the length part of a bencoded string.
        /// 
        internal const int LengthMaxDigits = 10;

        /// 
        /// The underlying bytes of the string.
        /// 
        public override ReadOnlyMemory Value { get; }

        /// 
        /// Gets the length of the string in bytes.
        /// 
        public int Length => Value.Length;

        private static readonly Encoding DefaultEncoding = Encoding.UTF8;

        /// 
        /// Gets or sets the encoding used as the default with ToString().
        /// 
        /// 
        public Encoding Encoding
        {
            get => _encoding;
            set => _encoding = value ?? DefaultEncoding;
        }
        private Encoding _encoding;

        /// 
        /// Creates an empty  ('0:').
        /// 
        public BString()
            : this((string)null)
        {
        }

        /// 
        /// Creates a  from bytes with the specified encoding.
        /// 
        /// The bytes representing the data.
        /// The encoding of the bytes. Defaults to .
        public BString(byte[] bytes, Encoding encoding = null)
        {
            Value = bytes ?? throw new ArgumentNullException(nameof(bytes));
            _encoding = encoding ?? DefaultEncoding;
        }

        /// 
        /// Creates a  using the specified encoding to convert the string to bytes.
        /// 
        /// The string.
        /// The encoding used to convert the string to bytes.
        /// 
        public BString(string str, Encoding encoding = null)
        {
            _encoding = encoding ?? DefaultEncoding;

            if (string.IsNullOrEmpty(str))
            {
                Value = Array.Empty();
            }
            else
            {
                var maxByteCount = _encoding.GetMaxByteCount(str.Length);
                var span = new byte[maxByteCount].AsSpan();

                var length = _encoding.GetBytes(str.AsSpan(), span);

                Value = span.Slice(0, length).ToArray();
            }
        }

        /// 
        public override int GetSizeInBytes() => Value.Length + 1 + Value.Length.DigitCount();

        /// 
        protected override void EncodeObject(Stream stream)
        {
            stream.Write(Value.Length);
            stream.Write(':');
            stream.Write(Value.Span);
        }

        /// 
        protected override void EncodeObject(PipeWriter writer)
        {
            // Init
            var size = GetSizeInBytes();
            var buffer = writer.GetSpan(size);

            // Write length
            var writtenBytes = Encoding.GetBytes(Value.Length.ToString().AsSpan(), buffer);

            // Write ':'
            buffer[writtenBytes] = (byte) ':';

            // Write value
            Value.Span.CopyTo(buffer.Slice(writtenBytes + 1));

            // Commit
            writer.Advance(size);
        }

#pragma warning disable 1591
        public static implicit operator BString(string value) => new BString(value);

        public static bool operator ==(BString first, BString second)
        {
            return first?.Equals(second) ?? second is null;
        }

        public static bool operator !=(BString first, BString second) => !(first == second);

        public override bool Equals(object other) => other is BString bstring && Value.Span.SequenceEqual(bstring.Value.Span);

        public bool Equals(BString bstring) => bstring != null && Value.Span.SequenceEqual(bstring.Value.Span);

        public override int GetHashCode()
        {
            var bytesToHash = Math.Min(Value.Length, 32);

            long hashValue = 0;
            for (var i = 0; i < bytesToHash; i++)
            {
                hashValue = (37 * hashValue + Value.Span[i]) % int.MaxValue;
            }

            return (int)hashValue;
        }

        public int CompareTo(BString other)
        {
            return Value.Span.SequenceCompareTo(other.Value.Span);
        }
#pragma warning restore 1591

        /// 
        /// Converts the underlying bytes to a string representation using the current value of the  property.
        /// 
        /// 
        /// A  that represents this instance.
        /// 
        public override string ToString()
        {
            return _encoding.GetString(Value.Span);
        }

        /// 
        /// Converts the underlying bytes to a string representation using the specified encoding.
        /// 
        /// The encoding to use to convert the underlying byte array to a .
        /// 
        /// A  that represents this instance.
        /// 
        public string ToString(Encoding encoding)
        {
            encoding ??= _encoding;
            return encoding.GetString(Value.Span);
        }
    }
}

Web Proxy Viewer  |  New URL  |  Original Page