1use super::{Expression, GeneralSpec, Irp, Message, Pronto, RepeatMarker, Unit, Vartable};
2use bitvec::prelude::*;
3use log::warn;
4use num::{ToPrimitive, Zero};
5use num_rational::Rational64;
6use std::{collections::HashMap, rc::Rc};
7
8impl Irp {
9 pub fn encode<'a>(&'a self, mut vars: Vartable<'a>) -> Result<[Vec<u32>; 3], String> {
11 self.check_parameters(&mut vars)?;
12
13 let mut encoder = Encoder::new(&self.general_spec, vars);
14
15 let mut res = [Vec::new(), Vec::new(), Vec::new()];
16
17 for (i, variant) in self.variants.iter().enumerate() {
18 if let Some(variant) = variant {
19 encoder.encode(variant, None)?;
20
21 if encoder.has_trailing_pulse() {
22 return Err("stream must end with a gap".into());
23 }
24
25 res[i] = encoder.done()
26 }
27 }
28
29 Ok(res)
30 }
31
32 pub fn encode_raw<'a>(&'a self, vars: Vartable<'a>, repeats: u64) -> Result<Message, String> {
34 let [down, repeat, up] = self.encode(vars)?;
35
36 let mut raw = down;
37
38 for _ in 0..repeats {
39 raw.extend_from_slice(&repeat);
40 }
41
42 raw.extend(up);
43
44 Ok(Message {
45 carrier: Some(self.general_spec.carrier.to_integer()),
46 duty_cycle: self.general_spec.duty_cycle,
47 raw,
48 })
49 }
50
51 pub fn encode_pronto<'a>(&'a self, vars: Vartable<'a>) -> Result<Pronto, String> {
54 let [down, repeat, up] = self.encode(vars)?;
55
56 let intro = down.iter().map(|v| *v as f64).collect();
57
58 let repeat = repeat.iter().map(|v| *v as f64).collect();
59
60 if !up.is_empty() {
61 warn!("ending sequence cannot be represented in pronto, dropped");
62 }
63
64 if !self.general_spec.carrier.is_zero() {
65 Ok(Pronto::LearnedModulated {
66 frequency: self.general_spec.carrier.to_f64().unwrap(),
67 intro,
68 repeat,
69 })
70 } else {
71 Ok(Pronto::LearnedUnmodulated {
72 frequency: 414514.0,
74 intro,
75 repeat,
76 })
77 }
78 }
79
80 fn check_parameters<'a>(&'a self, vars: &mut Vartable<'a>) -> Result<(), String> {
81 for p in &self.parameters {
82 let val = if let Ok(val) = vars.get(&p.name) {
83 val
84 } else if let Some(e) = &p.default {
85 let v = e.eval(vars)?;
86
87 vars.set(p.name.to_owned(), v);
88
89 v
90 } else {
91 return Err(format!("missing value for {}", p.name));
92 };
93
94 if val < p.min {
95 return Err(format!(
96 "{} is less than minimum value {} for parameter {}",
97 val, p.min, p.name
98 ));
99 }
100
101 if val > p.max {
102 return Err(format!(
103 "{} is more than maximum value {} for parameter {}",
104 val, p.max, p.name
105 ));
106 }
107 }
108
109 if !self.parameters.is_empty() {
111 for name in vars.vars.keys() {
112 if !self.parameters.iter().any(|p| &p.name == name) {
113 return Err(format!("no parameter called {name}"));
114 }
115 }
116 }
117
118 for e in &self.definitions {
119 if let Expression::Assignment(name, expr) = e {
120 vars.set_definition(name.clone(), expr.as_ref());
121 } else {
122 unreachable!();
123 }
124 }
125
126 Ok(())
127 }
128}
129
130impl<'a> Vartable<'a> {
131 pub fn new() -> Self {
132 Vartable {
133 vars: HashMap::new(),
134 }
135 }
136
137 fn set_definition(&mut self, id: String, expr: &'a Expression) {
139 self.vars.insert(id, (0, Some(expr)));
140 }
141
142 pub fn set(&mut self, id: String, value: i64) {
143 self.vars.insert(id, (value, None));
144 }
145
146 pub fn is_defined(&self, id: &str) -> bool {
147 self.vars.contains_key(id)
148 }
149
150 pub fn get(&self, id: &str) -> Result<i64, String> {
151 match self.vars.get(id) {
152 Some((val, None)) => Ok(*val),
153 Some((_, Some(expr))) => expr.eval(self),
154 None => Err(format!("variable `{id}ยด not defined")),
155 }
156 }
157}
158
159struct Encoder<'a, 'b> {
161 general_spec: &'a GeneralSpec,
163 raw: Vec<u32>,
165 leading_gap: bool,
167 total_length: i64,
169 extent_marker: i64,
171 vars: Vartable<'a>,
173 bitspec_scope: Vec<BitspecScope<'b>>,
175}
176
177struct BitspecScope<'a> {
179 bit_spec: &'a [Rc<Expression>],
181 bitstream: BitVec<usize, LocalBits>,
183}
184
185impl<'a, 'b> Encoder<'a, 'b> {
186 fn new(general_spec: &'a GeneralSpec, vars: Vartable<'a>) -> Self {
188 Encoder {
189 general_spec,
190 vars,
191 raw: Vec::new(),
192 leading_gap: true,
193 total_length: 0,
194 extent_marker: 0,
195 bitspec_scope: Vec::new(),
196 }
197 }
198
199 fn add_flash(&mut self, length: i64) -> Result<(), String> {
201 if length <= 0 {
202 warn!("length should be non-zero");
203 return Ok(());
204 }
205
206 if let Some(v) = self.total_length.checked_add(length) {
207 self.total_length = v;
208 } else {
209 return Err("length overflow".into());
210 }
211
212 if (self.raw.len() % 2) == 1 {
213 let raw = self.raw.last_mut().unwrap();
214
215 if let Some(v) = raw.checked_add(length as u32) {
216 *raw = v;
217 } else {
218 return Err("length overflow".into());
219 }
220 } else {
221 self.raw.push(length as u32);
222 }
223 self.leading_gap = false;
224 Ok(())
225 }
226
227 fn add_gap(&mut self, length: i64) -> Result<(), String> {
229 if length <= 0 {
230 warn!("length should be non-zero");
231 return Ok(());
232 }
233
234 if let Some(v) = self.total_length.checked_add(length) {
236 self.total_length = v;
237 } else {
238 return Err("length overflow".into());
239 }
240
241 let len = self.raw.len();
242
243 if self.leading_gap {
244 } else if (len % 2) == 0 {
246 let raw = self.raw.last_mut().unwrap();
247
248 if let Some(v) = raw.checked_add(length as u32) {
249 *raw = v;
250 } else {
251 return Err("length overflow".into());
252 }
253 } else {
254 self.raw.push(length as u32);
255 }
256 Ok(())
257 }
258
259 fn add_extent(&mut self, extent: i64) -> Result<(), String> {
261 let trimmed_extent = extent - (self.total_length - self.extent_marker);
263
264 if trimmed_extent > 0 {
265 self.add_gap(trimmed_extent)?;
266 } else {
267 return Err("extent shorter than duration".into());
270 }
271
272 self.extent_marker = self.total_length;
274
275 Ok(())
276 }
277
278 fn add_bits(&mut self, bits: i64, length: i64, level: Option<usize>) -> Result<(), String> {
280 match level {
281 Some(level) => {
282 let mut bv = BitVec::<usize, LocalBits>::from_element(bits as usize);
283
284 bv.truncate(length as usize);
285
286 bv.reverse();
287
288 let level = &mut self.bitspec_scope[level];
289
290 if self.general_spec.lsb {
291 bv.append(&mut level.bitstream);
292 level.bitstream = bv;
293 } else {
294 level.bitstream.append(&mut bv);
295 }
296
297 Ok(())
298 }
299 None => Err(String::from("bits not permitted")),
300 }
301 }
302
303 fn flush_level(&mut self, level: Option<usize>) -> Result<(), String> {
305 let level = match level {
306 Some(level) => level,
307 None => {
308 return Ok(());
309 }
310 };
311
312 let lower_level = if level > 0 { Some(level - 1) } else { None };
313
314 if !self.bitspec_scope[level].bitstream.is_empty() {
315 let mut bits = BitVec::new();
316
317 std::mem::swap(&mut bits, &mut self.bitspec_scope[level].bitstream);
320
321 let max_bit = self.bitspec_scope[level].bit_spec.len();
322
323 let bits_step = match max_bit {
324 1..=2 => 1,
325 3..=4 => 2,
326 5..=8 => 3,
327 9..=16 => 4,
328 _ => unreachable!(),
329 };
330
331 let bits_len = bits.len();
332
333 if (bits_len % bits_step) != 0 {
334 return Err(format!(
335 "Cannot encode {bits_len} bits with bitspec of {max_bit}"
336 ));
337 }
338
339 if !self.general_spec.lsb {
340 for bit in bits.chunks(bits_step) {
341 let bit = bit_to_usize(bit);
342
343 if bit >= max_bit {
344 return Err(format!("Cannot encode {bit} with current bit_spec"));
345 }
346
347 self.encode(
348 self.bitspec_scope[level].bit_spec[bit].as_ref(),
349 lower_level,
350 )?;
351 }
352 } else {
353 for bit in bits.chunks(bits_step).rev() {
354 let bit = bit_to_usize(bit);
355
356 if bit >= max_bit {
357 return Err(format!("Cannot encode {bit} with current bit_spec"));
358 }
359
360 self.encode(
361 self.bitspec_scope[level].bit_spec[bit].as_ref(),
362 lower_level,
363 )?;
364 }
365 }
366 }
367
368 self.flush_level(lower_level)?;
369
370 Ok(())
371 }
372
373 fn encode(&mut self, expr: &'b Expression, level: Option<usize>) -> Result<(), String> {
374 match expr {
375 Expression::FlashConstant(p, u) => {
376 self.flush_level(level)?;
377 self.add_flash(u.eval_rational(p, self.general_spec)?)?;
378 }
379 Expression::FlashIdentifier(id, u) => {
380 self.flush_level(level)?;
381 let v = u.eval(self.vars.get(id)?, self.general_spec)?;
382 if v > 0 {
383 self.add_flash(v)?;
384 } else {
385 self.add_gap(v.wrapping_neg())?;
386 }
387 }
388 Expression::ExtentConstant(p, u) => {
389 self.flush_level(level)?;
390 self.add_extent(u.eval_rational(p, self.general_spec)?)?;
391 }
392 Expression::ExtentIdentifier(id, u) => {
393 self.flush_level(level)?;
394 self.add_extent(u.eval(self.vars.get(id)?, self.general_spec)?)?;
395 }
396 Expression::GapConstant(p, u) => {
397 self.flush_level(level)?;
398 self.add_gap(u.eval_rational(p, self.general_spec)?)?;
399 }
400 Expression::GapIdentifier(id, u) => {
401 self.flush_level(level)?;
402 let v = u.eval(self.vars.get(id)?, self.general_spec)?;
403 if v > 0 {
404 self.add_gap(v)?;
405 } else {
406 self.add_flash(v.wrapping_neg())?;
407 }
408 }
409 Expression::Assignment(id, expr) => {
410 self.flush_level(level)?;
411
412 let v = expr.eval(&self.vars)?;
413
414 self.vars.set(id.into(), v);
415 }
416 Expression::Stream(stream) => {
417 let repeats = match stream.repeat {
418 None => 1,
419 Some(RepeatMarker::Count(num)) => num,
420 _ => unreachable!(),
421 };
422
423 let level = if !stream.bit_spec.is_empty() {
424 self.bitspec_scope.push(BitspecScope {
425 bit_spec: &stream.bit_spec,
426 bitstream: BitVec::new(),
427 });
428
429 match level {
430 None => Some(0),
431 Some(level) => Some(level + 1),
432 }
433 } else {
434 level
435 };
436
437 for _ in 0..repeats {
438 for expr in &stream.stream {
439 if let Expression::List(list) = expr.as_ref() {
440 if list.is_empty() {
441 break;
442 }
443 }
444 self.encode(expr, level)?;
445 }
446 }
447
448 self.flush_level(level)?;
449
450 if !stream.bit_spec.is_empty() {
451 self.bitspec_scope.pop();
452 }
453 }
454 Expression::BitField { .. } => {
455 let (bits, length) = expr.bitfield(&self.vars)?;
456
457 self.add_bits(bits, length, level)?;
458 }
459 Expression::List(list) => {
460 for expr in list {
461 self.encode(expr, level)?;
462 }
463 }
464 _ => unreachable!(),
465 }
466
467 Ok(())
468 }
469
470 fn has_trailing_pulse(&self) -> bool {
471 (self.raw.len() % 2) != 0
472 }
473
474 fn done(&mut self) -> Vec<u32> {
475 self.total_length = 0;
476 self.extent_marker = 0;
477 self.leading_gap = true;
478
479 let mut res = Vec::new();
480
481 std::mem::swap(&mut res, &mut self.raw);
482
483 res
484 }
485}
486
487impl Unit {
488 pub(crate) fn eval(&self, v: i64, spec: &GeneralSpec) -> Result<i64, String> {
489 match self {
490 Unit::Units if spec.unit.is_zero() => Err("cannot use units when unit set to 0".into()),
491 Unit::Units => Ok((spec.unit * v).to_integer()),
492 Unit::Microseconds => Ok(v),
493 Unit::Milliseconds => Ok(v * 1000),
494 Unit::Pulses if spec.carrier.is_zero() => {
495 Err("pulses cannot be used with zero carrier".into())
496 }
497 Unit::Pulses => Ok((Rational64::from(v) * 1_000_000 / spec.carrier).to_integer()),
498 }
499 }
500
501 pub(crate) fn eval_rational(&self, v: &Rational64, spec: &GeneralSpec) -> Result<i64, String> {
502 match self {
503 Unit::Units if spec.unit.is_zero() => Err("cannot use units when unit set to 0".into()),
504 Unit::Units => Ok((spec.unit * v).to_integer()),
505 Unit::Microseconds => Ok(v.to_integer()),
506 Unit::Milliseconds => Ok((v * 1000).to_integer()),
507 Unit::Pulses if spec.carrier.is_zero() => {
508 Err("pulses cannot be used with zero carrier".into())
509 }
510 Unit::Pulses => Ok((v * 1_000_000 / spec.carrier).to_integer()),
511 }
512 }
513}
514
515fn bit_to_usize(bit: &BitSlice) -> usize {
517 let mut v = 0;
518
519 for i in 0..bit.len() {
520 if bit[i] {
521 v |= 1 << (bit.len() - 1 - i);
522 }
523 }
524
525 v
526}