Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
TranscodingStream.cs
Go to the documentation of this file.
4using System.IO;
8
9namespace System.Text;
10
11internal sealed class TranscodingStream : Stream
12{
13 private readonly Encoding _innerEncoding;
14
15 private readonly Encoding _thisEncoding;
16
18
19 private readonly bool _leaveOpen;
20
22
24
26
28
30
31 private byte[] _readBuffer;
32
33 private int _readBufferOffset;
34
35 private int _readBufferCount;
36
37 public override bool CanRead => _innerStream?.CanRead ?? false;
38
39 public override bool CanSeek => false;
40
41 public override bool CanWrite => _innerStream?.CanWrite ?? false;
42
43 public override long Length
44 {
45 get
46 {
48 }
49 }
50
51 public override long Position
52 {
53 get
54 {
56 }
57 set
58 {
60 }
61 }
62
63 internal TranscodingStream(Stream innerStream, Encoding innerEncoding, Encoding thisEncoding, bool leaveOpen)
64 {
65 _innerStream = innerStream;
66 _leaveOpen = leaveOpen;
67 _innerEncoding = innerEncoding;
68 _thisEncoding = thisEncoding;
69 }
70
71 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
72 {
74 }
75
76 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
77 {
79 }
80
81 protected override void Dispose(bool disposing)
82 {
83 if (_innerStream != null)
84 {
86 if (arraySegment.Count != 0)
87 {
88 _innerStream.Write(arraySegment);
89 }
90 Stream innerStream = _innerStream;
91 _innerStream = null;
92 if (!_leaveOpen)
93 {
94 innerStream.Dispose();
95 }
96 }
97 }
98
99 public override ValueTask DisposeAsync()
100 {
101 if (_innerStream == null)
102 {
103 return default(ValueTask);
104 }
106 if (pendingData2.Count == 0)
107 {
108 Stream innerStream = _innerStream;
109 _innerStream = null;
110 if (!_leaveOpen)
111 {
112 return innerStream.DisposeAsync();
113 }
114 return default(ValueTask);
115 }
116 return DisposeAsyncCore(pendingData2);
117 async ValueTask DisposeAsyncCore(ArraySegment<byte> pendingData)
118 {
119 Stream innerStream2 = _innerStream;
120 _innerStream = null;
121 await innerStream2.WriteAsync(pendingData.AsMemory()).ConfigureAwait(continueOnCapturedContext: false);
122 if (!_leaveOpen)
123 {
124 await innerStream2.DisposeAsync().ConfigureAwait(continueOnCapturedContext: false);
125 }
126 }
127 }
128
129 public override int EndRead(IAsyncResult asyncResult)
130 {
131 return TaskToApm.End<int>(asyncResult);
132 }
133
134 public override void EndWrite(IAsyncResult asyncResult)
135 {
137 }
138
139 [MemberNotNull(new string[] { "_innerDecoder", "_thisEncoder", "_readBuffer" })]
141 {
143 if (_innerDecoder == null)
144 {
145 InitializeReadDataStructures();
146 }
147 void InitializeReadDataStructures()
148 {
149 if (!CanRead)
150 {
152 }
156 _readBuffer = GC.AllocateUninitializedArray<byte>(_thisEncoding.GetMaxByteCount(_readCharBufferMaxSize));
157 }
158 }
159
160 [MemberNotNull(new string[] { "_thisDecoder", "_innerEncoder" })]
162 {
164 if (_innerEncoder == null)
165 {
166 InitializeReadDataStructures();
167 }
168 void InitializeReadDataStructures()
169 {
170 if (!CanWrite)
171 {
173 }
176 }
177 }
178
180 {
181 if (_thisDecoder == null || _innerEncoder == null)
182 {
183 return default(ArraySegment<byte>);
184 }
185 char[] chars = Array.Empty<char>();
186 int num = _thisDecoder.GetCharCount(Array.Empty<byte>(), 0, 0, flush: true);
187 if (num > 0)
188 {
189 chars = new char[num];
190 num = _thisDecoder.GetChars(Array.Empty<byte>(), 0, 0, chars, 0, flush: true);
191 }
192 byte[] array = Array.Empty<byte>();
193 int num2 = _innerEncoder.GetByteCount(chars, 0, num, flush: true);
194 if (num2 > 0)
195 {
196 array = new byte[num2];
197 num2 = _innerEncoder.GetBytes(chars, 0, num, array, 0, flush: true);
198 }
199 return new ArraySegment<byte>(array, 0, num2);
200 }
201
202 public override void Flush()
203 {
206 }
207
213
214 public override int Read(byte[] buffer, int offset, int count)
215 {
217 return Read(new Span<byte>(buffer, offset, count));
218 }
219
220 public override int Read(Span<byte> buffer)
221 {
223 if (_readBufferCount == 0)
224 {
225 byte[] array = ArrayPool<byte>.Shared.Rent(4096);
226 char[] array2 = ArrayPool<char>.Shared.Rent(_readCharBufferMaxSize);
227 try
228 {
229 bool flag;
230 int bytes;
231 do
232 {
233 int num = _innerStream.Read(array, 0, 4096);
234 flag = num == 0;
235 int chars = _innerDecoder.GetChars(array, 0, num, array2, 0, flag);
236 bytes = _thisEncoder.GetBytes(array2, 0, chars, _readBuffer, 0, flag);
237 }
238 while (!flag && bytes == 0);
241 }
242 finally
243 {
245 ArrayPool<char>.Shared.Return(array2);
246 }
247 }
248 int num2 = Math.Min(_readBufferCount, buffer.Length);
249 _readBuffer.AsSpan(_readBufferOffset, num2).CopyTo(buffer);
250 _readBufferOffset += num2;
251 _readBufferCount -= num2;
252 return num2;
253 }
254
260
262 {
264 if (cancellationToken.IsCancellationRequested)
265 {
267 }
268 return ReadAsyncCore(buffer, cancellationToken);
270 {
271 if (_readBufferCount == 0)
272 {
273 byte[] rentedBytes = ArrayPool<byte>.Shared.Rent(4096);
274 char[] rentedChars = ArrayPool<char>.Shared.Rent(_readCharBufferMaxSize);
275 try
276 {
277 bool flag;
278 int bytes;
279 do
280 {
281 int num = await _innerStream.ReadAsync(rentedBytes.AsMemory(0, 4096), cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
282 flag = num == 0;
283 int chars = _innerDecoder.GetChars(rentedBytes, 0, num, rentedChars, 0, flag);
284 bytes = _thisEncoder.GetBytes(rentedChars, 0, chars, _readBuffer, 0, flag);
285 }
286 while (!flag && bytes == 0);
289 }
290 finally
291 {
292 ArrayPool<byte>.Shared.Return(rentedBytes);
293 ArrayPool<char>.Shared.Return(rentedChars);
294 }
295 }
296 int num2 = Math.Min(_readBufferCount, buffer.Length);
297 _readBuffer.AsSpan(_readBufferOffset, num2).CopyTo(buffer.Span);
298 _readBufferOffset += num2;
299 _readBufferCount -= num2;
300 return num2;
301 }
302 }
303
304 public unsafe override int ReadByte()
305 {
306 System.Runtime.CompilerServices.Unsafe.SkipInit(out byte result);
307 if (Read(new Span<byte>(&result, 1)) == 0)
308 {
309 return -1;
310 }
311 return result;
312 }
313
314 public override long Seek(long offset, SeekOrigin origin)
315 {
317 }
318
319 public override void SetLength(long value)
320 {
322 }
323
324 [StackTraceHidden]
325 private void ThrowIfDisposed()
326 {
327 if (_innerStream == null)
328 {
330 }
331 }
332
333 [DoesNotReturn]
334 [StackTraceHidden]
339
340 public override void Write(byte[] buffer, int offset, int count)
341 {
344 }
345
346 public override void Write(ReadOnlySpan<byte> buffer)
347 {
349 if (buffer.IsEmpty)
350 {
351 return;
352 }
353 int minimumLength = Math.Clamp(buffer.Length, 4096, 1048576);
354 char[] array = ArrayPool<char>.Shared.Rent(minimumLength);
355 byte[] array2 = ArrayPool<byte>.Shared.Rent(minimumLength);
356 try
357 {
358 bool completed;
359 do
360 {
361 _thisDecoder.Convert(buffer, array, flush: false, out var bytesUsed, out var charsUsed, out completed);
362 buffer = buffer.Slice(bytesUsed);
363 Span<char> span = array.AsSpan(0, charsUsed);
364 bool completed2;
365 do
366 {
367 _innerEncoder.Convert(span, array2, flush: false, out var charsUsed2, out var bytesUsed2, out completed2);
368 span = span.Slice(charsUsed2);
369 _innerStream.Write(array2, 0, bytesUsed2);
370 }
371 while (!completed2);
372 }
373 while (!completed);
374 }
375 finally
376 {
378 ArrayPool<byte>.Shared.Return(array2);
379 }
380 }
381
387
389 {
391 if (cancellationToken.IsCancellationRequested)
392 {
394 }
395 if (buffer.IsEmpty)
396 {
398 }
399 return WriteAsyncCore(buffer, cancellationToken);
400 async ValueTask WriteAsyncCore(ReadOnlyMemory<byte> remainingOuterEncodedBytes, CancellationToken cancellationToken)
401 {
402 int minimumLength = Math.Clamp(remainingOuterEncodedBytes.Length, 4096, 1048576);
403 char[] scratchChars = ArrayPool<char>.Shared.Rent(minimumLength);
404 byte[] scratchBytes = ArrayPool<byte>.Shared.Rent(minimumLength);
405 try
406 {
407 bool decoderFinished;
408 do
409 {
410 _thisDecoder.Convert(remainingOuterEncodedBytes.Span, scratchChars, flush: false, out var bytesUsed, out var charsUsed, out decoderFinished);
411 remainingOuterEncodedBytes = remainingOuterEncodedBytes.Slice(bytesUsed);
412 ArraySegment<char> decodedChars = new ArraySegment<char>(scratchChars, 0, charsUsed);
413 bool encoderFinished;
414 do
415 {
416 _innerEncoder.Convert(decodedChars, scratchBytes, flush: false, out var charsUsed2, out var bytesUsed2, out encoderFinished);
417 decodedChars = decodedChars.Slice(charsUsed2);
418 await _innerStream.WriteAsync(new ReadOnlyMemory<byte>(scratchBytes, 0, bytesUsed2), cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
419 }
420 while (!encoderFinished);
421 }
422 while (!decoderFinished);
423 }
424 finally
425 {
426 ArrayPool<char>.Shared.Return(scratchChars);
427 ArrayPool<byte>.Shared.Return(scratchBytes);
428 }
429 }
430 }
431
432 public unsafe override void WriteByte(byte value)
433 {
435 }
436}
static ArrayPool< T > Shared
Definition ArrayPool.cs:7
Definition GC.cs:8
Task FlushAsync()
Definition Stream.cs:669
static void ValidateBufferArguments(byte[] buffer, int offset, int count)
Definition Stream.cs:1044
Task WriteAsync(byte[] buffer, int offset, int count)
Definition Stream.cs:914
int Read(byte[] buffer, int offset, int count)
void Dispose()
Definition Stream.cs:639
Task< int > ReadAsync(byte[] buffer, int offset, int count)
Definition Stream.cs:762
void Write(byte[] buffer, int offset, int count)
virtual ValueTask DisposeAsync()
Definition Stream.cs:654
static byte Clamp(byte value, byte min, byte max)
Definition Math.cs:435
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static string NotSupported_UnseekableStream
Definition SR.cs:26
Definition SR.cs:7
virtual void Convert(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed)
Definition Decoder.cs:142
int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
int GetCharCount(byte[] bytes, int index, int count)
int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, bool flush)
virtual void Convert(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, int byteCount, bool flush, out int charsUsed, out int bytesUsed, out bool completed)
Definition Encoder.cs:135
int GetByteCount(char[] chars, int index, int count, bool flush)
int GetMaxCharCount(int byteCount)
int GetMaxByteCount(int charCount)
virtual Decoder GetDecoder()
Definition Encoding.cs:1004
virtual Encoder GetEncoder()
Definition Encoding.cs:1009
override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
override int Read(byte[] buffer, int offset, int count)
override Task< int > ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
override int Read(Span< byte > buffer)
override Task FlushAsync(CancellationToken cancellationToken)
TranscodingStream(Stream innerStream, Encoding innerEncoding, Encoding thisEncoding, bool leaveOpen)
override void EndWrite(IAsyncResult asyncResult)
override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
override ValueTask DisposeAsync()
override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
ArraySegment< byte > FinalFlushWriteBuffers()
override ValueTask< int > ReadAsync(Memory< byte > buffer, CancellationToken cancellationToken)
override void Write(byte[] buffer, int offset, int count)
unsafe override void WriteByte(byte value)
override void Write(ReadOnlySpan< byte > buffer)
override ValueTask WriteAsync(ReadOnlyMemory< byte > buffer, CancellationToken cancellationToken)
override int EndRead(IAsyncResult asyncResult)
override void SetLength(long value)
override long Seek(long offset, SeekOrigin origin)
override void Dispose(bool disposing)
static IAsyncResult Begin(Task task, AsyncCallback callback, object state)
Definition TaskToApm.cs:43
static void End(IAsyncResult asyncResult)
Definition TaskToApm.cs:48
new ConfiguredTaskAwaitable< TResult > ConfigureAwait(bool continueOnCapturedContext)
Definition Task.cs:226
static void ThrowNotSupportedException_UnwritableStream()
static void ThrowNotSupportedException_UnseekableStream()
static void ThrowObjectDisposedException_StreamClosed(string objectName)
static void ThrowNotSupportedException_UnreadableStream()
ArraySegment< T > Slice(int index)
unsafe ReadOnlySpan< T > Span
ReadOnlyMemory< T > Slice(int start)
Span< T > Slice(int start)
Definition Span.cs:271
static ValueTask CompletedTask
Definition ValueTask.cs:71
static ValueTask FromCanceled(CancellationToken cancellationToken)
Definition ValueTask.cs:180
ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext)
Definition ValueTask.cs:312