#pragma once
#include <drogon/exports.h>
#include <memory>
#include <string>
#include <future>
#include <algorithm>
#include <assert.h>
namespace drogon
{
namespace orm
{
class ConstResultIterator;
class ConstReverseResultIterator;
class Row;
class ResultImpl;
using ResultImplPtr = std::shared_ptr<ResultImpl>;
enum class SqlStatus
{
    Ok,
    End
};
class DROGON_EXPORT Result
{
  public:
    explicit Result(ResultImplPtr ptr) : resultPtr_(std::move(ptr))
    {
    }
    Result(const Result &r) noexcept = default;
    Result(Result &&) noexcept = default;
    Result &operator=(const Result &r) noexcept;
    Result &operator=(Result &&) noexcept;
    using DifferenceType = long;
    using SizeType = size_t;
    using Reference = Row;
    using ConstIterator = ConstResultIterator;
    using Iterator = ConstIterator;
    using RowSizeType = unsigned long;
    using FieldSizeType = unsigned long;
    using ConstReverseIterator = ConstReverseResultIterator;
    using ReverseIterator = ConstReverseIterator;
    using value_type = Row;
    using size_type = SizeType;
    using difference_type = DifferenceType;
    using reference = Reference;
    using const_reference = const Reference;
    using iterator = Iterator;
    using const_iterator = ConstIterator;
    using reverse_iterator = ConstReverseIterator;
    using const_reverse_iterator = ConstReverseIterator;
    SizeType size() const noexcept;
    SizeType capacity() const noexcept
    {
        return size();
    }
    ConstIterator begin() const noexcept;
    ConstIterator cbegin() const noexcept;
    ConstIterator end() const noexcept;
    ConstIterator cend() const noexcept;
    ConstReverseIterator rbegin() const;
    ConstReverseIterator crbegin() const;
    ConstReverseIterator rend() const;
    ConstReverseIterator crend() const;
    bool empty() const noexcept
    {
        return size() == 0;
    }
    Reference front() const noexcept;
    Reference back() const noexcept;
    Reference operator[](SizeType index) const noexcept;
    Reference at(SizeType index) const;
    void swap(Result &) noexcept;
    RowSizeType columns() const noexcept;
    const char *columnName(RowSizeType number) const;
    SizeType affectedRows() const noexcept;
    unsigned long long insertId() const noexcept;
#ifdef _MSC_VER
    Result() noexcept = default;
#endif
  private:
    ResultImplPtr resultPtr_;
    friend class Field;
    friend class Row;
    RowSizeType columnNumber(const char colName[]) const;
    RowSizeType columnNumber(const std::string &name) const
    {
        return columnNumber(name.c_str());
    }
    int oid(RowSizeType column) const noexcept;
    const char *getValue(SizeType row, RowSizeType column) const;
    bool isNull(SizeType row, RowSizeType column) const;
    FieldSizeType getLength(SizeType row, RowSizeType column) const;
};
inline void swap(Result &one, Result &two) noexcept
{
    one.swap(two);
}
}  
}  
#ifndef _MSC_VER
namespace std
{
template <>
inline void swap(drogon::orm::Result &one, drogon::orm::Result &two) noexcept
{
    one.swap(two);
}
}  
#endif