aboutsummaryrefslogtreecommitdiff
path: root/lib/Net.Compression/VNLib.Net.Compression/CompressionExtensions.cs
blob: 0d1fc73306cbb1a40ff896666605cb0261188742 (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
134
135
136
137
138
139
140
141
142
/*
* Copyright (c) 2024 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="compressorInstance">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 compressorInstance,
            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)
             */

            //Create the operation struct
            CompressionOperation operation = default;

            operation.flush = finalBlock ? 1 : 0;

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

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

                operation.outputBuffer = outPtr.Pointer;
                operation.outputSize = (uint)output.Length;

                //Call the native compress function
                nativeLib!.CompressBlock(compressorInstance, &operation);
               
                return new()
                {
                    BytesRead = (int)operation.bytesRead,
                    BytesWritten = (int)operation.bytesWritten
                };
            }
        }

        /// <summary>
        /// Compresses a block using the compressor context pointer provided
        /// </summary>
        /// <param name="nativeLib"></param>
        /// <param name="compressorInstance">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 compressorInstance,
            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)
             */

            //Create the operation struct
            CompressionOperation operation = default;
            operation.flush = finalBlock ? 1 : 0;

            checked
            {
                fixed (byte* inputPtr = &MemoryMarshal.GetReference(input),
                    outPtr = &MemoryMarshal.GetReference(output))
                {
                    //Configure the input and output buffers
                    operation.inputBuffer = inputPtr;
                    operation.inputSize = (uint)input.Length;

                    operation.outputBuffer = outPtr;
                    operation.outputSize = (uint)output.Length;

                    //Call the native compress function
                    nativeLib!.CompressBlock(compressorInstance, &operation);
                
                    return new()
                    {
                        BytesRead = (int)operation.bytesRead,
                        BytesWritten = (int)operation.bytesWritten
                    };
                }
            }
        }
    }
}