neo_mime/lib.rs
1#![doc(html_root_url = "https://docs.rs/neo-mime/0.1.1")]
2#![deny(warnings)]
3#![deny(missing_docs)]
4#![deny(missing_debug_implementations)]
5
6//! # MediaType and MediaRange
7//!
8//! The `mime` crate defines two major types for representing MIMEs in HTTP
9//! contexts:
10//!
11//! - A [`MediaType`](MediaType) is a concrete description of some content,
12//! such as `text/plain`.
13//! - A [`MediaRange`](MediaRange) is a range of types that an agent is willing
14//! to receive, such as `text/*`.
15//!
16//! ## Getting a `MediaType`
17//!
18//! There are several constants exported for common media types:
19//!
20//! ```
21//! let text = neo_mime::TEXT_PLAIN;
22//! let svg = neo_mime::IMAGE_SVG;
23//! let json = neo_mime::APPLICATION_JSON;
24//! // etc
25//! ```
26//!
27//! A [`MediaType`](MediaType) can also be parsed from a string, such as from
28//! a `Content-Type` HTTP header:
29//!
30//! ```
31//! match neo_mime::MediaType::parse("text/plain; charset=utf-8") {
32//! Ok(text) => assert_eq!(text, neo_mime::TEXT_PLAIN_UTF_8),
33//! Err(err) => panic!("you should handle this parse error: {}", err),
34//! }
35//! ```
36//!
37//! ## Inspecting `MediaType`s
38//!
39//! Once you have a `MediaType`, you can inspect the various parts of it.
40//! Since the `type_()` and `subtype()` methods return `&str`, you can make
41//! easy-to-read `match` statements to handle different media types. To prevent
42//! typos, many common type names are available as constants.
43//!
44//! ```
45//! let mime = neo_mime::TEXT_PLAIN;
46//! match (mime.type_(), mime.subtype()) {
47//! (neo_mime::TEXT, neo_mime::PLAIN) => println!("plain text!"),
48//! (neo_mime::TEXT, _) => println!("structured text"),
49//! _ => println!("not text"),
50//! }
51//! ```
52//!
53//! ## Using Media Ranges for matching
54//!
55//! [`MediaRange`](MediaRange)s are often used by agents to declare a "range"
56//! of media types that they can understand. A common place to find these is
57//! `Accept` HTTP header, perhaps like this:
58//!
59//! ```http
60//! GET /index.html HTTP/1.1
61//! Accept: text/html, text/*
62//! ```
63//!
64//! These can be parsed as `MediaRange`s, and then used to check if any of
65//! the `MediaType`s you have would satisfy them.
66//!
67//! ```
68//! match neo_mime::MediaRange::parse("text/*") {
69//! Ok(range) => {
70//! // There's a couple constants in case you don't need parsing...
71//! assert_eq!(range, neo_mime::TEXT_STAR);
72//!
73//! // "text/plain" is a match
74//! assert!(range.matches(&neo_mime::TEXT_PLAIN));
75//!
76//! // "application/json" is NOT
77//! assert!(!range.matches(&neo_mime::APPLICATION_JSON));
78//!
79//! },
80//! Err(err) => panic!("that's a bad range: {}", err),
81//! }
82//! ```
83#[cfg(feature = "macro")]
84use proc_macro_hack::proc_macro_hack;
85
86/// Compile-time `MediaType`s.
87///
88/// Performs validation and construction of a `MediaType` at compile-time,
89/// catching parse errors early, and allowing them to be used as constants
90/// or statics.
91///
92/// This requires the `macro` feature enabled on the mime crate. Something
93/// like this in your `Cargo.toml`:
94///
95/// ```toml
96/// [dependencies]
97/// mime = { version = "0.4", features = ["macro"] }
98/// ```
99///
100/// # Example
101///
102/// ```
103/// const VND_MYAPP: neo_mime::MediaType = neo_mime::media_type!("application/vnd.myapp+json");
104/// ```
105#[cfg(feature = "macro")]
106#[proc_macro_hack]
107pub use neo_mime_macro::media_type;
108
109pub use neo_mime_parse::constants::names::*;
110pub use self::constants::mimes::*;
111pub use self::error::InvalidMime;
112pub use self::range::MediaRange;
113pub use self::type_::MediaType;
114pub use self::value::{Value, UTF_8};
115
116mod cmp;
117mod constants;
118mod error;
119#[cfg(feature = "macro")]
120mod macros;
121mod range;
122#[cfg(feature = "serde")]
123mod serde;
124mod type_;
125mod value;
126
127
128fn _assert_traits() {
129 fn assert_send_sync<T: Send + Sync>() {}
130
131 assert_send_sync::<InvalidMime>();
132 assert_send_sync::<MediaRange>();
133 assert_send_sync::<MediaType>();
134 assert_send_sync::<Value>();
135}
136
137/// **DO NOT IMPORT THIS MODULE OR ITS TYPES.**
138///
139/// There is zero backwards-compatibility guarantee, your code *will* break.
140/// Kittens **will** die.
141#[doc(hidden)]
142#[cfg(feature = "macro")]
143pub mod private {
144 #[doc(hidden)]
145 pub use neo_mime_parse::{Mime, ParamSource, Source};
146}
147
148#[cfg_attr(not(debug_assertions), allow(unused))]
149fn is_ascii_lowercase(s: &str) -> bool {
150 !s.as_bytes().iter().any(u8::is_ascii_uppercase)
151}