aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs47
1 files changed, 41 insertions, 6 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 45add28..26be932 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,10 +15,12 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use chrono::{ DateTime, Utc };
-use serde::Deserialize;
+use serde::{ Deserialize, Deserializer };
use serde_json;
-use std::io::{ BufRead, Result };
+use std::io::{ self, BufRead };
use std::net::IpAddr;
+use std::result::Result;
+use std::str::FromStr;
#[derive(Deserialize)]
pub struct PhishTank {
@@ -27,13 +29,18 @@ pub struct PhishTank {
#[derive(Deserialize)]
pub struct Phish {
- pub phish_id: String,
+ #[serde(deserialize_with = "deserialize_number")]
+ pub phish_id: u64,
pub url: String,
pub phish_detail_url: String,
pub submission_time: DateTime<Utc>,
- pub verified: String,
+
+ #[serde(deserialize_with = "deserialize_yesno")]
+ pub verified: bool,
pub verified_time: Option<DateTime<Utc>>,
- pub online: String,
+
+ #[serde(deserialize_with = "deserialize_yesno")]
+ pub online: bool,
pub target: String,
pub details: Vec<PhishDetails>,
}
@@ -48,7 +55,35 @@ pub struct PhishDetails {
pub detail_time: DateTime<Utc>,
}
-pub fn load_phistank<R: BufRead>(input: R) -> Result<PhishTank> {
+pub fn load_phistank<R: BufRead>(input: R) -> Result<PhishTank, io::Error> {
let phishes = serde_json::from_reader(input)?;
Ok(PhishTank { phishes })
}
+
+// Helper function to deserialize a number represented as a string.
+//
+// The PhishTank dataset represents numbers this way, so the default
+// json deserializer implementation will only deserialize to a string.
+//
+fn deserialize_number<'de, D>(d: D) -> Result<u64, D::Error>
+ where D: Deserializer<'de>
+{
+ let s = String::deserialize(d)?;
+ u64::from_str(&s).map_err(serde::de::Error::custom)
+}
+
+// Helper function to deserialize "yes/no" into a bool.
+//
+// The PhishTank dataset uses the strings "yes" and "no" to represent
+// boolean values. This function helps us deserialize back into a proper
+// bool.
+//
+fn deserialize_yesno<'de, D>(d: D) -> Result<bool, D::Error>
+ where D: Deserializer<'de>
+{
+ match String::deserialize(d)?.as_ref() {
+ "yes" => Ok(true),
+ "no" => Ok(false),
+ _ => Err(serde::de::Error::custom("Expected \"yes\" or \"no\"."))
+ }
+}