1#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
2 html_favicon_url = "https://www.rust-lang.org/favicon.ico",
3 html_root_url = "https://docs.rs/simple-error")]
4#![deny(missing_docs)]
5use std::fmt;
15
16#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
20pub struct SimpleError {
21 err: String,
22}
23
24impl SimpleError {
25 #[inline]
41 pub fn new<T: Into<String>>(t: T) -> SimpleError {
42 SimpleError{ err: t.into() }
43 }
44
45 #[inline]
61 pub fn from<T: std::error::Error>(t: T) -> SimpleError {
62 SimpleError{ err: format!("{t}") }
63 }
64
65 #[inline]
81 pub fn with<T: std::error::Error>(s: &str, t: T) -> SimpleError {
82 SimpleError{ err: format!("{s}, {t}") }
83 }
84
85 #[inline]
96 pub fn as_str(&self) -> &str {
97 &self.err
98 }
99}
100
101impl From<&str> for SimpleError {
105 #[inline]
106 fn from(s: &str) -> SimpleError {
107 SimpleError{ err: s.into() }
108 }
109}
110
111impl fmt::Display for SimpleError {
112 #[inline]
113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114 self.err.fmt(f)
115 }
116}
117
118impl std::error::Error for SimpleError {
119}
120
121pub type SimpleResult<T> = Result<T, SimpleError>;
123
124#[macro_export]
166macro_rules! try_with {
167 ($expr: expr, $fmt:literal) => (match $expr {
168 Ok(val) => val,
169 Err(err) => {
170 return Err(::std::convert::From::from($crate::SimpleError::with(&format!($fmt), err)));
171 },
172 });
173 ($expr: expr, $str: expr) => (match $expr {
174 Ok(val) => val,
175 Err(err) => {
176 return Err(::std::convert::From::from($crate::SimpleError::with($str.as_ref(), err)));
177 },
178 });
179 ($expr: expr, $fmt:literal, $($arg:tt)+) => (match $expr {
180 Ok(val) => val,
181 Err(err) => {
182 return Err(::std::convert::From::from($crate::SimpleError::with(&format!($fmt, $($arg)+), err)));
183 },
184 });
185}
186
187#[macro_export]
229macro_rules! require_with {
230 ($expr: expr, $fmt:literal) => (match $expr {
231 Some(val) => val,
232 None => {
233 return Err(::std::convert::From::from($crate::SimpleError::new(format!($fmt))));
234 },
235 });
236 ($expr: expr, $str: expr) => (match $expr {
237 Some(val) => val,
238 None => {
239 return Err(::std::convert::From::from($crate::SimpleError::new(::std::convert::AsRef::<str>::as_ref($str))));
240 },
241 });
242 ($expr: expr, $fmt:literal, $($arg:tt)+) => (match $expr {
243 Some(val) => val,
244 None => {
245 return Err(::std::convert::From::from($crate::SimpleError::new(format!($fmt, $($arg)+))));
246 },
247 });
248}
249
250#[macro_export]
290macro_rules! ensure_with {
291 ($cond: expr, $fmt:literal) => ({
292 if !$cond {
293 return Err(::std::convert::From::from($crate::SimpleError::new(format!($fmt))));
294 }
295 });
296 ($cond: expr, $str: expr) => ({
297 if !$cond {
298 return Err(::std::convert::From::from($crate::SimpleError::new(::std::convert::AsRef::<str>::as_ref($str))));
299 }
300 });
301 ($cond: expr, $fmt:literal, $($arg:tt)+) => ({
302 if !$cond {
303 return Err(::std::convert::From::from($crate::SimpleError::new(format!($fmt, $($arg)+))));
304 }
305 });
306}
307
308#[macro_export]
348macro_rules! bail {
349 ($fmt:literal) => {
350 return Err(::std::convert::From::from($crate::SimpleError::new(format!($fmt))))
351 };
352 ($e:expr) => {
353 return Err(::std::convert::From::from($e))
354 };
355 ($fmt:literal, $($arg:tt)+) => {
356 return Err(::std::convert::From::from($crate::SimpleError::new(format!($fmt, $($arg)+))))
357 };
358}
359
360#[macro_export]
382macro_rules! simple_error {
383 ($fmt:literal) => {
384 $crate::SimpleError::new(format!($fmt))
385 };
386 ($e:expr) => {
387 $crate::SimpleError::new($e)
388 };
389 ($fmt:literal, $($arg:tt)+) => {
390 $crate::SimpleError::new(format!($fmt, $($arg)+))
391 };
392}
393
394#[macro_export]
416macro_rules! map_err_with {
417 ($r: expr, $fmt:literal) => {
418 $r.map_err(|e| $crate::SimpleError::with(&format!($fmt), e))
419 };
420 ($r: expr, $str: expr) => {
421 $r.map_err(|e| $crate::SimpleError::with($str.as_ref(), e))
422 };
423 ($r: expr, $fmt:literal, $($arg:tt)+) => {
424 $r.map_err(|e| $crate::SimpleError::with(&format!($fmt, $($arg)+), e))
425 };
426}
427
428
429#[cfg(test)]
430mod tests {
431 use super::SimpleError;
432 use std::error::Error;
433 use std::io;
434
435 pub struct ErrorSeed;
436
437 impl From<ErrorSeed> for SimpleError {
438 fn from(_: ErrorSeed) -> SimpleError {
439 SimpleError::new(".")
440 }
441 }
442
443 #[test]
444 fn new_from_string() {
445 let err = SimpleError::new(String::from("an error from String"));
446 assert_eq!("an error from String", format!("{err}"));
447 }
448
449 #[test]
450 fn new_from_str() {
451 let err = SimpleError::new("an error from str");
452 assert_eq!("an error from str", format!("{err}"));
453 }
454
455 #[test]
456 fn new_from_simple_error_macro() {
457 let err = SimpleError::new("an error from str");
458 assert_eq!(SimpleError::new("an error from str"), simple_error!("{err}"));
459 }
460
461 #[test]
462 fn map_error_with_macro() {
463 let err = crate::SimpleResult::<()>::Err(SimpleError::new("an error from str"));
464 let additional_reason = "error in current function";
465 assert_eq!(Err(SimpleError::new("error in current function, an error from str")), map_err_with!(err, "{additional_reason}"));
466 }
467
468 #[test]
469 fn from_io_error() {
470 let err = SimpleError::from(io::Error::new(io::ErrorKind::Other, "oh no"));
471 assert_eq!("oh no", format!("{err}"));
472 }
473
474 fn try_block(result: Result<(), SimpleError>, s: &str) -> Result<(), SimpleError> {
475 let _: () = try_with!(result, s);
476 Ok(())
477 }
478
479 fn try_block_format(result: Result<(), SimpleError>, s: &str) -> Result<(), SimpleError> {
480 let _: () = try_with!(result, "with {}", s);
481 Ok(())
482 }
483
484 fn try_block_format_with_capture(result: Result<(), SimpleError>, s: &str) -> Result<(), SimpleError> {
485 let _: () = try_with!(result, "with {s}");
486 Ok(())
487 }
488
489 #[test]
490 fn macro_try_with() {
491 assert_eq!(Ok(()), try_block(Ok(()), ""));
492 assert_eq!(Err(SimpleError::new("try block error, error foo")), try_block(Err(SimpleError::new("error foo")), "try block error"));
493 assert_eq!(Err(SimpleError::new("with try block error, error foo")), try_block_format(Err(SimpleError::new("error foo")), "try block error"));
494 assert_eq!(Err(SimpleError::new("with try block error, error foo")), try_block_format_with_capture(Err(SimpleError::new("error foo")), "try block error"));
495 }
496
497 fn require_block(option: Option<()>, s: &str) -> Result<(), SimpleError> {
498 let _: () = require_with!(option, s);
499 Ok(())
500 }
501
502 fn require_block_str_as_ref(option: Option<()>, s: &String) -> Result<(), SimpleError> {
503 let _: () = require_with!(option, s);
504 Ok(())
505 }
506
507 fn require_block_format(maybe: Option<()>, s: &str) -> Result<(), SimpleError> {
508 let _: () = require_with!(maybe, "with {}", s);
509 Ok(())
510 }
511
512 fn require_block_format_with_capture(maybe: Option<()>, s: &str) -> Result<(), SimpleError> {
513 let _: () = require_with!(maybe, "with {s}");
514 Ok(())
515 }
516
517 #[test]
518 fn macro_require_with() {
519 assert_eq!(Ok(()), require_block(Some(()), ""));
520 assert_eq!(Err(SimpleError::new("require block error")), require_block(None, "require block error"));
521 assert_eq!(Err(SimpleError::new("require block error")), require_block_str_as_ref(None, &"require block error".to_owned()));
522 assert_eq!(Err(SimpleError::new("with require block error")), require_block_format(None, "require block error"));
523 assert_eq!(Err(SimpleError::new("with require block error")), require_block_format_with_capture(None, "require block error"));
524 }
525
526 fn ensure_block(cond: bool, s: &str) -> Result<(), SimpleError> {
527 ensure_with!(cond, s);
528 Ok(())
529 }
530
531 fn ensure_block_str_as_ref(cond: bool, s: &String) -> Result<(), SimpleError> {
532 ensure_with!(cond, s);
533 Ok(())
534 }
535
536 fn ensure_block_format(cond: bool, s: &str) -> Result<(), SimpleError> {
537 ensure_with!(cond, "with {}", s);
538 Ok(())
539 }
540
541 fn ensure_block_format_with_capture(cond: bool, s: &str) -> Result<(), SimpleError> {
542 ensure_with!(cond, "with {s}");
543 Ok(())
544 }
545
546 fn ensure_block_format_to_box_error(cond: bool, s: &str) -> Result<(), Box<dyn Error>> {
547 ensure_with!(cond, "with {}", s);
548 Ok(())
549 }
550
551 #[test]
552 fn macro_ensure_with() {
553 assert_eq!(Ok(()), ensure_block(true, ""));
554 assert_eq!(Err(SimpleError::new("ensure block error")), ensure_block(false, "ensure block error"));
555 assert_eq!(Err(SimpleError::new("ensure block error")), ensure_block_str_as_ref(false, &"ensure block error".to_owned()));
556 assert_eq!(Err(SimpleError::new("with ensure block error")), ensure_block_format(false, "ensure block error"));
557 assert_eq!(Err(SimpleError::new("with ensure block error")), ensure_block_format_with_capture(false, "ensure block error"));
558 assert!(ensure_block_format_to_box_error(false, "ensure block error").is_err());
559 }
560
561 fn bail_block_into(es: ErrorSeed) -> Result<(), SimpleError> {
562 bail!(es);
563 }
564
565 fn bail_block_str(s: &str) -> Result<(), SimpleError> {
566 bail!(s);
567 }
568
569 fn bail_block_format(s: &str) -> Result<(), SimpleError> {
570 bail!("reason: {}", s);
571 }
572
573 fn bail_block_format_with_capture(s: &str) -> Result<(), SimpleError> {
574 bail!("reason: {s}");
575 }
576
577 fn bail_block_format_to_box_error(s: &str) -> Result<(), Box<dyn Error>> {
578 bail!("reason: {}", s);
579 }
580
581 fn bail_match_arm(n: u8) -> Result<u8, SimpleError> {
582 match n {
583 0 => bail!("zero"),
584 1 => bail!("reason: {}", n),
585 2 => bail!(ErrorSeed),
586 n => Ok(n),
587 }
588 }
589
590 #[test]
591 fn macro_bail() {
592 assert_eq!(Err(SimpleError::new(".")), bail_block_into(ErrorSeed));
593 assert_eq!(Err(SimpleError::new("no reason")), bail_block_str("no reason"));
594 assert_eq!(Err(SimpleError::new("reason: plane crashed")), bail_block_format("plane crashed"));
595 assert!(bail_block_format_to_box_error("plane crashed").is_err());
596 assert_eq!(Err(SimpleError::new("zero")), bail_match_arm(0));
597 assert_eq!(Err(SimpleError::new("reason: 1")), bail_match_arm(1));
598 assert_eq!(Err(SimpleError::new(".")), bail_match_arm(2));
599 assert_eq!(Ok(3), bail_match_arm(3));
600 }
601
602 #[test]
603 fn inline_format_arg_capture() {
604 assert_eq!(Err(SimpleError::new("reason: plane crashed")), bail_block_format_with_capture("plane crashed"));
605 }
606}