dysql_tpl/template/
section.rs1use super::{Block, Tag};
11use crate::encoding::Encoder;
12use crate::{Content, Next};
13use crate::traits::ContentSequence;
14use std::ops::Range;
15
16#[derive(Clone, Copy)]
19pub struct Section<'section, Contents: ContentSequence> {
20 blocks: &'section [Block],
21 contents: Contents,
22}
23
24impl<'section> Section<'section, ()> {
25 #[inline]
26 pub(crate) fn new(blocks: &'section [Block]) -> Self {
27 let rst = Self {
28 blocks,
29 contents: (),
30 };
31
32 rst
33 }
34}
35
36impl<'section, C> Section<'section, C>
37where
38 C: ContentSequence,
39{
40 #[inline]
41 fn slice(self, range: Range<usize>) -> Self {
42 let rst = Self {
43 blocks: &self.blocks[range],
44 contents: self.contents,
45 };
46
47 rst
48 }
49
50 #[inline]
53 pub fn with<X>(self, content: &X) -> Section<'section, Next<'section, C, &X>>
54 where
55 X: Content + ?Sized,
56 {
57 let rst = Section {
58 blocks: self.blocks,
59 contents: self.contents.combine(content),
60 };
61
62 rst
63 }
64
65 #[inline]
67 pub fn without_last(self) -> Section<'section, C::Previous>
68 {
69 let rst = Section {
70 blocks: self.blocks,
71 contents: self.contents.crawl_back(),
72 };
73
74 rst
75 }
76
77 pub fn render<E, IC: Content>(&self, encoder: &mut E, content: Option<&IC>) -> Result<(), E::Error>
79 where
80 E: Encoder,
81 {
82 let mut index = 0;
83
84 while let Some(block) = self.blocks.get(index) { index += 1;
86 encoder.write_unescaped(&block.html)?;
87
88 match block.tag {
89 Tag::Escaped => {
90 if block.name == "$value" {
91 if let Some(content) = content {
92 content.render_escaped(encoder)?;
93 }
94 } else {
95 self.contents.render_field_escaped(block.hash, &block.name, encoder)?;
96 }
97 }
98 Tag::Unescaped => {
99 if block.name == "$value" {
100 if let Some(content) = content {
101 content.render_unescaped(encoder)?;
102 }
103 } else {
104 self.contents.render_field_unescaped(block.hash, &block.name, encoder)?;
105 }
106
107 }
108 Tag::Section => {
109 self.contents.render_field_section(
110 block.hash, &block.name, self.slice(index..index + block.children as usize), encoder,
114 )?;
115 index += block.children as usize;
116 }
117 Tag::Inverse => {
118 self.contents.render_field_inverse(
119 block.hash,
120 &block.name,
121 self.slice(index..index + block.children as usize),
122 encoder,
123 )?;
124 index += block.children as usize;
125 }
126 Tag::NotNone => {
127 let rst = self.contents.render_field_notnone_section(
128 block.hash,
129 &block.name,
130 self.slice(index..index + block.children as usize),
131 encoder,
132 )?;
133
134 if !rst {
135 index += block.children as usize;
136 }
137 }
139 _ => {}
140 }
141 }
142
143 Ok(())
144 }
145}