1use std::cell::Cell;
2use std::fmt;
3use std::iter::{Enumerate, Peekable};
4use std::ops::Deref;
5use std::pin::Pin;
6
7// The re-exports are used in the generated code for macro hygiene. Even if the paths `::core` or
8// `::std` are shadowed, the generated code will still be able to access the crates.
9pub use {core, std};
10
11use crate::filters::FastWritable;
12
13pub struct TemplateLoop<I>
14where
15 I: Iterator,
16{
17 iter: Peekable<Enumerate<I>>,
18}
19
20impl<I> TemplateLoop<I>
21where
22 I: Iterator,
23{
24 #[inline]
25 pub fn new(iter: I) -> Self {
26 TemplateLoop {
27 iter: iter.enumerate().peekable(),
28 }
29 }
30}
31
32impl<I> Iterator for TemplateLoop<I>
33where
34 I: Iterator,
35{
36 type Item = (<I as Iterator>::Item, LoopItem);
37
38 #[inline]
39 fn next(&mut self) -> Option<(<I as Iterator>::Item, LoopItem)> {
40 self.iter.next().map(|(index: usize, item: ::Item)| {
41 (item, LoopItem {
42 index,
43 first: index == 0,
44 last: self.iter.peek().is_none(),
45 })
46 })
47 }
48}
49
50#[derive(Copy, Clone)]
51pub struct LoopItem {
52 pub index: usize,
53 pub first: bool,
54 pub last: bool,
55}
56
57pub struct FmtCell<F> {
58 func: Cell<Option<F>>,
59 err: Cell<Option<crate::Error>>,
60}
61
62impl<F> FmtCell<F>
63where
64 F: for<'a, 'b> dynFnOnce(&'a mut fmt::Formatter<'b>) -> crate::Result<()>,
65{
66 #[inline]
67 pub fn new(f: F) -> Self {
68 Self {
69 func: Cell::new(Some(f)),
70 err: Cell::new(None),
71 }
72 }
73
74 #[inline]
75 pub fn take_err(&self) -> crate::Result<()> {
76 Err(self.err.take().unwrap_or(default:crate::Error::Fmt))
77 }
78}
79
80impl<F> fmt::Display for FmtCell<F>
81where
82 F: for<'a, 'b> dynFnOnce(&'a mut fmt::Formatter<'b>) -> crate::Result<()>,
83{
84 #[inline]
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 if let Some(func: F) = self.func.take() {
87 if let Err(err: Error) = func(f) {
88 self.err.set(val:Some(err));
89 return Err(fmt::Error);
90 }
91 }
92 Ok(())
93 }
94}
95
96#[inline]
97pub fn get_primitive_value<T: PrimitiveType>(value: T) -> T::Value {
98 value.get()
99}
100
101pub trait PrimitiveType {
102 type Value;
103
104 fn get(&self) -> Self::Value;
105}
106
107macro_rules! primitive_type {
108 ($($ty:ty),* $(,)?) => {$(
109 impl PrimitiveType for $ty {
110 type Value = $ty;
111
112 #[inline]
113 fn get(&self) -> Self::Value {
114 *self
115 }
116 }
117 )*};
118}
119
120primitive_type! {
121 bool,
122 f32, f64,
123 i8, i16, i32, i64, i128, isize,
124 u8, u16, u32, u64, u128, usize,
125}
126
127crate::impl_for_ref! {
128 impl PrimitiveType for T {
129 type Value = T::Value;
130
131 #[inline]
132 fn get(&self) -> Self::Value {
133 <T>::get(self)
134 }
135 }
136}
137
138impl<T> PrimitiveType for Pin<T>
139where
140 T: Deref,
141 <T as Deref>::Target: PrimitiveType,
142{
143 type Value = <<T as Deref>::Target as PrimitiveType>::Value;
144
145 #[inline]
146 fn get(&self) -> Self::Value {
147 self.as_ref().get_ref().get()
148 }
149}
150
151/// Implement [`PrimitiveType`] for [`Cell<T>`]
152///
153/// ```
154/// # use std::cell::Cell;
155/// # use std::rc::Rc;
156/// # use std::pin::Pin;
157/// # use rinja::Template;
158/// #[derive(Template)]
159/// #[template(ext = "txt", source = "{{ value as u16 }}")]
160/// struct Test<'a> {
161/// value: &'a Pin<Rc<Cell<i16>>>
162/// }
163///
164/// assert_eq!(
165/// Test { value: &Rc::pin(Cell::new(-1)) }.to_string(),
166/// "65535",
167/// );
168/// ```
169impl<T: PrimitiveType + Copy> PrimitiveType for Cell<T> {
170 type Value = T::Value;
171
172 #[inline]
173 fn get(&self) -> Self::Value {
174 self.get().get()
175 }
176}
177
178/// An empty element, so nothing will be written.
179#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
180pub struct Empty;
181
182impl fmt::Display for Empty {
183 #[inline]
184 fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
185 Ok(())
186 }
187}
188
189impl FastWritable for Empty {
190 #[inline]
191 fn write_into<W: fmt::Write + ?Sized>(&self, _: &mut W) -> fmt::Result {
192 Ok(())
193 }
194}
195
196#[inline]
197pub fn as_bool<T: PrimitiveType<Value = bool>>(value: T) -> bool {
198 value.get()
199}
200