Skip to content

Commit a424273

Browse files
committed
Make sure more protocols are implemented and documented
1 parent 9c72ea8 commit a424273

File tree

14 files changed

+521
-231
lines changed

14 files changed

+521
-231
lines changed

crates/rune/src/modules/cmp.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! The `std::cmp` module.
22
33
use core::cmp::Ordering;
4+
use core::fmt::{self, Write};
45

56
use crate as rune;
7+
use crate::no_std::prelude::*;
68
use crate::runtime::{Protocol, Value, VmResult};
79
use crate::{ContextError, Module};
810

@@ -16,16 +18,17 @@ pub fn module() -> Result<Module, ContextError> {
1618
"",
1719
"# Examples",
1820
"",
19-
"```",
21+
"```rune",
2022
"use std::cmp::Ordering;",
23+
"use std::ops::cmp;",
2124
"",
22-
"let result = 1.cmp(2);",
25+
"let result = cmp(1, 2);",
2326
"assert_eq!(Ordering::Less, result);",
2427
"",
25-
"let result = 1.cmp(1);",
28+
"let result = cmp(1, 1);",
2629
"assert_eq!(Ordering::Equal, result);",
2730
"",
28-
"let result = 2.cmp(1);",
31+
"let result = cmp(2, 1);",
2932
"assert_eq!(Ordering::Greater, result);",
3033
"```",
3134
]);
@@ -52,6 +55,7 @@ pub fn module() -> Result<Module, ContextError> {
5255
lhs == rhs
5356
})?;
5457
m.associated_function(Protocol::EQ, |lhs: Ordering, rhs: Ordering| lhs == rhs)?;
58+
m.function_meta(ordering_string_debug)?;
5559
m.function_meta(min)?;
5660
m.function_meta(max)?;
5761
Ok(m)
@@ -100,3 +104,17 @@ fn min(v1: Value, v2: Value) -> VmResult<Value> {
100104
Ordering::Greater => v2,
101105
})
102106
}
107+
108+
/// Debug format [`Ordering`].
109+
///
110+
/// # Examples
111+
///
112+
/// ```rune
113+
/// use std::cmp::Ordering;
114+
///
115+
/// assert_eq!(format!("{:?}", Ordering::Less), "Less");
116+
/// ```
117+
#[rune::function(instance, protocol = STRING_DEBUG)]
118+
fn ordering_string_debug(this: Ordering, s: &mut String) -> fmt::Result {
119+
write!(s, "{:?}", this)
120+
}

crates/rune/src/modules/f64.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! The `std::f64` module.
22
3+
use core::cmp::Ordering;
34
use core::num::ParseFloatError;
45

56
use crate as rune;
7+
use crate::runtime::{VmErrorKind, VmResult};
68
use crate::{ContextError, Module};
79

810
/// Install the core package into the given functions namespace.
@@ -25,6 +27,10 @@ pub fn module() -> Result<Module, ContextError> {
2527
#[cfg(feature = "std")]
2628
m.function_meta(powi)?;
2729
m.function_meta(to_integer)?;
30+
m.function_meta(partial_eq)?;
31+
m.function_meta(eq)?;
32+
m.function_meta(partial_cmp)?;
33+
m.function_meta(cmp)?;
2834

2935
m.constant(["EPSILON"], f64::EPSILON)?;
3036
m.constant(["MIN"], f64::MIN)?;
@@ -254,3 +260,88 @@ fn powf(this: f64, other: f64) -> f64 {
254260
fn powi(this: f64, other: i32) -> f64 {
255261
this.powi(other)
256262
}
263+
264+
/// Test two floats for partial equality.
265+
///
266+
/// # Examples
267+
///
268+
/// ```rune
269+
/// assert!(5.0 == 5.0);
270+
/// assert!(5.0 != 10.0);
271+
/// assert!(10.0 != 5.0);
272+
/// assert!(10.0 != f64::NAN);
273+
/// assert!(f64::NAN != f64::NAN);
274+
/// ```
275+
#[rune::function(instance, protocol = PARTIAL_EQ)]
276+
#[inline]
277+
fn partial_eq(this: f64, rhs: f64) -> bool {
278+
this.eq(&rhs)
279+
}
280+
281+
/// Test two floats for total equality.
282+
///
283+
/// # Examples
284+
///
285+
/// ```rune
286+
/// use std::ops::eq;
287+
///
288+
/// assert_eq!(eq(5.0, 5.0), true);
289+
/// assert_eq!(eq(5.0, 10.0), false);
290+
/// assert_eq!(eq(10.0, 5.0), false);
291+
/// ```
292+
#[rune::function(instance, protocol = EQ)]
293+
#[inline]
294+
fn eq(this: f64, rhs: f64) -> VmResult<bool> {
295+
let Some(ordering) = this.partial_cmp(&rhs) else {
296+
return VmResult::err(VmErrorKind::IllegalFloatComparison {
297+
lhs: this,
298+
rhs,
299+
})
300+
};
301+
302+
VmResult::Ok(matches!(ordering, Ordering::Equal))
303+
}
304+
305+
/// Perform a partial ordered comparison between two floats.
306+
///
307+
/// # Examples
308+
///
309+
/// ```rune
310+
/// use std::cmp::Ordering;
311+
/// use std::ops::partial_cmp;
312+
///
313+
/// assert_eq!(partial_cmp(5.0, 10.0), Some(Ordering::Less));
314+
/// assert_eq!(partial_cmp(10.0, 5.0), Some(Ordering::Greater));
315+
/// assert_eq!(partial_cmp(5.0, 5.0), Some(Ordering::Equal));
316+
/// assert_eq!(partial_cmp(5.0, f64::NAN), None);
317+
/// ```
318+
#[rune::function(instance, protocol = PARTIAL_CMP)]
319+
#[inline]
320+
fn partial_cmp(this: f64, rhs: f64) -> Option<Ordering> {
321+
this.partial_cmp(&rhs)
322+
}
323+
324+
/// Perform a partial ordered comparison between two floats.
325+
///
326+
/// # Examples
327+
///
328+
/// ```rune
329+
/// use std::cmp::Ordering;
330+
/// use std::ops::cmp;
331+
///
332+
/// assert_eq!(cmp(5.0, 10.0), Ordering::Less);
333+
/// assert_eq!(cmp(10.0, 5.0), Ordering::Greater);
334+
/// assert_eq!(cmp(5.0, 5.0), Ordering::Equal);
335+
/// ```
336+
#[rune::function(instance, protocol = CMP)]
337+
#[inline]
338+
fn cmp(this: f64, rhs: f64) -> VmResult<Ordering> {
339+
let Some(ordering) = this.partial_cmp(&rhs) else {
340+
return VmResult::err(VmErrorKind::IllegalFloatComparison {
341+
lhs: this,
342+
rhs,
343+
})
344+
};
345+
346+
VmResult::Ok(ordering)
347+
}

crates/rune/src/modules/i64.rs

Lines changed: 74 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ pub fn module() -> Result<Module, ContextError> {
1313
let mut module = Module::with_crate_item("std", ["i64"]);
1414

1515
module.function(["parse"], parse)?;
16-
module.function_meta(cmp)?;
1716
module.function_meta(to_float)?;
1817

1918
module.function_meta(max)?;
@@ -43,6 +42,10 @@ pub fn module() -> Result<Module, ContextError> {
4342
module.function_meta(is_positive)?;
4443
module.function_meta(is_negative)?;
4544

45+
module.function_meta(partial_eq)?;
46+
module.function_meta(eq)?;
47+
module.function_meta(partial_cmp)?;
48+
module.function_meta(cmp)?;
4649
module.function_meta(to_string)?;
4750

4851
module.constant(["MIN"], i64::MIN)?.docs([
@@ -85,26 +88,6 @@ fn parse(s: &str) -> Result<i64, ParseIntError> {
8588
str::parse::<i64>(s)
8689
}
8790

88-
/// This method returns an Ordering between self and other.
89-
///
90-
/// By convention, `self.cmp(other)` returns the ordering matching the
91-
/// expression `self <operator> other` if true.
92-
///
93-
/// # Examples
94-
///
95-
/// ```rune
96-
/// use std::cmp::Ordering;
97-
///
98-
/// assert_eq!(5.cmp(10), Ordering::Less);
99-
/// assert_eq!(10.cmp(5), Ordering::Greater);
100-
/// assert_eq!(5.cmp(5), Ordering::Equal);
101-
/// ```
102-
#[rune::function(instance)]
103-
#[inline]
104-
fn cmp(this: i64, rhs: i64) -> Ordering {
105-
this.cmp(&rhs)
106-
}
107-
10891
/// Convert an `int` to a `float`.
10992
///
11093
/// # Examples
@@ -533,6 +516,76 @@ fn is_negative(this: i64) -> bool {
533516
i64::is_negative(this)
534517
}
535518

519+
/// Test two integers for partial equality.
520+
///
521+
/// # Examples
522+
///
523+
/// ```rune
524+
/// use std::ops::partial_eq;
525+
///
526+
/// assert_eq!(partial_eq(5, 5), true);
527+
/// assert_eq!(partial_eq(5, 10), false);
528+
/// assert_eq!(partial_eq(10, 5), false);
529+
/// ```
530+
#[rune::function(instance, protocol = PARTIAL_EQ)]
531+
#[inline]
532+
fn partial_eq(this: i64, rhs: i64) -> bool {
533+
this.eq(&rhs)
534+
}
535+
536+
/// Test two integers for total equality.
537+
///
538+
/// # Examples
539+
///
540+
/// ```rune
541+
/// use std::ops::eq;
542+
///
543+
/// assert_eq!(eq(5, 5), true);
544+
/// assert_eq!(eq(5, 10), false);
545+
/// assert_eq!(eq(10, 5), false);
546+
/// ```
547+
#[rune::function(instance, protocol = EQ)]
548+
#[inline]
549+
fn eq(this: i64, rhs: i64) -> bool {
550+
this.eq(&rhs)
551+
}
552+
553+
/// Perform a partial ordered comparison between two integers.
554+
///
555+
/// # Examples
556+
///
557+
/// ```rune
558+
/// use std::cmp::Ordering;
559+
/// use std::ops::partial_cmp;
560+
///
561+
/// assert_eq!(partial_cmp(5, 10), Some(Ordering::Less));
562+
/// assert_eq!(partial_cmp(10, 5), Some(Ordering::Greater));
563+
/// assert_eq!(partial_cmp(5, 5), Some(Ordering::Equal));
564+
/// ```
565+
#[rune::function(instance, protocol = PARTIAL_CMP)]
566+
#[inline]
567+
fn partial_cmp(this: i64, rhs: i64) -> Option<Ordering> {
568+
this.partial_cmp(&rhs)
569+
}
570+
571+
/// Perform a partial ordered comparison between two integers.
572+
///
573+
/// # Examples
574+
///
575+
/// ```rune
576+
/// use std::cmp::Ordering;
577+
/// use std::ops::cmp;
578+
///
579+
/// assert_eq!(cmp(5, 10), Ordering::Less);
580+
/// assert_eq!(cmp(10, 5), Ordering::Greater);
581+
/// assert_eq!(cmp(5, 5), Ordering::Equal);
582+
/// ```
583+
#[rune::function(instance, protocol = CMP)]
584+
#[inline]
585+
fn cmp(this: i64, rhs: i64) -> Ordering {
586+
this.cmp(&rhs)
587+
}
588+
536589
/// Returns the number as a string.
537590
///
538591
/// # Examples

crates/rune/src/modules/object.rs

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ use core::cmp::Ordering;
55
use crate::no_std::prelude::*;
66

77
use crate as rune;
8-
use crate::runtime::{
9-
EnvProtocolCaller, FromValue, Iterator, Object, Protocol, Ref, Value, VmResult,
10-
};
8+
use crate::runtime::{EnvProtocolCaller, Iterator, Object, Protocol, Value, VmResult};
119
use crate::{ContextError, Module};
1210

1311
/// Construct the `std::object` module.
@@ -30,10 +28,10 @@ pub fn module() -> Result<Module, ContextError> {
3028
m.function_meta(keys)?;
3129
m.function_meta(values)?;
3230
m.associated_function(Protocol::INTO_ITER, Object::rune_iter)?;
33-
m.associated_function(Protocol::PARTIAL_EQ, partial_eq)?;
34-
m.associated_function(Protocol::EQ, eq)?;
35-
m.associated_function(Protocol::PARTIAL_CMP, partial_cmp)?;
36-
m.associated_function(Protocol::CMP, cmp)?;
31+
m.function_meta(partial_eq)?;
32+
m.function_meta(eq)?;
33+
m.function_meta(partial_cmp)?;
34+
m.function_meta(cmp)?;
3735
Ok(m)
3836
}
3937

@@ -126,40 +124,22 @@ fn values(object: &Object) -> Iterator {
126124
Iterator::from_double_ended("std::object::Values", iter)
127125
}
128126

127+
#[rune::function(instance, protocol = PARTIAL_EQ)]
129128
fn partial_eq(this: &Object, other: Value) -> VmResult<bool> {
130-
let mut other = vm_try!(other.into_iter());
131-
132-
for (k1, v1) in this.iter() {
133-
let Some(value) = vm_try!(other.next()) else {
134-
return VmResult::Ok(false);
135-
};
136-
137-
let (k2, v2) = vm_try!(<(Ref<String>, Value)>::from_value(value));
138-
139-
if k1 != &*k2 {
140-
return VmResult::Ok(false);
141-
}
142-
143-
if !vm_try!(Value::partial_eq(v1, &v2)) {
144-
return VmResult::Ok(false);
145-
}
146-
}
147-
148-
if vm_try!(other.next()).is_some() {
149-
return VmResult::Ok(false);
150-
}
151-
152-
VmResult::Ok(true)
129+
Object::partial_eq_with(this, other, &mut EnvProtocolCaller)
153130
}
154131

132+
#[rune::function(instance, protocol = EQ)]
155133
fn eq(this: &Object, other: &Object) -> VmResult<bool> {
156-
Object::eq_with(this, other, &mut EnvProtocolCaller)
134+
Object::eq_with(this, other, Value::eq_with, &mut EnvProtocolCaller)
157135
}
158136

137+
#[rune::function(instance, protocol = PARTIAL_CMP)]
159138
fn partial_cmp(this: &Object, other: &Object) -> VmResult<Option<Ordering>> {
160139
Object::partial_cmp_with(this, other, &mut EnvProtocolCaller)
161140
}
162141

142+
#[rune::function(instance, protocol = CMP)]
163143
fn cmp(this: &Object, other: &Object) -> VmResult<Ordering> {
164144
Object::cmp_with(this, other, &mut EnvProtocolCaller)
165145
}

0 commit comments

Comments
 (0)