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
//! Types related to sticker sets.

use super::Sticker;
use crate::types::PhotoSize;
use is_macro::Is;
use serde::de::{Deserialize, Deserializer, IgnoredAny, MapAccess, Visitor};
use std::fmt::{self, Formatter};

/// Represents different kinds of a [`sticker::Set`].
///
/// [`sticker::Set`]: Set
#[derive(Debug, PartialEq, Eq, Clone, Copy, Is)]
#[non_exhaustive]
pub enum Kind {
    /// The stickers in the sticker set are neither animated nor masks.
    Plain,
    /// The sticker set contains animated stickers.
    Animated,
    /// The sticker set contains masks.
    Masks,
}

/// Represents a [`StickerSet`].
///
/// [`StickerSet`]: https://core.telegram.org/bots/api#stickerset
#[derive(Debug, PartialEq, Clone)]
#[non_exhaustive]
pub struct Set {
    /// The name of the sticker set (used in URLs).
    pub name: String,
    /// The title of the sticker set (shown to the user).
    pub title: String,
    /// The kind of the sticker set.
    pub kind: Kind,
    /// The stickers from this set.
    pub stickers: Vec<Sticker>,
    /// The thumb of the sticker set.
    pub thumb: Option<PhotoSize>,
}

const NAME: &str = "name";
const TITLE: &str = "title";
const IS_ANIMATED: &str = "is_animated";
const CONTAINS_MASKS: &str = "contains_masks";
const STICKERS: &str = "stickers";
const THUMB: &str = "thumb";

struct SetVisitor;

impl<'v> Visitor<'v> for SetVisitor {
    type Value = Set;

    fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
        write!(formatter, "struct sticker::Set")
    }

    fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
    where
        V: MapAccess<'v>,
    {
        let mut name = None;
        let mut title = None;
        let mut is_animated = None;
        let mut contains_masks = None;
        let mut stickers = None;
        let mut thumb = None;

        while let Some(key) = map.next_key()? {
            match key {
                NAME => name = Some(map.next_value()?),
                TITLE => title = Some(map.next_value()?),
                IS_ANIMATED => is_animated = Some(map.next_value()?),
                CONTAINS_MASKS => contains_masks = Some(map.next_value()?),
                STICKERS => stickers = Some(map.next_value()?),
                THUMB => thumb = Some(map.next_value()?),
                _ => {
                    let _ = map.next_value::<IgnoredAny>()?;
                }
            }
        }

        let kind = if contains_masks == Some(true) {
            Kind::Masks
        } else if is_animated == Some(true) {
            Kind::Animated
        } else {
            Kind::Plain
        };

        Ok(Set {
            name: name.ok_or_else(|| serde::de::Error::missing_field(NAME))?,
            title: title
                .ok_or_else(|| serde::de::Error::missing_field(TITLE))?,
            stickers: stickers
                .ok_or_else(|| serde::de::Error::missing_field(STICKERS))?,
            thumb,
            kind,
        })
    }
}

impl<'de> Deserialize<'de> for Set {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_struct(
            "sticker::Set",
            &[NAME, TITLE, IS_ANIMATED, CONTAINS_MASKS, STICKERS, THUMB],
            SetVisitor,
        )
    }
}