[ruby/digest] Use typed data in digest

https://github.com/ruby/digest/commit/9a22f921c9
This commit is contained in:
Nobuyoshi Nakada 2024-06-07 11:06:53 +09:00 committed by git
parent 0d91887c6a
commit 0619312bb5
2 changed files with 50 additions and 8 deletions

View File

@ -537,6 +537,36 @@ rb_digest_class_init(VALUE self)
* Data_Wrap_Struct(0, 0, 0, (void *)&sha1)); * Data_Wrap_Struct(0, 0, 0, (void *)&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 * static rb_digest_metadata_t *
get_digest_base_metadata(VALUE klass) get_digest_base_metadata(VALUE klass)
{ {
@ -554,8 +584,8 @@ get_digest_base_metadata(VALUE klass)
if (NIL_P(p)) if (NIL_P(p))
rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby"); rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
if (!RB_TYPE_P(obj, T_DATA) || RTYPEDDATA_P(obj)) { algo = get_metadata_ptr(obj);
wrong: if (!algo) {
if (p == klass) if (p == klass)
rb_raise(rb_eTypeError, "%"PRIsVALUE"::metadata is not initialized properly", rb_raise(rb_eTypeError, "%"PRIsVALUE"::metadata is not initialized properly",
klass); klass);
@ -564,12 +594,6 @@ get_digest_base_metadata(VALUE klass)
klass, p); 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) { switch (algo->api_version) {
case 3: case 3:
break; break;

View File

@ -64,10 +64,28 @@ rb_id_metadata(void)
return rb_intern_const("metadata"); 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 static inline VALUE
rb_digest_make_metadata(const rb_digest_metadata_t *meta) 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");
}
return wrapper(meta);
#else
#undef RUBY_UNTYPED_DATA_WARNING #undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0 #define RUBY_UNTYPED_DATA_WARNING 0
return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta)); return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta));
#endif
} }