1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
//! Library that exposes [`Termination`][1] trait, similar to [`std::process::Termination`][2]. //! //! [`Examples`][3]. //! //! [1]: trait.Termination.html //! [2]: https://doc.rust-lang.org/std/process/trait.Termination.html //! [3]: attr.display.html#examples /// Procedural macro that allows `main` return values to use [`Display`][1] instead of /// [`Debug`][2]. /// /// Any form of `fn main() -> _` should produce practically identical results with, /// or without this annotation, the only difference being the trait used to format the error /// values for printing. /// /// Additionally, [`Termination`][3], (not to be confused with [`std::process::Termination`][4]) is /// used by the annotated `main` instead. /// /// # Examples /// /// Functions that return unit type work the same. /// /// ``` /// #[termination::display] /// fn main() -> () { /// () /// } /// ``` /// /// It is possible to directly return exit code. /// /// ``` /// #[termination::display] /// fn main() -> i32 { /// 0 /// } /// ``` /// /// Default implementation of `Termination` for `Result<(), E> where E: Display` prints error to /// `stderr`, and returns appropriate error code to the operating system. /// /// ```no_run /// #[termination::display] /// fn main() -> Result<(), &'static str> { /// Err("Error: failed successfully.") /// } /// ``` /// /// It is still possible to use `!` as a return type; modified `main` never returns, therefore /// macro-generated code will most likely be stripped out by compiler. /// /// ``` /// #[termination::display] /// fn main() -> ! { /// std::process::exit(0); /// } /// ``` /// /// Custom implementations also are possible. /// /// ```no_run /// use termination::{display, Termination}; /// /// struct HelloWorld; /// /// impl Termination for HelloWorld { /// fn report(self) -> i32 { /// println!("Hello world!"); /// 42 /// } /// } /// /// #[display] /// fn main() -> HelloWorld { /// HelloWorld /// } /// ``` /// /// [1]: https://doc.rust-lang.org/std/fmt/trait.Display.html /// [2]: https://doc.rust-lang.org/std/fmt/trait.Debug.html /// [3]: trait.Termination.html /// [4]: https://doc.rust-lang.org/std/process/trait.Termination.html pub use termination_attrib::display; use std::fmt::Display; /// Code signaling successful termination of the process. /// /// Note that a `()`-returning `main` implicitly results in a successful /// termination, so there's no need to return this from `main` unless /// you're also returning other possible codes. pub const EXIT_SUCCESS: i32 = 0; /// Code signaling unsuccessful termination of the process. /// /// If you're only returning this and [`SUCCESS`][1] from `main`, consider /// instead returning [`Err(E)`][2] and [`Ok(())`][3] respectively, which will /// return the same codes (but will also [`eprintln!`][4] the error). /// /// [1]: constant.EXIT_SUCCESS.html /// [2]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err /// [3]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok /// [4]: https://doc.rust-lang.org/std/macro.eprintln.html pub const EXIT_FAILURE: i32 = 1; /// A trait for implementing arbitrary return types in the `main` function. /// /// The C-main function only supports to return integers as return type. /// So, every type implementing the `Termination` trait has to be converted /// to an integer. /// /// The default implementations are returning [`SUCCESS`][1] to indicate /// a successful execution. In case of a failure, [`FAILURE`][2] is returned. /// /// [1]: constant.EXIT_SUCCESS.html /// [2]: constant.EXIT_FAILURE.html pub trait Termination { /// Is called to get the representation of the value as status code. /// This status code is returned to the operating system. fn report(self) -> i32; } impl Termination for () { /// Always returns [`SUCCESS`][1]. /// /// [1]: constant.EXIT_SUCCESS.html fn report(self) -> i32 { EXIT_SUCCESS.report() } } impl Termination for i32 { /// Returns exact value that [`i32`][1] holds. /// /// [1]: https://doc.rust-lang.org/std/primitive.i32.html fn report(self) -> i32 { self } } impl<E: Display> Termination for Result<(), E> { /// Returns [`SUCCESS`][1] for [`Ok(())`][2], [`FAILURE`][3] for [`Err(E)`][4]. /// /// [1]: constant.EXIT_SUCCESS.html /// [2]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok /// [3]: constant.EXIT_FAILURE.html /// [4]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err fn report(self) -> i32 { match self { Ok(()) => ().report(), Err(e) => { eprintln!("{}", e); EXIT_FAILURE.report() }, } } }