private void ConvertFromBase64(Span <byte> tmpBuffer, Span <byte> outputBuffer, out int consumed, out int written) { int bytesToTransform = _inputIndex + tmpBuffer.Length; Debug.Assert(bytesToTransform >= 4); byte[]? transformBufferArray = null; Span <byte> transformBuffer = stackalloc byte[StackAllocSize]; if (bytesToTransform > StackAllocSize) { transformBuffer = transformBufferArray = CryptoPool.Rent(bytesToTransform); } // Copy _inputBuffer to transformBuffer and append tmpBuffer Debug.Assert(_inputIndex < _inputBuffer.Length); _inputBuffer.AsSpan(0, _inputIndex).CopyTo(transformBuffer); tmpBuffer.CopyTo(transformBuffer.Slice(_inputIndex)); // Save data that won't be transformed to _inputBuffer, so it can be transformed later _inputIndex = bytesToTransform & 3; // bit hack for % 4 bytesToTransform -= _inputIndex; // only transform up to the next multiple of 4 Debug.Assert(_inputIndex < _inputBuffer.Length); tmpBuffer.Slice(tmpBuffer.Length - _inputIndex).CopyTo(_inputBuffer); transformBuffer = transformBuffer.Slice(0, bytesToTransform); OperationStatus status = Base64.DecodeFromUtf8(transformBuffer, outputBuffer, out consumed, out written); if (status == OperationStatus.Done) { Debug.Assert(consumed == bytesToTransform); } else { Debug.Assert(status == OperationStatus.InvalidData); ThrowHelper.ThrowBase64FormatException(); } ReturnToCryptoPool(transformBufferArray, transformBuffer.Length); }
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { ThrowHelper.ValidateTransformBlock(inputBuffer, inputOffset, inputCount); int inputBlocks = Math.DivRem(inputCount, InputBlockSize, out int inputRemainder); if (inputBlocks == 0) { ThrowHelper.ThrowArgumentOutOfRange(ThrowHelper.ExceptionArgument.inputCount); } if (outputBuffer == null) { ThrowHelper.ThrowArgumentNull(ThrowHelper.ExceptionArgument.outputBuffer); } if (inputRemainder != 0) { ThrowHelper.ThrowArgumentOutOfRange(ThrowHelper.ExceptionArgument.inputCount); } int requiredOutputLength = checked (inputBlocks * OutputBlockSize); if (requiredOutputLength > outputBuffer.Length - outputOffset) { ThrowHelper.ThrowArgumentOutOfRange(ThrowHelper.ExceptionArgument.outputBuffer); } Span <byte> input = inputBuffer.AsSpan(inputOffset, inputCount); Span <byte> output = outputBuffer.AsSpan(outputOffset, requiredOutputLength); OperationStatus status = Base64.EncodeToUtf8(input, output, out int consumed, out int written, isFinalBlock: false); Debug.Assert(status == OperationStatus.Done); Debug.Assert(consumed == input.Length); Debug.Assert(written == output.Length); return(written); }