Skip to main content

rustidy_format/
vec.rs

1//! [`Vec<T>`] formatting
2
3// Imports
4use {
5	crate::{Context, Format, FormatOutput, Formattable},
6	core::ops::ControlFlow,
7	rustidy_util::AstStr,
8};
9
10impl<T: Formattable> Formattable for Vec<T> {
11	fn with_prefix_ws<O>(
12		&mut self,
13		ctx: &mut Context,
14		f: &mut impl FnMut(&mut rustidy_util::Whitespace,&mut Context) -> O,
15	) -> Result<O, ControlFlow<()>> {
16		for value in self {
17			match value.with_prefix_ws(ctx, f) {
18				Ok(output) => return Ok(output),
19				Err(ControlFlow::Continue(())) => (),
20				Err(ControlFlow::Break(())) => return Err(ControlFlow::Break(())),
21			}
22		}
23
24		Err(ControlFlow::Continue(()))
25	}
26
27	fn with_strings<O>(
28		&mut self,
29		ctx: &mut Context,
30		mut exclude_prefix_ws: bool,
31		f: &mut impl FnMut(&mut AstStr,&mut Context) -> ControlFlow<O>,
32	) -> ControlFlow<O, bool> {
33		let mut is_empty = true;
34		for value in self {
35			is_empty &= value.with_strings(ctx, exclude_prefix_ws, f)?;
36
37			if !is_empty {
38				exclude_prefix_ws = false;
39			}
40		}
41
42		ControlFlow::Continue(is_empty)
43	}
44
45	fn format_output(&mut self, ctx: &mut Context) -> FormatOutput {
46		self
47			.iter_mut()
48			.map(|value| value.format_output(ctx))
49			.fold(FormatOutput::default(), FormatOutput::join)
50	}
51}
52
53impl<T, PrefixWs, A> Format<PrefixWs, Args<PrefixWs, A>> for Vec<T>
54where
55	T: Format<PrefixWs, A>,
56	PrefixWs: Clone,
57	A: Clone, {
58	fn format(
59		&mut self,
60		ctx: &mut Context,
61		prefix_ws: PrefixWs,
62		args: Args<PrefixWs, A>
63	) -> FormatOutput {
64		// Note: Due to the way we're parsed, the first element will never be non-empty,
65		//       but it's possible for the caller to create this value during formatting
66		//       and have that not be true, so we always check.
67		let mut output = FormatOutput::default();
68		let mut prefix_ws = Some(prefix_ws);
69		for value in self {
70			let value_output = match &prefix_ws {
71				Some(prefix_ws) => ctx
72					.format_with(value, prefix_ws.clone(), args.args.clone()),
73				None => ctx.format_with(
74					value,
75					args.rest_prefix_ws.clone(),
76					args.args.clone()
77				),
78			};
79			value_output.append_to(&mut output);
80
81			if prefix_ws.is_some() && value_output.has_prefix_ws() {
82				prefix_ws = None;
83			}
84		}
85
86		output
87	}
88}
89
90/// Arguments for formatting a [`Vec<T>`]
91pub struct Args<PrefixWs, A> {
92	/// Whitespace formatter for the rest of the vector
93	rest_prefix_ws: PrefixWs,
94
95	/// Arguments for the rest of the vector
96	args:           A,
97}
98
99/// Creates vector arguments
100pub const fn args<PrefixWs, A>(rest_prefix_ws: PrefixWs, args: A) -> Args<PrefixWs, A> {
101	Args { rest_prefix_ws, args }
102}
103
104/// Creates vector arguments from just the prefix whitespace
105#[must_use]
106pub const fn args_prefix_ws<PrefixWs>(rest_prefix_ws: PrefixWs) -> Args<PrefixWs, ()> {
107	Args { rest_prefix_ws, args: (), }
108}