aboutsummaryrefslogtreecommitdiff
path: root/lib/Net.Compression/VNLib.Net.Compression/CompressionExtensions.cs
blob: 4509b67d57eed77a4b18bb128effc204c51ee5df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
* Copyright (c) 2023 Vaughn Nugent
* 
* Library: VNLib
* Package: VNLib.Net.Compression
* File: CompressionExtensions.cs 
*
* CompressionExtensions.cs is part of VNLib.Net.Compression which is part of 
* the larger VNLib collection of libraries and utilities.
*
* VNLib.Net.Compression is free software: you can redistribute it and/or modify 
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 2 of the License,
* or (at your option) any later version.
*
* VNLib.Net.Compression is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License 
* along with VNLib.Net.Compression. If not, see http://www.gnu.org/licenses/.
*/

using System;
using System.Buffers;
using System.Runtime.InteropServices;

using VNLib.Net.Http;

namespace VNLib.Net.Compression
{
    internal static class CompressionExtensions
    {
        /// <summary>
        /// Compresses a block using the compressor context pointer provided
        /// </summary>
        /// <param name="nativeLib"></param>
        /// <param name="comp">A pointer to the compressor context</param>
        /// <param name="output">A buffer to write the result to</param>
        /// <param name="input">The input block of memory to compress</param>
        /// <param name="finalBlock">A value that indicates if a flush is requested</param>
        /// <returns>The results of the compression operation</returns>
        public static unsafe CompressionResult CompressBlock(this LibraryWrapper nativeLib, IntPtr comp, Memory<byte> output, ReadOnlyMemory<byte> input, bool finalBlock)
        {
            /*
             * Since .NET only supports int32 size memory blocks
             * we dont need to worry about integer overflow.
             * 
             * Output sizes can never be larger than input 
             * sizes (read/written)
             */

            //get pointers to the input and output buffers
            using MemoryHandle inPtr = input.Pin();
            using MemoryHandle outPtr = output.Pin();

            //Create the operation struct
            CompressionOperation operation;
            CompressionOperation* op = &operation;

            op->flush = finalBlock ? 1 : 0;
            op->bytesRead = 0;
            op->bytesWritten = 0;

            //Configure the input and output buffers
            op->inputBuffer = inPtr.Pointer;
            op->inputSize = (uint)input.Length;

            op->outputBuffer = outPtr.Pointer;
            op->outputSize = (uint)output.Length;

            //Call the native compress function
            nativeLib!.CompressBlock(comp, &operation);

            //Return the number of bytes written
            return new()
            {
                BytesRead = (int)op->bytesRead,
                BytesWritten = (int)op->bytesWritten
            };
        }

        /// <summary>
        /// Compresses a block using the compressor context pointer provided
        /// </summary>
        /// <param name="nativeLib"></param>
        /// <param name="comp">A pointer to the compressor context</param>
        /// <param name="output">A buffer to write the result to</param>
        /// <param name="input">The input block of memory to compress</param>
        /// <param name="finalBlock">A value that indicates if a flush is requested</param>
        /// <returns>The results of the compression operation</returns>
        public static unsafe CompressionResult CompressBlock(this LibraryWrapper nativeLib, IntPtr comp, Span<byte> output, ReadOnlySpan<byte> input, bool finalBlock)
        {
            /*
             * Since .NET only supports int32 size memory blocks
             * we dont need to worry about integer overflow.
             * 
             * Output sizes can never be larger than input 
             * sizes (read/written)
             */

            fixed(byte* inputPtr = &MemoryMarshal.GetReference(input),
                outPtr = &MemoryMarshal.GetReference(output))
            {
                //Create the operation struct
                CompressionOperation operation;
                CompressionOperation* op = &operation;

                op->flush = finalBlock ? 1 : 0;
                op->bytesRead = 0;
                op->bytesWritten = 0;

                //Configure the input and output buffers
                op->inputBuffer = inputPtr;
                op->inputSize = (uint)input.Length;

                op->outputBuffer = outPtr;
                op->outputSize = (uint)output.Length;

                //Call the native compress function
                nativeLib!.CompressBlock(comp, &operation);

                //Return the number of bytes written
                return new()
                {
                    BytesRead = (int)op->bytesRead,
                    BytesWritten = (int)op->bytesWritten
                };
            }
        }
    }
}