stubr 0.6.2

Wiremock implemented in Rust
Documentation
use std::str::from_utf8;

use handlebars::{Context, Handlebars, Helper, HelperDef, HelperResult, Output, PathAndJson, RenderContext, RenderError};
use serde_json::Value;

use super::ValueExt;

pub struct Base64Helper;

impl Base64Helper {
    pub const NAME: &'static str = "base64";
    pub const DECODE: &'static str = "decode";
    pub const PADDING: &'static str = "padding";

    fn value<'a>(h: &'a Helper) -> Option<&'a str> {
        h.params()
            .get(0)
            .and_then(|it| it.value().as_str().or_else(|| it.relative_path().map(String::as_str)))
            .map(str::escape_single_quotes)
    }

    fn base64_encode(value: &str, with_padding: bool) -> String {
        use base64::Engine as _;
        if with_padding {
            base64::prelude::BASE64_STANDARD.encode(value)
        } else {
            base64::prelude::BASE64_STANDARD_NO_PAD.encode(value)
        }
    }

    fn base64_decode(value: &str) -> String {
        use base64::Engine as _;
        base64::prelude::BASE64_STANDARD
            .decode(value)
            .ok()
            .and_then(|it| from_utf8(it.as_slice()).map(str::to_string).ok())
            .unwrap_or_else(|| value.to_string())
    }

    fn is_decode(h: &Helper) -> bool {
        h.hash_get(Self::DECODE)
            .map(PathAndJson::value)
            .and_then(Value::as_bool)
            .unwrap_or_default()
    }

    fn with_padding(h: &Helper) -> bool {
        h.hash_get(Self::PADDING)
            .map(PathAndJson::value)
            .and_then(Value::as_bool)
            .unwrap_or(true)
    }
}

impl HelperDef for Base64Helper {
    fn call<'reg: 'rc, 'rc>(
        &self, h: &Helper<'reg, 'rc>, _: &'reg Handlebars<'reg>, _: &'rc Context, _: &mut RenderContext<'reg, 'rc>, out: &mut dyn Output,
    ) -> HelperResult {
        Self::value(h)
            .map(|value| {
                if Self::is_decode(h) {
                    Self::base64_decode(value)
                } else {
                    Self::base64_encode(value, Self::with_padding(h))
                }
            })
            .ok_or_else(|| RenderError::new("Failed templating base 64 (de)encoding"))
            .and_then(|s| out.write(&s).map_err(RenderError::from))
    }
}