public static unsafe string Create <TState>(int length, TState state, SpanAction <char, TState> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            if (length <= 0)
            {
                if (length == 0)
                {
                    return(string.Empty);
                }
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            string result = new string('\0', length);

            fixed(char *r = result)
            {
                action(new Span <char>(r, length), state);
            }

            return(result);
        }
        public static void Ctor_Validating_FromDelegate()
        {
            object expectedState = new object();
            SpanAction <byte, object> spanAction = (span, actualState) =>
            {
                Assert.Same(expectedState, actualState);
                Assert.NotEqual(0, span.Length); // shouldn't have been called for a zero-length span

                for (int i = 0; i < span.Length; i++)
                {
                    Assert.Equal(0, span[i]);         // should've been zero-inited
                    span[i] = (byte)('a' + (i % 26)); // writes "abc...xyzabc...xyz..."
                }
            };

            ArgumentException exception = Assert.Throws <ArgumentOutOfRangeException>(() => Utf8String.Create(-1, expectedState, spanAction));

            Assert.Equal("length", exception.ParamName);

            exception = Assert.Throws <ArgumentNullException>(() => Utf8String.Create(10, expectedState, action: null));
            Assert.Equal("action", exception.ParamName);

            Assert.Same(Utf8String.Empty, Utf8String.Create(0, expectedState, spanAction));

            Assert.Equal(u8("abcde"), Utf8String.Create(5, expectedState, spanAction));
        }
        public static void Ctor_CreateRelaxed_FromDelegate()
        {
            object expectedState = new object();
            SpanAction <byte, object> spanAction = (span, actualState) =>
            {
                Assert.Same(expectedState, actualState);
                Assert.NotEqual(0, span.Length); // shouldn't have been called for a zero-length span

                for (int i = 0; i < span.Length; i++)
                {
                    Assert.Equal(0, span[i]); // should've been zero-inited
                    span[i] = 0xFF;           // never a valid UTF-8 byte
                }
            };

            ArgumentException exception = Assert.Throws <ArgumentOutOfRangeException>(() => Utf8String.CreateRelaxed(-1, expectedState, spanAction));

            Assert.Equal("length", exception.ParamName);

            exception = Assert.Throws <ArgumentNullException>(() => Utf8String.CreateRelaxed(10, expectedState, action: null));
            Assert.Equal("action", exception.ParamName);

            Assert.Same(Utf8String.Empty, Utf8String.CreateRelaxed(0, expectedState, spanAction));

            Assert.Equal(u8("\uFFFD\uFFFD"), Utf8String.CreateRelaxed(2, expectedState, spanAction));
        }
Beispiel #4
0
        /// <summary>
        /// Creates a new <see cref="Utf8String"/> instance, allowing the provided delegate to populate the
        /// instance data of the returned object.
        /// </summary>
        /// <typeparam name="TState">Type of the state object provided to <paramref name="action"/>.</typeparam>
        /// <param name="length">The length, in bytes, of the <see cref="Utf8String"/> instance to create.</param>
        /// <param name="state">The state object to provide to <paramref name="action"/>.</param>
        /// <param name="action">The callback which will be invoked to populate the returned <see cref="Utf8String"/>.</param>
        /// <exception cref="ArgumentException">
        /// Thrown if <paramref name="action"/> populates the buffer with ill-formed UTF-8 data.
        /// </exception>
        /// <remarks>
        /// The runtime will perform UTF-8 validation over the contents provided by the <paramref name="action"/> delegate.
        /// If an invalid UTF-8 subsequence is detected, an exception is thrown.
        /// </remarks>
        public static Utf8String Create <TState>(int length, TState state, SpanAction <byte, TState> action)
        {
            if (length < 0)
            {
                ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
            }

            if (action is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
            }

            if (length == 0)
            {
                return(Empty); // special-case empty input
            }

            // Create and populate the Utf8String instance.
            // Can't use FastAllocateSkipZeroInit here because we're handing the raw buffer to user code.

            Utf8String newString = FastAllocate(length);

            action(newString.DangerousGetMutableSpan(), state);

            // Now perform validation.

            if (!Utf8Utility.IsWellFormedUtf8(newString.AsBytes()))
            {
                throw new ArgumentException(
                          message: SR.Utf8String_CallbackProvidedMalformedData,
                          paramName: nameof(action));
            }

            return(newString);
        }
Beispiel #5
0
        /// <summary>
        /// Creates a new <see cref="Utf8String"/> instance, allowing the provided delegate to populate the
        /// instance data of the returned object.
        /// </summary>
        /// <typeparam name="TState">Type of the state object provided to <paramref name="action"/>.</typeparam>
        /// <param name="length">The length, in bytes, of the <see cref="Utf8String"/> instance to create.</param>
        /// <param name="state">The state object to provide to <paramref name="action"/>.</param>
        /// <param name="action">The callback which will be invoked to populate the returned <see cref="Utf8String"/>.</param>
        /// <remarks>
        /// The runtime will perform UTF-8 validation over the contents provided by the <paramref name="action"/> delegate.
        /// If an invalid UTF-8 subsequence is detected, the invalid subsequence is replaced with <see cref="Rune.ReplacementChar"/>
        /// in the returned <see cref="Utf8String"/> instance. This could result in the returned <see cref="Utf8String"/> instance
        /// having a different byte length than specified by the <paramref name="length"/> parameter.
        /// </remarks>
        public static Utf8String CreateRelaxed <TState>(int length, TState state, SpanAction <byte, TState> action)
        {
            if (length < 0)
            {
                ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
            }

            if (action is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
            }

            if (length == 0)
            {
                return(Empty); // special-case empty input
            }

            // Create and populate the Utf8String instance.
            // Can't use FastAllocateSkipZeroInit here because we're handing the raw buffer to user code.

            Utf8String newString = FastAllocate(length);

            action(newString.DangerousGetMutableSpan(), state);

            // Now perform validation and fixup.

            return(Utf8Utility.ValidateAndFixupUtf8String(newString));
        }
Beispiel #6
0
        private static void TestClampSpan <T>(
            int length,
            T min,
            T max,
            SpanAction <T, T, T> clampAction,
            Func <T, T, T, T> refClampFunc)
            where T : unmanaged, IComparable <T>
        {
            Span <T> actual = new T[length];

            var r = new Random();

            for (int i = 0; i < length; i++)
            {
                actual[i] = (T)Convert.ChangeType(r.Next(byte.MinValue, byte.MaxValue), typeof(T));
            }

            Span <T> expected = new T[length];

            actual.CopyTo(expected);

            for (int i = 0; i < expected.Length; i++)
            {
                ref T v = ref expected[i];
                v = refClampFunc(v, min, max);
            }
Beispiel #7
0
        public static string Create <TState>(int length, TState state, SpanAction <char, TState> action)
        {
            Span <char> span = length <= 256 ? stackalloc char[length] : new char[length];

            action(span, state);
            return(span.ToString());
        }
Beispiel #8
0
        /// <summary>
        /// Allocates the specified amount of elements and perform an operation over them using a <see cref="Span{T}"/>.
        /// </summary>
        /// <typeparam name="T">Type of the allocated elements.</typeparam>
        /// <param name="elementCount">The number of elements to allocate.</param>
        /// <param name="stackAlloc">If <c>true</c> and the amount of elements is small the allocation may occur in the stack.</param>
        /// <param name="action">The action to perform over the elements using a span.</param>
        public unsafe void Borrow <T>(int elementCount, bool stackAlloc, SpanAction <T, int> action) where T : unmanaged
        {
#if BIT64
            const int bytesThreshold = 500000;
#else
            const int bytesThreshold = 250000;
#endif
            int totalBytes = sizeof(T) * elementCount;

            if (totalBytes > bytesThreshold && stackAlloc)
            {
                void *memBlock = stackalloc byte[totalBytes];
                action(new Span <T>(memBlock, elementCount), elementCount);
            }
            else
            {
                void *memBlock = Allocate(totalBytes);

                try
                {
                    action(new Span <T>(memBlock, elementCount), elementCount);
                }
                finally
                {
                    Free(memBlock);
                }
            }
        }
Beispiel #9
0
 public void WriteBitString <TState>(
     int byteLength,
     TState state,
     SpanAction <byte, TState> action,
     int unusedBitCount = 0)
 {
     WriteBitStringCore(Asn1Tag.PrimitiveBitString, byteLength, state, action, unusedBitCount);
 }
        public static void Ctor_Validating_FromDelegate_ThrowsIfDelegateProvidesInvalidData()
        {
            SpanAction <byte, object> spanAction = (span, actualState) =>
            {
                span[0] = 0xFF; // never a valid UTF-8 byte
            };

            Assert.Throws <ArgumentException>(() => Utf8String.Create(10, new object(), spanAction));
        }
Beispiel #11
0
        public void WriteBitString <TState>(
            Asn1Tag tag,
            int byteLength,
            TState state,
            SpanAction <byte, TState> action,
            int unusedBitCount = 0)
        {
            CheckUniversalTag(tag, UniversalTagNumber.BitString);

            // Primitive or constructed, doesn't matter.
            WriteBitStringCore(tag, byteLength, state, action, unusedBitCount);
        }
Beispiel #12
0
        /// <summary>
        /// Allocates the specified amount of elements and perform an operation over them using a <see cref="Span{T}"/>.
        /// </summary>
        /// <typeparam name="T">Type of the allocated elements.</typeparam>
        /// <param name="elementCount">The number of elements to allocate.</param>
        /// <param name="action">The action to perform over the elements using a span.</param>
        public unsafe void Borrow <T>(int elementCount, SpanAction <T, int> action) where T : unmanaged
        {
            void *memBlock = Allocate <T>(elementCount);

            try
            {
                action(new Span <T>(memBlock, elementCount), elementCount);
            }
            finally
            {
                Free(memBlock);
            }
        }
        public static string CreateString <TState>(int length, TState state, SpanAction <char, TState> action)
        {
            var result = new string((char)0, length);

            unsafe
            {
                fixed(char *chars = result)
                {
                    var charBuffer = new Span <char>(chars, result.Length);

                    action(charBuffer, state);
                }
            }
            return(result);
        }
        public static Utf8String Create <TState>(
            int length, TState state, SpanAction <byte, TState> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            if (length == 0)
            {
                return(Empty);
            }

            var str = new Utf8String(length);

            action.Invoke(str._bytes, state);
            return(str);
        }
Beispiel #15
0
        public static string Create <TState>(int length, TState state, SpanAction <char, TState> action)
        {
            ArgumentNullException.ThrowIfNull(action);

            if (length <= 0)
            {
                if (length == 0)
                {
                    return(Empty);
                }
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            string result = FastAllocateString(length);

            action(new Span <char>(ref result.GetRawStringData(), length), state);
            return(result);
        }
Beispiel #16
0
        public static string Create <T>(int length, T state, SpanAction <char, T> action)
        {
#if NETSTANDARD2_0
            unsafe
            {
                var str = new string((char)0, length);
                fixed(char *chars = str)
                {
                    var span = new Span <char>(chars, length);

                    action(span, state);
                }

                return(str);
            }
#else
            return(string.Create(length, state, action));
#endif
        }
Beispiel #17
0
        /// <summary>
        /// Utility function to apply a given <see cref="SpanAction{T, TArg}"/> to all <see cref="Destinations"/>.
        /// </summary>
        /// <param name="action">The action to execute on each elements.</param>
        private void ForEachDestination(SpanAction <SplitterDestination, int> action)
        {
            Span <SplitterDestination> temp = Destinations;

            int i = 0;

            while (true)
            {
                if (temp.IsEmpty)
                {
                    break;
                }

                Span <SplitterDestination> next = temp[0].Next;

                action.Invoke(temp, i++);

                temp = next;
            }
        }
Beispiel #18
0
        public ValueTask SetTypes(Type xType, Type yType)
        {
            if (!XTypes.Contains(xType) || !YTypes.Contains(yType))
            {
                throw new InvalidOperationException("Unsupported data types.");
            }

            Cursor = 0;

            xSize = xType switch {
                Type t when t == typeof(DateTime) => sizeof(int),
                Type t when t == typeof(HighPrecTime) => sizeof(long),
                _ => System.Runtime.InteropServices.Marshal.SizeOf(xType)
            };
            ySize = System.Runtime.InteropServices.Marshal.SizeOf(yType);

            xSerializer = GetSerializer(xType);
            ySerializer = GetSerializer(yType);

            return(default(ValueTask));
        }
Beispiel #19
0
 public static string BuildStringFromIndefiniteLengthTextString <TState>(int length, TState state, SpanAction <char, TState> action)
 => string.Create(length, state, action);
Beispiel #20
0
        private void WriteBitStringCore <TState>(
            Asn1Tag tag,
            int byteLength,
            TState state,
            SpanAction <byte, TState> action,
            int unusedBitCount = 0)
        {
            if (byteLength == 0)
            {
                WriteBitStringCore(tag, ReadOnlySpan <byte> .Empty, unusedBitCount);
                return;
            }

            // T-REC-X.690-201508 sec 8.6.2.2
            if (unusedBitCount < 0 || unusedBitCount > 7)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(unusedBitCount),
                          unusedBitCount,
                          SR.Cryptography_Asn_UnusedBitCountRange);
            }

            CheckDisposed();

            int         savedOffset = _offset;
            Span <byte> scratchSpace;

            byte[]? ensureNoExtraCopy = null;
            int expectedSize = 0;

            // T-REC-X.690-201508 sec 9.2
            //
            // If it's not within a primitive segment, use the constructed encoding.
            // (>= instead of > because of the unused bit count byte)
            bool segmentedWrite =
                RuleSet == AsnEncodingRules.CER && byteLength >= AsnReader.MaxCERSegmentSize;

            if (segmentedWrite)
            {
                // Rather than call the callback multiple times, grow the buffer to allow
                // for enough space for the final output, then return a buffer where the last segment
                // is in the correct place. (Data will shift backwards to the right spot while writing
                // other segments).
                expectedSize = DetermineCerBitStringTotalLength(tag, byteLength);
                EnsureWriteCapacity(expectedSize);
                int overhead = expectedSize - byteLength;

                // Start writing where the last content byte is in the correct place, which is
                // after all of the overhead, but ending before the two byte end-of-contents marker.
                int scratchStart = overhead - 2;
                ensureNoExtraCopy = _buffer;
                scratchSpace      = _buffer.AsSpan(scratchStart, byteLength);

                // Don't let gapped-writes be unpredictable.
                scratchSpace.Clear();
            }
            else
            {
                WriteTag(tag.AsPrimitive());
                // The unused bits byte requires +1.
                WriteLength(byteLength + 1);

                _buffer[_offset] = (byte)unusedBitCount;
                _offset++;

                scratchSpace = _buffer.AsSpan(_offset, byteLength);
            }

            action(scratchSpace, state);

            // T-REC-X.690-201508 sec 11.2
            //
            // This could be ignored for BER, but since DER is more common and
            // it likely suggests a program error on the caller, leave it enabled for
            // BER for now.
            if (!CheckValidLastByte(scratchSpace[byteLength - 1], unusedBitCount))
            {
                // Since we are restoring _offset we won't clear this on a grow or Dispose,
                // so clear it now.
                _offset = savedOffset;
                scratchSpace.Clear();

                // TODO: Probably warrants a distinct message.
                throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
            }

            if (segmentedWrite)
            {
                WriteConstructedCerBitString(tag, scratchSpace, unusedBitCount);
                Debug.Assert(_offset - savedOffset == expectedSize, $"expected size was {expectedSize}, actual was {_offset - savedOffset}");
                Debug.Assert(_buffer == ensureNoExtraCopy, $"_buffer was replaced during while writing a bit string via callback");
            }
            else
            {
                _offset += byteLength;
            }
        }
 public void Load(int dataLength, SpanAction <T> initialize, bool asPowerOfTwoTexture = true)
 {
     ArgumentNullException.ThrowIfNull(initialize);
     Load(dataLength, initialize,
Beispiel #22
0
 /// <inheritdoc cref="string.Create{T}(int,T,SpanAction{char,T})"/>
 public static string CreateString <TState>(this int length, TState state, SpanAction <char, TState> action) =>
 string.Create(length, state, action);
Beispiel #23
0
        /// <summary>
        /// Creates a new <see cref="Utf8String"/> instance, allowing the provided delegate to populate the
        /// instance data of the returned object. Please see remarks for important safety information about
        /// this method.
        /// </summary>
        /// <typeparam name="TState">Type of the state object provided to <paramref name="action"/>.</typeparam>
        /// <param name="length">The length, in bytes, of the <see cref="Utf8String"/> instance to create.</param>
        /// <param name="state">The state object to provide to <paramref name="action"/>.</param>
        /// <param name="action">The callback which will be invoked to populate the returned <see cref="Utf8String"/>.</param>
        /// <remarks>
        /// This factory method can be used as an optimization to skip the validation step that
        /// <see cref="Create{TState}(int, TState, SpanAction{byte, TState})"/> normally performs. The contract
        /// of this method requires that <paramref name="action"/> populate the buffer with well-formed UTF-8
        /// data, as <see cref="Utf8String"/> contractually guarantees that it contains only well-formed UTF-8 data,
        /// and runtime instability could occur if a caller violates this guarantee.
        /// </remarks>
        public static Utf8String UnsafeCreateWithoutValidation <TState>(int length, TState state, SpanAction <byte, TState> action)
        {
            if (length < 0)
            {
                ThrowHelper.ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum();
            }

            if (action is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
            }

            if (length == 0)
            {
                return(Empty); // special-case empty input
            }

            // Create and populate the Utf8String instance.
            // Can't use FastAllocateSkipZeroInit here because we're handing the raw buffer to user code.

            Utf8String newString = FastAllocate(length);

            action(newString.DangerousGetMutableSpan(), state);

            // The line below is removed entirely in release builds.

            Debug.Assert(Utf8Utility.IsWellFormedUtf8(newString.AsBytes()), "Callback populated the buffer with ill-formed UTF-8 data.");

            return(newString);
        }
Beispiel #24
0
 /// <summary>
 /// Shim for string.Create. Creates an array of chars, invokes <paramref name="action"/>, and then creates a new string from the array.
 /// </summary>
 public static string StringCreate <TState>(int length, TState state, SpanAction <char, TState> action)
 {
     char[] str = new char[length];
     action(str, state);
     return(new string(str));
 }
 public static string BuildStringFromIndefiniteLengthTextString <TState>(int length, TState state, SpanAction <char, TState> action)
 {
     char[] arr = new char[length];
     action(arr, state);
     return(new string(arr));
 }