OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-booking / node_modules / bare-type / binding.c

316 lines · c ref:
#include <assert.h>
#include <bare.h>
#include <js.h>
#include <stdint.h>
#include <utf.h>

typedef enum {
  // Base types
  bare_type_undefined = js_undefined,
  bare_type_null = js_null,
  bare_type_boolean = js_boolean,
  bare_type_number = js_number,
  bare_type_string = js_string,
  bare_type_symbol = js_symbol,
  bare_type_object = js_object,
  bare_type_function = js_function,
  bare_type_external = js_external,
  bare_type_bigint = js_bigint,

  // Number types
  bare_type_int32 = 1 << 8,
  bare_type_uint32 = 1 << 9,

  // Object types
  bare_type_array = 1 << 8,
  bare_type_arguments = 2 << 8,
  bare_type_date = 3 << 8,
  bare_type_regexp = 4 << 8,
  bare_type_error = 5 << 8,
  bare_type_promise = 6 << 8,
  bare_type_proxy = 7 << 8,
  bare_type_generator = 8 << 8,
  bare_type_map = 9 << 8,
  bare_type_set = 10 << 8,
  bare_type_weak_map = 11 << 8,
  bare_type_weak_set = 12 << 8,
  bare_type_weak_ref = 13 << 8,
  bare_type_arraybuffer = 14 << 8,
  bare_type_sharedarraybuffer = 15 << 8,
  bare_type_typedarray = 16 << 8,
  bare_type_dataview = 17 << 8,
  bare_type_module_namespace = 18 << 8,

  // TypedArray types
  bare_type_int8array = 1 << 16,
  bare_type_uint8array = 2 << 16,
  bare_type_uint8clampedarray = 3 << 16,
  bare_type_int16array = 4 << 16,
  bare_type_uint16array = 5 << 16,
  bare_type_int32array = 6 << 16,
  bare_type_uint32array = 7 << 16,
  bare_type_float16array = 12 << 16,
  bare_type_float32array = 8 << 16,
  bare_type_float64array = 9 << 16,
  bare_type_bigint64array = 10 << 16,
  bare_type_biguint64array = 11 << 16,

  // Function types
  bare_type_async_function = 1 << 8,
  bare_type_generator_function = 1 << 9,
} bare_type_t;

static js_value_t *
bare_type(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  js_value_t *value = argv[0];

  uint32_t type;
  err = js_typeof(env, value, (js_value_type_t *) &type);
  assert(err == 0);

  switch (type) {
  case bare_type_number: {
#define V(t) \
  bool is_##t; \
  err = js_is_##t(env, value, &is_##t); \
  assert(err == 0); \
  if (is_##t) type |= bare_type_##t;

    V(int32)
    V(uint32)
#undef V

    break;
  }

  case bare_type_object: {
#define V(t) \
  bool is_##t; \
  err = js_is_##t(env, value, &is_##t); \
  assert(err == 0); \
  if (is_##t) { \
    type |= bare_type_##t; \
    break; \
  }

    V(array)
    V(arguments)
    V(date)
    V(regexp)
    V(error)
    V(promise)
    V(proxy)
    V(generator)
    V(map)
    V(set)
    V(weak_map)
    V(weak_set)
    V(weak_ref)
    V(arraybuffer)
    V(sharedarraybuffer)
    V(typedarray)
    V(dataview)
    V(module_namespace)
#undef V

    break;
  }

  case bare_type_function: {
#define V(t) \
  bool is_##t; \
  err = js_is_##t(env, value, &is_##t); \
  assert(err == 0); \
  if (is_##t) type |= bare_type_##t;

    V(async_function)
    V(generator_function)
#undef V

    break;
  }
  }

  switch (type) {
  case bare_type_object | bare_type_typedarray: {
#define V(t) \
  bool is_##t; \
  err = js_is_##t(env, value, &is_##t); \
  assert(err == 0); \
  if (is_##t) { \
    type |= bare_type_##t; \
    break; \
  }

    V(int8array)
    V(uint8array)
    V(uint8clampedarray)
    V(int16array)
    V(uint16array)
    V(int32array)
    V(uint32array)
    V(float16array)
    V(float32array)
    V(float64array)
    V(bigint64array)
    V(biguint64array)
#undef V

    break;
  }
  }

  js_value_t *result;
  err = js_create_uint32(env, type, &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_type_add_tag(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 2;
  js_value_t *argv[2];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 2);

  js_type_tag_t *tag;
  err = js_get_typedarray_info(env, argv[1], NULL, (void **) &tag, NULL, NULL, NULL);
  assert(err == 0);

  js_add_type_tag(env, argv[0], tag);

  return NULL;
}

static js_value_t *
bare_type_check_tag(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 2;
  js_value_t *argv[2];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 2);

  js_type_tag_t *tag;
  err = js_get_typedarray_info(env, argv[1], NULL, (void **) &tag, NULL, NULL, NULL);
  assert(err == 0);

  bool matches;
  err = js_check_type_tag(env, argv[0], tag, &matches);
  assert(err == 0);

  js_value_t *result;
  err = js_get_boolean(env, matches, &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_type_exports(js_env_t *env, js_value_t *exports) {
  int err;

#define V(name, fn) \
  { \
    js_value_t *val; \
    err = js_create_function(env, name, -1, fn, NULL, &val); \
    assert(err == 0); \
    err = js_set_named_property(env, exports, name, val); \
    assert(err == 0); \
  }

  V("type", bare_type)
  V("addTag", bare_type_add_tag)
  V("checkTag", bare_type_check_tag)
#undef V

  js_value_t *constants;
  err = js_create_object(env, &constants);
  assert(err == 0);

  err = js_set_named_property(env, exports, "constants", constants);
  assert(err == 0);

#define V(name, n) \
  { \
    js_value_t *val; \
    err = js_create_uint32(env, n, &val); \
    assert(err == 0); \
    err = js_set_named_property(env, constants, name, val); \
    assert(err == 0); \
  }

  V("UNDEFINED", bare_type_undefined)
  V("NULL", bare_type_null)
  V("BOOLEAN", bare_type_boolean)
  V("NUMBER", bare_type_number)
  V("STRING", bare_type_string)
  V("SYMBOL", bare_type_symbol)
  V("OBJECT", bare_type_object)
  V("FUNCTION", bare_type_function)
  V("EXTERNAL", bare_type_external)
  V("BIGINT", bare_type_bigint)

  V("INT32", bare_type_int32)
  V("UINT32", bare_type_uint32)

  V("ARRAY", bare_type_array)
  V("ARGUMENTS", bare_type_arguments)
  V("DATE", bare_type_date)
  V("REGEXP", bare_type_regexp)
  V("ERROR", bare_type_error)
  V("PROMISE", bare_type_promise)
  V("PROXY", bare_type_proxy)
  V("GENERATOR", bare_type_generator)
  V("MAP", bare_type_map)
  V("SET", bare_type_set)
  V("WEAK_MAP", bare_type_weak_map)
  V("WEAK_SET", bare_type_weak_set)
  V("WEAK_REF", bare_type_weak_ref)
  V("ARRAYBUFFER", bare_type_arraybuffer)
  V("SHAREDARRAYBUFFER", bare_type_sharedarraybuffer)
  V("TYPEDARRAY", bare_type_typedarray)
  V("DATAVIEW", bare_type_dataview)
  V("MODULE_NAMESPACE", bare_type_module_namespace)

  V("INT8ARRAY", bare_type_int8array)
  V("UINT8ARRAY", bare_type_uint8array)
  V("UINT8CLAMPEDARRAY", bare_type_uint8clampedarray)
  V("INT16ARRAY", bare_type_int16array)
  V("UINT16ARRAY", bare_type_uint16array)
  V("INT32ARRAY", bare_type_int32array)
  V("UINT32ARRAY", bare_type_uint32array)
  V("FLOAT16ARRAY", bare_type_float16array)
  V("FLOAT32ARRAY", bare_type_float32array)
  V("FLOAT64ARRAY", bare_type_float64array)
  V("BIGINT64ARRAY", bare_type_bigint64array)
  V("BIGUINT64ARRAY", bare_type_biguint64array)

  V("ASYNC_FUNCTION", bare_type_async_function)
  V("GENERATOR_FUNCTION", bare_type_generator_function)
#undef V

  return exports;
}

BARE_MODULE(bare_type, bare_type_exports)