private static byte[] PickleWithBuffer(
            ReadOnlySpan <byte> source, LZ4Level level, Span <byte> buffer)
        {
            const int version      = 0;
            var       sourceLength = source.Length;

            Debug.Assert(buffer.Length >= sourceLength);
            var encodedLength = LZ4Codec.Encode(source, buffer, level);

            if (encodedLength <= 0 || encodedLength >= sourceLength)
            {
                var headerSize = GetUncompressedHeaderSize(version, sourceLength);
                var result     = new byte[headerSize + sourceLength];
                var target     = result.AsSpan();
                var offset     = EncodeUncompressedHeader(target, version, sourceLength);
                Debug.Assert(headerSize == offset, "Unexpected header size");
                source.CopyTo(target.Slice(offset));
                return(result);
            }
            else
            {
                var headerSize = GetCompressedHeaderSize(version, sourceLength, encodedLength);
                var result     = new byte[headerSize + encodedLength];
                var target     = result.AsSpan();
                var offset     = EncodeCompressedHeader(
                    target, version, headerSize, sourceLength, encodedLength);
                Debug.Assert(headerSize == offset, "Unexpected header size");
                buffer.Slice(0, encodedLength).CopyTo(target.Slice(offset));
                return(result);
            }
        }
Пример #2
0
        /// <summary>Compresses input buffer into self-contained package.</summary>
        /// <param name="source">Input buffer.</param>
        /// <param name="sourceLength">Length of input data.</param>
        /// <param name="level">Compression level.</param>
        /// <returns>Output buffer.</returns>
        public static unsafe byte[] Pickle(
            byte *source, int sourceLength, LZ4Level level = LZ4Level.L00_FAST)
        {
            if (sourceLength <= 0)
            {
                return(Array.Empty <byte>());
            }

            var targetLength = sourceLength - 1;
            var target       = (byte *)Mem.Alloc(sourceLength);

            try
            {
                var encodedLength = LZ4Codec.Encode(
                    source, sourceLength, target, targetLength, level);

                return(encodedLength <= 0
                                        ? PickleV0(source, sourceLength, sourceLength)
                                        : PickleV0(target, encodedLength, sourceLength));
            }
            finally
            {
                Mem.Free(target);
            }
        }
        /// <summary>Compresses input buffer into self-contained package.</summary>
        /// <param name="source">Input buffer.</param>
        /// <param name="writer">Where the compressed data is written.</param>
        /// <param name="level">Compression level.</param>
        /// <returns>Output buffer.</returns>
        public static void Pickle(
            ReadOnlySpan <byte> source, IBufferWriter <byte> writer,
            LZ4Level level = LZ4Level.L00_FAST)
        {
            if (writer is null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            var sourceLength = source.Length;

            if (sourceLength == 0)
            {
                return;
            }

            // this might be an argument at some point
            const int version = 0;

            // number of bytes is not decided on diff but rather of full length
            // although, diff would never be greater than full length
            var headerSize = GetPessimisticHeaderSize(version, sourceLength);
            var target     = writer.GetSpan(headerSize + sourceLength);

            var encodedLength = LZ4Codec.Encode(
                source, target.Slice(headerSize, sourceLength), level);

            if (encodedLength <= 0 || encodedLength >= sourceLength)
            {
                var offset = EncodeUncompressedHeader(target, version, sourceLength);
                source.CopyTo(target.Slice(offset));
                writer.Advance(offset + sourceLength);
            }
            else
            {
                var offset = EncodeCompressedHeader(
                    target, version, headerSize, sourceLength, encodedLength);
                Debug.Assert(headerSize == offset, "Unexpected header size");
                writer.Advance(offset + encodedLength);
            }
        }