// backend.cpp (Corrected)
#include "httplib.h"
#include "wren.h"
#include <iostream>
#include <string>
// A struct to hold the response data for our foreign object
struct ResponseData {
bool isError;
int statusCode;
std::string body;
};
// --- Response Class Foreign Methods ---
void responseAllocate(WrenVM* vm) {
// This is the constructor for the Response class.
ResponseData* data = (ResponseData*)wrenSetSlotNewForeign(vm, 0, 0, sizeof(ResponseData));
data->isError = false;
data->statusCode = 0;
}
void responseIsError(WrenVM* vm) {
ResponseData* data = (ResponseData*)wrenGetSlotForeign(vm, 0);
wrenSetSlotBool(vm, 0, data->isError);
}
void responseStatusCode(WrenVM* vm) {
ResponseData* data = (ResponseData*)wrenGetSlotForeign(vm, 0);
wrenSetSlotDouble(vm, 0, data->statusCode);
}
void responseBody(WrenVM* vm) {
ResponseData* data = (ResponseData*)wrenGetSlotForeign(vm, 0);
wrenSetSlotBytes(vm, 0, data->body.c_str(), data->body.length());
}
void responseJson(WrenVM* vm) {
// For a real implementation, you would use a JSON library here.
// For this example, we just return the body text.
ResponseData* data = (ResponseData*)wrenGetSlotForeign(vm, 0);
wrenSetSlotBytes(vm, 0, data->body.c_str(), data->body.length());
}
// --- Requests Class Foreign Methods ---
void requestsGet(WrenVM* vm) {
const char* url = wrenGetSlotString(vm, 1);
// TODO: Handle headers from slot 2.
httplib::Client cli("jsonplaceholder.typicode.com");
auto res = cli.Get("/posts/1");
// CHANGED: We need two slots: one for the Response class, one for the new instance.
wrenEnsureSlots(vm, 2);
// CHANGED: Get the 'Response' class from the 'requests' module and put it in slot 1.
wrenGetVariable(vm, "requests", "Response", 1);
// CHANGED: Create a new foreign object instance of the class in slot 1.
// The new instance is placed in slot 0, which becomes the return value.
ResponseData* data = (ResponseData*)wrenSetSlotNewForeign(vm, 0, 1, sizeof(ResponseData));
if (res) {
data->isError = false;
data->statusCode = res->status;
data->body = res->body;
} else {
data->isError = true;
data->statusCode = -1;
data->body = "GET request failed.";
}
}
void requestsPost(WrenVM* vm) {
const char* url = wrenGetSlotString(vm, 1);
const char* body = wrenGetSlotString(vm, 2);
const char* contentType = wrenGetSlotString(vm, 3);
// TODO: Handle headers from slot 4.
httplib::Client cli("jsonplaceholder.typicode.com");
auto res = cli.Post("/posts", body, contentType);
// CHANGED: We need two slots: one for the Response class, one for the new instance.
wrenEnsureSlots(vm, 2);
// CHANGED: Get the 'Response' class from the 'requests' module and put it in slot 1.
wrenGetVariable(vm, "requests", "Response", 1);
// CHANGED: Create a new foreign object instance of the class in slot 1.
// The new instance is placed in slot 0, which becomes the return value.
ResponseData* data = (ResponseData*)wrenSetSlotNewForeign(vm, 0, 1, sizeof(ResponseData));
if (res) {
data->isError = false;
data->statusCode = res->status;
data->body = res->body;
} else {
data->isError = true;
data->statusCode = -1;
data->body = "POST request failed.";
}
}
// --- FFI Binding Functions ---
WrenForeignMethodFn bindForeignMethod(WrenVM* vm, const char* module,
const char* className, bool isStatic, const char* signature) {
if (strcmp(module, "requests") != 0) return NULL;
if (strcmp(className, "Requests") == 0 && isStatic) {
if (strcmp(signature, "get_(_,_)") == 0) return requestsGet;
if (strcmp(signature, "post_(_,_,_,_)") == 0) return requestsPost;
}
if (strcmp(className, "Response") == 0 && !isStatic) {
if (strcmp(signature, "isError") == 0) return responseIsError;
if (strcmp(signature, "statusCode") == 0) return responseStatusCode;
if (strcmp(signature, "body") == 0) return responseBody;
if (strcmp(signature, "json()") == 0) return responseJson;
}
return NULL;
}
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods = {0};
if (strcmp(module, "requests") == 0) {
if (strcmp(className, "Response") == 0) {
methods.allocate = responseAllocate;
}
}
return methods;
}