font_features.rs

  1use schemars::{
  2    schema::{InstanceType, Schema, SchemaObject, SingleOrVec},
  3    JsonSchema,
  4};
  5
  6macro_rules! create_definitions {
  7    ($($(#[$meta:meta])* ($name:ident, $idx:expr)),* $(,)?) => {
  8        #[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
  9        pub struct FontFeatures {
 10            enabled: u64,
 11            disabled: u64,
 12        }
 13
 14        impl FontFeatures {
 15            $(
 16                pub fn $name(&self) -> Option<bool> {
 17                    if (self.enabled & (1 << $idx)) != 0 {
 18                        Some(true)
 19                    } else if (self.disabled & (1 << $idx)) != 0 {
 20                        Some(false)
 21                    } else {
 22                        None
 23                    }
 24                }
 25            )*
 26        }
 27
 28        impl std::fmt::Debug for FontFeatures {
 29            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 30                let mut debug = f.debug_struct("FontFeatures");
 31                $(
 32                    if let Some(value) = self.$name() {
 33                        debug.field(stringify!($name), &value);
 34                    };
 35                )*
 36                debug.finish()
 37            }
 38        }
 39
 40        impl<'de> serde::Deserialize<'de> for FontFeatures {
 41            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
 42            where
 43                D: serde::Deserializer<'de>,
 44            {
 45                use serde::de::{MapAccess, Visitor};
 46                use std::fmt;
 47
 48                struct FontFeaturesVisitor;
 49
 50                impl<'de> Visitor<'de> for FontFeaturesVisitor {
 51                    type Value = FontFeatures;
 52
 53                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
 54                        formatter.write_str("a map of font features")
 55                    }
 56
 57                    fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
 58                    where
 59                        M: MapAccess<'de>,
 60                    {
 61                        let mut enabled: u64 = 0;
 62                        let mut disabled: u64 = 0;
 63
 64                        while let Some((key, value)) = access.next_entry::<String, Option<bool>>()? {
 65                            let idx = match key.as_str() {
 66                                $(stringify!($name) => $idx,)*
 67                                _ => continue,
 68                            };
 69                            match value {
 70                                Some(true) => enabled |= 1 << idx,
 71                                Some(false) => disabled |= 1 << idx,
 72                                None => {}
 73                            };
 74                        }
 75                        Ok(FontFeatures { enabled, disabled })
 76                    }
 77                }
 78
 79                let features = deserializer.deserialize_map(FontFeaturesVisitor)?;
 80                Ok(features)
 81            }
 82        }
 83
 84        impl serde::Serialize for FontFeatures {
 85            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 86            where
 87                S: serde::Serializer,
 88            {
 89                use serde::ser::SerializeMap;
 90
 91                let mut map = serializer.serialize_map(None)?;
 92
 93                $(
 94                    let feature = stringify!($name);
 95                    if let Some(value) = self.$name() {
 96                        map.serialize_entry(feature, &value)?;
 97                    }
 98                )*
 99
100                map.end()
101            }
102        }
103
104        impl JsonSchema for FontFeatures {
105            fn schema_name() -> String {
106                "FontFeatures".into()
107            }
108
109            fn json_schema(_: &mut schemars::gen::SchemaGenerator) -> Schema {
110                let mut schema = SchemaObject::default();
111                let properties = &mut schema.object().properties;
112                let feature_schema = Schema::Object(SchemaObject {
113                    instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::Boolean))),
114                    ..Default::default()
115                });
116
117                $(
118                    properties.insert(stringify!($name).to_owned(), feature_schema.clone());
119                )*
120
121                schema.into()
122            }
123        }
124    };
125}
126
127create_definitions!(
128    (calt, 0),
129    (case, 1),
130    (cpsp, 2),
131    (frac, 3),
132    (liga, 4),
133    (onum, 5),
134    (ordn, 6),
135    (pnum, 7),
136    (ss01, 8),
137    (ss02, 9),
138    (ss03, 10),
139    (ss04, 11),
140    (ss05, 12),
141    (ss06, 13),
142    (ss07, 14),
143    (ss08, 15),
144    (ss09, 16),
145    (ss10, 17),
146    (ss11, 18),
147    (ss12, 19),
148    (ss13, 20),
149    (ss14, 21),
150    (ss15, 22),
151    (ss16, 23),
152    (ss17, 24),
153    (ss18, 25),
154    (ss19, 26),
155    (ss20, 27),
156    (subs, 28),
157    (sups, 29),
158    (swsh, 30),
159    (titl, 31),
160    (tnum, 32),
161    (zero, 33)
162);