int main(int argc, char **argv)
{
  Client::Configuration configuration;
  configuration.auto_connect = true;
  configuration.client_id = "libkafka_asio_example";
  configuration.socket_timeout = 10000;
  configuration.AddBrokerFromString("192.168.15.137:49162");

  boost::asio::io_service ios;
  Client client(ios, configuration);

  // Create a 'Fetch' request and try to get data for partition 0 of topic
  // 'mytopic', starting with offset 1
  FetchRequest request;
  request.FetchTopic("mytopic", 0, 1);

  // Helper to interpret the received bytes as string
  auto BytesToString = [](const libkafka_asio::Bytes& bytes) -> std::string
  {
    if (!bytes || bytes->empty())
    {
      return "";
    }
    return std::string((const char*) &(*bytes)[0], bytes->size());
  };

  // Send the prepared fetch request.
  // The client will attempt to automatically connect to the broker, specified
  // in the configuration.
  client.AsyncRequest(
    request,
    [&](const Client::ErrorCodeType& err,
        const FetchResponse::OptionalType& response)
  {
    if (err)
    {
      std::cerr
        << "Error: " << boost::system::system_error(err).what()
        << std::endl;
      return;
    }

    // Loop through the received messages.
    // A range based for loop might also work.
    std::for_each(response->begin(), response->end(),
      [&](const MessageAndOffset& message)
    {
      std::cout << BytesToString(message.value()) << std::endl;
    });
  });

  // Let's go!
  ios.run();
  return 0;
}
TEST_F(RequestWriteTest, RequestMessageWireSize)
{
  MessageAndOffset test_message;
  test_message.mutable_key().reset(new Bytes::element_type(1024));
  test_message.mutable_value().reset(new Bytes::element_type(2048));
  // See test above
  size_t expected_message_size = MessageWireSize(test_message);

  { // Metadata Request
    MetadataRequest req;
    req.AddTopicName("foo");
    req.AddTopicName("bar!");
    size_t expected_size =
      4 +        // Array size
        (2 + 3) +  // 'foo'
        (2 + 4);   // 'bar'
    ASSERT_EQ(expected_size, RequestMessageWireSize(req));
  }
  { // Produce Request
    ProduceRequest req;
    req.AddMessage(test_message, "bar!");
    size_t expected_size =
      2 +  // RequiredAcks
        4 +  // Timeout
        4 +  // Topic Array Size
        (2 + 4) +  // 'bar!'
        4 +  // Partition Array Size
        4 +  // Partition
        4 +  // MessageSetSize
        (8 + 4 + expected_message_size);  // MessageSet
    ASSERT_EQ(expected_size, RequestMessageWireSize(req));
  }
  { // Fetch Request
    FetchRequest req;
    req.FetchTopic("foo", 0);
    size_t expected_size =
      4 +  // ReplicaId
        4 +  // MaxWaitTime
        4 +  // MinBytes
        4 +  // Topic Array Size
        (2 + 3) +  // 'foo'
        4 +  // Partition Array Size
        4 +  // Partition
        8 +  // Fetch Offset
        4;   // MaxBytes
    ASSERT_EQ(expected_size, RequestMessageWireSize(req));
  }
  { // Offset Request
    OffsetRequest req;
    req.FetchTopicOffset("foo", 0, 2500);
    size_t expected_size =
      4 +  // ReplicaId
        4 +  // Topic Array Size
        (2 + 3) +  // 'foo'
        4 +  // Partition Array Size
        4 +  // Partition
        8 +  // Time
        4;   // MaxNumberOfOffsets
    ASSERT_EQ(expected_size, RequestMessageWireSize(req));
  }
}