runestick/modules/
option.rs

1//! The `std::option` module.
2
3use crate::{ContextError, Function, Module, Protocol, Shared, Value, VmError};
4
5/// Construct the `std::option` module.
6pub fn module() -> Result<Module, ContextError> {
7    let mut module = Module::with_crate_item("std", &["option"]);
8    module.option(&["Option"])?;
9    // Sorted for ease of finding
10    module.inst_fn("and_then", and_then_impl)?;
11    module.inst_fn("expect", expect_impl)?;
12    module.inst_fn("is_none", Option::<Value>::is_none)?;
13    module.inst_fn("is_some", Option::<Value>::is_some)?;
14    module.inst_fn("iter", option_iter)?;
15    module.inst_fn("map", map_impl)?;
16    module.inst_fn("take", take_impl)?;
17    module.inst_fn("transpose", transpose_impl)?;
18    module.inst_fn("unwrap", unwrap_impl)?;
19    module.inst_fn("unwrap_or", Option::<Value>::unwrap_or)?;
20    module.inst_fn("unwrap_or_else", unwrap_or_else_impl)?;
21    module.inst_fn(Protocol::INTO_ITER, option_iter)?;
22    Ok(module)
23}
24
25fn unwrap_or_else_impl(this: &Option<Value>, default: Function) -> Result<Value, VmError> {
26    if let Some(this) = this {
27        return Ok(this.clone());
28    }
29
30    Ok(default.call(())?)
31}
32
33/// Transpose functions, translates an Option<Result<T, E>> into a `Result<Option<T>, E>`.
34fn transpose_impl(this: &Option<Value>) -> Result<Value, VmError> {
35    Ok(Value::from(Shared::new(match this.clone() {
36        Some(some) => match some.into_result()?.borrow_ref()?.clone() {
37            Ok(ok) => Ok(Value::from(Shared::new(Some(ok)))),
38            Err(err) => Err(err),
39        },
40        None => Ok(Value::from(Shared::new(None::<Value>))),
41    })))
42}
43
44fn option_iter(option: &Option<Value>) -> crate::Iterator {
45    crate::Iterator::from_double_ended("std::option::Iter", option.clone().into_iter())
46}
47
48fn unwrap_impl(option: Option<Value>) -> Result<Value, VmError> {
49    option.ok_or_else(|| VmError::panic("called `Option::unwrap()` on a `None` value"))
50}
51
52fn expect_impl(option: Option<Value>, message: &str) -> Result<Value, VmError> {
53    option.ok_or_else(|| VmError::panic(message.to_owned()))
54}
55
56fn map_impl(option: &Option<Value>, then: Function) -> Result<Option<Value>, VmError> {
57    match option {
58        // no need to clone v, passing the same reference forward
59        Some(v) => then.call::<_, _>((v,)).map(Some),
60        None => Ok(None),
61    }
62}
63
64fn and_then_impl(option: &Option<Value>, then: Function) -> Result<Option<Value>, VmError> {
65    match option {
66        // no need to clone v, passing the same reference forward
67        Some(v) => then.call::<_, _>((v,)),
68        None => Ok(None),
69    }
70}
71
72fn take_impl(option: &mut Option<Value>) -> Option<Value> {
73    option.take()
74}