brim/
helper.rs

1use std::cmp::Ordering;
2use std::fmt::Display;
3use std::process::exit;
4
5use crate::{Cell, CellMod};
6
7/// Prints to stderr (in the format "msg: e") in red, then exits.
8pub fn err(msg: impl Display, e: impl Display) -> ! {
9    eprintln!("{0}[38:5:1m{1}: {2}{0}[0m", 27 as char, msg, e);
10    exit(1);
11}
12
13/// Prints a warning to stderr in yellow.
14pub fn warn(msg: impl Display) {
15    eprintln!("{0}[38:5:3m{1}{0}[0m", 27 as char, msg);
16}
17
18/// Wraps an addition/subtraction around array bounds.
19///
20/// With feature `dynamic_array`, just prevents underflow. Otherwise, wraps
21/// around 30000 and 0.
22#[inline]
23pub fn wrap_goto(x: usize, c: isize) -> usize {
24    #[cfg(not(feature = "dynamic_array"))]
25    if c > 0 {
26        (x + c as usize) % 30000
27    } else if c.unsigned_abs() > x {
28        30000 - (c.unsigned_abs() - x)
29    } else {
30        x - c.unsigned_abs()
31    }
32
33    #[cfg(feature = "dynamic_array")]
34    x.saturating_add_signed(c)
35}
36
37/// Wraps an addition/subtraction around 255 and 0.
38///
39/// With feature `nowrap`, instead prevents over/underflow without wrapping.
40#[inline]
41pub fn wrap_cell(x: Cell, c: CellMod) -> Cell {
42    #[cfg(not(feature = "nowrap"))]
43    return (x as CellMod).wrapping_add(c) as Cell;
44
45    #[cfg(feature = "nowrap")]
46    return (x as CellMod).saturating_add(c) as Cell;
47}
48
49/// Turns a relative index into left/right symbols.
50#[inline]
51pub fn left_right(i: isize) -> String {
52    match i.cmp(&0) {
53        Ordering::Greater => ">".repeat(i as usize),
54        Ordering::Less => "<".repeat(-i as usize),
55        Ordering::Equal => String::new(),
56    }
57}