Skip to content

Commit 1f99ef8

Browse files
committed
Add new function new_mut_list returns a list mutable from the minijinja context
1 parent 616300f commit 1f99ef8

File tree

4 files changed

+88
-0
lines changed

4 files changed

+88
-0
lines changed

src/cli_v2/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
//! A WIP new cli, to the openapi-codegen
22
33
mod frontmatter;
4+
mod mut_list;
5+
6+
pub(crate) use mut_list::new_mut_list;
47

58
#[derive(Debug, thiserror::Error)]
69
pub(super) enum Error {

src/cli_v2/mut_list.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use std::sync::{Arc, RwLock};
2+
3+
use minijinja::{ErrorKind, value::DynObject};
4+
5+
pub(crate) fn new_mut_list() -> DynObject {
6+
DynObject::new(Arc::new(MutList(RwLock::new(vec![]))))
7+
}
8+
9+
impl minijinja::value::Object for MutList {
10+
fn repr(self: &Arc<Self>) -> minijinja::value::ObjectRepr {
11+
minijinja::value::ObjectRepr::Iterable
12+
}
13+
14+
fn call_method(
15+
self: &Arc<Self>,
16+
state: &minijinja::State<'_, '_>,
17+
method: &str,
18+
args: &[minijinja::Value],
19+
) -> Result<minijinja::Value, minijinja::Error> {
20+
match method {
21+
"append" => self.append(state, args),
22+
_ => Err(minijinja::Error::new(
23+
ErrorKind::UnknownMethod,
24+
format!("Unexpected method {method}"),
25+
)),
26+
}
27+
}
28+
29+
fn enumerate(self: &Arc<Self>) -> minijinja::value::Enumerator {
30+
let vals = self
31+
.0
32+
.read()
33+
.expect("Unable to read from MutList, RwLock was poisoned")
34+
.iter()
35+
.map(|s| s.to_owned())
36+
.collect::<Vec<_>>();
37+
minijinja::value::Enumerator::Iter(Box::new(vals.into_iter()))
38+
}
39+
}
40+
41+
#[derive(Debug)]
42+
/// A mutable list of minijinja::Value, a work-around the minijinja limitations.
43+
struct MutList(RwLock<Vec<minijinja::Value>>);
44+
45+
impl MutList {
46+
fn append(
47+
self: &Arc<Self>,
48+
_state: &minijinja::State<'_, '_>,
49+
args: &[minijinja::Value],
50+
) -> Result<minijinja::Value, minijinja::Error> {
51+
ensure_n_args("append", 1, args)?;
52+
{
53+
let mut a = self
54+
.0
55+
.try_write()
56+
.map_err(|e| minijinja::Error::new(ErrorKind::InvalidOperation, e.to_string()))?;
57+
a.push(args[0].clone());
58+
}
59+
Ok(minijinja::Value::UNDEFINED)
60+
}
61+
}
62+
63+
fn ensure_n_args(
64+
method: &str,
65+
n: usize,
66+
args: &[minijinja::Value],
67+
) -> Result<(), minijinja::Error> {
68+
let args_len = args.len();
69+
let err = |kind| -> Result<(), minijinja::Error> {
70+
Err(minijinja::Error::new(
71+
kind,
72+
format!("{method} | Expected: {n} args, got {args_len} arguments",),
73+
))
74+
};
75+
76+
match args.len().cmp(&n) {
77+
std::cmp::Ordering::Less => err(ErrorKind::MissingArgument),
78+
std::cmp::Ordering::Greater => err(ErrorKind::TooManyArguments),
79+
std::cmp::Ordering::Equal => Ok(()),
80+
}
81+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ pub use crate::{
1212
codesamples::{CodeSample, CodesampleTemplates, generate_codesamples},
1313
postprocessing::CodegenLanguage,
1414
};
15+
pub(crate) use cli_v2::new_mut_list;

src/template.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use itertools::Itertools as _;
1010
use minijinja::{State, Value, path_loader, value::Kwargs};
1111
use serde::Deserialize;
1212

13+
use crate::new_mut_list;
14+
1315
pub fn env_with_dir(
1416
tpl_dir: &Utf8Path,
1517
) -> Result<minijinja::Environment<'static>, minijinja::Error> {
@@ -21,6 +23,7 @@ pub fn env_with_dir(
2123
pub fn populate_env(
2224
mut env: minijinja::Environment<'static>,
2325
) -> Result<minijinja::Environment<'static>, minijinja::Error> {
26+
env.add_function("new_mut_list", new_mut_list);
2427
// === Custom filters ===
2528

2629
// --- Case conversion ---

0 commit comments

Comments
 (0)