use std::fmt; use rocket::{request::FromParam, TypedError, catcher::TypedError}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DotJson(T); impl std::ops::Deref for DotJson { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Debug, TypedError)] pub enum FormatError { MissingFormat(&'static [&'static str]), Parse(T), } impl<'a, T: FromParam<'a>> FromParam<'a> for DotJson where T::Error: TypedError<'a> + fmt::Debug + 'static, { type Error = FormatError; fn from_param(param: &'a str) -> Result { param .strip_suffix(".json") .ok_or(FormatError::MissingFormat(&["json"])) .and_then(|s| T::from_param(s).map_err(FormatError::Parse)) .map(Self) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum FormatType { Json, Opml, Jsonp, Text, Xml, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Format(T, FormatType); impl Format { pub fn format(&self) -> FormatType { self.1 } } impl std::ops::Deref for Format { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } impl<'a, T: FromParam<'a>> FromParam<'a> for Format where T::Error: TypedError<'a> + fmt::Debug + 'static, { type Error = FormatError; fn from_param(param: &'a str) -> Result { // TODO: Support other formats if let Some(s) = param .strip_suffix(".json") { T::from_param(s).map_err(FormatError::Parse) .map(|v| Self(v, FormatType::Json)) } else { Err(FormatError::MissingFormat(&["json"])) } } }