summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibIPC/Decoder.cpp
blob: bfe6a1493c11bca59da872615770c112f916d50a (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
/*
 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <AK/JsonValue.h>
#include <AK/NumericLimits.h>
#include <AK/URL.h>
#include <LibCore/AnonymousBuffer.h>
#include <LibCore/DateTime.h>
#include <LibCore/Proxy.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Dictionary.h>
#include <LibIPC/File.h>
#include <fcntl.h>

namespace IPC {

ErrorOr<size_t> Decoder::decode_size()
{
    return static_cast<size_t>(TRY(decode<u32>()));
}

template<>
ErrorOr<DeprecatedString> decode(Decoder& decoder)
{
    auto length = TRY(decoder.decode_size());
    if (length == NumericLimits<u32>::max())
        return DeprecatedString {};
    if (length == 0)
        return DeprecatedString::empty();

    char* text_buffer = nullptr;
    auto text_impl = StringImpl::create_uninitialized(length, text_buffer);

    Bytes bytes { text_buffer, length };
    TRY(decoder.decode_into(bytes));

    return DeprecatedString { *text_impl };
}

template<>
ErrorOr<ByteBuffer> decode(Decoder& decoder)
{
    auto length = TRY(decoder.decode_size());
    if (length == 0)
        return ByteBuffer {};

    auto buffer = TRY(ByteBuffer::create_uninitialized(length));
    auto bytes = buffer.bytes();

    TRY(decoder.decode_into(bytes));
    return buffer;
}

template<>
ErrorOr<JsonValue> decode(Decoder& decoder)
{
    auto json = TRY(decoder.decode<DeprecatedString>());
    return JsonValue::from_string(json);
}

template<>
ErrorOr<URL> decode(Decoder& decoder)
{
    auto url = TRY(decoder.decode<DeprecatedString>());
    return URL { url };
}

template<>
ErrorOr<Dictionary> decode(Decoder& decoder)
{
    auto size = TRY(decoder.decode_size());
    Dictionary dictionary {};

    for (size_t i = 0; i < size; ++i) {
        auto key = TRY(decoder.decode<DeprecatedString>());
        auto value = TRY(decoder.decode<DeprecatedString>());
        dictionary.add(move(key), move(value));
    }

    return dictionary;
}

template<>
ErrorOr<File> decode(Decoder& decoder)
{
    int fd = TRY(decoder.socket().receive_fd(O_CLOEXEC));
    return File { fd, File::ConstructWithReceivedFileDescriptor };
}

template<>
ErrorOr<Empty> decode(Decoder&)
{
    return Empty {};
}

template<>
ErrorOr<Core::AnonymousBuffer> decode(Decoder& decoder)
{
    if (auto valid = TRY(decoder.decode<bool>()); !valid)
        return Core::AnonymousBuffer {};

    auto size = TRY(decoder.decode_size());
    auto anon_file = TRY(decoder.decode<IPC::File>());

    return Core::AnonymousBuffer::create_from_anon_fd(anon_file.take_fd(), size);
}

template<>
ErrorOr<Core::DateTime> decode(Decoder& decoder)
{
    auto timestamp = TRY(decoder.decode<i64>());
    return Core::DateTime::from_timestamp(static_cast<time_t>(timestamp));
}

template<>
ErrorOr<Core::ProxyData> decode(Decoder& decoder)
{
    auto type = TRY(decoder.decode<Core::ProxyData::Type>());
    auto host_ipv4 = TRY(decoder.decode<u32>());
    auto port = TRY(decoder.decode<int>());

    return Core::ProxyData { type, host_ipv4, port };
}

}