bacnet_emb/common/
daily_schedule.rs

1use core::fmt::Debug;
2
3use crate::common::{
4    error::Error,
5    helper::{encode_closing_tag, encode_opening_tag, get_tagged_body},
6    io::{Reader, Writer},
7    time_value::TimeValue,
8};
9
10#[cfg(feature = "alloc")]
11use {crate::common::spooky::Phantom, alloc::vec::Vec};
12
13// note that Debug is implemented manually here because of the reader in time value iter
14#[cfg(not(feature = "alloc"))]
15#[derive(Debug, Clone)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub struct WeeklySchedule<'a> {
18    pub monday: TimeValueList<'a>,
19    pub tuesday: TimeValueList<'a>,
20    pub wednesday: TimeValueList<'a>,
21    pub thursday: TimeValueList<'a>,
22    pub friday: TimeValueList<'a>,
23    pub saturday: TimeValueList<'a>,
24    pub sunday: TimeValueList<'a>,
25}
26
27#[cfg(feature = "alloc")]
28#[derive(Debug, Clone)]
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30pub struct WeeklySchedule<'a> {
31    pub monday: Vec<TimeValue>,
32    pub tuesday: Vec<TimeValue>,
33    pub wednesday: Vec<TimeValue>,
34    pub thursday: Vec<TimeValue>,
35    pub friday: Vec<TimeValue>,
36    pub saturday: Vec<TimeValue>,
37    pub sunday: Vec<TimeValue>,
38    _phantom: &'a Phantom,
39}
40
41#[cfg(feature = "alloc")]
42impl<'a> WeeklySchedule<'a> {
43    pub fn new(
44        monday: Vec<TimeValue>,
45        tuesday: Vec<TimeValue>,
46        wednesday: Vec<TimeValue>,
47        thursday: Vec<TimeValue>,
48        friday: Vec<TimeValue>,
49        saturday: Vec<TimeValue>,
50        sunday: Vec<TimeValue>,
51    ) -> Self {
52        use crate::common::spooky::PHANTOM;
53
54        Self {
55            monday,
56            tuesday,
57            wednesday,
58            thursday,
59            friday,
60            saturday,
61            sunday,
62            _phantom: &PHANTOM,
63        }
64    }
65
66    pub fn encode(&self, writer: &mut Writer) {
67        encode_day(writer, self.monday.iter());
68        encode_day(writer, self.tuesday.iter());
69        encode_day(writer, self.wednesday.iter());
70        encode_day(writer, self.thursday.iter());
71        encode_day(writer, self.friday.iter());
72        encode_day(writer, self.saturday.iter());
73        encode_day(writer, self.sunday.iter());
74    }
75
76    // due to the fact that WeeklySchedule contains an arbitrary number of TimeValue pairs we need to return an iterator
77    // because we cannot use an allocator
78    pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
79        let monday = Self::decode_day(reader, buf)?;
80        let tuesday = Self::decode_day(reader, buf)?;
81        let wednesday = Self::decode_day(reader, buf)?;
82        let thursday = Self::decode_day(reader, buf)?;
83        let friday = Self::decode_day(reader, buf)?;
84        let saturday = Self::decode_day(reader, buf)?;
85        let sunday = Self::decode_day(reader, buf)?;
86
87        Ok(Self::new(
88            monday, tuesday, wednesday, thursday, friday, saturday, sunday,
89        ))
90    }
91
92    fn decode_day(reader: &mut Reader, buf: &[u8]) -> Result<Vec<TimeValue>, Error> {
93        let (body_buf, _tag_num) = get_tagged_body(reader, buf)?;
94        let mut inner_reader = Reader::new_with_len(body_buf.len());
95        let mut time_values = Vec::new();
96        while !inner_reader.eof() {
97            let time_value = TimeValue::decode(&mut inner_reader, body_buf)?;
98            time_values.push(time_value);
99        }
100        Ok(time_values)
101    }
102}
103
104#[cfg(not(feature = "alloc"))]
105impl<'a> WeeklySchedule<'a> {
106    pub fn new(
107        monday: &'a [TimeValue],
108        tuesday: &'a [TimeValue],
109        wednesday: &'a [TimeValue],
110        thursday: &'a [TimeValue],
111        friday: &'a [TimeValue],
112        saturday: &'a [TimeValue],
113        sunday: &'a [TimeValue],
114    ) -> Self {
115        Self {
116            monday: TimeValueList::new(monday),
117            tuesday: TimeValueList::new(tuesday),
118            wednesday: TimeValueList::new(wednesday),
119            thursday: TimeValueList::new(thursday),
120            friday: TimeValueList::new(friday),
121            saturday: TimeValueList::new(saturday),
122            sunday: TimeValueList::new(sunday),
123        }
124    }
125
126    pub fn encode(&self, writer: &mut Writer) {
127        self.monday.encode(writer);
128        self.tuesday.encode(writer);
129        self.wednesday.encode(writer);
130        self.thursday.encode(writer);
131        self.friday.encode(writer);
132        self.saturday.encode(writer);
133        self.sunday.encode(writer);
134    }
135
136    // due to the fact that WeeklySchedule contains an arbitrary number of TimeValue pairs we need to return an iterator
137    // because we cannot use an allocator
138    pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
139        let monday = TimeValueList::decode(reader, buf)?;
140        let tuesday = TimeValueList::decode(reader, buf)?;
141        let wednesday = TimeValueList::decode(reader, buf)?;
142        let thursday = TimeValueList::decode(reader, buf)?;
143        let friday = TimeValueList::decode(reader, buf)?;
144        let saturday = TimeValueList::decode(reader, buf)?;
145        let sunday = TimeValueList::decode(reader, buf)?;
146
147        Ok(Self {
148            monday,
149            tuesday,
150            wednesday,
151            thursday,
152            friday,
153            saturday,
154            sunday,
155        })
156    }
157}
158
159// note that Debug is not implemented here because if does not add value
160#[derive(Debug, Clone)]
161#[cfg_attr(feature = "defmt", derive(defmt::Format))]
162pub struct TimeValueList<'a> {
163    pub time_values: &'a [TimeValue],
164    buf: &'a [u8],
165}
166
167fn encode_day<'b>(writer: &mut Writer, time_values: impl Iterator<Item = &'b TimeValue>) {
168    encode_opening_tag(writer, 0);
169    for time_value in time_values {
170        time_value.encode(writer)
171    }
172    encode_closing_tag(writer, 0);
173}
174
175impl<'a> TimeValueList<'a> {
176    pub fn new(time_values: &'a [TimeValue]) -> Self {
177        Self {
178            time_values,
179            buf: &[],
180        }
181    }
182
183    pub fn new_from_buf(buf: &'a [u8]) -> Self {
184        Self {
185            time_values: &[],
186            buf,
187        }
188    }
189
190    pub fn encode(&self, writer: &mut Writer) {
191        encode_day(writer, self.time_values.iter());
192    }
193
194    pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
195        let (body_buf, _tag_num) = get_tagged_body(reader, buf)?;
196        Ok(TimeValueList::new_from_buf(body_buf))
197    }
198}
199
200impl<'a> IntoIterator for &'_ TimeValueList<'a> {
201    type Item = Result<TimeValue, Error>;
202    type IntoIter = TimeValueIter<'a>;
203
204    fn into_iter(self) -> Self::IntoIter {
205        TimeValueIter {
206            buf: self.buf,
207            reader: Reader::new_with_len(self.buf.len()),
208        }
209    }
210}
211
212pub struct TimeValueIter<'a> {
213    reader: Reader,
214    buf: &'a [u8],
215}
216
217impl<'a> Iterator for TimeValueIter<'a> {
218    type Item = Result<TimeValue, Error>;
219
220    fn next(&mut self) -> Option<Self::Item> {
221        if self.reader.eof() {
222            return None;
223        }
224
225        Some(TimeValue::decode(&mut self.reader, self.buf))
226    }
227}