/*
 * Copyright 2013 MongoDB, Inc.
 *
 * Licensed 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.
 */

#ifndef MONGOC_RPC_PRIVATE_H
#define MONGOC_RPC_PRIVATE_H

#if !defined (MONGOC_COMPILATION)
#error "Only <mongoc.h> can be included directly."
#endif

#include <bson.h>
#include <stddef.h>

#include "mongoc-array-private.h"
#include "mongoc-iovec.h"
#include "mongoc-write-concern.h"
#include "mongoc-flags.h"


BSON_BEGIN_DECLS


#define RPC(_name, _code)                typedef struct { _code } mongoc_rpc_##_name##_t;
#define ENUM_FIELD(_name)                uint32_t _name;
#define INT32_FIELD(_name)               int32_t _name;
#define INT64_FIELD(_name)               int64_t _name;
#define INT64_ARRAY_FIELD(_len, _name)   int32_t _len; int64_t *_name;
#define CSTRING_FIELD(_name)             const char *_name;
#define BSON_FIELD(_name)                const uint8_t *_name;
#define BSON_ARRAY_FIELD(_name)          const uint8_t *_name; int32_t _name##_len;
#define IOVEC_ARRAY_FIELD(_name)         const mongoc_iovec_t *_name; int32_t n_##_name; mongoc_iovec_t _name##_recv;
#define RAW_BUFFER_FIELD(_name)          const uint8_t *_name; int32_t _name##_len;
#define BSON_OPTIONAL(_check, _code)     _code


#pragma pack(1)
#include "op-delete.def"
#include "op-get-more.def"
#include "op-header.def"
#include "op-insert.def"
#include "op-kill-cursors.def"
#include "op-msg.def"
#include "op-query.def"
#include "op-reply.def"
#include "op-reply-header.def"
#include "op-update.def"
/* restore default packing */
#pragma pack()


typedef union
{
   mongoc_rpc_delete_t       delete_;
   mongoc_rpc_get_more_t     get_more;
   mongoc_rpc_header_t       header;
   mongoc_rpc_insert_t       insert;
   mongoc_rpc_kill_cursors_t kill_cursors;
   mongoc_rpc_msg_t          msg;
   mongoc_rpc_query_t        query;
   mongoc_rpc_reply_t        reply;
   mongoc_rpc_reply_header_t reply_header;
   mongoc_rpc_update_t       update;
} mongoc_rpc_t;


BSON_STATIC_ASSERT (sizeof (mongoc_rpc_header_t) == 16);
BSON_STATIC_ASSERT (offsetof (mongoc_rpc_header_t, opcode) ==
                    offsetof (mongoc_rpc_reply_t, opcode));
BSON_STATIC_ASSERT (sizeof (mongoc_rpc_reply_header_t) == 36);


#undef RPC
#undef ENUM_FIELD
#undef INT32_FIELD
#undef INT64_FIELD
#undef INT64_ARRAY_FIELD
#undef CSTRING_FIELD
#undef BSON_FIELD
#undef BSON_ARRAY_FIELD
#undef IOVEC_ARRAY_FIELD
#undef BSON_OPTIONAL
#undef RAW_BUFFER_FIELD


void _mongoc_rpc_gather                    (mongoc_rpc_t                 *rpc,
                                            mongoc_array_t               *array);
bool _mongoc_rpc_needs_gle                 (mongoc_rpc_t                 *rpc,
                                            const mongoc_write_concern_t *write_concern);
void _mongoc_rpc_swab_to_le                (mongoc_rpc_t                 *rpc);
void _mongoc_rpc_swab_from_le              (mongoc_rpc_t                 *rpc);
void _mongoc_rpc_printf                    (mongoc_rpc_t                 *rpc);
bool _mongoc_rpc_scatter                   (mongoc_rpc_t                 *rpc,
                                            const uint8_t                *buf,
                                            size_t                        buflen);
bool _mongoc_rpc_scatter_reply_header_only (mongoc_rpc_t                 *rpc,
                                            const uint8_t                *buf,
                                            size_t                        buflen);
bool _mongoc_rpc_reply_get_first           (mongoc_rpc_reply_t           *reply,
                                            bson_t                       *bson);
void _mongoc_rpc_prep_command              (mongoc_rpc_t                 *rpc,
                                            const char                   *cmd_ns,
                                            const bson_t                 *command,
                                            mongoc_query_flags_t          flags);
bool _mongoc_rpc_parse_command_error       (mongoc_rpc_t                 *rpc,
                                            int32_t                       error_api_version,
                                            bson_error_t                 *error);
bool _mongoc_rpc_parse_query_error         (mongoc_rpc_t                 *rpc,
                                            int32_t                       error_api_version,
                                            bson_error_t                 *error);
bool _mongoc_populate_cmd_error            (const bson_t                 *doc,
                                            int32_t                       error_api_version,
                                            bson_error_t                 *error);

BSON_END_DECLS


#endif /* MONGOC_RPC_PRIVATE_H */
