use std::fmt::Display;
const STICKER_EFFECT_PREFIX: [u8; 20] = [
115, 116, 105, 99, 107, 101, 114, 69, 102, 102, 101, 99, 116, 58, 116, 121, 112, 101, 61, 34,
];
const STICKER_EFFECT_SUFFIX: [u8; 3] = [34, 47, 62];
#[derive(Debug, PartialEq, Eq)]
pub enum StickerEffect {
Normal,
Outline,
Comic,
Puffy,
Shiny,
Other(String),
}
impl StickerEffect {
fn from_exif(sticker_effect_type: &str) -> Self {
match sticker_effect_type {
"stroke" => Self::Outline,
"comic" => Self::Comic,
"puffy" => Self::Puffy,
"iridescent" => Self::Shiny,
other => Self::Other(other.to_owned()),
}
}
}
impl Display for StickerEffect {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
StickerEffect::Normal => write!(fmt, "Normal"),
StickerEffect::Outline => write!(fmt, "Outline"),
StickerEffect::Comic => write!(fmt, "Comic"),
StickerEffect::Puffy => write!(fmt, "Puffy"),
StickerEffect::Shiny => write!(fmt, "Shiny"),
StickerEffect::Other(name) => write!(fmt, "{name}"),
}
}
}
impl Default for StickerEffect {
fn default() -> Self {
Self::Normal
}
}
pub fn get_sticker_effect(mut heic_data: Vec<u8>) -> StickerEffect {
for idx in 0..heic_data.len() {
if idx + STICKER_EFFECT_PREFIX.len() < heic_data.len() {
let part = &heic_data[idx..idx + STICKER_EFFECT_PREFIX.len()];
if part == STICKER_EFFECT_PREFIX {
heic_data.drain(..idx + STICKER_EFFECT_PREFIX.len());
break;
}
} else {
return StickerEffect::Normal;
}
}
for idx in 1..heic_data.len() {
if idx >= heic_data.len() - 2 {
return StickerEffect::Other("Unknown".to_string());
}
let part = &heic_data[idx..idx + STICKER_EFFECT_SUFFIX.len()];
if part == STICKER_EFFECT_SUFFIX {
heic_data.truncate(idx);
break;
}
}
StickerEffect::from_exif(&String::from_utf8_lossy(&heic_data))
}
#[cfg(test)]
mod tests {
use std::env::current_dir;
use std::fs::File;
use std::io::Read;
use crate::message_types::sticker::{get_sticker_effect, StickerEffect};
#[test]
fn test_parse_sticker_normal() {
let sticker_path = current_dir()
.unwrap()
.as_path()
.join("test_data/stickers/no_effect.heic");
let mut file = File::open(sticker_path).unwrap();
let mut bytes = vec![];
file.read_to_end(&mut bytes).unwrap();
let effect = get_sticker_effect(bytes);
assert_eq!(effect, StickerEffect::Normal);
}
#[test]
fn test_parse_sticker_outline() {
let sticker_path = current_dir()
.unwrap()
.as_path()
.join("test_data/stickers/outline.heic");
let mut file = File::open(sticker_path).unwrap();
let mut bytes = vec![];
file.read_to_end(&mut bytes).unwrap();
let effect = get_sticker_effect(bytes);
assert_eq!(effect, StickerEffect::Outline);
}
#[test]
fn test_parse_sticker_comic() {
let sticker_path = current_dir()
.unwrap()
.as_path()
.join("test_data/stickers/comic.heic");
let mut file = File::open(sticker_path).unwrap();
let mut bytes = vec![];
file.read_to_end(&mut bytes).unwrap();
let effect = get_sticker_effect(bytes);
assert_eq!(effect, StickerEffect::Comic);
}
#[test]
fn test_parse_sticker_puffy() {
let sticker_path = current_dir()
.unwrap()
.as_path()
.join("test_data/stickers/puffy.heic");
let mut file = File::open(sticker_path).unwrap();
let mut bytes = vec![];
file.read_to_end(&mut bytes).unwrap();
let effect = get_sticker_effect(bytes);
assert_eq!(effect, StickerEffect::Puffy);
}
#[test]
fn test_parse_sticker_shiny() {
let sticker_path = current_dir()
.unwrap()
.as_path()
.join("test_data/stickers/shiny.heic");
let mut file = File::open(sticker_path).unwrap();
let mut bytes = vec![];
file.read_to_end(&mut bytes).unwrap();
let effect = get_sticker_effect(bytes);
assert_eq!(effect, StickerEffect::Shiny);
}
}