diff --git a/ufo2fontir/src/source.rs b/ufo2fontir/src/source.rs index af8984df..96cfee1b 100644 --- a/ufo2fontir/src/source.rs +++ b/ufo2fontir/src/source.rs @@ -670,121 +670,122 @@ fn postscript_names(lib_plist: &plist::Dictionary) -> Result Result, BadSource> { + // TODO: Use idiomatic error handling. + // TODO: Simplify. + const OPENTYPE_CATEGORIES: &str = "public.openTypeCategories"; // Registered tags that UFOv3 specifies but that are not in write-fonts const APPL: Tag = Tag::new(b"appl"); const BILD: Tag = Tag::new(b"bild"); - let property = lib_plist.get(OPENTYPE_CATEGORIES); + let Some(property) = lib_plist.get(OPENTYPE_CATEGORIES) else { + // Key was not present, use default: + return Ok(Default::default()); + }; - // TODO: Use idiomatic error handling. - // TODO: Simplify. + let Some(dictionary) = property.as_dictionary() else { + // Key is present but was not a dictionary, error. + return Err(BadSource::custom( + "lib.plist", + "public.postscriptNames must be a dictionary", + )); + }; - match property.map(plist::Value::as_dictionary) { - // Dictionary is present, interpret: - Some(Some(dictionary)) => dictionary - .iter() - .map(|(key, value)| { - // Parse each tag, and metadata as appropriate from tag. - let tag = Tag::new_checked(key.as_bytes()).map_err(|err| { - BadSource::custom( - "lib.plist", - format!("meta record has an invalid tag '{}': {}", key, err), - ) - })?; - - let metadata = match tag { - // "If present, [...] the registered tags dlng and slng have - // their values each stored as an array of ScriptLangTag - // strings" - DLNG | SLNG => Metadata::ScriptLangTags({ - // Interpret and validate as a plist array: - let array = value.as_array().ok_or_else(|| { - BadSource::custom( - "lib.plist", - format!( - "meta {} record must contain an array of ScriptLangTag strings", - tag - ), - ) - })?; - - // ...and as a plist array of strings - let strings = array - .iter() - .map(plist::Value::as_string) - .map(|value| { - value.ok_or_else(|| { - BadSource::custom( - "lib.plist", - format!( - "meta {} record array must only contain values", - tag - ), - ) - }) - }) - .collect::, _>>()?; - - // ...and as a plist array of ScriptLangTags - strings - .into_iter() - .map(|string| { - ScriptLangTag::new(string.into()).map_err(|err| { - BadSource::custom( - "lib.plist", - format!( - "meta {} record contains an invalid \ - ScriptLangTag '{}': {}", - tag, string, err - ), - ) - }) + // Dictionary is present, interpret. + dictionary + .iter() + .map(|(key, value)| { + // Parse each tag, and metadata as appropriate from tag. + let tag = Tag::new_checked(key.as_bytes()).map_err(|err| { + BadSource::custom( + "lib.plist", + format!("meta record has an invalid tag '{}': {}", key, err), + ) + })?; + + let metadata = match tag { + // "If present, [...] the registered tags dlng and slng have + // their values each stored as an array of ScriptLangTag + // strings" + DLNG | SLNG => Metadata::ScriptLangTags({ + // Interpret and validate as a plist array: + let array = value.as_array().ok_or_else(|| { + BadSource::custom( + "lib.plist", + format!( + "meta {} record must contain an array of ScriptLangTag strings", + tag + ), + ) + })?; + + // ...and as a plist array of strings + let strings = array + .iter() + .map(plist::Value::as_string) + .map(|value| { + value.ok_or_else(|| { + BadSource::custom( + "lib.plist", + format!( + "meta {} record array must only contain values", + tag + ), + ) }) - .collect::>()? - }), - // "If present, the registered tags appl and bild have their - // values stored as data" - APPL | BILD => Metadata::Other( - value - .as_data() - .ok_or_else(|| { + }) + .collect::, _>>()?; + + // ...and as a plist array of ScriptLangTags + strings + .into_iter() + .map(|string| { + ScriptLangTag::new(string.into()).map_err(|err| { BadSource::custom( "lib.plist", - format!("meta table {} record must contain ", tag), + format!( + "meta {} record contains an invalid \ + ScriptLangTag '{}': {}", + tag, string, err + ), ) - })? - .to_vec(), - ), - // "Any private tag must have its value stored as data or - // string" - _ => { - let other: Vec = match value { - plist::Value::Data(vec) => Ok(vec.to_owned()), - plist::Value::String(string) => Ok(string.as_bytes().to_vec()), - _ => Err(BadSource::custom( + }) + }) + .collect::>()? + }), + // "If present, the registered tags appl and bild have their + // values stored as data" + APPL | BILD => Metadata::Other( + value + .as_data() + .ok_or_else(|| { + BadSource::custom( "lib.plist", - "Private meta table records must be or ", - )), - }?; - - Metadata::Other(other) - } - }; - - Ok((tag, metadata)) - }) - .collect(), + format!("meta table {} record must contain ", tag), + ) + })? + .to_vec(), + ), + // "Any private tag must have its value stored as data or + // string" + _ => { + let other: Vec = match value { + plist::Value::Data(vec) => Ok(vec.to_owned()), + plist::Value::String(string) => Ok(string.as_bytes().to_vec()), + _ => Err(BadSource::custom( + "lib.plist", + "Private meta table records must be or ", + )), + }?; + + Metadata::Other(other) + } + }; - // Key is present but was not a dictionary, error: - Some(None) => Err(BadSource::custom( - "lib.plist", - "public.postscriptNames must be a dictionary", - )), - // Key was not present, use default: - None => Ok(Default::default()), - } + Ok((tag, metadata)) + }) + .collect() } fn units_per_em<'a>(font_infos: impl Iterator) -> Result {