| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-02-26 09:06:40 -07:00
										 |  |  |  * Copyright (c) 2020-2022, the SerenityOS developers. | 
					
						
							| 
									
										
										
										
											2021-04-22 23:40:43 +03:00
										 |  |  |  * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org> | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <LibCompress/Gzip.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  | #include <AK/DeprecatedString.h>
 | 
					
						
							| 
									
										
										
										
											2023-01-25 20:19:05 +01:00
										 |  |  | #include <AK/MemoryStream.h>
 | 
					
						
							| 
									
										
										
										
											2021-05-07 23:40:02 +03:00
										 |  |  | #include <LibCore/DateTime.h>
 | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Compress { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 23:54:07 +02:00
										 |  |  | bool GzipDecompressor::is_likely_compressed(ReadonlyBytes bytes) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return bytes.size() >= 2 && bytes[0] == gzip_magic_1 && bytes[1] == gzip_magic_2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | bool BlockHeader::valid_magic_number() const | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-03 23:54:07 +02:00
										 |  |  |     return identification_1 == gzip_magic_1 && identification_2 == gzip_magic_2; | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | bool BlockHeader::supported_by_implementation() const | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (compression_method != 0x08) { | 
					
						
							|  |  |  |         // RFC 1952 does not define any compression methods other than deflate.
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (flags > Flags::MAX) { | 
					
						
							|  |  |  |         // RFC 1952 does not define any more flags.
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-10 01:00:18 +01:00
										 |  |  | ErrorOr<NonnullOwnPtr<GzipDecompressor::Member>> GzipDecompressor::Member::construct(BlockHeader header, Stream& stream) | 
					
						
							| 
									
										
										
										
											2023-01-01 00:38:05 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-02-10 01:00:18 +01:00
										 |  |  |     auto deflate_stream = TRY(DeflateDecompressor::construct(MaybeOwned<Stream>(stream))); | 
					
						
							| 
									
										
										
										
											2023-01-01 00:38:05 +01:00
										 |  |  |     return TRY(adopt_nonnull_own_or_enomem(new (nothrow) Member(header, move(deflate_stream)))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GzipDecompressor::Member::Member(BlockHeader header, NonnullOwnPtr<DeflateDecompressor> stream) | 
					
						
							|  |  |  |     : m_header(header) | 
					
						
							|  |  |  |     , m_stream(move(stream)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-10 01:00:18 +01:00
										 |  |  | GzipDecompressor::GzipDecompressor(NonnullOwnPtr<Stream> stream) | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |     : m_input_stream(move(stream)) | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GzipDecompressor::~GzipDecompressor() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_current_member.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-24 22:38:01 +01:00
										 |  |  | ErrorOr<Bytes> GzipDecompressor::read_some(Bytes bytes) | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |     size_t total_read = 0; | 
					
						
							|  |  |  |     while (total_read < bytes.size()) { | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |         if (is_eof()) | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2020-09-05 16:39:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |         auto slice = bytes.slice(total_read); | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 00:38:05 +01:00
										 |  |  |         if (m_current_member) { | 
					
						
							| 
									
										
										
										
											2023-02-24 22:38:01 +01:00
										 |  |  |             auto current_slice = TRY(current_member().m_stream->read_some(slice)); | 
					
						
							| 
									
										
										
										
											2022-12-02 22:01:44 +01:00
										 |  |  |             current_member().m_checksum.update(current_slice); | 
					
						
							|  |  |  |             current_member().m_nread += current_slice.size(); | 
					
						
							| 
									
										
										
										
											2020-09-05 13:18:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 22:01:44 +01:00
										 |  |  |             if (current_slice.size() < slice.size()) { | 
					
						
							| 
									
										
										
										
											2023-03-01 17:24:50 +01:00
										 |  |  |                 u32 crc32 = TRY(m_input_stream->read_value<LittleEndian<u32>>()); | 
					
						
							|  |  |  |                 u32 input_size = TRY(m_input_stream->read_value<LittleEndian<u32>>()); | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |                 if (crc32 != current_member().m_checksum.digest()) | 
					
						
							|  |  |  |                     return Error::from_string_literal("Stored CRC32 does not match the calculated CRC32 of the current member"); | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |                 if (input_size != current_member().m_nread) | 
					
						
							|  |  |  |                     return Error::from_string_literal("Input size does not match the number of read bytes"); | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |                 m_current_member.clear(); | 
					
						
							| 
									
										
										
										
											2020-09-13 12:24:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 22:01:44 +01:00
										 |  |  |                 total_read += current_slice.size(); | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-03-16 17:39:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 22:01:44 +01:00
										 |  |  |             total_read += current_slice.size(); | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |             continue; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |             auto current_partial_header_slice = Bytes { m_partial_header, sizeof(BlockHeader) }.slice(m_partial_header_offset); | 
					
						
							| 
									
										
										
										
											2023-02-24 22:38:01 +01:00
										 |  |  |             auto current_partial_header_data = TRY(m_input_stream->read_some(current_partial_header_slice)); | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |             m_partial_header_offset += current_partial_header_data.size(); | 
					
						
							| 
									
										
										
										
											2021-03-16 17:39:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |             if (is_eof()) | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |             if (m_partial_header_offset < sizeof(BlockHeader)) { | 
					
						
							|  |  |  |                 break; // partial header read
 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             m_partial_header_offset = 0; | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |             BlockHeader header = *(reinterpret_cast<BlockHeader*>(m_partial_header)); | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |             if (!header.valid_magic_number()) | 
					
						
							|  |  |  |                 return Error::from_string_literal("Header does not have a valid magic number"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (!header.supported_by_implementation()) | 
					
						
							|  |  |  |                 return Error::from_string_literal("Header is not supported by implementation"); | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |             if (header.flags & Flags::FEXTRA) { | 
					
						
							| 
									
										
										
										
											2023-03-01 17:24:50 +01:00
										 |  |  |                 u16 subfield_id = TRY(m_input_stream->read_value<LittleEndian<u16>>()); | 
					
						
							|  |  |  |                 u16 length = TRY(m_input_stream->read_value<LittleEndian<u16>>()); | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |                 TRY(m_input_stream->discard(length)); | 
					
						
							| 
									
										
										
										
											2023-03-01 17:24:50 +01:00
										 |  |  |                 (void)subfield_id; | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-03-03 23:54:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |             auto discard_string = [&]() -> ErrorOr<void> { | 
					
						
							| 
									
										
										
										
											2021-05-18 00:26:16 +03:00
										 |  |  |                 char next_char; | 
					
						
							|  |  |  |                 do { | 
					
						
							| 
									
										
										
										
											2023-03-01 17:24:50 +01:00
										 |  |  |                     next_char = TRY(m_input_stream->read_value<char>()); | 
					
						
							| 
									
										
										
										
											2021-05-18 00:26:16 +03:00
										 |  |  |                 } while (next_char); | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 return {}; | 
					
						
							| 
									
										
										
										
											2021-05-18 00:26:16 +03:00
										 |  |  |             }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |             if (header.flags & Flags::FNAME) | 
					
						
							|  |  |  |                 TRY(discard_string()); | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |             if (header.flags & Flags::FCOMMENT) | 
					
						
							|  |  |  |                 TRY(discard_string()); | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (header.flags & Flags::FHCRC) { | 
					
						
							| 
									
										
										
										
											2023-03-01 17:24:50 +01:00
										 |  |  |                 u16 crc = TRY(m_input_stream->read_value<LittleEndian<u16>>()); | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |                 // FIXME: we should probably verify this instead of just assuming it matches
 | 
					
						
							| 
									
										
										
										
											2023-03-01 17:24:50 +01:00
										 |  |  |                 (void)crc; | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 00:38:05 +01:00
										 |  |  |             m_current_member = TRY(Member::construct(header, *m_input_stream)); | 
					
						
							| 
									
										
										
										
											2021-03-21 15:13:19 +02:00
										 |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |     return bytes.slice(0, total_read); | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  | Optional<DeprecatedString> GzipDecompressor::describe_header(ReadonlyBytes bytes) | 
					
						
							| 
									
										
										
										
											2021-05-07 23:40:02 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     if (bytes.size() < sizeof(BlockHeader)) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 20:58:27 +03:00
										 |  |  |     auto& header = *(reinterpret_cast<BlockHeader const*>(bytes.data())); | 
					
						
							| 
									
										
										
										
											2021-05-07 23:40:02 +03:00
										 |  |  |     if (!header.valid_magic_number() || !header.supported_by_implementation()) | 
					
						
							|  |  |  |         return {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 20:58:27 +03:00
										 |  |  |     LittleEndian<u32> original_size = *reinterpret_cast<u32 const*>(bytes.offset(bytes.size() - sizeof(u32))); | 
					
						
							| 
									
										
										
										
											2022-12-06 01:12:49 +00:00
										 |  |  |     return DeprecatedString::formatted("last modified: {}, original size {}", Core::DateTime::from_timestamp(header.modification_time).to_deprecated_string(), (u32)original_size); | 
					
						
							| 
									
										
										
										
											2021-05-07 23:40:02 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  | ErrorOr<ByteBuffer> GzipDecompressor::decompress_all(ReadonlyBytes bytes) | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-30 11:05:43 +01:00
										 |  |  |     auto memory_stream = TRY(try_make<FixedMemoryStream>(bytes)); | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |     auto gzip_stream = make<GzipDecompressor>(move(memory_stream)); | 
					
						
							| 
									
										
										
										
											2023-01-25 20:19:05 +01:00
										 |  |  |     AllocatingMemoryStream output_stream; | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  |     auto buffer = TRY(ByteBuffer::create_uninitialized(4096)); | 
					
						
							|  |  |  |     while (!gzip_stream->is_eof()) { | 
					
						
							| 
									
										
										
										
											2023-02-24 22:38:01 +01:00
										 |  |  |         auto const data = TRY(gzip_stream->read_some(buffer)); | 
					
						
							| 
									
										
										
										
											2023-03-01 15:37:45 +01:00
										 |  |  |         TRY(output_stream.write_until_depleted(data)); | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-01 00:55:23 +01:00
										 |  |  |     auto output_buffer = TRY(ByteBuffer::create_uninitialized(output_stream.used_buffer_size())); | 
					
						
							| 
									
										
										
										
											2023-03-01 15:27:35 +01:00
										 |  |  |     TRY(output_stream.read_until_filled(output_buffer)); | 
					
						
							| 
									
										
										
										
											2023-01-01 00:55:23 +01:00
										 |  |  |     return output_buffer; | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-29 15:43:31 +01:00
										 |  |  | bool GzipDecompressor::is_eof() const { return m_input_stream->is_eof(); } | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-24 22:38:01 +01:00
										 |  |  | ErrorOr<size_t> GzipDecompressor::write_some(ReadonlyBytes) | 
					
						
							| 
									
										
										
										
											2021-03-16 15:20:46 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-12-14 14:30:58 +01:00
										 |  |  |     return Error::from_errno(EBADF); | 
					
						
							| 
									
										
										
										
											2021-03-16 15:20:46 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-10 01:00:18 +01:00
										 |  |  | GzipCompressor::GzipCompressor(MaybeOwned<Stream> stream) | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  |     : m_output_stream(move(stream)) | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-24 22:38:01 +01:00
										 |  |  | ErrorOr<Bytes> GzipCompressor::read_some(Bytes) | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return Error::from_errno(EBADF); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-24 22:38:01 +01:00
										 |  |  | ErrorOr<size_t> GzipCompressor::write_some(ReadonlyBytes bytes) | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     BlockHeader header; | 
					
						
							|  |  |  |     header.identification_1 = 0x1f; | 
					
						
							|  |  |  |     header.identification_2 = 0x8b; | 
					
						
							|  |  |  |     header.compression_method = 0x08; | 
					
						
							|  |  |  |     header.flags = 0; | 
					
						
							|  |  |  |     header.modification_time = 0; | 
					
						
							|  |  |  |     header.extra_flags = 3;      // DEFLATE sets 2 for maximum compression and 4 for minimum compression
 | 
					
						
							|  |  |  |     header.operating_system = 3; // unix
 | 
					
						
							| 
									
										
										
										
											2023-03-01 15:37:45 +01:00
										 |  |  |     TRY(m_output_stream->write_until_depleted({ &header, sizeof(header) })); | 
					
						
							| 
									
										
										
										
											2023-01-22 04:24:18 +01:00
										 |  |  |     auto compressed_stream = TRY(DeflateCompressor::construct(MaybeOwned(*m_output_stream))); | 
					
						
							| 
									
										
										
										
											2023-03-01 15:37:45 +01:00
										 |  |  |     TRY(compressed_stream->write_until_depleted(bytes)); | 
					
						
							| 
									
										
										
										
											2023-01-03 18:59:27 +01:00
										 |  |  |     TRY(compressed_stream->final_flush()); | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  |     Crypto::Checksum::CRC32 crc32; | 
					
						
							|  |  |  |     crc32.update(bytes); | 
					
						
							|  |  |  |     LittleEndian<u32> digest = crc32.digest(); | 
					
						
							|  |  |  |     LittleEndian<u32> size = bytes.size(); | 
					
						
							| 
									
										
										
										
											2023-03-01 15:37:45 +01:00
										 |  |  |     TRY(m_output_stream->write_until_depleted(digest.bytes())); | 
					
						
							|  |  |  |     TRY(m_output_stream->write_until_depleted(size.bytes())); | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  |     return bytes.size(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  | bool GzipCompressor::is_eof() const | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  | bool GzipCompressor::is_open() const | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  |     return m_output_stream->is_open(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  | void GzipCompressor::close() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  | ErrorOr<ByteBuffer> GzipCompressor::compress_all(ReadonlyBytes bytes) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-25 20:19:05 +01:00
										 |  |  |     auto output_stream = TRY(try_make<AllocatingMemoryStream>()); | 
					
						
							| 
									
										
										
										
											2023-02-10 01:00:18 +01:00
										 |  |  |     GzipCompressor gzip_stream { MaybeOwned<Stream>(*output_stream) }; | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-01 15:37:45 +01:00
										 |  |  |     TRY(gzip_stream.write_until_depleted(bytes)); | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto buffer = TRY(ByteBuffer::create_uninitialized(output_stream->used_buffer_size())); | 
					
						
							| 
									
										
										
										
											2023-03-01 15:27:35 +01:00
										 |  |  |     TRY(output_stream->read_until_filled(buffer.bytes())); | 
					
						
							| 
									
										
										
										
											2022-12-27 11:40:23 +01:00
										 |  |  |     return buffer; | 
					
						
							| 
									
										
										
										
											2021-03-13 01:26:44 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-28 17:53:57 +02:00
										 |  |  | } |