Coverage Report

Created: 2025-03-04 07:22

/src/serenity/Userland/Libraries/LibCompress/PackBitsDecoder.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2023, Lucas Chollet <lucas.chollet@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include "PackBitsDecoder.h"
8
#include <AK/MemoryStream.h>
9
10
namespace Compress::PackBits {
11
12
ErrorOr<ByteBuffer> decode_all(ReadonlyBytes bytes, Optional<u64> expected_output_size, CompatibilityMode mode)
13
4.15k
{
14
    // This implementation uses unsigned values for the selector, as described in the PDF spec.
15
    // Note that this remains compatible with other implementations based on signed numbers.
16
17
4.15k
    auto memory_stream = make<FixedMemoryStream>(bytes);
18
19
4.15k
    ByteBuffer decoded_bytes;
20
21
4.15k
    if (expected_output_size.has_value())
22
4.00k
        TRY(decoded_bytes.try_ensure_capacity(*expected_output_size));
23
24
1.71M
    while (memory_stream->remaining() > 0 && decoded_bytes.size() < expected_output_size.value_or(NumericLimits<u64>::max())) {
25
1.71M
        auto const length = TRY(memory_stream->read_value<u8>());
26
27
1.71M
        if (length < 128) {
28
1.91M
            for (u8 i = 0; i <= length; ++i)
29
1.67M
                TRY(decoded_bytes.try_append(TRY(memory_stream->read_value<u8>())));
30
1.47M
        } else if (length > 128) {
31
1.47M
            auto const next_byte = TRY(memory_stream->read_value<u8>());
32
33
128M
            for (u8 i = 0; i < 257 - length; ++i)
34
127M
                TRY(decoded_bytes.try_append(next_byte));
35
1.47M
        } else {
36
1.45k
            VERIFY(length == 128);
37
1.45k
            if (mode == CompatibilityMode::PDF)
38
0
                break;
39
1.45k
        }
40
1.71M
    }
41
42
4.08k
    return decoded_bytes;
43
4.15k
}
44
45
}