1#[cfg(feature = "alloc")]
4pub extern crate alloc;
5pub extern crate core;
6#[cfg(feature = "std")]
7pub extern crate std;
8
9use core::cell::Cell;
10use core::fmt;
11use core::iter::{Enumerate, Peekable};
12use core::ops::Deref;
13use core::pin::Pin;
14
15pub use crate::error::{ErrorMarker, ResultConverter};
16use crate::filters::FastWritable;
17pub use crate::values::get_value;
18
19pub struct TemplateLoop<I>
20where
21 I: Iterator,
22{
23 iter: Peekable<Enumerate<I>>,
24}
25
26impl<I> TemplateLoop<I>
27where
28 I: Iterator,
29{
30 #[inline]
31 pub fn new(iter: I) -> Self {
32 TemplateLoop {
33 iter: iter.enumerate().peekable(),
34 }
35 }
36}
37
38impl<I> Iterator for TemplateLoop<I>
39where
40 I: Iterator,
41{
42 type Item = (<I as Iterator>::Item, LoopItem);
43
44 #[inline]
45 fn next(&mut self) -> Option<(<I as Iterator>::Item, LoopItem)> {
46 self.iter.next().map(|(index, item)| {
47 (
48 item,
49 LoopItem {
50 index,
51 first: index == 0,
52 last: self.iter.peek().is_none(),
53 },
54 )
55 })
56 }
57}
58
59#[derive(Copy, Clone)]
60pub struct LoopItem {
61 pub index: usize,
62 pub first: bool,
63 pub last: bool,
64}
65
66pub struct FmtCell<F> {
67 func: Cell<Option<F>>,
68 err: Cell<Option<crate::Error>>,
69}
70
71impl<F> FmtCell<F>
72where
73 F: for<'a, 'b> FnOnce(&'a mut fmt::Formatter<'b>) -> crate::Result<()>,
74{
75 #[inline]
76 pub fn new(f: F) -> Self {
77 Self {
78 func: Cell::new(Some(f)),
79 err: Cell::new(None),
80 }
81 }
82
83 #[inline]
84 pub fn take_err(&self) -> crate::Result<()> {
85 Err(self.err.take().unwrap_or(crate::Error::Fmt))
86 }
87}
88
89impl<F> fmt::Display for FmtCell<F>
90where
91 F: for<'a, 'b> FnOnce(&'a mut fmt::Formatter<'b>) -> crate::Result<()>,
92{
93 #[inline]
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 if let Some(func) = self.func.take() {
96 if let Err(err) = func(f) {
97 self.err.set(Some(err));
98 return Err(fmt::Error);
99 }
100 }
101 Ok(())
102 }
103}
104
105#[inline]
106pub fn get_primitive_value<T: PrimitiveType>(value: T) -> T::Value {
107 value.get()
108}
109
110pub trait PrimitiveType {
112 type Value: Copy + Send + Sync + 'static;
113
114 fn get(&self) -> Self::Value;
115}
116
117macro_rules! primitive_type {
118 ($($ty:ty),* $(,)?) => {$(
119 impl PrimitiveType for $ty {
120 type Value = $ty;
121
122 #[inline]
123 fn get(&self) -> Self::Value {
124 *self
125 }
126 }
127 )*};
128}
129
130primitive_type! {
131 bool,
132 f32, f64,
133 i8, i16, i32, i64, i128, isize,
134 u8, u16, u32, u64, u128, usize,
135}
136
137crate::impl_for_ref! {
138 impl PrimitiveType for T {
139 type Value = T::Value;
140
141 #[inline]
142 fn get(&self) -> Self::Value {
143 <T>::get(self)
144 }
145 }
146}
147
148impl<T> PrimitiveType for Pin<T>
149where
150 T: Deref,
151 <T as Deref>::Target: PrimitiveType,
152{
153 type Value = <<T as Deref>::Target as PrimitiveType>::Value;
154
155 #[inline]
156 fn get(&self) -> Self::Value {
157 self.as_ref().get_ref().get()
158 }
159}
160
161impl<T: PrimitiveType + Copy> PrimitiveType for Cell<T> {
181 type Value = T::Value;
182
183 #[inline]
184 fn get(&self) -> Self::Value {
185 self.get().get()
186 }
187}
188
189impl<T: PrimitiveType> PrimitiveType for core::num::Wrapping<T> {
190 type Value = T::Value;
191
192 #[inline]
193 fn get(&self) -> Self::Value {
194 self.0.get()
195 }
196}
197
198impl<T: PrimitiveType> PrimitiveType for core::num::Saturating<T> {
199 type Value = T::Value;
200
201 #[inline]
202 fn get(&self) -> Self::Value {
203 self.0.get()
204 }
205}
206
207macro_rules! primitize_nz {
208 ($($nz:ty => $bare:ident,)+) => { $(
209 impl PrimitiveType for $nz {
210 type Value = $bare;
211
212 #[inline]
213 fn get(&self) -> Self::Value {
214 <$nz>::get(*self).get()
215 }
216 }
217 )+ };
218}
219
220primitize_nz! {
221 core::num::NonZeroI8 => i8,
222 core::num::NonZeroI16 => i16,
223 core::num::NonZeroI32 => i32,
224 core::num::NonZeroI64 => i64,
225 core::num::NonZeroI128 => i128,
226 core::num::NonZeroIsize => isize,
227 core::num::NonZeroU8 => u8,
228 core::num::NonZeroU16 => u16,
229 core::num::NonZeroU32 => u32,
230 core::num::NonZeroU64 => u64,
231 core::num::NonZeroU128 => u128,
232 core::num::NonZeroUsize => usize,
233}
234
235#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
237pub struct Empty;
238
239impl fmt::Display for Empty {
240 #[inline]
241 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
242 Ok(())
243 }
244}
245
246impl FastWritable for Empty {
247 #[inline]
248 fn write_into<W: fmt::Write + ?Sized>(&self, _: &mut W) -> crate::Result<()> {
249 Ok(())
250 }
251}
252
253#[inline]
254pub fn as_bool<T: PrimitiveType<Value = bool>>(value: T) -> bool {
255 value.get()
256}
257
258pub struct Concat<L, R>(pub L, pub R);
259
260impl<L: fmt::Display, R: fmt::Display> fmt::Display for Concat<L, R> {
261 #[inline]
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 self.0.fmt(f)?;
264 self.1.fmt(f)
265 }
266}
267
268impl<L: FastWritable, R: FastWritable> FastWritable for Concat<L, R> {
269 #[inline]
270 fn write_into<W: fmt::Write + ?Sized>(&self, dest: &mut W) -> crate::Result<()> {
271 self.0.write_into(dest)?;
272 self.1.write_into(dest)
273 }
274}
275
276pub trait EnumVariantTemplate {
277 fn render_into_with_values<W: fmt::Write + ?Sized>(
278 &self,
279 writer: &mut W,
280 values: &dyn crate::Values,
281 ) -> crate::Result<()>;
282}