summaryrefslogtreecommitdiff
path: root/ext/digest
diff options
context:
space:
mode:
Diffstat (limited to 'ext/digest')
-rw-r--r--ext/digest/digest.c42
-rw-r--r--ext/digest/digest.h19
2 files changed, 52 insertions, 9 deletions
diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index 68837a674c..bd8d3e815f 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -534,9 +534,39 @@ rb_digest_class_init(VALUE self)
*
*
* rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
- * Data_Wrap_Struct(0, 0, 0, (void *)&sha1));
+ * rb_digest_make_metadata(&sha1));
*/
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+static const rb_data_type_t metadata_type = {
+ "digest/metadata",
+ {0},
+};
+
+RUBY_FUNC_EXPORTED VALUE
+rb_digest_wrap_metadata(const rb_digest_metadata_t *meta)
+{
+ return rb_obj_freeze(TypedData_Wrap_Struct(0, &metadata_type, (void *)meta));
+}
+#endif
+
+static rb_digest_metadata_t *
+get_metadata_ptr(VALUE obj)
+{
+ rb_digest_metadata_t *algo;
+
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ if (!rb_typeddata_is_kind_of(obj, &metadata_type)) return 0;
+ algo = RTYPEDDATA_DATA(obj);
+#else
+# undef RUBY_UNTYPED_DATA_WARNING
+# define RUBY_UNTYPED_DATA_WARNING 0
+ Data_Get_Struct(obj, rb_digest_metadata_t, algo);
+#endif
+
+ return algo;
+}
+
static rb_digest_metadata_t *
get_digest_base_metadata(VALUE klass)
{
@@ -554,8 +584,8 @@ get_digest_base_metadata(VALUE klass)
if (NIL_P(p))
rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
- if (!RB_TYPE_P(obj, T_DATA) || RTYPEDDATA_P(obj)) {
- wrong:
+ algo = get_metadata_ptr(obj);
+ if (!algo) {
if (p == klass)
rb_raise(rb_eTypeError, "%"PRIsVALUE"::metadata is not initialized properly",
klass);
@@ -564,12 +594,6 @@ get_digest_base_metadata(VALUE klass)
klass, p);
}
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- Data_Get_Struct(obj, rb_digest_metadata_t, algo);
-
- if (!algo) goto wrong;
-
switch (algo->api_version) {
case 3:
break;
diff --git a/ext/digest/digest.h b/ext/digest/digest.h
index 68a3da5dd2..4503929bab 100644
--- a/ext/digest/digest.h
+++ b/ext/digest/digest.h
@@ -64,10 +64,29 @@ rb_id_metadata(void)
return rb_intern_const("metadata");
}
+#if !defined(HAVE_RB_EXT_RESOLVE_SYMBOL)
+#elif !defined(RUBY_UNTYPED_DATA_WARNING)
+# error RUBY_UNTYPED_DATA_WARNING is not defined
+#elif RUBY_UNTYPED_DATA_WARNING
+/* rb_ext_resolve_symbol() has been defined since Ruby 3.3, but digest
+ * bundled with 3.3 didn't use it. */
+# define DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 1
+#endif
+
static inline VALUE
rb_digest_make_metadata(const rb_digest_metadata_t *meta)
{
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ typedef VALUE (*wrapper_func_type)(const rb_digest_metadata_t *meta);
+ static wrapper_func_type wrapper;
+ if (!wrapper) {
+ wrapper = (wrapper_func_type)rb_ext_resolve_symbol("digest.so", "rb_digest_wrap_metadata");
+ if (!wrapper) rb_raise(rb_eLoadError, "rb_digest_wrap_metadata not found");
+ }
+ return wrapper(meta);
+#else
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta));
+#endif
}