Coverage Report

Created: 2025-11-02 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibIPC/Encoder.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
3
 * Copyright (c) 2021, kleines Filmröllchen <filmroellchen@serenityos.org>
4
 * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 */
8
9
#include <AK/BitCast.h>
10
#include <AK/ByteBuffer.h>
11
#include <AK/ByteString.h>
12
#include <AK/JsonObject.h>
13
#include <AK/JsonValue.h>
14
#include <AK/NumericLimits.h>
15
#include <AK/String.h>
16
#include <AK/Time.h>
17
#include <LibCore/AnonymousBuffer.h>
18
#include <LibCore/DateTime.h>
19
#include <LibCore/Proxy.h>
20
#include <LibCore/System.h>
21
#include <LibIPC/Encoder.h>
22
#include <LibIPC/File.h>
23
#include <LibURL/Origin.h>
24
#include <LibURL/URL.h>
25
26
namespace IPC {
27
28
ErrorOr<void> Encoder::encode_size(size_t size)
29
0
{
30
0
    if (static_cast<u64>(size) > static_cast<u64>(NumericLimits<u32>::max()))
31
0
        return Error::from_string_literal("Container exceeds the maximum allowed size");
32
0
    return encode(static_cast<u32>(size));
33
0
}
34
35
template<>
36
ErrorOr<void> encode(Encoder& encoder, float const& value)
37
0
{
38
0
    return encoder.encode(bit_cast<u32>(value));
39
0
}
40
41
template<>
42
ErrorOr<void> encode(Encoder& encoder, double const& value)
43
0
{
44
0
    return encoder.encode(bit_cast<u64>(value));
45
0
}
46
47
template<>
48
ErrorOr<void> encode(Encoder& encoder, String const& value)
49
0
{
50
0
    auto bytes = value.bytes();
51
0
    TRY(encoder.encode_size(bytes.size()));
52
0
    TRY(encoder.append(bytes.data(), bytes.size()));
53
0
    return {};
54
0
}
55
56
template<>
57
ErrorOr<void> encode(Encoder& encoder, StringView const& value)
58
0
{
59
    // NOTE: Do not change this encoding without also updating LibC/netdb.cpp.
60
0
    if (value.is_null())
61
0
        return encoder.encode(NumericLimits<u32>::max());
62
63
0
    TRY(encoder.encode_size(value.length()));
64
0
    TRY(encoder.append(reinterpret_cast<u8 const*>(value.characters_without_null_termination()), value.length()));
65
0
    return {};
66
0
}
67
68
template<>
69
ErrorOr<void> encode(Encoder& encoder, ByteString const& value)
70
0
{
71
0
    return encoder.encode(value.view());
72
0
}
73
74
template<>
75
ErrorOr<void> encode(Encoder& encoder, ByteBuffer const& value)
76
0
{
77
0
    TRY(encoder.encode_size(value.size()));
78
0
    TRY(encoder.append(value.data(), value.size()));
79
0
    return {};
80
0
}
81
82
template<>
83
ErrorOr<void> encode(Encoder& encoder, JsonValue const& value)
84
0
{
85
0
    return encoder.encode(value.serialized<StringBuilder>());
86
0
}
87
88
template<>
89
ErrorOr<void> encode(Encoder& encoder, Duration const& value)
90
0
{
91
0
    return encoder.encode(value.to_nanoseconds());
92
0
}
93
94
template<>
95
ErrorOr<void> encode(Encoder& encoder, UnixDateTime const& value)
96
0
{
97
0
    return encoder.encode(value.nanoseconds_since_epoch());
98
0
}
99
100
template<>
101
ErrorOr<void> encode(Encoder& encoder, URL::URL const& value)
102
0
{
103
0
    TRY(encoder.encode(value.serialize()));
104
105
0
    if (!value.blob_url_entry().has_value())
106
0
        return encoder.encode(false);
107
108
0
    TRY(encoder.encode(true));
109
110
0
    auto const& blob = value.blob_url_entry().value();
111
112
0
    TRY(encoder.encode(blob.type));
113
0
    TRY(encoder.encode(blob.byte_buffer));
114
0
    TRY(encoder.encode(blob.environment_origin));
115
116
0
    return {};
117
0
}
118
119
template<>
120
ErrorOr<void> encode(Encoder& encoder, URL::Origin const& origin)
121
0
{
122
0
    TRY(encoder.encode<ByteString>(origin.scheme()));
123
0
    TRY(encoder.encode(origin.host()));
124
0
    TRY(encoder.encode(origin.port()));
125
126
0
    return {};
127
0
}
128
129
template<>
130
ErrorOr<void> encode(Encoder& encoder, File const& file)
131
0
{
132
0
    int fd = file.take_fd();
133
134
0
    TRY(encoder.append_file_descriptor(fd));
135
0
    return {};
136
0
}
137
138
template<>
139
ErrorOr<void> encode(Encoder&, Empty const&)
140
0
{
141
0
    return {};
142
0
}
143
144
template<>
145
ErrorOr<void> encode(Encoder& encoder, Core::AnonymousBuffer const& buffer)
146
0
{
147
0
    TRY(encoder.encode(buffer.is_valid()));
148
149
0
    if (buffer.is_valid()) {
150
0
        TRY(encoder.encode_size(buffer.size()));
151
0
        TRY(encoder.encode(TRY(IPC::File::clone_fd(buffer.fd()))));
152
0
    }
153
154
0
    return {};
155
0
}
156
157
template<>
158
ErrorOr<void> encode(Encoder& encoder, Core::DateTime const& datetime)
159
0
{
160
0
    return encoder.encode(static_cast<i64>(datetime.timestamp()));
161
0
}
162
163
template<>
164
ErrorOr<void> encode(Encoder& encoder, Core::ProxyData const& proxy)
165
0
{
166
0
    TRY(encoder.encode(proxy.type));
167
0
    TRY(encoder.encode(proxy.host_ipv4));
168
0
    TRY(encoder.encode(proxy.port));
169
0
    return {};
170
0
}
171
172
}