blob: 3bae529815cd46658169fcd2902f25668c506784 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Deserialization for pairs of `.all_fonts.json` and `.local_fonts.json` files.
//!
//! A pair of these files is generated per target product using the `generated_file` GN rule (see
//! "//src/fonts/build/fonts.gni").
use {
crate::serde_ext::{self, LoadError},
serde::Deserialize,
std::{
collections::{btree_map::Iter as BTreeMapIter, BTreeMap, BTreeSet},
path::Path,
},
};
/// Describes which set a font belongs to, local or downloadable.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Hash)]
#[serde(rename_all = "lowercase")]
pub enum FontSet {
/// Font files in the local set. Bundled directly in the font server's `/config/data`.
Local,
/// Available to download as a Fuchsia package (`fuchsia-pkg://fuchsia.com/font-package-...`).
Download,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
pub struct FontSets {
map: BTreeMap<String, FontSet>,
}
impl FontSets {
pub fn load_from_all_and_local_paths<T: AsRef<Path>>(
all_path: T,
local_path: T,
) -> Result<Self, LoadError> {
let all_file_names: BTreeSet<String> = serde_ext::load_from_path(all_path)?;
let local_file_names: BTreeSet<String> = serde_ext::load_from_path(local_path)?;
let mut map = BTreeMap::new();
for file_name in all_file_names {
map.insert(file_name, FontSet::Download);
}
// The Local set takes precedence.
for file_name in local_file_names {
map.insert(file_name, FontSet::Local);
}
Ok(Self::new(map))
}
/// Creates a new `FontSets` collection from a map of font file names to [`FontSet`] values,
/// as generated in [`FontSets::load_from_all_and_local_paths`].
///
/// _Visible for tests only._
pub(crate) fn new(map: BTreeMap<String, FontSet>) -> Self {
Self { map }
}
pub fn get_font_set(&self, file_name: &str) -> Option<&FontSet> {
self.map.get(file_name)
}
pub fn iter(&self) -> impl Iterator<Item = (&String, &FontSet)> {
self.into_iter()
}
}
impl<'a> IntoIterator for &'a FontSets {
type Item = (&'a String, &'a FontSet);
type IntoIter = BTreeMapIter<'a, String, FontSet>;
fn into_iter(self) -> Self::IntoIter {
self.map.iter()
}
}
#[cfg(test)]
mod tests {
use {
super::*, anyhow::Error, pretty_assertions::assert_eq, serde_json::json, std::io::Write,
tempfile::NamedTempFile,
};
#[test]
fn test_load_from_all_and_local_paths() -> Result<(), Error> {
let all_fonts_contents =
json!(["a.ttf", "b.ttf", "c.ttf", "d.ttf", "e.ttf", "f.ttf"]).to_string();
let mut all_fonts_file = NamedTempFile::new()?;
all_fonts_file.write_all(all_fonts_contents.as_bytes())?;
let local_fonts_contents = json!(["a.ttf", "b.ttf", "c.ttf"]).to_string();
let mut local_fonts_file = NamedTempFile::new()?;
local_fonts_file.write_all(local_fonts_contents.as_bytes())?;
let font_sets = FontSets::load_from_all_and_local_paths(
all_fonts_file.path(),
local_fonts_file.path(),
)?;
assert_eq!(font_sets.get_font_set("a.ttf"), Some(&FontSet::Local));
assert_eq!(font_sets.get_font_set("b.ttf"), Some(&FontSet::Local));
assert_eq!(font_sets.get_font_set("c.ttf"), Some(&FontSet::Local));
assert_eq!(font_sets.get_font_set("d.ttf"), Some(&FontSet::Download));
assert_eq!(font_sets.get_font_set("e.ttf"), Some(&FontSet::Download));
assert_eq!(font_sets.get_font_set("f.ttf"), Some(&FontSet::Download));
assert_eq!(font_sets.get_font_set("404.ttf"), None);
Ok(())
}
}