teloxide_core/types/
mask_position.rs

1use std::hash::Hash;
2
3use serde::{Deserialize, Serialize};
4
5/// This object describes the position on faces where a mask should be placed by
6/// default.
7///
8/// [The official docs](https://core.telegram.org/bots/api#maskposition).
9#[serde_with::skip_serializing_none]
10#[derive(Clone, Copy, Debug)]
11#[derive(Serialize, Deserialize)]
12pub struct MaskPosition {
13    /// The part of the face relative to which the mask should be placed. One
14    /// of `forehead`, `eyes`, `mouth`, or `chin`.
15    pub point: MaskPoint,
16
17    /// Shift by X-axis measured in widths of the mask scaled to the face size,
18    /// from left to right. For example, choosing `-1.0` will place mask just
19    /// to the left of the default mask position.
20    pub x_shift: f64,
21
22    /// Shift by Y-axis measured in heights of the mask scaled to the face
23    /// size, from top to bottom. For example, `1.0` will place the mask just
24    /// below the default mask position.
25    pub y_shift: f64,
26
27    /// Mask scaling coefficient. For example, `2.0` means double size.
28    pub scale: f64,
29}
30
31impl PartialEq for MaskPosition {
32    fn eq(&self, other: &Self) -> bool {
33        self.point == other.point
34            && self.x_shift.total_cmp(&other.x_shift).is_eq()
35            && self.y_shift.total_cmp(&other.y_shift).is_eq()
36            && self.scale.total_cmp(&other.scale).is_eq()
37    }
38}
39
40impl Eq for MaskPosition {}
41
42impl Hash for MaskPosition {
43    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
44        self.point.hash(state);
45
46        // Skip values which are NaN and canonicalize negative zero (-0.0 + 0.0 == +0.0)
47        if !self.x_shift.is_nan() {
48            (self.x_shift + 0.0).to_bits().hash(state);
49        }
50        if !self.y_shift.is_nan() {
51            (self.y_shift + 0.0).to_bits().hash(state);
52        }
53        if !self.scale.is_nan() {
54            (self.scale + 0.0).to_bits().hash(state);
55        }
56    }
57}
58
59/// The part of the face relative to which the mask should be placed.
60#[derive(Clone, Copy, Debug)]
61#[derive(PartialEq, Eq, Hash)]
62#[derive(Serialize, Deserialize)]
63#[serde(rename_all = "snake_case")]
64pub enum MaskPoint {
65    Forehead,
66    Eyes,
67    Mouth,
68    Chin,
69}
70
71impl MaskPosition {
72    #[must_use]
73    pub const fn new(point: MaskPoint, x_shift: f64, y_shift: f64, scale: f64) -> Self {
74        Self { point, x_shift, y_shift, scale }
75    }
76
77    #[must_use]
78    pub const fn point(mut self, val: MaskPoint) -> Self {
79        self.point = val;
80        self
81    }
82
83    #[must_use]
84    pub const fn x_shift(mut self, val: f64) -> Self {
85        self.x_shift = val;
86        self
87    }
88
89    #[must_use]
90    pub const fn y_shift(mut self, val: f64) -> Self {
91        self.y_shift = val;
92        self
93    }
94
95    #[must_use]
96    pub const fn scale(mut self, val: f64) -> Self {
97        self.scale = val;
98        self
99    }
100}