rune/modules/
result.rs

1//! The [`Result`] type.
2
3use core::cmp::Ordering;
4use core::hash::Hasher as _;
5
6use crate as rune;
7use crate::alloc::fmt::TryWrite;
8use crate::alloc::prelude::*;
9use crate::runtime::{
10    ControlFlow, EnvProtocolCaller, Formatter, Function, Hasher, Panic, Protocol, Value, VmResult,
11};
12use crate::{hash_in, ContextError, Hash, Module};
13
14/// The [`Result`] type.
15///
16/// This module deals with the fundamental [`Result`] type in Rune.
17#[rune::module(::std::result)]
18pub fn module() -> Result<Module, ContextError> {
19    let mut m = Module::from_meta(self::module_meta)?;
20
21    // Sorted for ease of finding
22    let mut result = m
23        .ty::<Result<Value, Value>>()?
24        .static_docs(&["Result is a type that represents either success (Ok) or failure (Err)."])?
25        .make_enum(&["Ok", "Err"])?;
26
27    result
28        .variant_mut(0)?
29        .make_unnamed(1)?
30        .constructor(Result::Ok)?
31        .static_docs(&["Contains the success value"])?;
32
33    result
34        .variant_mut(1)?
35        .make_unnamed(1)?
36        .constructor(Result::Err)?
37        .static_docs(&["Contains the error value"])?;
38
39    m.associated_function(
40        &Protocol::IS_VARIANT,
41        |this: &Result<Value, Value>, hash: Hash| match (this, hash) {
42            (Result::Ok(_), hash_in!(crate, ::std::result::Result::Ok)) => true,
43            (Result::Err(_), hash_in!(crate, ::std::result::Result::Err)) => true,
44            _ => false,
45        },
46    )?;
47
48    m.index_function(
49        &Protocol::GET,
50        0,
51        |this: &Result<Value, Value>| match this {
52            Result::Ok(value) => VmResult::Ok(value.clone()),
53            Result::Err(value) => VmResult::Ok(value.clone()),
54        },
55    )?;
56
57    m.function_meta(ok)?;
58    m.function_meta(is_ok)?;
59    m.function_meta(is_err)?;
60    m.function_meta(unwrap)?;
61    m.function_meta(unwrap_or)?;
62    m.function_meta(unwrap_or_else)?;
63    m.function_meta(expect)?;
64    m.function_meta(and_then)?;
65    m.function_meta(map)?;
66
67    m.function_meta(clone__meta)?;
68    m.implement_trait::<Result<Value, Value>>(rune::item!(::std::clone::Clone))?;
69
70    m.function_meta(partial_eq__meta)?;
71    m.implement_trait::<Result<Value, Value>>(rune::item!(::std::cmp::PartialEq))?;
72
73    m.function_meta(eq__meta)?;
74    m.implement_trait::<Result<Value, Value>>(rune::item!(::std::cmp::Eq))?;
75
76    m.function_meta(partial_cmp__meta)?;
77    m.implement_trait::<Result<Value, Value>>(rune::item!(::std::cmp::PartialOrd))?;
78
79    m.function_meta(cmp__meta)?;
80    m.implement_trait::<Result<Value, Value>>(rune::item!(::std::cmp::Ord))?;
81
82    m.function_meta(hash__meta)?;
83    m.function_meta(debug_fmt__meta)?;
84
85    m.function_meta(result_try__meta)?;
86    Ok(m)
87}
88
89/// Converts from `Result` to `Option`.
90///
91/// # Examples
92///
93/// ```rune
94/// let a = Ok(2);
95/// let b = Err(3);
96///
97/// assert_eq!(a.ok(), Some(2));
98/// assert_eq!(b.ok(), None);
99/// ```
100#[rune::function(instance)]
101fn ok(result: &Result<Value, Value>) -> Option<Value> {
102    result.as_ref().ok().cloned()
103}
104
105/// Returns `true` if the result is [`Ok`].
106///
107/// # Examples
108///
109/// ```rune
110/// let x = Ok(-3);
111/// assert_eq!(x.is_ok(), true);
112///
113/// let x = Err("Some error message");
114/// assert_eq!(x.is_ok(), false);
115/// ```
116#[rune::function(instance)]
117fn is_ok(result: &Result<Value, Value>) -> bool {
118    result.is_ok()
119}
120
121/// Returns `true` if the result is [`Err`].
122///
123/// # Examples
124///
125/// ```rune
126/// let x = Ok(-3);
127/// assert_eq!(x.is_err(), false);
128///
129/// let x = Err("Some error message");
130/// assert_eq!(x.is_err(), true);
131/// ```
132#[rune::function(instance)]
133fn is_err(result: &Result<Value, Value>) -> bool {
134    result.is_err()
135}
136
137/// Returns the contained [`Ok`] value, consuming the `self` value.
138///
139/// Because this function may panic, its use is generally discouraged. Instead,
140/// prefer to use pattern matching and handle the [`Err`] case explicitly, or
141/// call [`unwrap_or`], [`unwrap_or_else`], or [`unwrap_or_default`].
142///
143/// [`unwrap_or`]: Result::unwrap_or
144/// [`unwrap_or_else`]: Result::unwrap_or_else
145/// [`unwrap_or_default`]: Result::unwrap_or_default
146///
147/// # Panics
148///
149/// Panics if the value is an [`Err`], with a panic message provided by the
150/// [`Err`]'s value.
151///
152/// # Examples
153///
154/// Basic usage:
155///
156/// ```rune
157/// let x = Ok(2);
158/// assert_eq!(x.unwrap(), 2);
159/// ```
160///
161/// ```rune,should_panic
162/// let x = Err("emergency failure");
163/// x.unwrap(); // panics with `emergency failure`
164/// ```
165#[rune::function(instance)]
166fn unwrap(result: &Result<Value, Value>) -> VmResult<Value> {
167    match result {
168        Ok(value) => VmResult::Ok(value.clone()),
169        Err(err) => {
170            let mut m = String::new();
171            vm_try!(vm_write!(
172                m,
173                "Called `Result::unwrap()` on an `Err` value: "
174            ));
175            vm_try!(Formatter::format_with(&mut m, |f| err.debug_fmt(f)));
176            VmResult::err(Panic::custom(m))
177        }
178    }
179}
180
181/// Returns the contained [`Ok`] value or a provided default.
182///
183/// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing
184/// the result of a function call, it is recommended to use [`unwrap_or_else`],
185/// which is lazily evaluated.
186///
187/// [`unwrap_or_else`]: Result::unwrap_or_else
188///
189/// # Examples
190///
191/// ```rune
192/// let default_value = 2;
193/// let x = Ok(9);
194/// assert_eq!(x.unwrap_or(default_value), 9);
195///
196/// let x = Err("error");
197/// assert_eq!(x.unwrap_or(default_value), default_value);
198/// ```
199#[rune::function(instance)]
200fn unwrap_or(this: &Result<Value, Value>, default: Value) -> Value {
201    match this {
202        Ok(value) => value.clone(),
203        Err(_) => default.clone(),
204    }
205}
206
207/// Returns the contained [`Ok`] value or computes it from a closure.
208///
209///
210/// # Examples
211///
212/// ```rune
213/// fn count(x) {
214///     x.len()
215/// }
216///
217/// assert_eq!(Ok(2).unwrap_or_else(count), 2);
218/// assert_eq!(Err("foo").unwrap_or_else(count), 3);
219/// ```
220#[rune::function(instance)]
221fn unwrap_or_else(this: &Result<Value, Value>, default: Function) -> VmResult<Value> {
222    match this {
223        Ok(value) => VmResult::Ok(value.clone()),
224        Err(error) => default.call((error,)),
225    }
226}
227
228/// Returns the contained [`Ok`] value, consuming the `self` value.
229///
230/// Because this function may panic, its use is generally discouraged. Instead,
231/// prefer to use pattern matching and handle the [`Err`] case explicitly, or
232/// call [`unwrap_or`], [`unwrap_or_else`], or [`unwrap_or_default`].
233///
234/// [`unwrap_or`]: Result::unwrap_or
235/// [`unwrap_or_else`]: Result::unwrap_or_else
236/// [`unwrap_or_default`]: Result::unwrap_or_default
237///
238/// # Panics
239///
240/// Panics if the value is an [`Err`], with a panic message including the passed
241/// message, and the content of the [`Err`].
242///
243/// # Examples
244///
245/// ```rune,should_panic
246/// let x = Err("emergency failure");
247/// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
248/// ```
249///
250/// # Recommended Message Style
251///
252/// We recommend that `expect` messages are used to describe the reason you
253/// _expect_ the `Result` should be `Ok`. If you're having trouble remembering
254/// how to phrase expect error messages remember to focus on the word "should"
255/// as in "env variable should be set by blah" or "the given binary should be
256/// available and executable by the current user".
257#[rune::function(instance)]
258fn expect(result: &Result<Value, Value>, message: Value) -> VmResult<Value> {
259    match result {
260        Ok(value) => VmResult::Ok(value.clone()),
261        Err(err) => {
262            let mut s = String::new();
263            vm_try!(Formatter::format_with(&mut s, |f| {
264                vm_try!(message.display_fmt(f));
265                vm_try!(f.try_write_str(": "));
266                vm_try!(err.debug_fmt(f));
267                VmResult::Ok(())
268            }));
269            VmResult::err(Panic::custom(s))
270        }
271    }
272}
273
274/// Calls `op` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`.
275///
276/// This function can be used for control flow based on `Result` values.
277///
278/// # Examples
279///
280/// ```rune
281/// fn sq_then_to_string(x) {
282///     x.checked_mul(x).ok_or("overflowed")
283/// }
284///
285/// assert_eq!(Ok(2).and_then(sq_then_to_string), Ok(4));
286/// assert_eq!(Ok(u64::MAX).and_then(sq_then_to_string), Err("overflowed"));
287/// assert_eq!(Err("not a number").and_then(sq_then_to_string), Err("not a number"));
288/// ```
289#[rune::function(instance)]
290fn and_then(this: &Result<Value, Value>, op: Function) -> VmResult<Result<Value, Value>> {
291    match this {
292        Ok(v) => VmResult::Ok(vm_try!(op.call((v,)))),
293        Err(e) => VmResult::Ok(Err(e.clone())),
294    }
295}
296
297/// Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a
298/// contained [`Ok`] value, leaving an [`Err`] value untouched.
299///
300/// This function can be used to compose the results of two functions.
301///
302/// # Examples
303///
304/// Print the numbers on each line of a string multiplied by two.
305///
306/// ```rune
307/// let lines = ["1", "2", "3", "4"];
308/// let out = [];
309///
310/// for num in lines {
311///     out.push(i64::parse(num).map(|i| i * 2)?);
312/// }
313///
314/// assert_eq!(out, [2, 4, 6, 8]);
315/// ```
316#[rune::function(instance)]
317fn map(this: &Result<Value, Value>, then: Function) -> VmResult<Result<Value, Value>> {
318    match this {
319        Ok(v) => VmResult::Ok(Ok(vm_try!(then.call((v,))))),
320        Err(e) => VmResult::Ok(Err(e.clone())),
321    }
322}
323
324/// Clone the result.
325///
326/// # Examples
327///
328/// ```rune
329/// let a = Ok(b"hello world");
330/// let b = a.clone();
331///
332/// a?.extend(b"!");
333///
334/// assert_eq!(a, Ok(b"hello world!"));
335/// assert_eq!(b, Ok(b"hello world"));
336/// ```
337#[rune::function(keep, instance, protocol = CLONE)]
338fn clone(this: &Result<Value, Value>) -> VmResult<Result<Value, Value>> {
339    VmResult::Ok(match this {
340        Ok(ok) => Ok(vm_try!(ok.clone_with(&mut EnvProtocolCaller))),
341        Err(err) => Err(vm_try!(err.clone_with(&mut EnvProtocolCaller))),
342    })
343}
344
345/// Test two results for partial equality.
346///
347/// # Examples
348///
349/// ```rune
350/// assert_eq!(Ok(b"a") == Ok(b"a"), true);
351/// assert_eq!(Ok(b"a") == Ok(b"ab"), false);
352/// assert_eq!(Ok(b"ab") == Ok(b"a"), false);
353/// ```
354///
355/// Using explicit functions:
356///
357/// ```rune
358/// use std::ops::partial_eq;
359///
360/// assert_eq!(partial_eq(Ok(b"a"), Ok(b"a")), true);
361/// assert_eq!(partial_eq(Ok(b"a"), Ok(b"ab")), false);
362/// assert_eq!(partial_eq(Ok(b"ab"), Ok(b"a")), false);
363/// ```
364#[rune::function(keep, instance, protocol = PARTIAL_EQ)]
365#[inline]
366fn partial_eq(this: &Result<Value, Value>, rhs: &Result<Value, Value>) -> VmResult<bool> {
367    match (this, rhs) {
368        (Ok(a), Ok(b)) => Value::partial_eq(a, b),
369        (Err(a), Err(b)) => Value::partial_eq(a, b),
370        _ => VmResult::Ok(false),
371    }
372}
373
374/// Test two results for total equality.
375///
376/// # Examples
377///
378/// ```rune
379/// use std::ops::eq;
380///
381/// assert_eq!(eq(Ok(b"a"), Ok(b"a")), true);
382/// assert_eq!(eq(Ok(b"a"), Ok(b"ab")), false);
383/// assert_eq!(eq(Ok(b"ab"), Ok(b"a")), false);
384/// ```
385#[rune::function(keep, instance, protocol = EQ)]
386#[inline]
387fn eq(this: &Result<Value, Value>, rhs: &Result<Value, Value>) -> VmResult<bool> {
388    match (this, rhs) {
389        (Ok(a), Ok(b)) => Value::eq(a, b),
390        (Err(a), Err(b)) => Value::eq(a, b),
391        _ => VmResult::Ok(false),
392    }
393}
394
395/// Perform a partial ordered comparison between two results.
396///
397/// # Examples
398///
399/// ```rune
400/// assert!(Ok(b"a") < Ok(b"ab"));
401/// assert!(Ok(b"ab") > Ok(b"a"));
402/// assert!(Ok(b"a") == Ok(b"a"));
403/// ```
404///
405/// Using explicit functions:
406///
407/// ```rune
408/// use std::cmp::Ordering;
409/// use std::ops::partial_cmp;
410///
411/// assert_eq!(partial_cmp(Ok(b"a"), Ok(b"ab")), Some(Ordering::Less));
412/// assert_eq!(partial_cmp(Ok(b"ab"), Ok(b"a")), Some(Ordering::Greater));
413/// assert_eq!(partial_cmp(Ok(b"a"), Ok(b"a")), Some(Ordering::Equal));
414/// ```
415#[rune::function(keep, instance, protocol = PARTIAL_CMP)]
416#[inline]
417fn partial_cmp(
418    this: &Result<Value, Value>,
419    rhs: &Result<Value, Value>,
420) -> VmResult<Option<Ordering>> {
421    match (this, rhs) {
422        (Ok(a), Ok(b)) => Value::partial_cmp(a, b),
423        (Err(a), Err(b)) => Value::partial_cmp(a, b),
424        (Ok(..), Err(..)) => VmResult::Ok(Some(Ordering::Greater)),
425        (Err(..), Ok(..)) => VmResult::Ok(Some(Ordering::Less)),
426    }
427}
428
429/// Perform a totally ordered comparison between two results.
430///
431/// # Examples
432///
433/// ```rune
434/// use std::cmp::Ordering;
435/// use std::ops::cmp;
436///
437/// assert_eq!(cmp(Ok(b"a"), Ok(b"ab")), Ordering::Less);
438/// assert_eq!(cmp(Ok(b"ab"), Ok(b"a")), Ordering::Greater);
439/// assert_eq!(cmp(Ok(b"a"), Ok(b"a")), Ordering::Equal);
440/// ```
441#[rune::function(keep, instance, protocol = CMP)]
442#[inline]
443fn cmp(this: &Result<Value, Value>, rhs: &Result<Value, Value>) -> VmResult<Ordering> {
444    match (this, rhs) {
445        (Ok(a), Ok(b)) => Value::cmp(a, b),
446        (Err(a), Err(b)) => Value::cmp(a, b),
447        (Ok(..), Err(..)) => VmResult::Ok(Ordering::Greater),
448        (Err(..), Ok(..)) => VmResult::Ok(Ordering::Less),
449    }
450}
451
452/// Hash the result.
453///
454/// # Examples
455///
456/// ```rune
457/// use std::ops::hash;
458///
459/// let a = Ok("hello");
460/// let b = Ok("hello");
461///
462/// assert_eq!(hash(a), hash(b));
463/// ```
464#[rune::function(keep, instance, protocol = HASH)]
465fn hash(this: &Result<Value, Value>, hasher: &mut Hasher) -> VmResult<()> {
466    match this {
467        Ok(value) => {
468            hasher.write_u64(0);
469            vm_try!(value.hash(hasher));
470        }
471        Err(value) => {
472            hasher.write_u64(1);
473            vm_try!(value.hash(hasher));
474        }
475    }
476
477    VmResult::Ok(())
478}
479
480/// Write a debug representation of a result.
481///
482/// # Examples
483///
484/// ```rune
485/// println!("{:?}", Ok("Hello"));
486/// println!("{:?}", Err("Hello"));
487/// ```
488#[rune::function(keep, instance, protocol = DEBUG_FMT)]
489#[inline]
490fn debug_fmt(this: &Result<Value, Value>, f: &mut Formatter) -> VmResult<()> {
491    match this {
492        Ok(value) => {
493            vm_try!(f.try_write_str("Ok("));
494            vm_try!(value.debug_fmt(f));
495            vm_try!(f.try_write_str(")"));
496        }
497        Err(value) => {
498            vm_try!(f.try_write_str("Err("));
499            vm_try!(value.debug_fmt(f));
500            vm_try!(f.try_write_str(")"));
501        }
502    }
503
504    VmResult::Ok(())
505}
506
507/// Using [`Result`] with the try protocol.
508///
509/// # Examples
510///
511/// ```rune
512/// fn maybe_add_one(value) {
513///     Ok(value? + 1)
514/// }
515///
516/// assert_eq!(maybe_add_one(Ok(4)), Ok(5));
517/// assert_eq!(maybe_add_one(Err("not a number")), Err("not a number"));
518/// ```
519#[rune::function(keep, instance, protocol = TRY)]
520pub(crate) fn result_try(this: &Result<Value, Value>) -> VmResult<ControlFlow> {
521    VmResult::Ok(match this {
522        Ok(value) => ControlFlow::Continue(value.clone()),
523        Err(error) => ControlFlow::Break(vm_try!(Value::try_from(Err(error.clone())))),
524    })
525}