calc_rational

CLI calculator for rational numbers.
git clone https://git.philomathiclife.com/repos/calc_rational
Log | Files | Refs | README

main.rs (2641B)


      1 //! # `calc`
      2 //!
      3 //! Consult [`README.md`](https://crates.io/crates/calc_rational).
      4 #[cfg(not(feature = "std"))]
      5 use calc_lib as _;
      6 #[cfg(feature = "std")]
      7 use calc_lib::{EvalIter, lending_iterator::LendingIterator as _};
      8 #[cfg(feature = "std")]
      9 use core::fmt::{self, Display, Formatter};
     10 use num_bigint as _;
     11 use num_integer as _;
     12 use num_rational as _;
     13 use num_traits as _;
     14 #[cfg(all(feature = "priv_sep", not(target_os = "openbsd")))]
     15 use priv_sep as _;
     16 #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
     17 use priv_sep::{Promise, Promises};
     18 #[cfg(feature = "rand")]
     19 use rand as _;
     20 #[cfg(feature = "std")]
     21 use std::{
     22     error,
     23     io::{self, Error, Write as _},
     24 };
     25 /// Error returned by [`main`].
     26 #[cfg(feature = "std")]
     27 #[derive(Debug)]
     28 enum Err {
     29     /// Error returned from [`writeln`].
     30     Io(Error),
     31     #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
     32     /// Error returned from `pledge`.
     33     Pledge(Error),
     34 }
     35 #[cfg(feature = "std")]
     36 impl Display for Err {
     37     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
     38         match *self {
     39             Self::Io(ref e) => e.fmt(f),
     40             #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
     41             Self::Pledge(ref e) => write!(f, "pledge(2)ing 'stdio' failed with {e}"),
     42         }
     43     }
     44 }
     45 #[cfg(feature = "std")]
     46 impl error::Error for Err {}
     47 #[cfg(not(feature = "std"))]
     48 fn main() {}
     49 /// Entry point to the calc program.
     50 ///
     51 /// # Errors
     52 ///
     53 /// Returns [`Error`] if[`writeln`] returns one when writing
     54 /// to the global standard output stream. Returns [`Error`] if
     55 /// [`pledge`](https://docs.rs/priv_sep/latest/priv_sep/fn.pledge.html)
     56 /// does when compiled with the `priv_sep` feature which
     57 /// currently only works on OpenBSD-stable.
     58 #[cfg(feature = "std")]
     59 fn main() -> Result<(), Err> {
     60     /// Calls `pledge(2)` with the "stdio" promise.
     61     #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
     62     fn privsep() -> Result<(), Err> {
     63         Promises::new([Promise::Stdio])
     64             .pledge()
     65             .map_err(Err::Pledge)
     66     }
     67     /// Returns Ok.
     68     #[expect(
     69         clippy::unnecessary_wraps,
     70         reason = "consistent return type with priv_sep feature"
     71     )]
     72     #[cfg(not(all(feature = "priv_sep", target_os = "openbsd")))]
     73     const fn privsep() -> Result<(), Err> {
     74         Ok(())
     75     }
     76     privsep().and_then(|()| {
     77         let mut out = io::stdout().lock();
     78         EvalIter::new(io::stdin().lock()).lend_try_fold((), |(), res| {
     79             match res {
     80                 Ok(o) => writeln!(&mut out, "{o}"),
     81                 Err(e) => writeln!(&mut out, "{e}"),
     82             }
     83             .map_err(Err::Io)
     84         })
     85     })
     86 }