diff rust/src/types.rs @ 611:f3e39e2107fd rust

still doesn't compile, improvements to TemplogError and tokio curl though
author Matt Johnston <matt@ucc.asn.au>
date Tue, 28 Feb 2017 22:58:47 +0800
parents af0dac00d40b
children 5fc41e0833b4
line wrap: on
line diff
--- a/rust/src/types.rs	Thu Feb 23 23:27:09 2017 +0800
+++ b/rust/src/types.rs	Tue Feb 28 22:58:47 2017 +0800
@@ -2,11 +2,17 @@
 use std::time::{Duration,Instant};
 use std::error::Error;
 use std::fmt;
+use std::io;
 use std::cmp;
 use std::cell::Cell;
 use std::iter::FromIterator;
+use std;
 
+use futures::{Stream,IntoFuture};
 use serde::{Deserialize,Serialize};
+use toml;
+use curl;
+use serde_json;
 
 #[derive(Deserialize, Serialize, Debug)]
 pub struct Params {
@@ -77,34 +83,128 @@
 }
 
 #[derive(Debug)]
+pub enum TemplogErrorKind {
+    None,
+    Io(io::Error),
+    ParseFloat(std::num::ParseFloatError),
+    TomlDe(toml::de::Error),
+    SerdeJson(serde_json::Error),
+    Curl(curl::Error),
+}
+
+#[derive(Debug)]
 pub struct TemplogError {
     desc: String,
+    kind: TemplogErrorKind,
 }
 
 impl Error for TemplogError {
-    fn description(&self) -> &str { &self.desc }
-    fn cause(&self) -> Option<&Error> { None }
+    fn description(&self) -> &str { 
+        &format!("{}", self)
+    }
+
+    fn cause(&self) -> Option<&Error> { 
+        match self.kind {
+            TemplogErrorKind::None => None,
+            TemplogErrorKind::Io(e) => Some(&e),
+            TemplogErrorKind::ParseFloat(e) => Some(&e),
+            TemplogErrorKind::TomlDe(e) => Some(&e),
+            TemplogErrorKind::SerdeJson(e) => Some(&e),
+            TemplogErrorKind::Curl(e) => Some(&e),
+        }
+    }
 }
 
 impl fmt::Display for TemplogError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TemplogError: {}", self.desc);
+        match self.kind {
+            TemplogErrorKind::None => write!(f, "Templog Error: {}", self.desc),
+            TemplogErrorKind::Io(e) => write!(f, "Templog IO error {}: {}", self.desc, e),
+            TemplogErrorKind::TomlDe(e) => write!(f, "Templog toml error {}: {}", self.desc, e),
+            TemplogErrorKind::SerdeJson(e) => write!(f, "Json decode error {}: {}", self.desc, e),
+            TemplogErrorKind::ParseFloat(e) => write!(f, "Templog parse error {}: {}", self.desc, e),
+            TemplogErrorKind::Curl(e) => write!(f, "Templog curl http error {}: {}", self.desc, e),
+        };
         Ok(())
     }
-
-
 }
 
 impl TemplogError {
     pub fn new(desc: &str) -> Self {
         TemplogError { 
             desc: desc.to_string(),
+            kind: TemplogErrorKind::None,
+        }
+    }
+
+    pub fn new_io(desc: &str, e: io::Error) -> Self {
+        TemplogError { 
+            desc: desc.to_string(),
+            kind: TemplogErrorKind::Io(e),
+        }
+    }
+
+    pub fn new_toml_de(desc: &str, e: toml::de::Error) -> Self {
+        TemplogError { 
+            desc: desc.to_string(),
+            kind: TemplogErrorKind::TomlDe(e),
+        }
+    }
+
+    pub fn new_parse_float(desc: &str, e: std::num::ParseFloatError) -> Self {
+        TemplogError { 
+            desc: desc.to_string(),
+            kind: TemplogErrorKind::ParseFloat(e),
+        }
+    }
+
+    pub fn new_curl(desc: &str, e: curl::Error) -> Self {
+        TemplogError { 
+            desc: desc.to_string(),
+            kind: TemplogErrorKind::Curl(e),
+        }
+    }
+
+    pub fn new_serde_json(desc: &str, e: serde_json::Error) -> Self {
+        TemplogError { 
+            desc: desc.to_string(),
+            kind: TemplogErrorKind::SerdeJson(e),
         }
     }
 }
 
+impl From<io::Error> for TemplogError {
+    fn from(e: io::Error) -> Self {
+        TemplogError::new_io("", e)
+    }
+}
+
+impl From<toml::de::Error> for TemplogError {
+    fn from(e: toml::de::Error) -> Self {
+        TemplogError::new_toml_de("", e)
+    }
+}
+
+impl From<std::num::ParseFloatError> for TemplogError {
+    fn from(e: std::num::ParseFloatError) -> Self {
+        TemplogError::new_parse_float("", e)
+    }
+}
+
+impl From<curl::Error> for TemplogError {
+    fn from(e: curl::Error) -> Self {
+        TemplogError::new_curl("", e)
+    }
+}
+
+impl From<serde_json::Error> for TemplogError {
+    fn from(e: serde_json::Error) -> Self {
+        TemplogError::new_serde_json("", e)
+    }
+}
 
 /// Call closures with a rate limit. Useful for log message ratelimiting
+#[derive(Clone)]
 pub struct NotTooOften {
     last: Cell<Instant>,
     limit: Duration,
@@ -200,3 +300,22 @@
     }
 }
 
+/// Takes a stream and returns a stream without errors.
+pub fn consume_errors<S>(s: S) -> Box<Stream<Item=S::Item, Error=S::Error>> 
+// XXX not sure why 'static is really necessary here?
+    where 
+    S: Stream+Send+'static, 
+    <S as Stream>::Error: std::fmt::Display+Send+'static,
+    <S as Stream>::Item: Send+'static,
+    {
+    s.then(|r| {
+        match r {
+            Ok(v) => Ok(Some(v)),
+            Err(e) => {
+                debug!("Stream error: {}", e);
+                Ok(None)
+            }
+        }
+    })
+    .filter_map(|p| p).boxed()
+}