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
//! # base_emoji
//!
//! Convert everything to Emojis.
//!
//! ๐Ÿซ๐Ÿ”ฆ๐Ÿ”ฅ๐ŸŽฒ๐Ÿฌ๐Ÿ€๐ŸŸ๐Ÿ”‹๐Ÿฌ๐ŸŽฒ๐Ÿฌ๐Ÿ€๐ŸŽ๐ŸŸ๐Ÿ’ง๐Ÿ‘‚๐Ÿ”ฅ๐Ÿšช๐Ÿ”‹๐ŸŸ๐Ÿ”ฆ๐Ÿ”‹๐Ÿš—๐Ÿ‘ฃ๐Ÿ”ฆ๐ŸŒ๐Ÿ‘‚๐Ÿค๐Ÿ—
//!
//! Reimplementation of [base_emoji](https://github.com/pfrazee/base-emoji) (JavaScript).
//!
//! ## Example
//!
//! ```rust
//! let input = [0xde, 0xad, 0xbe, 0xef];
//! let output = "โ„๏ธ๐Ÿผ๐Ÿš“๐Ÿ‘…";
//!
//! assert_eq!(base_emoji::to_string(&input), output);
//! ```
//!
//! ## Encoding (same as original implementation)
//!
//! Citing [the README](https://github.com/pfrazee/base-emoji/blob/04b6c1e24ae5071804285cb358162628ea4a9bc8/README.md):
//!
//! > The emojis used are in `emojis.json`. There are 843 emojis there, but the
//! > converter reads sequences of 8 bits at a time, and so only maps the value to
//! > the first 256 of them. To stay consistent with other renderings, make sure you
//! > don't change the order of your emojis.json.
//!
//! ## License
//!
//! MIT. See included `LICENSE` file.
extern crate phf;

include!(concat!(env!("OUT_DIR"), "/emojis.rs"));

/// Encode buffer as a base-emoji string
///
/// ```rust
/// let input = [0xde, 0xad, 0xbe, 0xef];
/// let output = "โ„๏ธ๐Ÿผ๐Ÿš“๐Ÿ‘…";
///
/// assert_eq!(base_emoji::to_string(&input), output);
/// ```
pub fn to_string<T: AsRef<[u8]>>(buf: T) -> String {
    buf
        .as_ref()
        .iter()
        .map(|c| EMOJIS.get(c).unwrap().0)
        .collect::<Vec<_>>()
        .concat()
}

/// Encode buffer as a base-emoji buffer
///
/// ```rust
/// let input = [0xde, 0xad, 0xbe, 0xef];
/// let output = "โ„๏ธ๐Ÿผ๐Ÿš“๐Ÿ‘…".as_bytes();
///
/// assert_eq!(base_emoji::to_bytes(&input), output);
/// ```
pub fn to_bytes<T: AsRef<[u8]>>(buf: T) -> Vec<u8> {
    to_string(buf).into_bytes()
}

/// Encode buffer as a string of emoji names
///
/// ```rust
/// let input = [0xde, 0xad, 0xbe, 0xef];
/// let output = ":snowflake::panda_face::police_car::tongue:";
/// assert_eq!(base_emoji::to_names(&input), output);
/// ```
pub fn to_names<T: AsRef<[u8]>>(buf: T) -> String {
    to_custom(buf, |_, name| format!(":{}:", name))
}

/// Encode buffer as custom-mapped string
///
/// ```rust
/// let input = [0xde];
/// let output = "<img src='/img/snowflake.png' alt='โ„๏ธ' title='snowflake'>";
/// assert_eq!(
///     base_emoji::to_custom(&input, |ch, name| {
///         format!("<img src='/img/{}.png' alt='{}' title='{}'>",
///                 name, ch, name)
///     }),
///     output);
/// ```
pub fn to_custom<T: AsRef<[u8]>, F: Fn(&str, &str) -> String>(buf: T, f: F) -> String {
    buf
        .as_ref()
        .iter()
        .map(|c| {
            let emoji = EMOJIS.get(c).unwrap();
            f(emoji.0, emoji.1)
        })
        .collect::<Vec<_>>()
        .concat()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn long() {
        let res = "๐Ÿ’ฏ๐Ÿ”ข๐Ÿ‘๐Ÿ‘Ž๐ŸŽฑ๐Ÿ…ฐ๐Ÿšกโœˆ๏ธ๐Ÿ‘ฝ๐Ÿš‘โš“๏ธ๐Ÿ‘ผ๐Ÿ’ข๐Ÿ˜ ๐Ÿœ๐ŸŽโฌ‡๏ธโฌ…๏ธโžก๏ธโฌ†๏ธ๐ŸŽจ๐Ÿง๐Ÿ‘ถ๐Ÿผ๐ŸŽˆ๐ŸŽ๐ŸŒโ€ผ๏ธ๐Ÿ“Š๐Ÿ’ˆ๐Ÿ€๐Ÿ›€๐Ÿ”‹๐Ÿป๐Ÿ๐Ÿบ๐Ÿž๐Ÿ””๐Ÿšด๐Ÿ‘™๐ŸŽ‚๐Ÿƒ๐ŸŒผ๐Ÿ“˜๐Ÿš™๐Ÿ’™๐Ÿ—โ›ต๏ธ๐Ÿ’ฃ๐Ÿ“–๐Ÿ“š๐Ÿ’ฅ๐Ÿ‘ข๐Ÿ’๐ŸŽณ๐Ÿ‘ฆ๐Ÿž๐Ÿ‘ฐ๐Ÿ’ผ๐Ÿ’”๐Ÿ›๐Ÿ’ก๐ŸšŒ๐Ÿ‘ค๐ŸŒต๐Ÿฐ๐Ÿ“†๐Ÿซ๐Ÿฌ๐Ÿš—๐Ÿˆ๐Ÿ’ฟ๐Ÿ๐Ÿ’๐Ÿ”๐Ÿซ๐ŸŽ„๐Ÿ‘๐ŸŽฌโ˜๏ธ๐Ÿธโ˜•๏ธ๐Ÿ’ป๐ŸŽŠ๐Ÿšง๐Ÿช๐ŸŒฝ๐Ÿ‘ซ๐Ÿ„๐ŸŠ๐Ÿ‘‘๐Ÿ”ฎ๐Ÿ’˜๐ŸŒ€๐Ÿ’ƒ๐ŸŽฏ๐Ÿ’จ๐ŸŒณ๐Ÿ’ซ๐Ÿ•๐Ÿ’ต๐Ÿฌ๐Ÿฉ๐Ÿšช๐Ÿ’ง๐Ÿ‘‚๐ŸŒ๐Ÿ‘“๐Ÿ‘Š๐Ÿ‘ฃ๐Ÿ”ฅ๐Ÿ”ฆ๐Ÿ’พ๐Ÿˆ๐Ÿ€๐Ÿค๐ŸŸ๐Ÿธ๐ŸŽฒ๐Ÿ’Ž๐Ÿ‘ป๐ŸŽ๐ŸŒโ›ณ๏ธ๐Ÿ‡๐Ÿ๐ŸŽธ๐Ÿ”ซ๐Ÿ”๐Ÿ”จ๐Ÿ‘œ๐Ÿฃ๐ŸŒฟ๐Ÿ”†๐Ÿ‘ ๐ŸดโŒ›๏ธ๐Ÿจ๐ŸŽƒ๐Ÿ”‘๐Ÿ’‹๐Ÿจ๐Ÿƒ๐Ÿ”—๐Ÿ”’๐Ÿ“ข๐Ÿ”๐Ÿ“ซ๐Ÿ๐Ÿ“ฃ๐Ÿ“๐ŸŽค๐Ÿ”ฌ๐Ÿ’ฐ๐Ÿ’๐ŸŒ™๐Ÿ๐ŸŽฅ๐Ÿ’ช๐Ÿ„๐ŸŽน๐ŸŽต๐Ÿ‘”๐Ÿ“ฐ๐Ÿ”•โ›”๏ธ๐Ÿšซ๐Ÿ‘ƒ๐Ÿ”ฉ๐Ÿ™๐Ÿ‘Œ๐Ÿ‘๐Ÿ‚๐Ÿผโ›…๏ธ๐Ÿพ๐Ÿ‘๐Ÿ๐Ÿง๐ŸŽญโ˜Ž๏ธ๐Ÿ–๐Ÿฝ๐Ÿ’Š๐Ÿ๐Ÿ•๐Ÿ‘‡๐Ÿ‘ˆ๐Ÿ‘‰๐Ÿ‘†๐Ÿš“๐Ÿฉ๐Ÿ’ฉ๐Ÿ“ฏ๐Ÿ—๐Ÿ™๐Ÿ‘›๐Ÿ“Œ๐Ÿ‡๐ŸŽ๐Ÿ“ป๐Ÿ€๐ŸŽ€๐Ÿš๐Ÿ’๐Ÿš€๐Ÿ“๐ŸŒน๐Ÿšจ๐Ÿ“๐Ÿƒ๐ŸŽ…๐Ÿ“ก๐ŸŽทโœ‚๏ธ๐Ÿš๐Ÿ‘•๐Ÿšฟ๐Ÿ’€๐Ÿ˜„๐ŸŒ๐Ÿโ„๏ธโ›„๏ธ๐Ÿ˜ญโšฝ๏ธ๐Ÿ”‰๐Ÿ‘พ๐Ÿ’ฌโญ๏ธ๐Ÿ“๐Ÿ˜Ž๐Ÿ’ฆ๐ŸŠ๐Ÿ’‰๐Ÿ”ญ๐ŸŽพ๐Ÿ’ญ๐Ÿšฝ๐Ÿ‘…๐ŸŽฉ๐Ÿšฅ๐Ÿ†๐ŸŽบ๐Ÿข๐Ÿšฆ๐Ÿ“ผ๐ŸŽฎ๐ŸŽปโŒš๏ธ๐Ÿ‹๐Ÿท๐Ÿบ๐Ÿ”งโšก๏ธ๐Ÿ’ค";

        let input = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff];
        assert_eq!(to_string(&input[..]), res);
    }

    #[test]
    fn from_string() {
        let input = "Convert everything to Emojis.";
        let output = "๐Ÿซ๐Ÿ”ฆ๐Ÿ”ฅ๐ŸŽฒ๐Ÿฌ๐Ÿ€๐ŸŸ๐Ÿ”‹๐Ÿฌ๐ŸŽฒ๐Ÿฌ๐Ÿ€๐ŸŽ๐ŸŸ๐Ÿ’ง๐Ÿ‘‚๐Ÿ”ฅ๐Ÿšช๐Ÿ”‹๐ŸŸ๐Ÿ”ฆ๐Ÿ”‹๐Ÿš—๐Ÿ‘ฃ๐Ÿ”ฆ๐ŸŒ๐Ÿ‘‚๐Ÿค๐Ÿ—";

        assert_eq!(to_string(input), output);
    }
}