use std::borrow::Cow;
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Format(pub Cow<'static, str>);
impl Format {
pub const JSON: Format = Format(Cow::Borrowed("application/json"));
pub const VALUE_JSON: Format = Format(Cow::Borrowed(
"application/vnd.structfs.value+json;version=1",
));
pub const PROTOBUF: Format = Format(Cow::Borrowed("application/protobuf"));
pub const MSGPACK: Format = Format(Cow::Borrowed("application/msgpack"));
pub const CBOR: Format = Format(Cow::Borrowed("application/cbor"));
pub const FLEXBUFFERS: Format = Format(Cow::Borrowed("application/x-flexbuffers"));
pub const OCTET_STREAM: Format = Format(Cow::Borrowed("application/octet-stream"));
pub const VALUE: Format = Format(Cow::Borrowed("application/x-structfs-value"));
pub const fn from_static(s: &'static str) -> Self {
Format(Cow::Borrowed(s))
}
pub fn new(s: impl Into<String>) -> Self {
Format(Cow::Owned(s.into()))
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn is_json(&self) -> bool {
self == &Self::JSON
}
pub fn is_protobuf(&self) -> bool {
self == &Self::PROTOBUF
}
pub fn is_value(&self) -> bool {
self == &Self::VALUE
}
}
impl fmt::Display for Format {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<&'static str> for Format {
fn from(s: &'static str) -> Self {
Format(Cow::Borrowed(s))
}
}
impl From<String> for Format {
fn from(s: String) -> Self {
Format(Cow::Owned(s))
}
}
impl AsRef<str> for Format {
fn as_ref(&self) -> &str {
&self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn constants_work() {
assert_eq!(Format::JSON.as_str(), "application/json");
assert!(Format::JSON.is_json());
assert!(!Format::JSON.is_protobuf());
}
#[test]
fn custom_formats() {
let f = Format::new("application/x-custom");
assert_eq!(f.as_str(), "application/x-custom");
}
#[test]
fn equality() {
assert_eq!(Format::JSON, Format::from("application/json"));
assert_eq!(Format::JSON, Format::new("application/json".to_string()));
}
#[test]
fn from_static() {
let f = Format::from_static("text/plain");
assert_eq!(f.as_str(), "text/plain");
}
#[test]
fn is_protobuf() {
assert!(Format::PROTOBUF.is_protobuf());
assert!(!Format::JSON.is_protobuf());
}
#[test]
fn is_value() {
assert!(Format::VALUE.is_value());
assert!(!Format::JSON.is_value());
}
#[test]
fn display_impl() {
let f = Format::JSON;
assert_eq!(format!("{}", f), "application/json");
let custom = Format::new("text/html");
assert_eq!(format!("{}", custom), "text/html");
}
#[test]
fn from_string() {
let owned = String::from("application/xml");
let f: Format = owned.into();
assert_eq!(f.as_str(), "application/xml");
}
#[test]
fn as_ref_str() {
let f = Format::CBOR;
let s: &str = f.as_ref();
assert_eq!(s, "application/cbor");
}
#[test]
fn hash_works() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(Format::JSON);
set.insert(Format::PROTOBUF);
set.insert(Format::JSON);
assert_eq!(set.len(), 2);
assert!(set.contains(&Format::JSON));
assert!(set.contains(&Format::PROTOBUF));
}
#[test]
fn all_constants() {
assert_eq!(Format::MSGPACK.as_str(), "application/msgpack");
assert_eq!(Format::CBOR.as_str(), "application/cbor");
assert_eq!(Format::FLEXBUFFERS.as_str(), "application/x-flexbuffers");
assert_eq!(Format::OCTET_STREAM.as_str(), "application/octet-stream");
assert_eq!(Format::VALUE.as_str(), "application/x-structfs-value");
}
#[test]
fn clone_works() {
let f1 = Format::new("custom/format");
let f2 = f1.clone();
assert_eq!(f1, f2);
}
#[test]
fn debug_impl() {
let f = Format::JSON;
let debug = format!("{:?}", f);
assert!(debug.contains("application/json"));
}
}