PackageTrack
Sign in Get early access

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 2025
2023 2024 2025 2026
Release Pre-release

Releases

latest 7
  1. 0.8.0 26 Aug 2025
    Release notes

    Magnus 0.8.0 adds a handful of features and fixes. The old-api feature 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 fatal exception raised when a Rust function bound to Ruby panics can no longer be caught with rescue Exception.
    • Fixed type bounds for TryConvertOwned for (T, ...) so that T must be TryConvertOwned.

    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 a Ruby handle that can only be obtained on a Ruby thread. The older associated functions API is now marked as deprecated by default. The old-api feature can be enabled to disable deprecation warnings for the old API. In a future version of Magnus will remove this feature.

    The FString type 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 Time and Rust's SystemTime now preserve nanosecond precision.

    RString::to_string will 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

    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.

    FromIterator for RArray and RHash are hidden behind the old-api feature (which will be removed in a future version of Magnus). Use Ruby::ary_from_iter and Ruby::hash_from_iter rather than RArray/Rhash::from_iter or collect::<RArray>()/collect::<RHash>().


    See the changelog for all the changes.

    Thanks

    @ankane for implementing TryConvert for NonZero types, i128/u128 support, and some additional improvements.
    @emwalker for the chrono feature.
    @erickguan for improvements to docs, some fixes, and IO features including Ruby::io_extract_modeenc.
    @ianks and @sandbergja for other fixes.
    @yaroslav for a detailed issue report that lead to an improvement.

    Open source →
    Release notes

    Added

    • Ruby::time_nano_new, Ruby::time_timespec_new, and Time::timespec.
    • The chrono feature can be enabled to allow automatic conversions between chrono::DateTime<Utc> and chrono::DateTime<FixedOffset> and Ruby Time objects.
    • typed_data::Writebarrier::writebarrier and writebarrier_unprotect.
    • Implement TryConvert for NonZero types.
    • io module available with io feature, supporting io_extract_modeenc, OpenFlags, FMode, and IoEncoding.
    • Ruby::io_extract_modeenc, a safe wrapper around rb_io_extract_modeenc, allowing structured extraction of open flags, mode flags, and IO encoding metadata.
    • OpenFlags struct, which wraps Ruby's O_ open flags (e.g. O_RDONLY, O_CREAT) in a convenient bitflag-like interface.
    • FMode struct, representing FMODE_ flags used internally by Ruby to represent IO modes (READ, WRITE, BINARY_MODE, etc.).
    • IoEncoding, a safe Rust struct for temporarily owning and inspecting rb_io_encoding, including safe accessors for internal/external encoding and encoding options.
    • Automatic type conversions to/from i128/u128.
    • to_i128/to_u128 for Fixnum/Bignum/Integer.
    • Ruby::integer_from_i128 & Ruby::integer_from_u128.
    • RHash::to_btree_map and automatic conversion from Hash to BTreeMap.

    Changed

    • Minimum supported Rust version is now 1.65.
    • Conversions between Ruby's Time and Rust's SystemTime now preserve nanosecond precision.
    • 'old-api' feature, which disables deprecation warnings for the old api is no longer a default feature.
    • RString::to_string will 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_str now returns an RString rather than an FString.

    Deprecated

    • thread_fd_close as it will be a no-op as of Ruby 3.5

    Removed

    • FString 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.
    • RString::as_interned_str as its only purpose was to return an FString.

    Fixed

    • The fatal exception raised when a Rust function bound to Ruby panics can no longer be caught with rescue Exception.
    • Fixed type bounds for TryConvertOwned for (T, ...) so that T must be TryConvertOwned.
    • Defining functions with an arity of 16
    Open source →
  2. 0.6.0 29 Jul 2023
    Release notes

    Added

    • value::Opaque can be used to wrap a Ruby type to make it Send + Sync.
    • value::Lazy lazily initialises a Ruby value so it can be assigned to a static.
    • value::OpaqueId is a Send + Sync version of value::Id.
    • value::LazyId is an Id with a const constructor so can be assigned to a static and derefs to OpaqueId.
    • error::OpaqueError is a Send + Sync version of Error.
    • The #[magnus(opaque_attr_reader)] attribute can be set on Opaque wrapped fields of a struct when deriving TypedData to generate a method to return the inner value.
    • Ruby::init function 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_func to remove a class' allocator function only if it is Ruby's default allocator function.
    • Class::obj_alloc and Class::define_alloc_func for allocating an object without calling initialize, and for defining an allocator function.
    • RTypedData::wrap_as & typed_data::Obj<T>::wrap_as can 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_class returns the class of an exception as an ExceptionClass.
    • The kwargs!() macro and KwArgs type can be used to pass keyword arguments to ReprValue::funcall, et al.

    Changed

    • Minimum supported Rust version in now 1.61.
    • The bytes-crate feature has been renamed to bytes.
    • The rb-sys-interop feature has been renamed to rb-sys.
    • Ruby types are no longer Send or Sync. These types can be made Send & Sync with the deprecated-send-sync-value feature. This feature is meant to ease upgrading and will be removed with the next release.
    • Value's methods moved to the ReprValue trait.
    • typed_data::Obj<T> derefs to T so now T's methods can be called directly on typed_data::Obj<T>.
    • ReprValue and TryConvert added to magnus::prelude.
    • typed_data::Cmp, typed_data::Dup and typed_data::Inspect traits to help with implementing #<=>, #dup & #clone, and #inspect methods for wrapped structs.
    • Wrapped data must be Sync to enable frozen_shareable flag.
    • TypedData::class and TypedData::class_for now take a &Ruby argument.
    • DataTypeFunctions::mark and DataTypeFunctions::compact now take &gc::Marker and &gc::Compactor arguments respectively.
    • Init function marked with #[magnus::init] optionally takes a &Ruby argument.
    • Functions bound as Ruby methods with method!() and function!() optionally take &Ruby as a first argument.
    • The value returned from embed::init derefs to Ruby.
    • DataTypeBuilder::new/DataType::builder now take their name argument as a 'static CStr (see the magnus::data_type_builder! macro to construct a DataTypeBuilder with a 'static CStr name).
    • All methods on DataTypeBuilder are now const, so DataType can be constructed in a const context and be assigned to a static.
    • The #[wrap] and #[derive(TypedData)] macros now support setting the #[magnus(unsafe_generics)] attribute to allow deriving TypedData for types with generics. The derived implementation is not guaranteed to be correct.

    Deprecated

    • typed_data::Obj::get as it is made redundant by the Deref implementation for typed_data::Obj.
    • The QTRUE, QFALSE, and QNIL constants. Please use value::qtrue(), value::qfalse(), and value::qnil().
    • Class::undef_alloc_func. Please use Class::undef_default_alloc_func.
    • Value::try_convert, prefer TryConvert::try_convert or T::try_convert.
    • Binding. To call methods on Ruby's binding, use ReprValue::funcall on a Value know to be an instance of Ruby's Binding class.
    • gc::{mark, mark_slice, mark_movable, location}, instead use gc::Marker::{mark, mark_slice, mark_movable} and Compactor::location.
    • RStruct::as_slice.

    Removed

    • Inherent methods on RClass, import magnus::Class trait or magnus::prelude::*.
    • Into<Value>/From<T> for Value implementations, use IntoValue.
    • Default implementations for Value, RClass, and ExceptionClass.
    • Error can no longer be directly constructed, must use Error::new or Error::from/Exception::into.
    • RString::append (use RString::buf_append).
    • Error::runtime_error (use Error::new(exception::runtime_error(), msg)).

    Fixed

    • RFloat::from_value now returns None when value is a Flonum.
    Open source →
  3. 0.4.1 28 Mar 2023
    Release notes

    Fixed

    • scan_args::get_kwargs error/segfault when leading optional args were not provided, due to trying to convert the type of the missing value.
    Open source →
  4. 0.4.0 11 Feb 2023
    Release notes

    Added

    • Value::funcall_with_block.
    • impl TryConvert for Exception and ExceptionClass.
    • Class trait (implemented for RClass and ExceptionClass).
    • define_error and Module::define_error helpers for defining an Exception Class.
    • RTypedData::wrap and RTypedData::get inherent 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. Use Proc::from_fn + Value::funcall_with_block for closures that capture variables.
    • Proc::new only accepts a function pointer, use Proc::from_fn for closures that capture variables.
    • ExceptionClass::default() now returns StandardError rather than RuntimeError.
    • TryConvert now takes Value by value (rather than a reference).

    Deprecated

    • DataTypeBuilder::free_immediatly (use free_immediately).
    • free_immediatly attribute in wrap macro (use free_immediately).
    • free_immediatly in magnus attribute of derive(TypedData) macro (use free_immediately).

    Removed

    • String::encode_utf8, use r_string.conv_enc(RbEncoding::utf8()) instead.
    • Value::leak, use gc::register_mark_object instead.
    • define_global_variable (use define_variable).

    Fixed

    • Memory leak of the message when returning an Error to raise an exception.
    • Flonum support disabled for Ruby built with USE_FLONUM=0 (e.g. 32 bit systems).
    • Correct spelling of free_immediatly (to free_immediately) in the DataTypeBuilder struct, and wrap and derive(TypedData) macros.

    Security

    • printf-style format strings no longer interpreted in error messages when automatically raised as Ruby exceptions.
    Open source →
  5. 0.3.0 24 Dec 2022
    Release notes

    Added

    • RString::new_shared and RString::new_frozen.
    • encoding module, including encoding::Index and RbEncoding types.
    • RString::enc_coderange and related methods.
    • RString::codepoints and RString::char_bytes iterators over string contents.
    • The following methods for RArray: dup, concat, plus, delete, delete_at, resize, reverse, rotate, and sort.
    • New methods for RString: enc_new, len, length, and is_empty.
    • RHash gains the methods delete and clear.
    • require, current_receiver, call_super, and define_global_const functions.
    • Object::singleton_class and Object::extend_object.
    • Proc::new, Proc::arity, and Proc::is_lambda.
    • superclass and name methods for RClass.
    • scan_args::check_arity.
    • Methods for Module: include_module, prepend_module, const_set, ancestors, define_attr, and define_alias.
    • rb-sys-interop feature to use low level bindings from rb-sys, and rb_sys module to expose functions for working with rb-sys.
    • Added gc::register_mark_object, gc::register_address, gc::unregister_address, gc::count, gc::stat, and gc::all_stats.
    • Error::iter_break.
    • StaticSymbol::check and Id::check to check if a symbol exists.

    Changed

    • RArray::cat, RArray::from_slice, and gc::mark_slice will accept a slice of any Ruby type as an argument, rather than only a slice of Value. This may change type inference rules such that things like RArray::from_slice(&[1.into()]) will no longer work. Use RArray::from_slice(&[Value::from(1)]) instead.
    • Similar to above, gc::location will accept any Ruby type as an argument.
    • BoxValue can hold any Ruby type, not just Value.
    • Improved performance for conversion between Ruby floats/integers and Rust types.
    • The parameters to the closure passed to RHash::foreach will now be automatically converted from Value to Rust types.
    • Module::define_method, Module::define_private_method, Module::define_protected_method, RModule::define_singleton_method, and Object::define_singleton_method all return Result<(), Error> rather than () as they may fail in the unusual case that the receiver is frozen.

    Deprecated

    • String::encode_utf8, use r_string.conv_enc(RbEncoding::utf8()) instead.
    • Value::leak, use gc::register_mark_object instead.
    • define_global_variable (use define_variable) to better match Ruby C API naming.
    • Exception::backtrace, use ex.funcall("backtrace", ()) instead.

    Removed

    • error::protect removed as it should not be needed when using Magnus. For use with rb-sys enable the rb-sys-interop feature and use magnus::rb_sys::protect.
    • Qfalse::new, Qnil::new, Qtrue::new, Qundef::new (use QFALSE/QNIL/QTRUE/QUNDEF).
    • Functions for generating an Error with a specific Ruby type. E.g. Error::type_error("..."), use Error::new(exception::type_error(), "...").

    Fixed

    • creating a StaticSymbol from a &str with characters outside the ASCII range.
    • panicking in any of the functions of DataTypeFunctions will abort the process to avoid undefined behaviour.
    • panicking in the closure passed to RHash::foreach won't result in undefined behaviour.
    Open source →
  6. 0.2.0 19 Nov 2022
    Release notes

    Added

    • Functions in class, module, and error modules to access built-in classes/modules.
    • Many doc examples.
    • RArray::len, RArray::includes, RArray::join, RArray::is_shared, RArray::replace, and RArray::subseq.
    • Implement From<&str> and From<String> for RString.
    • Support for Range.
    • Pre-built bindings for Ruby 3.1 on Windows.
    • Support calling Ruby methods with Rust closure as a Ruby block.
    • Class::new and Module::new for creating anonymous classes/modules.
    • r_string! macro to create Ruby string from a str literal.
    • Value::equal and Value::eql for object equality.
    • Value::respond_to and Value::check_funcall for conditionally calling Ruby methods only when they are defined.
    • scan_args and get_kwargs for complex argument parsing.

    Changed

    • Qundef::to_value now marked unsafe.
    • RArray::cat, RArray::push, RArray::unshift, and RArray::store now return Result<(), 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 Error with a specific Ruby type. E.g. Error::type_error("...") is now Error::new(exception::type_error(), "...")
    • Binding::new. This will be removed in the future as the underlying rb_binding_new will not function as of Ruby 3.2.

    Fixed

    • Converting Ruby integers to isize/i64/usize/u64 on Windows.
    • Edge case where static symbol created after a dynamic symbol with the same name wouldn't be detected as static.
    • Many RArray methods now correctly protect from exceptions (instead returning Result<_, Error> when an exception occurs).
    Open source →
  7. 0.1.0 26 Feb 2022
    Release notes

    Added

    • Support for most core classes, String, Symbol, Integer, Float, Array, Hash and 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.
    • Enumerator as a iterator.
    • yield to Ruby blocks.
    • #[init] macro to mark init function to load extension with require.
    • Pre-built bindings for Ruby 2.6 - 3.1 on common platforms, build-time generated bindings otherwise.
    Open source →

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive