pochoir-lang 0.12.2

Custom parser and interpreter for the pochoir template engine
Documentation
//! Iterate over an array while keeping a lot of useful information about the current iteration in an object.
//!
//! Structure of the object generated for each value:
//!
//! | Field   | Type   | Description                                                   |
//! | ------- | ------ | ------------------------------------------------------------- |
//! | value   | Value  | the original value included in the array                      |
//! | index   | Number | the 1-indexed position of the value in the array              |
//! | index0  | Number | the 0-indexed position of the value in the array              |
//! | rindex  | Number | the 1-indexed position of the value from the end of the array |
//! | rindex0 | Number | the 0-indexed position of the value from the end of the array |
//! | first   | Bool   | whether it is the first value of the array                    |
//! | last    | Bool   | whether it is the last value of the array                     |
//!
//! ### Example
//!
//! <div class="example-wrap"><pre class="rust rust-example-rendered"><span style="position: absolute; right: 0; top: 0; padding: 0.1rem 0.4rem 0 0; font-size: 0.75em; font-weight: bold; color: #333;">input</span><code><span class="fn">iter</span>([<span class="string">"hello"</span>, <span class="number">42</span>])</code></pre></div>
//!
//! <div class="example-wrap"><pre class="rust rust-example-rendered"><span style="position: absolute; right: 0; top: 0; padding: 0.1rem 0.4rem 0 0; font-size: 0.75em; font-weight: bold; color: #333;">output</span><code>[{
//!   value: <span class="string">"hello"</span>,
//!   index: <span class="number">1</span>,
//!   index0: <span class="number">0</span>,
//!   rindex: <span class="number">2</span>,
//!   rindex0: <span class="number">1</span>,
//!   first: <span class="bool-val">true</span>,
//!   last: <span class="bool-val">false</span>,
//! }, {
//!   value: <span class="number">42</span>,
//!   index: <span class="number">2</span>,
//!   index0: <span class="number">1</span>,
//!   rindex: <span class="number">1</span>,
//!   rindex0: <span class="number">0</span>,
//!   first: <span class="bool-val">false</span>,
//!   last: <span class="bool-val">true</span>,
//! }]</code></pre></div>
use crate::{object, FunctionResult, Value};

#[allow(clippy::cast_precision_loss)]
pub(crate) fn iter(val: Vec<Value>) -> FunctionResult<Vec<Value>> {
    let len = val.len();
    Ok(val
        .into_iter()
        .enumerate()
        .map(|(index0, val)| {
            Value::Object(object! {
                "value" => val,
                "index" => Value::Number((index0 + 1) as f64),
                "index0" => Value::Number(index0 as f64),
                "rindex" => Value::Number((len - index0) as f64),
                "rindex0" => Value::Number((len - (index0 + 1)) as f64),
                "first" => Value::Bool(index0 == 0),
                "last" => Value::Bool(index0 == len - 1),
            })
        })
        .collect())
}

#[cfg(test)]
mod tests {
    use crate::IntoValue;

    use super::*;

    #[test]
    fn iter_test() {
        assert_eq!(
            iter(vec!["hello".into_value(), 42.into_value()]).unwrap(),
            vec![
                object! {
                   "value" => "hello".into_value(),
                   "index" => 1.into_value(),
                   "index0" => 0.into_value(),
                   "rindex" => 2.into_value(),
                   "rindex0" => 1.into_value(),
                   "first" => true.into_value(),
                   "last" => false.into_value(),
                }
                .into_value(),
                object! {
                   "value" => Value::Number(42.0),
                   "index" => 2.into_value(),
                   "index0" => 1.into_value(),
                   "rindex" => 1.into_value(),
                   "rindex0" => 0.into_value(),
                   "first" => false.into_value(),
                   "last" => true.into_value(),
                }
                .into_value(),
            ],
        );
    }
}