1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#![doc(html_root_url = "https://docs.rs/neo-mime/0.1.1")]
#![deny(warnings)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

//! # MediaType and MediaRange
//!
//! The `mime` crate defines two major types for representing MIMEs in HTTP
//! contexts:
//!
//! - A [`MediaType`](MediaType) is a concrete description of some content,
//!   such as `text/plain`.
//! - A [`MediaRange`](MediaRange) is a range of types that an agent is willing
//!   to receive, such as `text/*`.
//!
//! ## Getting a `MediaType`
//!
//! There are several constants exported for common media types:
//!
//! ```
//! let text = neo_mime::TEXT_PLAIN;
//! let svg = neo_mime::IMAGE_SVG;
//! let json = neo_mime::APPLICATION_JSON;
//! // etc
//! ```
//!
//! A [`MediaType`](MediaType) can also be parsed from a string, such as from
//! a `Content-Type` HTTP header:
//!
//! ```
//! match neo_mime::MediaType::parse("text/plain; charset=utf-8") {
//!     Ok(text) => assert_eq!(text, neo_mime::TEXT_PLAIN_UTF_8),
//!     Err(err) => panic!("you should handle this parse error: {}", err),
//! }
//! ```
//!
//! ## Inspecting `MediaType`s
//!
//! Once you have a `MediaType`, you can inspect the various parts of it.
//! Since the `type_()` and `subtype()` methods return `&str`, you can make
//! easy-to-read `match` statements to handle different media types. To prevent
//! typos, many common type names are available as constants.
//!
//! ```
//! let mime = neo_mime::TEXT_PLAIN;
//! match (mime.type_(), mime.subtype()) {
//!     (neo_mime::TEXT, neo_mime::PLAIN) => println!("plain text!"),
//!     (neo_mime::TEXT, _) => println!("structured text"),
//!     _ => println!("not text"),
//! }
//! ```
//!
//! ## Using Media Ranges for matching
//!
//! [`MediaRange`](MediaRange)s are often used by agents to declare a "range"
//! of media types that they can understand. A common place to find these is
//! `Accept` HTTP header, perhaps like this:
//!
//! ```http
//! GET /index.html HTTP/1.1
//! Accept: text/html, text/*
//! ```
//!
//! These can be parsed as `MediaRange`s, and then used to check if any of
//! the `MediaType`s you have would satisfy them.
//!
//! ```
//! match neo_mime::MediaRange::parse("text/*") {
//!     Ok(range) => {
//!         // There's a couple constants in case you don't need parsing...
//!         assert_eq!(range, neo_mime::TEXT_STAR);
//!
//!         // "text/plain" is a match
//!         assert!(range.matches(&neo_mime::TEXT_PLAIN));
//!
//!         // "application/json" is NOT
//!         assert!(!range.matches(&neo_mime::APPLICATION_JSON));
//!
//!     },
//!     Err(err) => panic!("that's a bad range: {}", err),
//! }
//! ```
#[cfg(feature = "macro")]
use proc_macro_hack::proc_macro_hack;

/// Compile-time `MediaType`s.
///
/// Performs validation and construction of a `MediaType` at compile-time,
/// catching parse errors early, and allowing them to be used as constants
/// or statics.
///
/// This requires the `macro` feature enabled on the mime crate. Something
/// like this in your `Cargo.toml`:
///
/// ```toml
/// [dependencies]
/// mime = { version = "0.4", features = ["macro"] }
/// ```
///
/// # Example
///
/// ```
/// const VND_MYAPP: neo_mime::MediaType = neo_mime::media_type!("application/vnd.myapp+json");
/// ```
#[cfg(feature = "macro")]
#[proc_macro_hack]
pub use neo_mime_macro::media_type;

pub use neo_mime_parse::constants::names::*;
pub use self::constants::mimes::*;
pub use self::error::InvalidMime;
pub use self::range::MediaRange;
pub use self::type_::MediaType;
pub use self::value::{Value, UTF_8};

mod cmp;
mod constants;
mod error;
#[cfg(feature = "macro")]
mod macros;
mod range;
#[cfg(feature = "serde")]
mod serde;
mod type_;
mod value;


fn _assert_traits() {
    fn assert_send_sync<T: Send + Sync>() {}

    assert_send_sync::<InvalidMime>();
    assert_send_sync::<MediaRange>();
    assert_send_sync::<MediaType>();
    assert_send_sync::<Value>();
}

/// **DO NOT IMPORT THIS MODULE OR ITS TYPES.**
///
/// There is zero backwards-compatibility guarantee, your code *will* break.
/// Kittens **will** die.
#[doc(hidden)]
#[cfg(feature = "macro")]
pub mod private {
    #[doc(hidden)]
    pub use neo_mime_parse::{Mime, ParamSource, Source};
}

#[cfg_attr(not(debug_assertions), allow(unused))]
fn is_ascii_lowercase(s: &str) -> bool {
    !s.as_bytes().iter().any(u8::is_ascii_uppercase)
}