calc_rational

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

main.rs (3236B)


      1 //! # `calc`
      2 //!
      3 //! Consult [`README.md`](https://crates.io/crates/calc_rational).
      4 #![cfg_attr(all(doc, channel_nightly), feature(doc_auto_cfg))]
      5 #![deny(
      6     unknown_lints,
      7     future_incompatible,
      8     let_underscore,
      9     missing_docs,
     10     nonstandard_style,
     11     refining_impl_trait,
     12     rust_2018_compatibility,
     13     rust_2018_idioms,
     14     rust_2021_compatibility,
     15     rust_2024_compatibility,
     16     unsafe_code,
     17     unused,
     18     warnings,
     19     clippy::all,
     20     clippy::cargo,
     21     clippy::complexity,
     22     clippy::correctness,
     23     clippy::nursery,
     24     clippy::pedantic,
     25     clippy::perf,
     26     clippy::restriction,
     27     clippy::style,
     28     clippy::suspicious
     29 )]
     30 #![allow(
     31     clippy::blanket_clippy_restriction_lints,
     32     clippy::implicit_return,
     33     clippy::min_ident_chars,
     34     clippy::missing_trait_methods,
     35     clippy::ref_patterns,
     36     clippy::single_call_fn,
     37     reason = "noisy, opinionated, and likely doesn't prevent bugs or improve APIs"
     38 )]
     39 #[cfg(feature = "std")]
     40 use calc_lib::{lending_iterator::LendingIterator, EvalIter};
     41 #[cfg(feature = "std")]
     42 use core::fmt::{self, Display, Formatter};
     43 #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
     44 use priv_sep::{Promise, Promises};
     45 #[cfg(feature = "std")]
     46 use std::{
     47     error,
     48     io::{self, Error, Write},
     49 };
     50 /// Error returned by [`main`].
     51 #[cfg(feature = "std")]
     52 #[derive(Debug)]
     53 enum Err {
     54     /// Error returned from [`writeln`].
     55     Io(Error),
     56     #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
     57     /// Error returned from [`pledge`].
     58     Pledge(Error),
     59 }
     60 #[cfg(feature = "std")]
     61 impl Display for Err {
     62     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
     63         match *self {
     64             Self::Io(ref e) => e.fmt(f),
     65             #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
     66             Self::Pledge(ref e) => write!(f, "pledge(2)ing 'stdio' failed with {e}"),
     67         }
     68     }
     69 }
     70 #[cfg(feature = "std")]
     71 impl error::Error for Err {}
     72 #[cfg(not(feature = "std"))]
     73 fn main() {}
     74 /// Entry point to the calc program.
     75 ///
     76 /// # Errors
     77 ///
     78 /// Returns [`Error`] if[`writeln`] returns one when writing
     79 /// to the global standard output stream. Returns [`Error`] if
     80 /// [`pledge`](https://docs.rs/priv_sep/latest/priv_sep/fn.pledge.html)
     81 /// does when compiled with the `priv_sep` feature which
     82 /// currently only works on OpenBSD-stable.
     83 #[cfg(feature = "std")]
     84 fn main() -> Result<(), Err> {
     85     /// Calls `pledge(2)` with the "stdio" promise.
     86     #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
     87     fn privsep() -> Result<(), Err> {
     88         Promises::new([Promise::Stdio])
     89             .pledge()
     90             .map_err(Err::Pledge)
     91     }
     92     /// Returns Ok.
     93     #[expect(
     94         clippy::unnecessary_wraps,
     95         reason = "consistent return type with priv_sep feature"
     96     )]
     97     #[cfg(not(all(feature = "priv_sep", target_os = "openbsd")))]
     98     const fn privsep() -> Result<(), Err> {
     99         Ok(())
    100     }
    101     privsep().and_then(|()| {
    102         let mut out = io::stdout().lock();
    103         EvalIter::new(io::stdin().lock()).lend_try_fold((), |(), res| {
    104             match res {
    105                 Ok(o) => writeln!(&mut out, "{o}"),
    106                 Err(e) => writeln!(&mut out, "{e}"),
    107             }
    108             .map_err(Err::Io)
    109         })
    110     })
    111 }