Guest User

Untitled

a guest
Oct 23rd, 2019
92
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. use std::error::Error;
  2. use std::fmt;
  3. use std::str;
  4. use std::mem::MaybeUninit;
  5.  
  6. type DynError = dyn Error + Send + Sync + 'static;
  7.  
  8. #[derive(Debug, Default)]
  9. pub struct AggErr {
  10. errors: Vec<(&'static str, Box<DynError>)>,
  11. }
  12.  
  13. impl AggErr {
  14. pub fn new() -> Self {
  15. Default::default()
  16. }
  17.  
  18. pub fn len(&self) -> usize {
  19. self.errors.len()
  20. }
  21.  
  22. pub fn is_empty(&self) -> bool {
  23. self.errors.is_empty()
  24. }
  25.  
  26. #[doc(hidden)]
  27. pub fn add_result<T, E: Into<Box<DynError>>>(
  28. &mut self,
  29. binding: &'static str,
  30. r: Result<T, E>,
  31. ) -> MaybeUninit<T> {
  32. match r {
  33. Ok(x) => MaybeUninit::new(x),
  34. Err(e) => {
  35. self.errors.push((binding, e.into()));
  36. MaybeUninit::uninit()
  37. }
  38. }
  39. }
  40. }
  41.  
  42. impl Error for AggErr {}
  43.  
  44. impl fmt::Display for AggErr {
  45. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  46. write!(f, "{} errors:\n", self.len())?;
  47. for (b, e) in &self.errors {
  48. write!(f, " {}: {}\n", b, e)?;
  49. }
  50. Ok(())
  51. }
  52. }
  53.  
  54. macro_rules! validated {
  55. (let+ $($t:tt)*) => {
  56. validated!([] [] err => let+ $($t)*)
  57. };
  58.  
  59. (
  60. [$($pre:tt)*] [$($post:tt)*] $err:ident =>
  61. let+ $p:pat = $e:expr; $($rest:tt)*
  62. ) => {
  63. validated!(
  64. [
  65. $($pre)*
  66. let x = $err.add_result(stringify!($p), $e);
  67. ]
  68. [
  69. $($post)*
  70. let $p = unsafe { x.assume_init() };
  71. ]
  72. $err => $($rest)*
  73. )
  74. };
  75.  
  76. (
  77. [$($pre:tt)*] [$($post:tt)*] $err:ident =>
  78. $e:expr
  79. ) => {
  80. {
  81. let mut $err = $crate::AggErr::new();
  82. $($pre)*
  83. if $err.is_empty() {
  84. $($post)*
  85. Ok($e)
  86. } else {
  87. Err($err)
  88. }
  89. }
  90. };
  91. }
  92.  
  93. #[derive(Debug, PartialEq)]
  94. struct Validated<'a> {
  95. a: &'a str,
  96. b: &'a str,
  97. c: &'a str,
  98. }
  99.  
  100. fn main() {
  101. let res: Result<String, AggErr> = validated! {
  102. let+ a = str::from_utf8(b"yay");
  103. let+ b = str::from_utf8(b"wo\xffw");
  104. let+ c = str::from_utf8(b"\xff\xff");
  105. format!("{}, {}, {}", a, b, c)
  106. };
  107. eprintln!("{:?}", res);
  108.  
  109. let res: Result<Validated, AggErr> = validated! {
  110. let+ a = str::from_utf8(b"yay");
  111. let+ b = str::from_utf8(b"wow");
  112. let+ c = str::from_utf8(b"");
  113. Validated { a, b, c }
  114. };
  115. eprintln!("{:?}", res);
  116. }
RAW Paste Data