1use crate::encoding::Encoder;
6#[cfg(feature = "indexes")]
7use crate::template::Indexed;
8use crate::template::{Section, Template};
9use crate::traits::ContentSequence;
10
11use arrayvec::ArrayVec;
12use std::borrow::{Borrow, Cow, ToOwned};
13use std::collections::{BTreeMap, HashMap};
14use std::hash::{BuildHasher, Hash};
15use std::ops::Deref;
16
17pub trait Content {
21 #[inline]
23 fn is_truthy(&self) -> bool {
24 true
25 }
26
27 #[inline]
30 fn capacity_hint(&self, _tpl: &Template) -> usize {
31 0
32 }
33
34 #[inline]
38 fn render_escaped<E: Encoder>(&self, _encoder: &mut E) -> Result<(), E::Error> {
39 Ok(())
40 }
41
42 #[inline]
46 fn render_unescaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
47 self.render_escaped(encoder)
48 }
49
50 #[inline]
52 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
53 where
54 C: ContentSequence,
55 E: Encoder,
56 {
57 if self.is_truthy() {
58 section.render(encoder)
59 } else {
60 Ok(())
61 }
62 }
63
64 #[inline]
66 fn render_inverse<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
67 where
68 C: ContentSequence,
69 E: Encoder,
70 {
71 if !self.is_truthy() {
72 section.render(encoder)
73 } else {
74 Ok(())
75 }
76 }
77
78 #[inline]
83 fn render_field_escaped<E: Encoder>(
84 &self,
85 _hash: u64,
86 _name: &str,
87 _encoder: &mut E,
88 ) -> Result<bool, E::Error> {
89 Ok(false)
90 }
91
92 #[inline]
97 fn render_field_unescaped<E: Encoder>(
98 &self,
99 _hash: u64,
100 _name: &str,
101 _encoder: &mut E,
102 ) -> Result<bool, E::Error> {
103 Ok(false)
104 }
105
106 #[inline]
109 fn render_field_section<C, E>(
110 &self,
111 _hash: u64,
112 _name: &str,
113 _section: Section<C>,
114 _encoder: &mut E,
115 ) -> Result<bool, E::Error>
116 where
117 C: ContentSequence,
118 E: Encoder,
119 {
120 Ok(false)
121 }
122
123 #[inline]
126 fn render_field_inverse<C, E>(
127 &self,
128 _hash: u64,
129 _name: &str,
130 _section: Section<C>,
131 _encoder: &mut E,
132 ) -> Result<bool, E::Error>
133 where
134 C: ContentSequence,
135 E: Encoder,
136 {
137 Ok(false)
138 }
139
140 #[cfg(feature = "indexes")]
143 #[inline]
144 fn render_index_section<'section, P, E>(
145 &self,
146 _indexed: &Indexed,
147 _section: Section<'section, P>,
148 _encoder: &mut E,
149 ) -> Result<bool, E::Error>
150 where
151 P: ContentSequence,
152 E: Encoder,
153 {
154 Ok(false)
155 }
156}
157
158impl Content for () {
159 #[inline]
160 fn is_truthy(&self) -> bool {
161 false
162 }
163}
164
165impl Content for str {
166 #[inline]
167 fn is_truthy(&self) -> bool {
168 !self.is_empty()
169 }
170
171 #[inline]
172 fn capacity_hint(&self, _tpl: &Template) -> usize {
173 self.len()
174 }
175
176 #[inline]
177 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
178 encoder.write_escaped(self)
179 }
180
181 #[inline]
182 fn render_unescaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
183 encoder.write_unescaped(self)
184 }
185}
186
187impl Content for String {
188 #[inline]
189 fn is_truthy(&self) -> bool {
190 !self.is_empty()
191 }
192
193 #[inline]
194 fn capacity_hint(&self, _tpl: &Template) -> usize {
195 self.len()
196 }
197
198 #[inline]
199 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
200 encoder.write_escaped(self)
201 }
202
203 #[inline]
204 fn render_unescaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
205 encoder.write_unescaped(self)
206 }
207}
208
209impl Content for bool {
210 #[inline]
211 fn is_truthy(&self) -> bool {
212 *self
213 }
214
215 #[inline]
216 fn capacity_hint(&self, _tpl: &Template) -> usize {
217 5
218 }
219
220 #[inline]
221 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
222 encoder.write_unescaped(if *self { "true" } else { "false" })
224 }
225}
226
227macro_rules! impl_number_types {
228 ($( $ty:ty ),*) => {
229 $(
230 impl Content for $ty {
231 #[inline]
232 fn is_truthy(&self) -> bool {
233 *self != 0 as $ty
234 }
235
236 #[inline]
237 fn capacity_hint(&self, _tpl: &Template) -> usize {
238 5
239 }
240
241 #[inline]
242 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error>
243 {
244 encoder.format_unescaped(self)
246 }
247 }
248 )*
249 }
250}
251
252impl_number_types!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
253
254impl Content for f32 {
255 #[inline]
256 fn is_truthy(&self) -> bool {
257 self.abs() > f32::EPSILON
259 }
260
261 #[inline]
262 fn capacity_hint(&self, _tpl: &Template) -> usize {
263 5
264 }
265
266 #[inline]
267 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
268 encoder.format_unescaped(self)
270 }
271}
272
273impl Content for f64 {
274 #[inline]
275 fn is_truthy(&self) -> bool {
276 self.abs() > f64::EPSILON
278 }
279
280 #[inline]
281 fn capacity_hint(&self, _tpl: &Template) -> usize {
282 5
283 }
284
285 #[inline]
286 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
287 encoder.format_unescaped(self)
289 }
290}
291
292impl<T: Content> Content for Option<T> {
293 #[inline]
294 fn is_truthy(&self) -> bool {
295 self.is_some()
296 }
297
298 #[inline]
299 fn capacity_hint(&self, tpl: &Template) -> usize {
300 match self {
301 Some(inner) => inner.capacity_hint(tpl),
302 _ => 0,
303 }
304 }
305
306 #[inline]
307 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
308 if let Some(inner) = self {
309 inner.render_escaped(encoder)?;
310 }
311
312 Ok(())
313 }
314
315 #[inline]
316 fn render_unescaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
317 if let Some(ref inner) = self {
318 inner.render_unescaped(encoder)?;
319 }
320
321 Ok(())
322 }
323
324 #[inline]
325 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
326 where
327 C: ContentSequence,
328 E: Encoder,
329 {
330 if let Some(ref item) = self {
331 item.render_section(section, encoder)?;
332 }
333
334 Ok(())
335 }
336}
337
338impl<T: Content, U> Content for Result<T, U> {
339 #[inline]
340 fn is_truthy(&self) -> bool {
341 self.is_ok()
342 }
343
344 #[inline]
345 fn capacity_hint(&self, tpl: &Template) -> usize {
346 match self {
347 Ok(inner) => inner.capacity_hint(tpl),
348 _ => 0,
349 }
350 }
351
352 #[inline]
353 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
354 if let Ok(inner) = self {
355 inner.render_escaped(encoder)?;
356 }
357
358 Ok(())
359 }
360
361 #[inline]
362 fn render_unescaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
363 if let Ok(ref inner) = self {
364 inner.render_unescaped(encoder)?;
365 }
366
367 Ok(())
368 }
369
370 #[inline]
371 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
372 where
373 C: ContentSequence,
374 E: Encoder,
375 {
376 if let Ok(item) = self {
377 item.render_section(section, encoder)?;
378 }
379
380 Ok(())
381 }
382}
383
384impl<T: Content> Content for Vec<T> {
385 #[inline]
386 fn is_truthy(&self) -> bool {
387 !self.is_empty()
388 }
389
390 #[inline]
391 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
392 where
393 C: ContentSequence,
394 E: Encoder,
395 {
396 #[cfg(feature = "indexes")]
397 for (index, item) in self.iter().enumerate() {
398 IndexBasedRender {
399 length: self.len(),
400 index,
401 item,
402 }
403 .render_section(section, encoder)?;
404 }
405 #[cfg(not(feature = "indexes"))]
406 for item in self.iter() {
407 item.render_section(section, encoder)?;
408 }
409
410 Ok(())
411 }
412}
413
414#[cfg(feature = "indexes")]
415struct IndexBasedRender<'a, T> {
416 length: usize,
417 index: usize,
418 item: &'a T,
419}
420#[cfg(feature = "indexes")]
421impl<T: Content> Content for IndexBasedRender<'_, T> {
422 #[inline]
423 fn is_truthy(&self) -> bool {
424 true
425 }
426
427 #[inline]
429 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
430 where
431 C: ContentSequence,
432 E: Encoder,
433 {
434 if self.is_truthy() {
435 section.with(self).render(encoder)
436 } else {
437 Ok(())
438 }
439 }
440
441 #[inline]
442 fn render_index_section<'section, P, E>(
443 &self,
444 indexed: &Indexed,
445 section: Section<'section, P>,
446 encoder: &mut E,
447 ) -> Result<bool, E::Error>
448 where
449 P: ContentSequence,
450 E: Encoder,
451 {
452 if indexed.is_truthy(self.length, self.index) {
453 self.item.render_section(section, encoder)?;
454 }
455 Ok(true)
456 }
457
458 fn render_field_escaped<E>(
459 &self,
460 hash: u64,
461 name: &str,
462 encoder: &mut E,
463 ) -> Result<bool, E::Error>
464 where
465 E: Encoder,
466 {
467 self.item.render_field_escaped(hash, name, encoder)
468 }
469
470 fn render_field_unescaped<E>(
471 &self,
472 hash: u64,
473 name: &str,
474 encoder: &mut E,
475 ) -> Result<bool, E::Error>
476 where
477 E: Encoder,
478 {
479 self.item.render_field_unescaped(hash, name, encoder)
480 }
481
482 fn render_field_section<C, E>(
483 &self,
484 hash: u64,
485 name: &str,
486 section: Section<C>,
487 encoder: &mut E,
488 ) -> Result<bool, E::Error>
489 where
490 C: ContentSequence,
491 E: Encoder,
492 {
493 self.item.render_field_section(hash, name, section, encoder)
494 }
495
496 fn render_field_inverse<C, E>(
497 &self,
498 hash: u64,
499 name: &str,
500 section: Section<C>,
501 encoder: &mut E,
502 ) -> Result<bool, E::Error>
503 where
504 C: ContentSequence,
505 E: Encoder,
506 {
507 self.item.render_field_inverse(hash, name, section, encoder)
508 }
509}
510
511impl<T: Content> Content for [T] {
512 #[inline]
513 fn is_truthy(&self) -> bool {
514 !self.is_empty()
515 }
516
517 #[inline]
518 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
519 where
520 C: ContentSequence,
521 E: Encoder,
522 {
523 for item in self.iter() {
524 item.render_section(section, encoder)?;
525 }
526
527 Ok(())
528 }
529}
530
531impl<T: Content, const N: usize> Content for [T; N] {
532 #[inline]
533 fn is_truthy(&self) -> bool {
534 !self.is_empty()
535 }
536
537 #[inline]
538 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
539 where
540 C: ContentSequence,
541 E: Encoder,
542 {
543 for item in self.iter() {
544 item.render_section(section, encoder)?;
545 }
546
547 Ok(())
548 }
549}
550
551impl<T: Content, const N: usize> Content for ArrayVec<T, N> {
552 #[inline]
553 fn is_truthy(&self) -> bool {
554 !self.is_empty()
555 }
556
557 #[inline]
558 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
559 where
560 C: ContentSequence,
561 E: Encoder,
562 {
563 for item in self.iter() {
564 item.render_section(section, encoder)?;
565 }
566
567 Ok(())
568 }
569}
570
571impl<K, V, S> Content for HashMap<K, V, S>
572where
573 K: Borrow<str> + Hash + Eq,
574 V: Content,
575 S: BuildHasher,
576{
577 fn is_truthy(&self) -> bool {
578 !self.is_empty()
579 }
580
581 #[inline]
583 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
584 where
585 C: ContentSequence,
586 E: Encoder,
587 {
588 if self.is_truthy() {
589 section.with(self).render(encoder)
590 } else {
591 Ok(())
592 }
593 }
594
595 fn render_field_escaped<E>(&self, _: u64, name: &str, encoder: &mut E) -> Result<bool, E::Error>
596 where
597 E: Encoder,
598 {
599 match self.get(name) {
600 Some(v) => v.render_escaped(encoder).map(|_| true),
601 None => Ok(false),
602 }
603 }
604
605 fn render_field_unescaped<E>(
606 &self,
607 _: u64,
608 name: &str,
609 encoder: &mut E,
610 ) -> Result<bool, E::Error>
611 where
612 E: Encoder,
613 {
614 match self.get(name) {
615 Some(v) => v.render_unescaped(encoder).map(|_| true),
616 None => Ok(false),
617 }
618 }
619
620 fn render_field_section<C, E>(
621 &self,
622 _: u64,
623 name: &str,
624 section: Section<C>,
625 encoder: &mut E,
626 ) -> Result<bool, E::Error>
627 where
628 C: ContentSequence,
629 E: Encoder,
630 {
631 match self.get(name) {
632 Some(v) => v.render_section(section, encoder).map(|_| true),
633 None => Ok(false),
634 }
635 }
636
637 fn render_field_inverse<C, E>(
638 &self,
639 _: u64,
640 name: &str,
641 section: Section<C>,
642 encoder: &mut E,
643 ) -> Result<bool, E::Error>
644 where
645 C: ContentSequence,
646 E: Encoder,
647 {
648 match self.get(name) {
649 Some(v) => v.render_inverse(section, encoder).map(|_| true),
650 None => Ok(false),
651 }
652 }
653}
654
655impl<K, V> Content for BTreeMap<K, V>
656where
657 K: Borrow<str> + Ord,
658 V: Content,
659{
660 fn is_truthy(&self) -> bool {
661 !self.is_empty()
662 }
663
664 #[inline]
666 fn render_section<C, E>(&self, section: Section<C>, encoder: &mut E) -> Result<(), E::Error>
667 where
668 C: ContentSequence,
669 E: Encoder,
670 {
671 if self.is_truthy() {
672 section.with(self).render(encoder)
673 } else {
674 Ok(())
675 }
676 }
677
678 fn render_field_escaped<E>(&self, _: u64, name: &str, encoder: &mut E) -> Result<bool, E::Error>
679 where
680 E: Encoder,
681 {
682 match self.get(name) {
683 Some(v) => v.render_escaped(encoder).map(|_| true),
684 None => Ok(false),
685 }
686 }
687
688 fn render_field_unescaped<E>(
689 &self,
690 _: u64,
691 name: &str,
692 encoder: &mut E,
693 ) -> Result<bool, E::Error>
694 where
695 E: Encoder,
696 {
697 match self.get(name) {
698 Some(v) => v.render_unescaped(encoder).map(|_| true),
699 None => Ok(false),
700 }
701 }
702
703 fn render_field_section<C, E>(
704 &self,
705 _: u64,
706 name: &str,
707 section: Section<C>,
708 encoder: &mut E,
709 ) -> Result<bool, E::Error>
710 where
711 C: ContentSequence,
712 E: Encoder,
713 {
714 match self.get(name) {
715 Some(v) => v.render_section(section, encoder).map(|_| true),
716 None => Ok(false),
717 }
718 }
719
720 fn render_field_inverse<C, E>(
721 &self,
722 _: u64,
723 name: &str,
724 section: Section<C>,
725 encoder: &mut E,
726 ) -> Result<bool, E::Error>
727 where
728 C: ContentSequence,
729 E: Encoder,
730 {
731 match self.get(name) {
732 Some(v) => v.render_inverse(section, encoder).map(|_| true),
733 None => Ok(false),
734 }
735 }
736}
737
738macro_rules! impl_pointer_types {
739 ($( $ty:ty $(: $bounds:ident)? ),*) => {
740 $(
741 impl<T: Content $(+ $bounds)? + ?Sized> Content for $ty {
742 #[inline]
743 fn is_truthy(&self) -> bool {
744 self.deref().is_truthy()
745 }
746
747 #[inline]
748 fn capacity_hint(&self, tpl: &Template) -> usize {
749 self.deref().capacity_hint(tpl)
750 }
751
752 #[inline]
753 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
754 self.deref().render_escaped(encoder)
755 }
756
757 #[inline]
758 fn render_unescaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
759 self.deref().render_unescaped(encoder)
760 }
761
762 #[inline]
763 fn render_section<C, E>(
764 &self,
765 section: Section<C>,
766 encoder: &mut E,
767 ) -> Result<(), E::Error>
768 where
769 C: ContentSequence,
770 E: Encoder,
771 {
772 self.deref().render_section(section, encoder)
773 }
774
775 #[inline]
776 fn render_inverse<C, E>(
777 &self,
778 section: Section<C>,
779 encoder: &mut E,
780 ) -> Result<(), E::Error>
781 where
782 C: ContentSequence,
783 E: Encoder,
784 {
785 self.deref().render_inverse(section, encoder)
786 }
787
788 #[inline]
789 fn render_field_escaped<E: Encoder>(
790 &self,
791 hash: u64,
792 name: &str,
793 encoder: &mut E,
794 ) -> Result<bool, E::Error> {
795 self.deref().render_field_escaped(hash, name, encoder)
796 }
797
798 #[inline]
799 fn render_field_unescaped<E: Encoder>(
800 &self,
801 hash: u64,
802 name: &str,
803 encoder: &mut E,
804 ) -> Result<bool, E::Error> {
805 self.deref().render_field_unescaped(hash, name, encoder)
806 }
807
808 #[inline]
809 fn render_field_section<C, E>(
810 &self,
811 hash: u64,
812 name: &str,
813 section: Section<C>,
814 encoder: &mut E,
815 ) -> Result<bool, E::Error>
816 where
817 C: ContentSequence,
818 E: Encoder,
819 {
820 self.deref().render_field_section(hash, name, section, encoder)
821 }
822
823 #[inline]
824 fn render_field_inverse<C, E>(
825 &self,
826 hash: u64,
827 name: &str,
828 section: Section<C>,
829 encoder: &mut E,
830 ) -> Result<bool, E::Error>
831 where
832 C: ContentSequence,
833 E: Encoder,
834 {
835 self.deref().render_field_inverse(hash, name, section, encoder)
836 }
837
838 #[cfg(feature = "indexes")]
839 #[inline]
840 fn render_index_section<'section, P, E>(
841 &self,
842 indexed: &Indexed,
843 section: Section<'section, P>,
844 encoder: &mut E,
845 ) -> Result<bool, E::Error>
846 where
847 P: ContentSequence,
848 E: Encoder,
849 {
850 self.deref().render_index_section(indexed, section, encoder)
851 }
852 }
853 )*
854 }
855}
856
857impl_pointer_types!(&T, Box<T>, std::rc::Rc<T>, std::sync::Arc<T>, Cow<'_, T>: ToOwned, beef::Cow<'_, [T]>: Clone);
858
859#[cfg(target_pointer_width = "64")]
860impl_pointer_types!(beef::lean::Cow<'_, [T]>: Clone);
861
862impl Content for beef::Cow<'_, str> {
864 #[inline]
865 fn is_truthy(&self) -> bool {
866 !self.is_empty()
867 }
868
869 #[inline]
870 fn capacity_hint(&self, _tpl: &Template) -> usize {
871 self.len()
872 }
873
874 #[inline]
875 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
876 encoder.write_escaped(self)
877 }
878
879 #[inline]
880 fn render_unescaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
881 encoder.write_unescaped(self)
882 }
883}
884
885#[cfg(target_pointer_width = "64")]
886impl Content for beef::lean::Cow<'_, str> {
887 #[inline]
888 fn is_truthy(&self) -> bool {
889 !self.is_empty()
890 }
891
892 #[inline]
893 fn capacity_hint(&self, _tpl: &Template) -> usize {
894 self.len()
895 }
896
897 #[inline]
898 fn render_escaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
899 encoder.write_escaped(self)
900 }
901
902 #[inline]
903 fn render_unescaped<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
904 encoder.write_unescaped(self)
905 }
906}