// This file was GENERATED by command:
//     pump.py callback_function.h.pump
// DO NOT EDIT BY HAND!!!

// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// 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 COBALT_SCRIPT_CALLBACK_FUNCTION_H_
#define COBALT_SCRIPT_CALLBACK_FUNCTION_H_

#include "base/callback.h"
#include "base/callback_internal.h"

// Abstract template interface that represents an IDL callback function
// http://heycam.github.io/webidl/#idl-callback-functions
//
// The JavaScript implementation will instantiate a class that implements this
// interface, and will execute JavaScript code when the Run(...) function is
// executed.

namespace cobalt {
namespace script {

template <typename R>
struct CallbackResult {
  CallbackResult() : result(R()), exception(false) {}
  R result;
  bool exception;
};

template <>
struct CallbackResult<void> {
  CallbackResult() : exception(false) {}
  bool exception;
};

// First, we forward declare the CallbackFunction class template. This informs
// the compiler that the template only has 1 type parameter which is the
// function signature that the CallbackFunction is representing.
//
// See base/callback.h.pump for further discussion on this pattern.
template <typename Sig>
class CallbackFunction;

template <typename R>
class CallbackFunction<R(void)> {
 public:
  typedef R Signature(void);
  typedef CallbackResult<R> ReturnValue;

  virtual CallbackResult<R> Run()
      const = 0;

 protected:
  virtual ~CallbackFunction() {}
};
template <typename R, typename A1>
class CallbackFunction<R(A1)> {
 public:
  typedef R Signature(A1);
  typedef CallbackResult<R> ReturnValue;

  virtual CallbackResult<R> Run(
      typename base::internal::CallbackParamTraits<A1>::ForwardType a1)
      const = 0;

 protected:
  virtual ~CallbackFunction() {}
};
template <typename R, typename A1, typename A2>
class CallbackFunction<R(A1, A2)> {
 public:
  typedef R Signature(A1, A2);
  typedef CallbackResult<R> ReturnValue;

  virtual CallbackResult<R> Run(
      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
      typename base::internal::CallbackParamTraits<A2>::ForwardType a2)
      const = 0;

 protected:
  virtual ~CallbackFunction() {}
};
template <typename R, typename A1, typename A2, typename A3>
class CallbackFunction<R(A1, A2, A3)> {
 public:
  typedef R Signature(A1, A2, A3);
  typedef CallbackResult<R> ReturnValue;

  virtual CallbackResult<R> Run(
      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
      typename base::internal::CallbackParamTraits<A3>::ForwardType a3)
      const = 0;

 protected:
  virtual ~CallbackFunction() {}
};
template <typename R, typename A1, typename A2, typename A3, typename A4>
class CallbackFunction<R(A1, A2, A3, A4)> {
 public:
  typedef R Signature(A1, A2, A3, A4);
  typedef CallbackResult<R> ReturnValue;

  virtual CallbackResult<R> Run(
      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
      typename base::internal::CallbackParamTraits<A4>::ForwardType a4)
      const = 0;

 protected:
  virtual ~CallbackFunction() {}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
    typename A5>
class CallbackFunction<R(A1, A2, A3, A4, A5)> {
 public:
  typedef R Signature(A1, A2, A3, A4, A5);
  typedef CallbackResult<R> ReturnValue;

  virtual CallbackResult<R> Run(
      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
      typename base::internal::CallbackParamTraits<A5>::ForwardType a5)
      const = 0;

 protected:
  virtual ~CallbackFunction() {}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
    typename A5, typename A6>
class CallbackFunction<R(A1, A2, A3, A4, A5, A6)> {
 public:
  typedef R Signature(A1, A2, A3, A4, A5, A6);
  typedef CallbackResult<R> ReturnValue;

  virtual CallbackResult<R> Run(
      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
      typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
      typename base::internal::CallbackParamTraits<A6>::ForwardType a6)
      const = 0;

 protected:
  virtual ~CallbackFunction() {}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
    typename A5, typename A6, typename A7>
class CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> {
 public:
  typedef R Signature(A1, A2, A3, A4, A5, A6, A7);
  typedef CallbackResult<R> ReturnValue;

  virtual CallbackResult<R> Run(
      typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
      typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
      typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
      typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
      typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
      typename base::internal::CallbackParamTraits<A6>::ForwardType a6,
      typename base::internal::CallbackParamTraits<A7>::ForwardType a7)
      const = 0;

 protected:
  virtual ~CallbackFunction() {}
};

}  // namespace script
}  // namespace cobalt

#endif  // COBALT_SCRIPT_CALLBACK_FUNCTION_H_
