include/wrenbind17/any.hpp

include/wrenbind17/any.hpp #

Namespaces #

Name
wrenbind17

Classes #

Name
class wrenbind17::ReturnValue A return value when calling a Wren function (alias Any)

Source code #

#pragma once

#include <typeinfo>
#include <memory>

#include "handle.hpp"
#include "pop.hpp"
#include "push.hpp"

namespace wrenbind17 {
    class ReturnValue {
    public:
        ReturnValue() = default;
        explicit ReturnValue(const WrenType type, Handle handle) : type(type), handle(std::move(handle)) {
        }
        ~ReturnValue() = default;

        ReturnValue(const ReturnValue& other) = delete;
        ReturnValue(ReturnValue&& other) noexcept {
            swap(other);
        }

        ReturnValue& operator=(const ReturnValue& other) = delete;
        ReturnValue& operator=(ReturnValue&& other) noexcept {
            if (this != &other) {
                swap(other);
            }
            return *this;
        }

        void swap(ReturnValue& other) noexcept {
            std::swap(type, other.type);
            std::swap(handle, other.handle);
        }

        const Handle& getHandle() const {
            return handle;
        }

        Handle& getHandle() {
            return handle;
        }

        WrenType getType() const {
            return type;
        }

        template <class T> bool is() const {
            if (type == WREN_TYPE_NULL) {
                return false;
            }
            if (const auto vm = handle.getVmWeak().lock()) {
                wrenEnsureSlots(vm.get(), 1);
                wrenSetSlotHandle(vm.get(), 0, handle.getHandle());
                using Type = typename std::remove_reference<typename std::remove_pointer<T>::type>::type;
                return detail::is<Type>(vm.get(), 0);
            } else {
                throw RuntimeError("Invalid handle");
            }
        }

        bool isMap() const {
            return type == WREN_TYPE_MAP;
        }

        bool isList() const {
            return type == WREN_TYPE_LIST;
        }

        template <class T> T as() {
            if (type == WREN_TYPE_NULL) {
                throw BadCast("Bad cast when getting value from Wren");
            }
            if (const auto vm = handle.getVmWeak().lock()) {
                wrenEnsureSlots(vm.get(), 1);
                wrenSetSlotHandle(vm.get(), 0, handle.getHandle());
                return detail::PopHelper<T>::f(vm.get(), 0);
            } else {
                throw RuntimeError("Invalid handle");
            }
        }

        template <class T> std::shared_ptr<T> shared() {
            return as<std::shared_ptr<T>>();
        }

    private:
        WrenType type = WrenType::WREN_TYPE_NULL;
        Handle handle;
    };

#ifndef DOXYGEN_SHOULD_SKIP_THIS
    template <> inline bool ReturnValue::is<int8_t>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<char>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<short>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<int>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<long>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<long long>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<unsigned char>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<unsigned short>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<unsigned int>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<unsigned long>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<unsigned long long>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<float>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<double>() const {
        return type == WREN_TYPE_NUM;
    }

    template <> inline bool ReturnValue::is<bool>() const {
        return type == WREN_TYPE_BOOL;
    }

    template <> inline bool ReturnValue::is<std::nullptr_t>() const {
        return type == WREN_TYPE_NULL;
    }

    template <> inline bool ReturnValue::is<std::string>() const {
        return type == WREN_TYPE_STRING;
    }

    template <> inline std::nullptr_t ReturnValue::as<std::nullptr_t>() {
        if (!is<std::nullptr_t>()) {
            throw BadCast("Return value is not a null");
        }
        return nullptr;
    }
#endif

    using Any = ReturnValue;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
    template <> inline Any detail::getSlot(WrenVM* vm, const int idx) {
        const auto type = wrenGetSlotType(vm, 0);
        if (type == WREN_TYPE_NULL) {
            return Any();
        }
        return Any(type, Handle(getSharedVm(vm), wrenGetSlotHandle(vm, idx)));
    }
#endif
} // namespace wrenbind17

Updated on 17 October 2023 at 12:26:25 UTC