blob: 82652ae4a9e66b7c79d95f678c83c881f1e74204 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "ignite/common/bytes_view.h"
#include "ignite/common/detail/bytes.h"
#include "ignite/common/uuid.h"
#include "ignite/protocol/bitset_span.h"
#include "ignite/protocol/buffer_adapter.h"
#include "ignite/protocol/extension_types.h"
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <msgpack.h>
#include <string_view>
namespace ignite::protocol {
/**
* Writer.
*/
class writer {
public:
// Default
~writer() = default;
// Deleted
writer() = delete;
writer(writer &&) = delete;
writer(const writer &) = delete;
writer &operator=(writer &&) = delete;
writer &operator=(const writer &) = delete;
/**
* Constructor.
*
* @param buffer Buffer.
*/
explicit writer(buffer_adapter &buffer)
: m_buffer(buffer)
, m_packer(msgpack_packer_new(&m_buffer, write_callback), msgpack_packer_free) {
assert(m_packer.get());
}
/**
* Write int value.
*
* @param value Value to write.
*/
void write(std::int8_t value) { msgpack_pack_int8(m_packer.get(), value); }
/**
* Write int value.
*
* @param value Value to write.
*/
void write(std::int16_t value) { msgpack_pack_int16(m_packer.get(), value); }
/**
* Write int value.
*
* @param value Value to write.
*/
void write(std::int32_t value) { msgpack_pack_int32(m_packer.get(), value); }
/**
* Write int value.
*
* @param value Value to write.
*/
void write(std::int64_t value) { msgpack_pack_int64(m_packer.get(), value); }
/**
* Write string value.
*
* @param value Value to write.
*/
void write(std::string_view value) { msgpack_pack_str_with_body(m_packer.get(), value.data(), value.size()); }
/**
* Write UUID value.
*
* @param value Value to write.
*/
void write(uuid value) {
std::byte data[16];
detail::bytes::store<detail::endian::LITTLE, std::int64_t>(&data[0], value.get_most_significant_bits());
detail::bytes::store<detail::endian::LITTLE, std::int64_t>(&data[8], value.get_least_significant_bits());
msgpack_pack_ext_with_body(m_packer.get(), &data, 16, std::int8_t(extension_type::UUID));
}
/**
* Write nil value.
*/
void write_nil() { msgpack_pack_nil(m_packer.get()); }
/**
* Write empty binary data.
*/
void write_binary_empty() { msgpack_pack_bin(m_packer.get(), 0); }
/**
* Write binary data.
*
* @param data Binary data to pack.
*/
void write_binary(bytes_view data) { msgpack_pack_bin_with_body(m_packer.get(), data.data(), data.size()); }
/**
* Write empty map.
*/
void write_map_empty() { msgpack_pack_map(m_packer.get(), 0); }
/**
* Write map.
*
* @param values Map.
*/
void write_map(const std::map<std::string, std::string> &values) {
write(std::int32_t(values.size()));
for (const auto &pair : values) {
write(pair.first);
write(pair.second);
}
}
/**
* Write bitset.
*
* @param data Bitset to write.
*/
void write_bitset(bytes_view data) {
msgpack_pack_ext_with_body(m_packer.get(), data.data(), data.size(), std::int8_t(extension_type::BITMASK));
}
/**
* Write boolean.
*
* @param value Value to write.
*/
void write_bool(bool value) {
if (value) {
msgpack_pack_true(m_packer.get());
} else {
msgpack_pack_false(m_packer.get());
}
}
private:
/**
* Write callback.
*
* @param data Pointer to the instance.
* @param buf Data to write.
* @param len Data length.
* @return Write result.
*/
static int write_callback(void *data, const char *buf, size_t len);
/** Buffer adapter. */
buffer_adapter &m_buffer;
/** Packer. */
std::unique_ptr<msgpack_packer, void (*)(msgpack_packer *)> m_packer;
};
/**
* Write message to buffer.
*
* @param buffer Buffer to use.
* @param func Function.
*/
inline void write_message_to_buffer(buffer_adapter &buffer, const std::function<void(writer &)> &func) {
buffer.reserve_length_header();
protocol::writer writer(buffer);
func(writer);
buffer.write_length_header();
}
} // namespace ignite::protocol