Skip to main content

rustidy_print/
lib.rs

1//! Printing
2
3// Features
4#![feature(never_type, decl_macro, coverage_attribute, macro_metavar_expr_concat)]
5
6// Modules
7mod whitespace;
8mod str;
9mod output;
10
11// Exports
12pub use rustidy_macros::Print;
13pub use self::output::PrintOutput;
14
15// Imports
16use {core::marker::PhantomData, rustidy_util::{ArenaData, ArenaIdx, AstStr}};
17
18/// Printable types
19pub trait Print: Sized {
20	/// Prints this type onto a writer
21	fn print(&self, f: &mut PrintFmt);
22
23	/// Prints this type onto a writer excluding whitespace
24	///
25	/// Note that this excludes necessary whitespace too, so this
26	/// won't provide valid rust code.
27	fn print_non_ws(&self, f: &mut PrintFmt);
28
29	/// Prints this type using `p` as the printer function and returns the output
30	fn print_to(&self, p: impl FnOnce(&Self,&mut PrintFmt)) -> PrintOutput {
31		let mut f = PrintFmt::new();
32		p(self, &mut f);
33		f.output
34	}
35}
36
37impl<T: Print> Print for &'_ T {
38	fn print(&self, f: &mut PrintFmt) {
39		(**self).print(f);
40	}
41
42	fn print_non_ws(&self, f: &mut PrintFmt) {
43		(**self).print(f);
44	}
45}
46
47impl<T: Print> Print for Box<T> {
48	fn print(&self, f: &mut PrintFmt) {
49		(**self).print(f);
50	}
51
52	fn print_non_ws(&self, f: &mut PrintFmt) {
53		(**self).print(f);
54	}
55}
56
57impl<T: Print> Print for Option<T> {
58	fn print(&self, f: &mut PrintFmt) {
59		if let Some(value) = self {
60			value.print(f);
61		}
62	}
63
64	fn print_non_ws(&self, f: &mut PrintFmt) {
65		if let Some(value) = self {
66			value.print_non_ws(f);
67		}
68	}
69}
70
71impl<T: Print> Print for Vec<T> {
72	fn print(&self, f: &mut PrintFmt) {
73		for value in self {
74			value.print(f);
75		}
76	}
77
78	fn print_non_ws(&self, f: &mut PrintFmt) {
79		for value in self {
80			value.print_non_ws(f);
81		}
82	}
83}
84
85impl Print for ! {
86	fn print(&self, _f: &mut PrintFmt) {
87		*self
88	}
89
90	fn print_non_ws(&self, _f: &mut PrintFmt) {
91		*self
92	}
93}
94
95impl<T> Print for PhantomData<T> {
96	fn print(&self, _f: &mut PrintFmt) {}
97
98	fn print_non_ws(&self, _f: &mut PrintFmt) {}
99}
100
101impl Print for () {
102	fn print(&self, _f: &mut PrintFmt) {}
103
104	fn print_non_ws(&self, _f: &mut PrintFmt) {}
105}
106
107macro tuple_impl(
108	$N:literal, $($T:ident),* $(,)?
109) {
110	#[automatically_derived]
111	impl< $($T: Print,)* > Print for ( $($T,)* ) {
112		#[expect(non_snake_case)]
113		fn print(&self, f: &mut PrintFmt) {
114			let ( $($T,)* ) = self;
115			$(
116				$T.print(f);
117			)*
118		}
119
120		#[expect(non_snake_case)]
121		fn print_non_ws(&self, f: &mut PrintFmt) {
122			let ( $($T,)* ) = self;
123			$(
124				$T.print_non_ws(f);
125			)*
126		}
127	}
128}
129
130tuple_impl! { 1, T0 }
131tuple_impl! { 2, T0, T1 }
132tuple_impl! { 3, T0, T1, T2 }
133
134impl Print for AstStr {
135	fn print(&self, f: &mut PrintFmt) {
136		str::write(self, &mut f.output);
137	}
138
139	fn print_non_ws(&self, f: &mut PrintFmt) {
140		str::write(self, &mut f.output);
141	}
142}
143
144impl<T: ArenaData + Print> Print for ArenaIdx<T> {
145	fn print(&self, f: &mut PrintFmt) {
146		(**self).print(f);
147	}
148
149	fn print_non_ws(&self, f: &mut PrintFmt) {
150		(**self).print(f);
151	}
152}
153
154/// Print formatter
155#[derive(Debug)]
156pub struct PrintFmt {
157	output: PrintOutput,
158}
159
160impl PrintFmt {
161	/// Creates a new formatter
162	#[must_use]
163	pub const fn new() -> Self {
164		Self { output: PrintOutput::Empty }
165	}
166
167	/// Returns the output
168	#[must_use]
169	pub const fn output(&self) -> &PrintOutput {
170		&self.output
171	}
172}
173
174impl Default for PrintFmt {
175	fn default() -> Self {
176		Self::new()
177	}
178}