use std::fmt; use std::borrow::Cow; use rocket::request::{FromParam,FromFormValue}; use rocket::http::RawStr; use adjective_adjective_animal::Generator; use serde::{Deserialize, Serialize}; /// A _probably_ unique paste ID. #[derive(Deserialize, Serialize, Debug)] pub struct PasteID<'a>(Cow<'a, str>); impl<'a> PasteID<'a> { /// Generate a _probably_ unique ID with `size` characters. For readability, /// the characters used are from the sets [0-9], [A-Z], [a-z]. The /// probability of a collision depends on the value of `size` and the number /// of IDs generated thus far. pub fn new() -> PasteID<'static> { let mut generator = Generator::default(); PasteID(Cow::Owned(generator.next().unwrap())) } pub fn of(s : &'a str) -> PasteID<'a> { PasteID(Cow::Borrowed(s)) } } impl<'a> fmt::Display for PasteID<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) } } /// Returns `true` if `id` is a valid paste ID and `false` otherwise. fn valid_id(id: &str) -> bool { id.len() > 3 && id.chars().all(|c| { (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') }) } /// Returns an instance of `PasteID` if the path segment is a valid ID. /// Otherwise returns the invalid ID as the `Err` value. impl<'a> FromParam<'a> for PasteID<'a> { type Error = &'a RawStr; fn from_param(param: &'a RawStr) -> Result, &'a RawStr> { match valid_id(param) { true => Ok(PasteID(Cow::Borrowed(param))), false => Err(param) } } } impl<'a> FromFormValue<'a> for PasteID<'a> { type Error = &'a RawStr; fn from_form_value(param: &'a RawStr) -> Result, &'a RawStr> { match valid_id(param) { true => Ok(PasteID(Cow::Borrowed(param))), false => Err(param) } } }