twemoji_assets/
lib.rs

1#![warn(missing_docs)]
2#![warn(rustdoc::missing_crate_level_docs)]
3
4//! A sophisticated crate that provides the assets from Twemoji.
5//!
6//! [Twemoji](https://github.com/jdecked/twemoji) used to be an open-source project by Twitter that
7//! provided Recommended for General Interchange (RGI) emoji images in both SVG and PNG formats.
8//! Since the acquisition of Twitter by Elon Musk, the project has moved to its original creators
9//! ([source](https://github.com/jdecked/twemoji/issues/10)).
10//! This crate makes it easy to use these assets in Rust projects.
11//!
12//! The PNGs are embedded using the [`include_bytes`] macro and the SVGs are
13//! embedded using the [`include_str`] macro.
14//! Assets can be accessed either by their Unicode representation in the [`svg::codes`]
15//! and [`png::codes`] modules or by their human-readable names from
16//! [Emojibase](https://github.com/milesj/emojibase) in the [`svg::names`] and
17//! [`png::names`] modules.
18//! The `from_emoji` and `from_name` methods in the [`SvgTwemojiAsset`](svg::SvgTwemojiAsset) and
19//! [`PngTwemojiAsset`](png::PngTwemojiAsset) modules provide convenient ways to select the correct
20//! asset at runtime, and the crate's macros allow the selection of the right emojis at compile
21//! time.
22//!
23//! # Feature Flags
24//!
25//! For a better documentation experience, it is recommended to use the search feature.
26//! Additionally, you can
27//! [locally generate documentation](https://doc.rust-lang.org/cargo/commands/cargo-doc.html)
28//! and select the appropriate features to declutter the search results and improve results found
29//! by IntelliSense.
30//! This crate uses three feature flags: `svg`, `png`, and `names`.
31//! The `svg` and `png` flags include the respective file formats, while the `names` flag includes
32//! the modules with human-readable names provided by Emojibase.
33//! By default, the `svg` and `names` flags are selected.
34//!
35//! # Example
36//!
37//! Here's a simple example that shows how to use this crate to retrieve the SVG and PNG assets for
38//! the 🦆 (duck) emoji:
39//!
40//! ```
41//! use twemoji_assets::svg::SvgTwemojiAsset;
42//!
43//! let svg_asset: &SvgTwemojiAsset = SvgTwemojiAsset::from_emoji("🦆").unwrap();
44//! let svg_data: &str = &svg_asset;
45//! println!("SVG data for 🦆: {:?}", svg_data);
46//!
47//! #[cfg(feature = "png")]
48//! {
49//!     use twemoji_assets::png::PngTwemojiAsset;
50//!
51//!     let png_asset: &PngTwemojiAsset = PngTwemojiAsset::from_emoji("🦆").unwrap();
52//!     let png_data: &[u8] = &png_asset;
53//!     println!("PNG data for 🦆: {:?}", png_data);
54//! }
55//! ```
56//!
57//! # Usage
58//!
59//! This crate does not provide any direct methods for utilizing the Twemoji assets.
60//! The following additional crates may be necessary to take full advantage of these emoji graphics:
61//! - [`image`](https://crates.io/crates/image) for PNG image manipulation
62//! - [`resvg`](https://crates.io/crates/resvg) for SVG rendering
63//! - [`unicode-segmentation`](https://crates.io/crates/unicode-segmentation)
64//!   for splitting words into Unicode graphemes
65//! - [`emoji`](https://crates.io/crates/emoji) for working with emojis, which can later be
66//!   converted to Twemoji assets
67//!
68//! # Version Scheme
69//!
70//! This crate follows the semantic versioning scheme as required by the
71//! [Rust documentation](https://doc.rust-lang.org/cargo/reference/semver.html).
72//! The version number is represented as `x.y.z+a.b.c`, where `x.y.z` is the version of the crate
73//! and `a.b.c` is the version of the integrated Twemoji assets.
74//! The `+` symbol is used to separate the two version numbers.
75//! The version of the crate may increase without a corresponding increase in the version of the
76//! integrated Twemoji assets, however, whenever the Twemoji assets are updated and new assets are
77//! added, the crate version will at least increase in the minor value (`y`).
78//!
79//! # Licensing
80//!
81//! The codebase and names provided by Emojibase for this crate are licensed under the MIT License
82//! and the included graphics are licensed by Twitter (Copyright 2020 Twitter, Inc and other
83//! contributors) under the
84//! [Creative Commons Attribution 4.0 International (CC-BY 4.0) license](https://creativecommons.org/licenses/by/4.0/).
85//! Proper attribution must be given to Twitter and other contributors if these graphics are used
86//! or modified.
87//!
88//! # Comparison to twemoji-rs
89//!
90//! Another crate with similar goals to this crate is
91//! [`twemoji-rs`](https://crates.io/crates/twemoji-rs).
92//! It also provides the assets from Twemoji and makes them easily available, but instead of
93//! directly including them, it finds the paths for the particular graphic.
94//!
95//! Pros:
96//! - Assets may be lazy loaded.
97//! - Simpler API than this crate.
98//!
99//! Cons:
100//! - Deployment is not possible on a device the application is not built on, as the paths are
101//!   absolute from the directory the app was built in.
102//! - Assets are not part of the built binary, making deployment even more challenging.
103//! - `twemoji-rs` only supports PNG.
104//! - `twemoji-rs` has no overview of all available Twemojis.
105
106use std::cmp::Ordering;
107use std::hash::{Hash, Hasher};
108
109#[cfg(feature = "svg")]
110pub mod svg;
111
112#[cfg(feature = "png")]
113pub mod png;
114
115/// Wrapper struct for the Twemoji assets.
116///
117/// This struct is the generic form of the Twemoji asset wrapper.
118/// The specific implementations of this struct, [`SvgTwemojiAsset`](svg::SvgTwemojiAsset) and
119/// [`PngTwemojiAsset`](png::PngTwemojiAsset), provide specialized variants for handling SVGs and
120/// PNGs respectively.
121///
122/// The generic `TwemojiAsset<T>` is mostly used for implementing traits and provides common
123/// functionality, while both the specific variants implement the [`Deref`](std::ops::Deref)
124/// trait to allow direct access to the underlying asset data stored in the `data` field.
125/// This makes it convenient to work with the asset data as if it were a simple reference to the
126/// raw data.
127#[allow(clippy::derive_ord_xor_partial_ord)]
128#[derive(Eq, Ord)]
129pub struct TwemojiAsset<T> {
130    /// The underlying image data of the Twemoji asset.
131    pub data: T,
132    /// A string slice representing the emoji character.
133    pub emoji: &'static str,
134    /// An optional string slice representing the label of the emoji provide by Emojibase.
135    pub label: Option<&'static str>,
136}
137
138impl<T> PartialEq for TwemojiAsset<T> {
139    fn eq(&self, other: &Self) -> bool {
140        self.emoji.eq(other.emoji)
141    }
142}
143
144impl<T> PartialOrd for TwemojiAsset<T> {
145    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
146        self.emoji.partial_cmp(other.emoji)
147    }
148}
149
150impl<T> Hash for TwemojiAsset<T> {
151    fn hash<H: Hasher>(&self, state: &mut H) {
152        self.emoji.hash(state)
153    }
154}
155
156// dummy macros for docs
157
158/// Inserts a [`SvgTwemojiAsset`](svg::SvgTwemojiAsset) for a given emoji string literal.
159///
160/// The `svg_twemoji_asset!` macro takes a string literal of an emoji, such as `"🦆"`, and yields
161/// the `&SvgTwemojiAsset` for the [🦆 emoji asset](svg::codes::U_1F986).
162/// If the emoji asset is unknown for the given literal, the compilation will fail.
163///
164/// # Example
165///
166/// Example for 🦆 (duck):
167/// ```
168/// use twemoji_assets::svg_twemoji_asset;
169///
170/// let duck = svg_twemoji_asset!("🦆");
171/// println!("SVG data for 🦆: {:?}", duck);
172/// ```
173#[cfg(all(doc, feature = "svg"))]
174#[macro_export]
175macro_rules! svg_twemoji_asset {
176    ($emoji:literal) => {};
177}
178
179/// Inserts a [`SvgTwemojiAsset`](svg::SvgTwemojiAsset) from a string literal of an emoji name.
180///
181/// The `svg_twemoji_asset_from_name!` macro takes a string literal of an emoji name, such as
182/// `"duck"`, and yields the `&SvgTwemojiAsset` for the corresponding
183/// [🦆 emoji asset](svg::codes::U_1F986).
184/// The names are provided by [Emojibase](https://github.com/milesj/emojibase).
185/// If the name or the corresponding emoji asset is unknown for the given literal, the compilation will fail.
186///
187/// # Example
188///
189/// Example for 🦆 (duck):
190/// ```
191/// use twemoji_assets::svg_twemoji_asset_from_name;
192///
193/// let duck = svg_twemoji_asset_from_name!("duck");
194/// println!("SVG data for 🦆: {:?}", duck);
195/// ```
196#[cfg(all(doc, feature = "svg", feature = "names"))]
197#[macro_export]
198macro_rules! svg_twemoji_asset_from_name {
199    ($emoji:literal) => {};
200}
201
202/// Inserts a [`PngTwemojiAsset`](png::PngTwemojiAsset) for a given emoji string literal.
203///
204/// The `png_twemoji_asset!` macro takes a string literal of an emoji, such as `"🦆"`, and yields
205/// the `&PngTwemojiAsset` for the [🦆 emoji asset](png::codes::U_1F986).
206/// If the emoji asset is unknown for the given literal, the compilation will fail.
207///
208/// # Example
209///
210/// Example for 🦆 (duck):
211/// ```
212/// use twemoji_assets::png_twemoji_asset;
213///
214/// let duck = png_twemoji_asset!("🦆");
215/// println!("PNG data for 🦆: {:?}", duck);
216/// ```
217#[cfg(all(doc, feature = "png"))]
218#[macro_export]
219macro_rules! png_twemoji_asset {
220    ($emoji:literal) => {};
221}
222
223/// Inserts a [`PngTwemojiAsset`](png::PngTwemojiAsset) from a string literal of an emoji name.
224///
225/// The `png_twemoji_asset_from_name!` macro takes a string literal of an emoji name, such as
226/// `"duck"`, and yields the `&PngTwemojiAsset` for the corresponding
227/// [🦆 emoji asset](svg::codes::U_1F986).
228/// The names are provided by [Emojibase](https://github.com/milesj/emojibase).
229/// If the name or the corresponding emoji asset is unknown for the given literal, the compilation will fail.
230///
231/// # Example
232///
233/// Example for 🦆 (duck):
234/// ```
235/// use twemoji_assets::png_twemoji_asset_from_name;
236///
237/// let duck = png_twemoji_asset_from_name!("duck");
238/// println!("PNG data for 🦆: {:?}", duck);
239/// ```
240#[cfg(all(doc, feature = "png", feature = "names"))]
241#[cfg(doc)]
242#[macro_export]
243macro_rules! png_twemoji_asset_from_name {
244    ($emoji:literal) => {};
245}