SHARE
TWEET

Untitled

a guest Oct 23rd, 2019 77 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
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top