Skip to content

Commit b1e5403

Browse files
committed
Change BString value type to ReadOnlyMemory<byte>
1 parent a373657 commit b1e5403

File tree

1 file changed

+36
-69
lines changed

1 file changed

+36
-69
lines changed

BencodeNET/Objects/BString.cs

Lines changed: 36 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.IO;
43
using System.IO.Pipelines;
5-
using System.Linq;
64
using System.Text;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using BencodeNET.IO;
78

89
namespace BencodeNET.Objects
910
{
@@ -14,7 +15,7 @@ namespace BencodeNET.Objects
1415
/// <remarks>
1516
/// The underlying value is a <see cref="byte"/> array.
1617
/// </remarks>
17-
public sealed class BString : BObject<IReadOnlyList<byte>>, IComparable<BString>
18+
public sealed class BString : BObject<ReadOnlyMemory<byte>>, IComparable<BString>
1819
{
1920
/// <summary>
2021
/// The maximum number of digits that can be handled as the length part of a bencoded string.
@@ -24,13 +25,12 @@ public sealed class BString : BObject<IReadOnlyList<byte>>, IComparable<BString>
2425
/// <summary>
2526
/// The underlying bytes of the string.
2627
/// </summary>
27-
public override IReadOnlyList<byte> Value => _value;
28-
private readonly byte[] _value;
28+
public override ReadOnlyMemory<byte> Value { get; }
2929

3030
/// <summary>
3131
/// Gets the length of the string in bytes.
3232
/// </summary>
33-
public int Length => _value.Length;
33+
public int Length => Value.Length;
3434

3535
private static readonly Encoding DefaultEncoding = Encoding.UTF8;
3636

@@ -58,12 +58,10 @@ public BString()
5858
/// </summary>
5959
/// <param name="bytes">The bytes representing the data.</param>
6060
/// <param name="encoding">The encoding of the bytes. Defaults to <see cref="System.Text.Encoding.UTF8"/>.</param>
61-
public BString(IEnumerable<byte> bytes, Encoding encoding = null)
61+
public BString(byte[] bytes, Encoding encoding = null)
6262
{
63-
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
64-
63+
Value = bytes ?? throw new ArgumentNullException(nameof(bytes));
6564
_encoding = encoding ?? DefaultEncoding;
66-
_value = bytes as byte[] ?? bytes.ToArray();
6765
}
6866

6967
/// <summary>
@@ -75,20 +73,31 @@ public BString(IEnumerable<byte> bytes, Encoding encoding = null)
7573
public BString(string str, Encoding encoding = null)
7674
{
7775
_encoding = encoding ?? DefaultEncoding;
78-
_value = string.IsNullOrEmpty(str)
79-
? Array.Empty<byte>()
80-
: _encoding.GetBytes(str);
76+
77+
if (string.IsNullOrEmpty(str))
78+
{
79+
Value = Array.Empty<byte>();
80+
}
81+
else
82+
{
83+
var maxByteCount = _encoding.GetMaxByteCount(str.Length);
84+
var span = new byte[maxByteCount].AsSpan();
85+
86+
var length = _encoding.GetBytes(str.AsSpan(), span);
87+
88+
Value = span.Slice(0, length).ToArray();
89+
}
8190
}
8291

8392
/// <inheritdoc/>
84-
public override int GetSizeInBytes() => _value.Length + 1 + _value.Length.DigitCount();
93+
public override int GetSizeInBytes() => Value.Length + 1 + Value.Length.DigitCount();
8594

8695
/// <inheritdoc/>
8796
protected override void EncodeObject(Stream stream)
8897
{
89-
stream.Write(_value.Length);
98+
stream.Write(Value.Length);
9099
stream.Write(':');
91-
stream.Write(_value);
100+
stream.Write(Value.Span);
92101
}
93102

94103
/// <inheritdoc/>
@@ -98,26 +107,14 @@ protected override void EncodeObject(PipeWriter writer)
98107
var size = GetSizeInBytes();
99108
var buffer = writer.GetSpan(size);
100109

101-
#if NETCOREAPP
102110
// Write length
103-
var writtenBytes = Encoding.GetBytes(_value.Length.ToString().AsSpan(), buffer);
111+
var writtenBytes = Encoding.GetBytes(Value.Length.ToString().AsSpan(), buffer);
104112

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

108116
// Write value
109-
_value.AsSpan().CopyTo(buffer.Slice(writtenBytes + 1));
110-
#else
111-
// Write length
112-
var lengthBytes = Encoding.GetBytes(_value.Length.ToString());
113-
lengthBytes.CopyTo(buffer);
114-
115-
// Write ':'
116-
buffer[lengthBytes.Length] = (byte) ':';
117-
118-
// Write value
119-
_value.AsSpan().CopyTo(buffer.Slice(lengthBytes.Length + 1));
120-
#endif
117+
Value.Span.CopyTo(buffer.Slice(writtenBytes + 1));
121118

122119
// Commit
123120
writer.Advance(size);
@@ -128,56 +125,34 @@ protected override void EncodeObject(PipeWriter writer)
128125

129126
public static bool operator ==(BString first, BString second)
130127
{
131-
if (ReferenceEquals(first, null))
132-
return ReferenceEquals(second, null);
128+
if (first is null)
129+
return second is null;
133130

134131
return first.Equals(second);
135132
}
136133

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

139-
public override bool Equals(object other) => other is BString bstring && Value.SequenceEqual(bstring.Value);
136+
public override bool Equals(object other) => other is BString bstring && Value.Span.SequenceEqual(bstring.Value.Span);
140137

141-
public bool Equals(BString bstring) => bstring != null && Value.SequenceEqual(bstring.Value);
138+
public bool Equals(BString bstring) => bstring != null && Value.Span.SequenceEqual(bstring.Value.Span);
142139

143140
public override int GetHashCode()
144141
{
145-
var bytesToHash = Math.Min(Value.Count, 32);
142+
var bytesToHash = Math.Min(Value.Length, 32);
146143

147144
long hashValue = 0;
148145
for (var i = 0; i < bytesToHash; i++)
149146
{
150-
hashValue = (37 * hashValue + Value[i]) % int.MaxValue;
147+
hashValue = (37 * hashValue + Value.Span[i]) % int.MaxValue;
151148
}
152149

153150
return (int)hashValue;
154151
}
155152

156153
public int CompareTo(BString other)
157154
{
158-
if (other == null)
159-
return 1;
160-
161-
var maxLength = Math.Max(this.Length, other.Length);
162-
163-
for (var i = 0; i < maxLength; i++)
164-
{
165-
// This is shorter and thereby this is "less than" the other
166-
if (i >= this.Length)
167-
return -1;
168-
169-
// The other is shorter and thereby this is "greater than" the other
170-
if (i >= other.Length)
171-
return 1;
172-
173-
if (this.Value[i] > other.Value[i])
174-
return 1;
175-
176-
if (this.Value[i] < other.Value[i])
177-
return -1;
178-
}
179-
180-
return 0;
155+
return Value.Span.SequenceCompareTo(other.Value.Span);
181156
}
182157
#pragma warning restore 1591
183158

@@ -189,11 +164,7 @@ public int CompareTo(BString other)
189164
/// </returns>
190165
public override string ToString()
191166
{
192-
#if NETCOREAPP
193-
return _encoding.GetString(_value.AsSpan());
194-
#else
195-
return _encoding.GetString(_value);
196-
#endif
167+
return _encoding.GetString(Value.Span);
197168
}
198169

199170
/// <summary>
@@ -206,11 +177,7 @@ public override string ToString()
206177
public string ToString(Encoding encoding)
207178
{
208179
encoding = encoding ?? _encoding;
209-
#if NETCOREAPP
210-
return encoding.GetString(_value.AsSpan());
211-
#else
212-
return encoding.GetString(_value);
213-
#endif
180+
return encoding.GetString(Value.Span);
214181
}
215182
}
216183
}

0 commit comments

Comments
 (0)