magnus-macros
Derive and proc macros for magnus
0.8.0
5.4M downloads/mo
#4387 most downloaded on crates.io
matsadler/magnus
What this package is like to depend on
Last release 12 months ago
26 Aug 2025
Ships unpredictably
gaps range from 5 weeks to 2.1 years
Nearly every release is documented
notes for 7 of 7 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
7 releases · first in 2022
0 releases in the last 12 months
see the full history below
Release timeline
7 releases · Feb 2022 to Aug 2025Releases
latest 7-
0.8.026 Aug 2025Release notes
Open source →Magnus 0.8.0 adds a handful of features and fixes. The
old-apifeature introduced in 0.7.0 is no longer a default feature, so functions marked as part of the old API will be deprecated by default. Otherwise it is largely compatible with 0.7.Magnus is a Rust library providing a high-level easy-to-use interface to the C API of the Ruby programming language. Magnus lets you write Ruby extension libraries (or 'gems') in Rust, or embed Ruby in your Rust program.
Fixes
- The
fatalexception raised when a Rust function bound to Ruby panics can no longer be caught withrescue Exception. - Fixed type bounds for
TryConvertOwnedfor(T, ...)so thatTmust beTryConvertOwned.
API changes
The minimum supported Rust version in now 1.65.
Magnus 0.5 and earlier would allow you to create Ruby objects with associated functions, like
RArray::new. In Magnus 0.6 a new set of APIs for creating Ruby objects was added, as methods on aRubyhandle that can only be obtained on a Ruby thread. The older associated functions API is now marked as deprecated by default. Theold-apifeature can be enabled to disable deprecation warnings for the old API. In a future version of Magnus will remove this feature.The
FStringtype has been removed as it can not safely uphold the promise it was making. Either due to Ruby's apis changing or a misinterpretation of old documentation it had been designed assuming interned strings (aka 'fstrings') would not be garbage collected, which is not the case.Conversions between Ruby's
Timeand Rust'sSystemTimenow preserve nanosecond precision.RString::to_stringwill now use a Ruby utf-8 validation api that caches the results of the validity check. This will greatly improve performance in the case a string is already known to be utf-8, but may slightly reduce performance when not known.New Features
Ruby::time_nano_new,Ruby::time_timespec_new, andTime::timespec.- The
chronofeature can be enabled to allow automatic conversions betweenchrono::DateTime<Utc>andchrono::DateTime<FixedOffset>and RubyTimeobjects. typed_data::Writebarrier::writebarrierandwritebarrier_unprotect.- Automatic type conversions for
NonZerotypes,i128/u128, andBTreeMap. Ruby::io_extract_modeenc.
Upgrading
Upgrading from Magnus 0.6 or 0.7 should be straightforward. If upgrading from 0.5 or earlier, it's recommended to upgrade to 0.6 first.
FromIteratorforRArrayandRHashare hidden behind theold-apifeature (which will be removed in a future version of Magnus). UseRuby::ary_from_iterandRuby::hash_from_iterrather thanRArray/Rhash::from_iterorcollect::<RArray>()/collect::<RHash>().
See the changelog for all the changes.
Thanks
@ankane for implementing
TryConvertforNonZerotypes,i128/u128support, and some additional improvements.
@emwalker for thechronofeature.
@erickguan for improvements to docs, some fixes, and IO features includingRuby::io_extract_modeenc.
@ianks and @sandbergja for other fixes.
@yaroslav for a detailed issue report that lead to an improvement.Release notes
Open source →Added
Ruby::time_nano_new,Ruby::time_timespec_new, andTime::timespec.- The
chronofeature can be enabled to allow automatic conversions betweenchrono::DateTime<Utc>andchrono::DateTime<FixedOffset>and RubyTimeobjects. typed_data::Writebarrier::writebarrierandwritebarrier_unprotect.- Implement
TryConvertforNonZerotypes. iomodule available withiofeature, supportingio_extract_modeenc,OpenFlags,FMode, andIoEncoding.Ruby::io_extract_modeenc, a safe wrapper aroundrb_io_extract_modeenc, allowing structured extraction of open flags, mode flags, and IO encoding metadata.OpenFlagsstruct, which wraps Ruby'sO_open flags (e.g.O_RDONLY,O_CREAT) in a convenient bitflag-like interface.FModestruct, representingFMODE_flags used internally by Ruby to represent IO modes (READ,WRITE,BINARY_MODE, etc.).IoEncoding, a safe Rust struct for temporarily owning and inspectingrb_io_encoding, including safe accessors for internal/external encoding and encoding options.- Automatic type conversions to/from
i128/u128. to_i128/to_u128forFixnum/Bignum/Integer.Ruby::integer_from_i128&Ruby::integer_from_u128.RHash::to_btree_mapand automatic conversion fromHashtoBTreeMap.
Changed
- Minimum supported Rust version is now 1.65.
- Conversions between Ruby's
Timeand Rust'sSystemTimenow preserve nanosecond precision. - 'old-api' feature, which disables deprecation warnings for the old api is no longer a default feature.
RString::to_stringwill now use a Ruby utf-8 validation api that caches the results of the validity check. This will greatly improve performance in the case a string is already known to be utf-8, but may slightly reduce performance when not known.RString::to_interned_strnow returns anRStringrather than anFString.
Deprecated
thread_fd_closeas it will be a no-op as of Ruby 3.5
Removed
FStringas it can not safely uphold the promise it was making. Either due to Ruby's apis changing or a misinterpretation of old documentation it had been designed assuming interned strings (aka fstrings) would not be garbage collected, which is not the case.RString::as_interned_stras its only purpose was to return anFString.
Fixed
- The
fatalexception raised when a Rust function bound to Ruby panics can no longer be caught withrescue Exception. - Fixed type bounds for
TryConvertOwnedfor(T, ...)so thatTmust beTryConvertOwned. - Defining functions with an arity of 16
- The
-
0.6.029 Jul 2023Release notes
Open source →Added
value::Opaquecan be used to wrap a Ruby type to make itSend+Sync.value::Lazylazily initialises a Ruby value so it can be assigned to astatic.value::OpaqueIdis aSend+Syncversion ofvalue::Id.value::LazyIdis anIdwith aconstconstructor so can be assigned to astaticand derefs toOpaqueId.error::OpaqueErroris aSend+Syncversion ofError.- The
#[magnus(opaque_attr_reader)]attribute can be set onOpaquewrapped fields of a struct when derivingTypedDatato generate a method to return the inner value. Ruby::initfunction to initialise Ruby when embedding Ruby in Rust that runs a function with Ruby initialised, passing&Ruby.rb_assert!()macro to assert a Ruby expression evaluates to a truthy value.Class::undef_default_alloc_functo remove a class' allocator function only if it is Ruby's default allocator function.Class::obj_allocandClass::define_alloc_funcfor allocating an object without callinginitialize, and for defining an allocator function.RTypedData::wrap_as&typed_data::Obj<T>::wrap_ascan be used to dynamically set the class when wrapping Rust data in a Ruby object. This can be used to allow wrapped data to be subclassed in Ruby.Exception::exception_classreturns the class of an exception as anExceptionClass.- The
kwargs!()macro andKwArgstype can be used to pass keyword arguments toReprValue::funcall, et al.
Changed
- Minimum supported Rust version in now 1.61.
- The
bytes-cratefeature has been renamed tobytes. - The
rb-sys-interopfeature has been renamed torb-sys. - Ruby types are no longer
SendorSync. These types can be madeSend&Syncwith thedeprecated-send-sync-valuefeature. This feature is meant to ease upgrading and will be removed with the next release. Value's methods moved to theReprValuetrait.typed_data::Obj<T>derefs toTso nowT's methods can be called directly ontyped_data::Obj<T>.ReprValueandTryConvertadded tomagnus::prelude.typed_data::Cmp,typed_data::Dupandtyped_data::Inspecttraits to help with implementing#<=>,#dup&#clone, and#inspectmethods for wrapped structs.- Wrapped data must be
Syncto enablefrozen_shareableflag. TypedData::classandTypedData::class_fornow take a&Rubyargument.DataTypeFunctions::markandDataTypeFunctions::compactnow take&gc::Markerand&gc::Compactorarguments respectively.- Init function marked with
#[magnus::init]optionally takes a&Rubyargument. - Functions bound as Ruby methods with
method!()andfunction!()optionally take&Rubyas a first argument. - The value returned from
embed::initderefs toRuby. DataTypeBuilder::new/DataType::buildernow take theirnameargument as a'static CStr(see themagnus::data_type_builder!macro to construct aDataTypeBuilderwith a'static CStrname).- All methods on
DataTypeBuilderare nowconst, soDataTypecan be constructed in aconstcontext and be assigned to astatic. - The
#[wrap]and#[derive(TypedData)]macros now support setting the#[magnus(unsafe_generics)]attribute to allow derivingTypedDatafor types with generics. The derived implementation is not guaranteed to be correct.
Deprecated
typed_data::Obj::getas it is made redundant by theDerefimplementation fortyped_data::Obj.- The
QTRUE,QFALSE, andQNILconstants. Please usevalue::qtrue(),value::qfalse(), andvalue::qnil(). Class::undef_alloc_func. Please useClass::undef_default_alloc_func.Value::try_convert, preferTryConvert::try_convertorT::try_convert.Binding. To call methods on Ruby's binding, useReprValue::funcallon aValueknow to be an instance of Ruby's Binding class.gc::{mark, mark_slice, mark_movable, location}, instead usegc::Marker::{mark, mark_slice, mark_movable}andCompactor::location.RStruct::as_slice.
Removed
- Inherent methods on
RClass, importmagnus::Classtrait ormagnus::prelude::*. Into<Value>/From<T> for Valueimplementations, useIntoValue.Defaultimplementations forValue,RClass, andExceptionClass.Errorcan no longer be directly constructed, must useError::neworError::from/Exception::into.RString::append(useRString::buf_append).Error::runtime_error(useError::new(exception::runtime_error(), msg)).
Fixed
RFloat::from_valuenow returnsNonewhen value is aFlonum.
-
0.4.128 Mar 2023Release notes
Open source →Fixed
scan_args::get_kwargserror/segfault when leading optional args were not provided, due to trying to convert the type of the missing value.
-
0.4.011 Feb 2023Release notes
Open source →Added
Value::funcall_with_block.- impl
TryConvertforExceptionandExceptionClass. Classtrait (implemented forRClassandExceptionClass).define_errorandModule::define_errorhelpers for defining an Exception Class.RTypedData::wrapandRTypedData::getinherent methods for wrapping Rust types in Ruby objects.- Support for Ruby 3.2 preview.
- Support for mswin platform (msvc) on Windows with Ruby 3.2 (in addition to the mingw support previously available for all Ruby versions on Windows).
Changed
- Switched to rb-sys for low level bindings.
- Rust types wrapped in Ruby objects must be
Send. - Only function pointers (fn or non-capturing closure) are accepted as argument
for
Value::block_call. UseProc::from_fn+Value::funcall_with_blockfor closures that capture variables. Proc::newonly accepts a function pointer, useProc::from_fnfor closures that capture variables.ExceptionClass::default()now returnsStandardErrorrather thanRuntimeError.TryConvertnow takesValueby value (rather than a reference).
Deprecated
DataTypeBuilder::free_immediatly(usefree_immediately).free_immediatlyattribute inwrapmacro (usefree_immediately).free_immediatlyinmagnusattribute ofderive(TypedData)macro (usefree_immediately).
Removed
String::encode_utf8, user_string.conv_enc(RbEncoding::utf8())instead.Value::leak, usegc::register_mark_objectinstead.define_global_variable(usedefine_variable).
Fixed
- Memory leak of the message when returning an
Errorto raise an exception. Flonumsupport disabled for Ruby built with USE_FLONUM=0 (e.g. 32 bit systems).- Correct spelling of
free_immediatly(tofree_immediately) in theDataTypeBuilderstruct, andwrapandderive(TypedData)macros.
Security
printf-style format strings no longer interpreted in error messages when automatically raised as Ruby exceptions.
-
0.3.024 Dec 2022Release notes
Open source →Added
RString::new_sharedandRString::new_frozen.encodingmodule, includingencoding::IndexandRbEncodingtypes.RString::enc_coderangeand related methods.RString::codepointsandRString::char_bytesiterators over string contents.- The following methods for
RArray:dup,concat,plus,delete,delete_at,resize,reverse,rotate, andsort. - New methods for
RString:enc_new,len,length, andis_empty. RHashgains the methodsdeleteandclear.require,current_receiver,call_super, anddefine_global_constfunctions.Object::singleton_classandObject::extend_object.Proc::new,Proc::arity, andProc::is_lambda.superclassandnamemethods forRClass.scan_args::check_arity.- Methods for
Module:include_module,prepend_module,const_set,ancestors,define_attr, anddefine_alias. rb-sys-interopfeature to use low level bindings from rb-sys, andrb_sysmodule to expose functions for working with rb-sys.- Added
gc::register_mark_object,gc::register_address,gc::unregister_address,gc::count,gc::stat, andgc::all_stats. Error::iter_break.StaticSymbol::checkandId::checkto check if a symbol exists.
Changed
RArray::cat,RArray::from_slice, andgc::mark_slicewill accept a slice of any Ruby type as an argument, rather than only a slice ofValue. This may change type inference rules such that things likeRArray::from_slice(&[1.into()])will no longer work. UseRArray::from_slice(&[Value::from(1)])instead.- Similar to above,
gc::locationwill accept any Ruby type as an argument. BoxValuecan hold any Ruby type, not justValue.- Improved performance for conversion between Ruby floats/integers and Rust types.
- The parameters to the closure passed to
RHash::foreachwill now be automatically converted fromValueto Rust types. Module::define_method,Module::define_private_method,Module::define_protected_method,RModule::define_singleton_method, andObject::define_singleton_methodall returnResult<(), Error>rather than()as they may fail in the unusual case that the receiver is frozen.
Deprecated
String::encode_utf8, user_string.conv_enc(RbEncoding::utf8())instead.Value::leak, usegc::register_mark_objectinstead.define_global_variable(usedefine_variable) to better match Ruby C API naming.Exception::backtrace, useex.funcall("backtrace", ())instead.
Removed
error::protectremoved as it should not be needed when using Magnus. For use with rb-sys enable therb-sys-interopfeature and usemagnus::rb_sys::protect.Qfalse::new,Qnil::new,Qtrue::new,Qundef::new(use QFALSE/QNIL/QTRUE/QUNDEF).- Functions for generating an
Errorwith a specific Ruby type. E.g.Error::type_error("..."), useError::new(exception::type_error(), "...").
Fixed
- creating a
StaticSymbolfrom a&strwith characters outside the ASCII range. - panicking in any of the functions of
DataTypeFunctionswill abort the process to avoid undefined behaviour. - panicking in the closure passed to
RHash::foreachwon't result in undefined behaviour.
-
0.2.019 Nov 2022Release notes
Open source →Added
- Functions in
class,module, anderrormodules to access built-in classes/modules. - Many doc examples.
RArray::len,RArray::includes,RArray::join,RArray::is_shared,RArray::replace, andRArray::subseq.- Implement
From<&str>andFrom<String>forRString. - Support for
Range. - Pre-built bindings for Ruby 3.1 on Windows.
- Support calling Ruby methods with Rust closure as a Ruby block.
Class::newandModule::newfor creating anonymous classes/modules.r_string!macro to create Ruby string from astrliteral.Value::equalandValue::eqlfor object equality.Value::respond_toandValue::check_funcallfor conditionally calling Ruby methods only when they are defined.scan_argsandget_kwargsfor complex argument parsing.
Changed
Qundef::to_valuenow markedunsafe.RArray::cat,RArray::push,RArray::unshift, andRArray::storenow returnResult<(), Error>.eval!macro uses anonymous (rather than caller's) binding.
Deprecated
Qfalse::new,Qnil::new,Qtrue::new,Qundef::new(use QFALSE/QNIL/QTRUE/QUNDEF).- Functions for generating an
Errorwith a specific Ruby type. E.g.Error::type_error("...")is nowError::new(exception::type_error(), "...") Binding::new. This will be removed in the future as the underlyingrb_binding_newwill not function as of Ruby 3.2.
Fixed
- Converting Ruby integers to
isize/i64/usize/u64on Windows. - Edge case where static symbol created after a dynamic symbol with the same name wouldn't be detected as static.
- Many
RArraymethods now correctly protect from exceptions (instead returningResult<_, Error>when an exception occurs).
- Functions in
-
0.1.026 Feb 2022Release notes
Open source →Added
- Support for most core classes,
String,Symbol,Integer,Float,Array,Hashand more. - Defining Rust methods as Ruby functions.
- Calling Ruby methods from Rust.
- Automatic type conversion between Rust and Ruby types.
- Conversion from Ruby exceptions to Rust Results and visa versa.
- Support for wrapping custom Rust structs as Ruby objects.
Enumeratoras a iterator.yieldto Ruby blocks.#[init]macro to mark init function to load extension withrequire.- Pre-built bindings for Ruby 2.6 - 3.1 on common platforms, build-time generated bindings otherwise.
- Support for most core classes,