Thanks to visit codestin.com
Credit goes to docs.rs

magnus/
module.rs

1//! Types and functions for working with Ruby modules.
2//!
3//! See also [`Ruby`](Ruby#core-modules) for more module related methods.
4
5use std::{ffi::CString, fmt, mem::transmute, os::raw::c_int};
6
7use rb_sys::{
8    rb_alias, rb_attr, rb_class_inherited_p, rb_const_get, rb_const_set, rb_define_class_id_under,
9    rb_define_method_id, rb_define_module_function, rb_define_module_id_under,
10    rb_define_private_method, rb_define_protected_method, rb_include_module, rb_mComparable,
11    rb_mEnumerable, rb_mErrno, rb_mFileTest, rb_mGC, rb_mKernel, rb_mMath, rb_mProcess,
12    rb_mWaitReadable, rb_mWaitWritable, rb_mod_ancestors, rb_module_new, rb_prepend_module,
13    ruby_value_type, VALUE,
14};
15
16use crate::{
17    class::{Class, RClass},
18    error::{protect, Error},
19    exception::ExceptionClass,
20    into_value::IntoValue,
21    method::Method,
22    object::Object,
23    r_array::RArray,
24    try_convert::TryConvert,
25    value::{
26        private::{self, ReprValue as _},
27        IntoId, NonZeroValue, ReprValue, Value,
28    },
29    Ruby,
30};
31
32/// # `RModule`
33///
34/// Functions that can be used to create Ruby modules.
35///
36/// See also the [`RModule`] type.
37impl Ruby {
38    /// Create a new anonymous module.
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// use magnus::{prelude::*, Error, Ruby};
44    ///
45    /// fn example(ruby: &Ruby) -> Result<(), Error> {
46    ///     let module = ruby.module_new();
47    ///     assert!(module.is_kind_of(ruby.class_module()));
48    ///
49    ///     Ok(())
50    /// }
51    /// # Ruby::init(example).unwrap()
52    /// ```
53    pub fn module_new(&self) -> RModule {
54        unsafe { RModule::from_rb_value_unchecked(rb_module_new()) }
55    }
56}
57
58/// A Value pointer to a RModule struct, Ruby's internal representation of
59/// modules.
60///
61/// See the [`Module`] trait for defining instance methods and nested
62/// classes/modules.
63/// See the [`Object`] trait for defining singleton methods (aka class methods).
64///
65/// See the [`ReprValue`] trait for additional methods available on this type.
66/// See [`Ruby`](Ruby#rmodule) for methods to create an `RModule`.
67#[derive(Clone, Copy)]
68#[repr(transparent)]
69pub struct RModule(NonZeroValue);
70
71impl RModule {
72    /// Return `Some(RModule)` if `val` is a `RModule`, `None` otherwise.
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// use magnus::{eval, RModule};
78    /// # let _cleanup = unsafe { magnus::embed::init() };
79    ///
80    /// assert!(RModule::from_value(eval("Enumerable").unwrap()).is_some());
81    /// assert!(RModule::from_value(eval("String").unwrap()).is_none());
82    /// assert!(RModule::from_value(eval("nil").unwrap()).is_none());
83    /// ```
84    #[inline]
85    pub fn from_value(val: Value) -> Option<Self> {
86        unsafe {
87            (val.rb_type() == ruby_value_type::RUBY_T_MODULE)
88                .then(|| Self(NonZeroValue::new_unchecked(val)))
89        }
90    }
91
92    #[inline]
93    pub(crate) unsafe fn from_rb_value_unchecked(val: VALUE) -> Self {
94        Self(NonZeroValue::new_unchecked(Value::new(val)))
95    }
96
97    /// Create a new anonymous module.
98    ///
99    /// # Panics
100    ///
101    /// Panics if called from a non-Ruby thread. See [`Ruby::module_new`] for
102    /// the non-panicking version.
103    ///
104    /// # Examples
105    ///
106    /// ```
107    /// # #![allow(deprecated)]
108    /// use magnus::{class, prelude::*, RModule};
109    /// # let _cleanup = unsafe { magnus::embed::init() };
110    ///
111    /// let module = RModule::new();
112    /// assert!(module.is_kind_of(class::module()));
113    /// ```
114    #[cfg_attr(
115        not(feature = "old-api"),
116        deprecated(note = "please use `Ruby::module_new` instead")
117    )]
118    #[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
119    #[inline]
120    pub fn new() -> Self {
121        get_ruby!().module_new()
122    }
123
124    /// Define a method in `self`'s scope as a 'module function'. This method
125    /// will be visible as a public 'class' method on the module and a private
126    /// instance method on any object including the module.
127    ///
128    /// # Examples
129    ///
130    /// ```
131    /// use magnus::{function, r_string, rb_assert, Error, RString, Ruby};
132    ///
133    /// fn greet(ruby: &Ruby) -> RString {
134    ///     r_string!(ruby, "Hello, world!")
135    /// }
136    ///
137    /// fn example(ruby: &Ruby) -> Result<(), Error> {
138    ///     let module = ruby.define_module("Greeting")?;
139    ///     module.define_module_function("greet", function!(greet, 0))?;
140    ///
141    ///     rb_assert!(ruby, r#"Greeting.greet == "Hello, world!""#);
142    ///
143    ///     rb_assert!(
144    ///         ruby,
145    ///         r#"
146    ///             include Greeting
147    ///             greet == "Hello, world!"
148    ///         "#,
149    ///     );
150    ///
151    ///     Ok(())
152    /// }
153    /// # Ruby::init(example).unwrap()
154    /// ```
155    pub fn define_module_function<M>(self, name: &str, func: M) -> Result<(), Error>
156    where
157        M: Method,
158    {
159        debug_assert_value!(self);
160        let name = CString::new(name).unwrap();
161        protect(|| {
162            unsafe {
163                rb_define_module_function(
164                    self.as_rb_value(),
165                    name.as_ptr(),
166                    transmute(func.as_ptr()),
167                    M::arity().into(),
168                )
169            };
170            Ruby::get_with(self).qnil()
171        })?;
172        Ok(())
173    }
174}
175
176impl fmt::Display for RModule {
177    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178        write!(f, "{}", unsafe { self.to_s_infallible() })
179    }
180}
181
182impl fmt::Debug for RModule {
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        write!(f, "{}", self.inspect())
185    }
186}
187
188impl IntoValue for RModule {
189    #[inline]
190    fn into_value_with(self, _: &Ruby) -> Value {
191        self.0.get()
192    }
193}
194
195impl Object for RModule {}
196impl Module for RModule {}
197
198unsafe impl private::ReprValue for RModule {}
199
200impl ReprValue for RModule {}
201
202impl TryConvert for RModule {
203    fn try_convert(val: Value) -> Result<Self, Error> {
204        Self::from_value(val).ok_or_else(|| {
205            Error::new(
206                Ruby::get_with(val).exception_type_error(),
207                format!("no implicit conversion of {} into Module", unsafe {
208                    val.classname()
209                },),
210            )
211        })
212    }
213}
214
215/// Functions available on both classes and modules.
216pub trait Module: Object + ReprValue + Copy {
217    /// Define a class in `self`'s scope.
218    ///
219    /// # Examples
220    ///
221    /// ```
222    /// use magnus::{prelude::*, rb_assert, Error, Ruby};
223    ///
224    /// fn example(ruby: &Ruby) -> Result<(), Error> {
225    ///     let outer = ruby.define_module("Outer")?;
226    ///     outer.define_class("Inner", ruby.class_object())?;
227    ///     rb_assert!(ruby, "Outer::Inner.is_a?(Class)");
228    ///
229    ///     Ok(())
230    /// }
231    /// # Ruby::init(example).unwrap()
232    /// ```
233    fn define_class<T>(self, name: T, superclass: RClass) -> Result<RClass, Error>
234    where
235        T: IntoId,
236    {
237        debug_assert_value!(self);
238        debug_assert_value!(superclass);
239        let id = name.into_id_with(&Ruby::get_with(self));
240        let superclass = superclass.as_rb_value();
241        protect(|| unsafe {
242            RClass::from_rb_value_unchecked(rb_define_class_id_under(
243                self.as_rb_value(),
244                id.as_rb_id(),
245                superclass,
246            ))
247        })
248    }
249
250    /// Define a module in `self`'s scope.
251    ///
252    /// # Examples
253    ///
254    /// ```
255    /// use magnus::{prelude::*, rb_assert, Error, Ruby};
256    ///
257    /// fn example(ruby: &Ruby) -> Result<(), Error> {
258    ///     let outer = ruby.define_module("Outer")?;
259    ///     outer.define_module("Inner")?;
260    ///     rb_assert!(ruby, "Outer::Inner.is_a?(Module)");
261    ///     rb_assert!(ruby, "!Outer::Inner.is_a?(Class)");
262    ///
263    ///     Ok(())
264    /// }
265    /// # Ruby::init(example).unwrap()
266    /// ```
267    fn define_module<T>(self, name: T) -> Result<RModule, Error>
268    where
269        T: IntoId,
270    {
271        let id = name.into_id_with(&Ruby::get_with(self));
272        protect(|| unsafe {
273            RModule::from_rb_value_unchecked(rb_define_module_id_under(
274                self.as_rb_value(),
275                id.as_rb_id(),
276            ))
277        })
278    }
279
280    /// Define an exception class in `self`'s scope.
281    ///
282    /// # Examples
283    ///
284    /// ```
285    /// use magnus::{prelude::*, rb_assert, Error, Ruby};
286    ///
287    /// fn example(ruby: &Ruby) -> Result<(), Error> {
288    ///     let outer = ruby.define_module("Outer")?;
289    ///     outer.define_error("InnerError", ruby.exception_standard_error())?;
290    ///     rb_assert!(ruby, "Outer::InnerError.is_a?(Class)");
291    ///     rb_assert!(ruby, "Outer::InnerError < Exception");
292    ///
293    ///     Ok(())
294    /// }
295    /// # Ruby::init(example).unwrap()
296    /// ```
297    fn define_error<T>(self, name: T, superclass: ExceptionClass) -> Result<ExceptionClass, Error>
298    where
299        T: IntoId,
300    {
301        self.define_class(name, superclass.as_r_class())
302            .map(|c| unsafe { ExceptionClass::from_value_unchecked(c.as_value()) })
303    }
304
305    /// Include `module` into `self`.
306    ///
307    /// Effectively makes `module` the superclass of `self`. See also
308    /// [`prepend_module`](Module::prepend_module).
309    ///
310    /// # Examples
311    ///
312    /// ```
313    /// use magnus::{function, prelude::*, rb_assert, Error, RClass, Ruby};
314    ///
315    /// fn test() -> i64 {
316    ///     42
317    /// }
318    ///
319    /// fn example(ruby: &Ruby) -> Result<(), Error> {
320    ///     let module = ruby.module_new();
321    ///     module.define_method("test", function!(test, 0))?;
322    ///
323    ///     let class = RClass::new(ruby.class_object())?;
324    ///     class.include_module(module)?;
325    ///
326    ///     let obj = class.new_instance(())?;
327    ///     rb_assert!(ruby, "obj.test == 42", obj);
328    ///
329    ///     Ok(())
330    /// }
331    /// # Ruby::init(example).unwrap()
332    /// ```
333    fn include_module(self, module: RModule) -> Result<(), Error> {
334        protect(|| {
335            unsafe { rb_include_module(self.as_rb_value(), module.as_rb_value()) };
336            Ruby::get_with(self).qnil()
337        })?;
338        Ok(())
339    }
340
341    /// Prepend `self` with `module`.
342    ///
343    /// Similar to [`include_module`](Module::include_module), but inserts
344    /// `module` as if it were a subclass in the inheritance chain.
345    ///
346    /// # Examples
347    ///
348    /// ```
349    /// use magnus::{function, prelude::*, rb_assert, Error, RClass, Ruby};
350    ///
351    /// fn test(ruby: &Ruby) -> Result<i64, Error> {
352    ///     Ok(ruby.call_super::<_, i64>(())? + 2)
353    /// }
354    ///
355    /// fn example(ruby: &Ruby) -> Result<(), Error> {
356    ///     let module = ruby.module_new();
357    ///     module.define_method("test", function!(test, 0))?;
358    ///
359    ///     let class: RClass = ruby.eval(
360    ///         r#"
361    ///             class Example
362    ///               def test
363    ///                 40
364    ///               end
365    ///             end
366    ///             Example
367    ///         "#,
368    ///     )?;
369    ///     class.prepend_module(module)?;
370    ///
371    ///     let obj = class.new_instance(())?;
372    ///     rb_assert!("obj.test == 42", obj);
373    ///
374    ///     Ok(())
375    /// }
376    /// # Ruby::init(example).unwrap()
377    /// ```
378    fn prepend_module(self, module: RModule) -> Result<(), Error> {
379        protect(|| {
380            unsafe { rb_prepend_module(self.as_rb_value(), module.as_rb_value()) };
381            Ruby::get_with(self).qnil()
382        })?;
383        Ok(())
384    }
385
386    /// Set the value for the constant `name` within `self`'s scope.
387    ///
388    /// # Examples
389    ///
390    /// ```
391    /// use magnus::{rb_assert, Error, Module, Ruby};
392    ///
393    /// fn example(ruby: &Ruby) -> Result<(), Error> {
394    ///     ruby.class_array().const_set("EXAMPLE", 42)?;
395    ///
396    ///     rb_assert!(ruby, "Array::EXAMPLE == 42");
397    ///
398    ///     Ok(())
399    /// }
400    /// # Ruby::init(example).unwrap()
401    /// ```
402    fn const_set<T, U>(self, name: T, value: U) -> Result<(), Error>
403    where
404        T: IntoId,
405        U: IntoValue,
406    {
407        let handle = Ruby::get_with(self);
408        let id = name.into_id_with(&handle);
409        let val = value.into_value_with(&handle);
410        protect(|| {
411            unsafe { rb_const_set(self.as_rb_value(), id.as_rb_id(), val.as_rb_value()) };
412            handle.qnil()
413        })?;
414        Ok(())
415    }
416
417    /// Get the value for the constant `name` within `self`'s scope.
418    ///
419    /// # Examples
420    ///
421    /// ```
422    /// use magnus::{rb_assert, Error, Module, RClass, Ruby, Value};
423    ///
424    /// fn example(ruby: &Ruby) -> Result<(), Error> {
425    ///     ruby.eval::<Value>(
426    ///         "
427    ///           class Example
428    ///             VALUE = 42
429    ///           end
430    ///         ",
431    ///     )?;
432    ///
433    ///     let class = ruby.class_object().const_get::<_, RClass>("Example")?;
434    ///     rb_assert!(ruby, "klass::VALUE == 42", klass = class);
435    ///
436    ///     Ok(())
437    /// }
438    /// # Ruby::init(example).unwrap()
439    /// ```
440    fn const_get<T, U>(self, name: T) -> Result<U, Error>
441    where
442        T: IntoId,
443        U: TryConvert,
444    {
445        debug_assert_value!(self);
446        let id = name.into_id_with(&Ruby::get_with(self));
447        let res =
448            unsafe { protect(|| Value::new(rb_const_get(self.as_rb_value(), id.as_rb_id()))) };
449        res.and_then(TryConvert::try_convert)
450    }
451
452    /// Returns whether or not `self` inherits from `other`.
453    ///
454    /// Classes including a module are considered to inherit from that module.
455    ///
456    /// # Examples
457    ///
458    /// ```
459    /// use magnus::{prelude::*, Error, Module, RClass, Ruby};
460    ///
461    /// fn example(ruby: &Ruby) -> Result<(), Error> {
462    ///     let a = RClass::new(ruby.class_object())?;
463    ///     let b = RClass::new(a)?;
464    ///     assert!(b.is_inherited(a));
465    ///     assert!(!a.is_inherited(b));
466    ///
467    ///     Ok(())
468    /// }
469    /// # Ruby::init(example).unwrap()
470    /// ```
471    fn is_inherited<T>(self, other: T) -> bool
472    where
473        T: ReprValue + Module,
474    {
475        unsafe {
476            Value::new(rb_class_inherited_p(
477                self.as_rb_value(),
478                other.as_rb_value(),
479            ))
480            .to_bool()
481        }
482    }
483
484    /// Return the classes and modules `self` inherits, includes, or prepends.
485    ///
486    /// # Examples
487    ///
488    /// ```
489    /// use magnus::{rb_assert, Error, Module, Ruby};
490    ///
491    /// fn example(ruby: &Ruby) -> Result<(), Error> {
492    ///     let ary = ruby.class_string().ancestors();
493    ///
494    ///     rb_assert!(
495    ///         ruby,
496    ///         "ary == [String, Comparable, Object, Kernel, BasicObject]",
497    ///         ary,
498    ///     );
499    ///
500    ///     Ok(())
501    /// }
502    /// # Ruby::init(example).unwrap()
503    /// ```
504    fn ancestors(self) -> RArray {
505        unsafe { RArray::from_rb_value_unchecked(rb_mod_ancestors(self.as_rb_value())) }
506    }
507
508    /// Define a method in `self`'s scope.
509    ///
510    /// # Examples
511    ///
512    /// ```
513    /// use magnus::{method, rb_assert, Error, Module, Ruby};
514    ///
515    /// fn escape_unicode(s: String) -> String {
516    ///     s.escape_unicode().to_string()
517    /// }
518    ///
519    /// fn example(ruby: &Ruby) -> Result<(), Error> {
520    ///     ruby.class_string()
521    ///         .define_method("escape_unicode", method!(escape_unicode, 0))?;
522    ///
523    ///     rb_assert!(
524    ///         ruby,
525    ///         r#""🤖\etest".escape_unicode == "\\u{1f916}\\u{1b}\\u{74}\\u{65}\\u{73}\\u{74}""#,
526    ///     );
527    ///
528    ///     Ok(())
529    /// }
530    /// # Ruby::init(example).unwrap()
531    /// ```
532    fn define_method<T, M>(self, name: T, func: M) -> Result<(), Error>
533    where
534        T: IntoId,
535        M: Method,
536    {
537        debug_assert_value!(self);
538        let handle = Ruby::get_with(self);
539        let id = name.into_id_with(&handle);
540        protect(|| {
541            unsafe {
542                rb_define_method_id(
543                    self.as_rb_value(),
544                    id.as_rb_id(),
545                    transmute(func.as_ptr()),
546                    M::arity().into(),
547                )
548            };
549            handle.qnil()
550        })?;
551        Ok(())
552    }
553
554    /// Define a private method in `self`'s scope.
555    ///
556    /// # Examples
557    ///
558    /// ```
559    /// use magnus::{eval, function, rb_assert, Error, Module, Ruby, Value};
560    ///
561    /// fn percent_encode(c: char) -> String {
562    ///     if c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '.' || c == '~' {
563    ///         String::from(c)
564    ///     } else {
565    ///         format!("%{:X}", c as u32)
566    ///     }
567    /// }
568    ///
569    /// fn example(ruby: &Ruby) -> Result<(), Error> {
570    ///     ruby.class_string()
571    ///         .define_private_method("percent_encode_char", function!(percent_encode, 1))?;
572    ///
573    ///     ruby.eval::<Value>(
574    ///         r#"
575    ///             class String
576    ///               def percent_encode
577    ///                 chars.map {|c| percent_encode_char(c)}.join("")
578    ///               end
579    ///             end
580    ///         "#,
581    ///     )?;
582    ///
583    ///     rb_assert!(ruby, r#""foo bar".percent_encode == "foo%20bar""#);
584    ///
585    ///     assert!(eval::<bool>(r#"" ".percent_encode_char(" ")"#)
586    ///         .unwrap_err()
587    ///         .is_kind_of(ruby.exception_no_method_error()));
588    ///
589    ///     Ok(())
590    /// }
591    /// # Ruby::init(example).unwrap()
592    /// ```
593    fn define_private_method<M>(self, name: &str, func: M) -> Result<(), Error>
594    where
595        M: Method,
596    {
597        debug_assert_value!(self);
598        let name = CString::new(name).unwrap();
599        protect(|| {
600            unsafe {
601                rb_define_private_method(
602                    self.as_rb_value(),
603                    name.as_ptr(),
604                    transmute(func.as_ptr()),
605                    M::arity().into(),
606                )
607            };
608            Ruby::get_with(self).qnil()
609        })?;
610        Ok(())
611    }
612
613    /// Define a protected method in `self`'s scope.
614    ///
615    /// # Examples
616    ///
617    /// ```
618    /// use magnus::{method, rb_assert, Error, Module, Ruby, Value};
619    ///
620    /// fn escape_unicode(s: String) -> String {
621    ///     s.escape_unicode().to_string()
622    /// }
623    ///
624    /// fn is_invisible(c: char) -> bool {
625    ///     c.is_control() || c.is_whitespace()
626    /// }
627    ///
628    /// fn example(ruby: &Ruby) -> Result<(), Error> {
629    ///     ruby.class_string()
630    ///         .define_method("escape_unicode", method!(escape_unicode, 0))?;
631    ///     ruby.class_string()
632    ///         .define_protected_method("invisible?", method!(is_invisible, 0))?;
633    ///
634    ///     ruby.eval::<Value>(
635    ///         r#"
636    ///             class String
637    ///               def escape_invisible
638    ///                 chars.map {|c| c.invisible? ? c.escape_unicode : c}.join("")
639    ///               end
640    ///             end
641    ///         "#,
642    ///     )?;
643    ///
644    ///     rb_assert!(
645    ///         ruby,
646    ///         r#""🤖\tfoo bar".escape_invisible == "🤖\\u{9}foo\\u{20}bar""#,
647    ///     );
648    ///
649    ///     assert!(ruby
650    ///         .eval::<bool>(r#"" ".invisible?"#)
651    ///         .unwrap_err()
652    ///         .is_kind_of(ruby.exception_no_method_error()));
653    ///
654    ///     Ok(())
655    /// }
656    /// # Ruby::init(example).unwrap()
657    /// ```
658    fn define_protected_method<M>(self, name: &str, func: M) -> Result<(), Error>
659    where
660        M: Method,
661    {
662        debug_assert_value!(self);
663        let name = CString::new(name).unwrap();
664        protect(|| {
665            unsafe {
666                rb_define_protected_method(
667                    self.as_rb_value(),
668                    name.as_ptr(),
669                    transmute(func.as_ptr()),
670                    M::arity().into(),
671                )
672            };
673            Ruby::get_with(self).qnil()
674        })?;
675        Ok(())
676    }
677
678    /// Define public accessor methods for the attribute `name`.
679    ///
680    /// `name` should be **without** the preceding `@`.
681    ///
682    /// # Examples
683    ///
684    /// ```
685    /// use magnus::{eval, prelude::*, rb_assert, Attr, Error, Module, RClass, Ruby, Value};
686    ///
687    /// fn example(ruby: &Ruby) -> Result<(), Error> {
688    ///     let class = RClass::new(ruby.class_object())?;
689    ///     class.define_attr("example", Attr::ReadWrite)?;
690    ///
691    ///     let obj = class.new_instance(())?;
692    ///     let _: Value = eval!(ruby, "obj.example = 42", obj)?;
693    ///     rb_assert!(ruby, "obj.example == 42", obj);
694    ///
695    ///     Ok(())
696    /// }
697    /// # Ruby::init(example).unwrap()
698    /// ```
699    fn define_attr<T>(self, name: T, rw: Attr) -> Result<(), Error>
700    where
701        T: IntoId,
702    {
703        let handle = Ruby::get_with(self);
704        let id = name.into_id_with(&handle);
705        protect(|| {
706            unsafe {
707                rb_attr(
708                    self.as_rb_value(),
709                    id.as_rb_id(),
710                    rw.is_read() as c_int,
711                    rw.is_write() as c_int,
712                    0,
713                )
714            };
715            handle.qnil()
716        })?;
717        Ok(())
718    }
719
720    /// Alias the method `src` of `self` as `dst`.
721    ///
722    /// # Examples
723    ///
724    /// ```
725    /// use magnus::{function, prelude::*, rb_assert, Error, Module, RClass, Ruby};
726    ///
727    /// fn test() -> i64 {
728    ///     42
729    /// }
730    ///
731    /// fn example(ruby: &Ruby) -> Result<(), Error> {
732    ///     let class = RClass::new(ruby.class_object())?;
733    ///     class.define_method("test", function!(test, 0))?;
734    ///     class.define_alias("example", "test")?;
735    ///
736    ///     let obj = class.new_instance(())?;
737    ///     rb_assert!(ruby, "obj.example == 42", obj);
738    ///
739    ///     Ok(())
740    /// }
741    /// # Ruby::init(example).unwrap()
742    /// ```
743    fn define_alias<T, U>(self, dst: T, src: U) -> Result<(), Error>
744    where
745        T: IntoId,
746        U: IntoId,
747    {
748        let handle = Ruby::get_with(self);
749        let d_id = dst.into_id_with(&handle);
750        let s_id = src.into_id_with(&handle);
751        protect(|| {
752            unsafe { rb_alias(self.as_rb_value(), d_id.as_rb_id(), s_id.as_rb_id()) };
753            handle.qnil()
754        })?;
755        Ok(())
756    }
757}
758
759/// Argument for [`define_attr`](Module::define_attr).
760#[derive(Clone, Copy, Debug)]
761pub enum Attr {
762    /// Define a reader method like `name`.
763    Read,
764    /// Define a writer method like `name=`.
765    Write,
766    /// Define both reader and writer methods like `name` and `name=`.
767    ReadWrite,
768}
769
770impl Attr {
771    fn is_read(self) -> bool {
772        match self {
773            Attr::Read | Attr::ReadWrite => true,
774            Attr::Write => false,
775        }
776    }
777
778    fn is_write(self) -> bool {
779        match self {
780            Attr::Write | Attr::ReadWrite => true,
781            Attr::Read => false,
782        }
783    }
784}
785
786/// # Core Modules
787///
788/// Functions to access Ruby's built-in modules.
789///
790/// See also [`Ruby::define_module`] and the [`module`](self) module.
791impl Ruby {
792    /// Return Ruby's `Comparable` module.
793    ///
794    /// # Examples
795    ///
796    /// ```
797    /// use magnus::{rb_assert, Error, Ruby};
798    ///
799    /// fn example(ruby: &Ruby) -> Result<(), Error> {
800    ///     rb_assert!(ruby, "md == Comparable", md = ruby.module_comparable());
801    ///
802    ///     Ok(())
803    /// }
804    /// # Ruby::init(example).unwrap()
805    /// ```
806    #[inline]
807    pub fn module_comparable(&self) -> RModule {
808        unsafe { RModule::from_rb_value_unchecked(rb_mComparable) }
809    }
810
811    /// Return Ruby's `Enumerable` module.
812    ///
813    /// # Examples
814    ///
815    /// ```
816    /// use magnus::{rb_assert, Error, Ruby};
817    ///
818    /// fn example(ruby: &Ruby) -> Result<(), Error> {
819    ///     rb_assert!(ruby, "md == Enumerable", md = ruby.module_enumerable());
820    ///
821    ///     Ok(())
822    /// }
823    /// # Ruby::init(example).unwrap()
824    /// ```
825    #[inline]
826    pub fn module_enumerable(&self) -> RModule {
827        unsafe { RModule::from_rb_value_unchecked(rb_mEnumerable) }
828    }
829
830    /// Return Ruby's `Errno` module.
831    ///
832    /// # Examples
833    ///
834    /// ```
835    /// use magnus::{rb_assert, Error, Ruby};
836    ///
837    /// fn example(ruby: &Ruby) -> Result<(), Error> {
838    ///     rb_assert!(ruby, "md == Errno", md = ruby.module_errno());
839    ///
840    ///     Ok(())
841    /// }
842    /// # Ruby::init(example).unwrap()
843    /// ```
844    #[inline]
845    pub fn module_errno(&self) -> RModule {
846        unsafe { RModule::from_rb_value_unchecked(rb_mErrno) }
847    }
848
849    /// Return Ruby's `FileTest` module.
850    ///
851    /// # Examples
852    ///
853    /// ```
854    /// use magnus::{rb_assert, Error, Ruby};
855    ///
856    /// fn example(ruby: &Ruby) -> Result<(), Error> {
857    ///     rb_assert!(ruby, "md == FileTest", md = ruby.module_file_test());
858    ///
859    ///     Ok(())
860    /// }
861    /// # Ruby::init(example).unwrap()
862    /// ```
863    #[inline]
864    pub fn module_file_test(&self) -> RModule {
865        unsafe { RModule::from_rb_value_unchecked(rb_mFileTest) }
866    }
867
868    /// Return Ruby's `GC` module.
869    ///
870    /// # Examples
871    ///
872    /// ```
873    /// use magnus::{rb_assert, Error, Ruby};
874    ///
875    /// fn example(ruby: &Ruby) -> Result<(), Error> {
876    ///     rb_assert!(ruby, "md == GC", md = ruby.module_gc());
877    ///
878    ///     Ok(())
879    /// }
880    /// # Ruby::init(example).unwrap()
881    /// ```
882    #[inline]
883    pub fn module_gc(&self) -> RModule {
884        unsafe { RModule::from_rb_value_unchecked(rb_mGC) }
885    }
886
887    /// Return Ruby's `Kernel` module.
888    ///
889    /// # Examples
890    ///
891    /// ```
892    /// use magnus::{rb_assert, Error, Ruby};
893    ///
894    /// fn example(ruby: &Ruby) -> Result<(), Error> {
895    ///     rb_assert!(ruby, "md == Kernel", md = ruby.module_kernel());
896    ///
897    ///     Ok(())
898    /// }
899    /// # Ruby::init(example).unwrap()
900    /// ```
901    #[inline]
902    pub fn module_kernel(&self) -> RModule {
903        unsafe { RModule::from_rb_value_unchecked(rb_mKernel) }
904    }
905
906    /// Return Ruby's `Math` module.
907    ///
908    /// # Examples
909    ///
910    /// ```
911    /// use magnus::{rb_assert, Error, Ruby};
912    ///
913    /// fn example(ruby: &Ruby) -> Result<(), Error> {
914    ///     rb_assert!(ruby, "md == Math", md = ruby.module_math());
915    ///
916    ///     Ok(())
917    /// }
918    /// # Ruby::init(example).unwrap()
919    /// ```
920    #[inline]
921    pub fn module_math(&self) -> RModule {
922        unsafe { RModule::from_rb_value_unchecked(rb_mMath) }
923    }
924
925    /// Return Ruby's `Process` module.
926    ///
927    /// # Examples
928    ///
929    /// ```
930    /// use magnus::{rb_assert, Error, Ruby};
931    ///
932    /// fn example(ruby: &Ruby) -> Result<(), Error> {
933    ///     rb_assert!(ruby, "md == Process", md = ruby.module_process());
934    ///
935    ///     Ok(())
936    /// }
937    /// # Ruby::init(example).unwrap()
938    /// ```
939    #[inline]
940    pub fn module_process(&self) -> RModule {
941        unsafe { RModule::from_rb_value_unchecked(rb_mProcess) }
942    }
943
944    /// Return Ruby's `IO::WaitReadable` module.
945    ///
946    /// # Examples
947    ///
948    /// ```
949    /// use magnus::{rb_assert, Error, Ruby};
950    ///
951    /// fn example(ruby: &Ruby) -> Result<(), Error> {
952    ///     rb_assert!(
953    ///         ruby,
954    ///         "md == IO::WaitReadable",
955    ///         md = ruby.module_wait_readable()
956    ///     );
957    ///
958    ///     Ok(())
959    /// }
960    /// # Ruby::init(example).unwrap()
961    /// ```
962    #[inline]
963    pub fn module_wait_readable(&self) -> RModule {
964        unsafe { RModule::from_rb_value_unchecked(rb_mWaitReadable) }
965    }
966
967    /// Return Ruby's `IO::WaitWritable` module.
968    ///
969    /// # Examples
970    ///
971    /// ```
972    /// use magnus::{rb_assert, Error, Ruby};
973    ///
974    /// fn example(ruby: &Ruby) -> Result<(), Error> {
975    ///     rb_assert!(
976    ///         ruby,
977    ///         "md == IO::WaitWritable",
978    ///         md = ruby.module_wait_writable()
979    ///     );
980    ///
981    ///     Ok(())
982    /// }
983    /// # Ruby::init(example).unwrap()
984    /// ```
985    #[inline]
986    pub fn module_wait_writable(&self) -> RModule {
987        unsafe { RModule::from_rb_value_unchecked(rb_mWaitWritable) }
988    }
989}
990
991/// Return Ruby's `Comparable` module.
992///
993/// # Panics
994///
995/// Panics if called from a non-Ruby thread. See [`Ruby::module_comparable`]
996/// for the non-panicking version.
997#[cfg_attr(
998    not(feature = "old-api"),
999    deprecated(note = "please use `Ruby::module_comparable` instead")
1000)]
1001#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1002#[inline]
1003pub fn comparable() -> RModule {
1004    get_ruby!().module_comparable()
1005}
1006
1007/// Return Ruby's `Enumerable` module.
1008///
1009/// # Panics
1010///
1011/// Panics if called from a non-Ruby thread. See [`Ruby::module_enumerable`]
1012/// for the non-panicking version.
1013#[cfg_attr(
1014    not(feature = "old-api"),
1015    deprecated(note = "please use `Ruby::module_enumerable` instead")
1016)]
1017#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1018#[inline]
1019pub fn enumerable() -> RModule {
1020    get_ruby!().module_enumerable()
1021}
1022
1023/// Return Ruby's `Errno` module.
1024///
1025/// # Panics
1026///
1027/// Panics if called from a non-Ruby thread. See [`Ruby::module_errno`] for the
1028/// non-panicking version.
1029#[cfg_attr(
1030    not(feature = "old-api"),
1031    deprecated(note = "please use `Ruby::module_errno` instead")
1032)]
1033#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1034#[inline]
1035pub fn errno() -> RModule {
1036    get_ruby!().module_errno()
1037}
1038
1039/// Return Ruby's `FileTest` module.
1040///
1041/// # Panics
1042///
1043/// Panics if called from a non-Ruby thread. See [`Ruby::module_file_test`] for
1044/// the non-panicking version.
1045#[cfg_attr(
1046    not(feature = "old-api"),
1047    deprecated(note = "please use `Ruby::module_file_test` instead")
1048)]
1049#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1050#[inline]
1051pub fn file_test() -> RModule {
1052    get_ruby!().module_file_test()
1053}
1054
1055/// Return Ruby's `GC` module.
1056///
1057/// # Panics
1058///
1059/// Panics if called from a non-Ruby thread. See [`Ruby::module_gc`] for the
1060/// non-panicking version.
1061#[cfg_attr(
1062    not(feature = "old-api"),
1063    deprecated(note = "please use `Ruby::module_gc` instead")
1064)]
1065#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1066#[inline]
1067pub fn gc() -> RModule {
1068    get_ruby!().module_gc()
1069}
1070
1071/// Return Ruby's `Kernel` module.
1072///
1073/// # Panics
1074///
1075/// Panics if called from a non-Ruby thread. See [`Ruby::module_kernel`] for
1076/// the non-panicking version.
1077#[cfg_attr(
1078    not(feature = "old-api"),
1079    deprecated(note = "please use `Ruby::module_kernel` instead")
1080)]
1081#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1082#[inline]
1083pub fn kernel() -> RModule {
1084    get_ruby!().module_kernel()
1085}
1086
1087/// Return Ruby's `Math` module.
1088///
1089/// # Panics
1090///
1091/// Panics if called from a non-Ruby thread. See [`Ruby::module_math`] for the
1092/// non-panicking version.
1093#[cfg_attr(
1094    not(feature = "old-api"),
1095    deprecated(note = "please use `Ruby::module_math` instead")
1096)]
1097#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1098#[inline]
1099pub fn math() -> RModule {
1100    get_ruby!().module_math()
1101}
1102
1103/// Return Ruby's `Process` module.
1104///
1105/// # Panics
1106///
1107/// Panics if called from a non-Ruby thread. See [`Ruby::module_process`] for
1108/// the non-panicking version.
1109#[cfg_attr(
1110    not(feature = "old-api"),
1111    deprecated(note = "please use `Ruby::module_process` instead")
1112)]
1113#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1114#[inline]
1115pub fn process() -> RModule {
1116    get_ruby!().module_process()
1117}
1118
1119/// Return Ruby's `IO::WaitReadable` module.
1120///
1121/// # Panics
1122///
1123/// Panics if called from a non-Ruby thread. See [`Ruby::module_wait_readable`]
1124/// for the non-panicking version.
1125#[cfg_attr(
1126    not(feature = "old-api"),
1127    deprecated(note = "please use `Ruby::module_wait_readable` instead")
1128)]
1129#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1130#[inline]
1131pub fn wait_readable() -> RModule {
1132    get_ruby!().module_wait_readable()
1133}
1134
1135/// Return Ruby's `IO::WaitWritable` module.
1136///
1137/// # Panics
1138///
1139/// Panics if called from a non-Ruby thread. See [`Ruby::module_wait_writable`]
1140/// for the non-panicking version.
1141#[cfg_attr(
1142    not(feature = "old-api"),
1143    deprecated(note = "please use `Ruby::module_wait_writable` instead")
1144)]
1145#[cfg_attr(docsrs, doc(cfg(feature = "old-api")))]
1146#[inline]
1147pub fn wait_writable() -> RModule {
1148    get_ruby!().module_wait_writable()
1149}