use std::{collections::HashMap, error::Error}; use base64::Engine; use once_cell::sync::Lazy; use serde::de::IgnoredAny; use serde_json::Value; // decoders -- /// Defines Decoder for `contentEncoding`. #[derive(Clone, Copy)] pub struct Decoder { /// Name of the encoding pub name: &'static str, /// Decodes given string to bytes #[allow(clippy::type_complexity)] pub func: fn(s: &str) -> Result, Box>, } pub(crate) static DECODERS: Lazy> = Lazy::new(|| { let mut m = HashMap::<&'static str, Decoder>::new(); m.insert( "base64", Decoder { name: "base64", func: decode_base64, }, ); m }); fn decode_base64(s: &str) -> Result, Box> { Ok(base64::engine::general_purpose::STANDARD.decode(s)?) } // mediatypes -- /// Defines Mediatype for `contentMediaType`. #[derive(Clone, Copy)] pub struct MediaType { /// Name of this media-type as defined in RFC 2046. /// Example: `application/json` pub name: &'static str, /// whether this media type can be deserialized to json. If so it can /// be validated by `contentSchema` keyword. pub json_compatible: bool, /** Check whether `bytes` conforms to this media-type. Should return `Ok(Some(Value))` if `deserialize` is `true`, otherwise it can return `Ok(None)`. Ideally you could deserialize to `serde::de::IgnoredAny` if `deserialize` is `false` to gain some performance. `deserialize` is always `false` if `json_compatible` is `false`. */ #[allow(clippy::type_complexity)] pub func: fn(bytes: &[u8], deserialize: bool) -> Result, Box>, } pub(crate) static MEDIA_TYPES: Lazy> = Lazy::new(|| { let mut m = HashMap::<&'static str, MediaType>::new(); m.insert( "application/json", MediaType { name: "application/json", json_compatible: true, func: check_json, }, ); m }); fn check_json(bytes: &[u8], deserialize: bool) -> Result, Box> { if deserialize { return Ok(Some(serde_json::from_slice(bytes)?)); } serde_json::from_slice::(bytes)?; Ok(None) }