Skip to content

Commit

Permalink
After much frustration with glif::write bugs, I rewrote it.
Browse files Browse the repository at this point in the history
This time I focused on code hygeine etc. I'm much more confident in this
version of glifparser's writer.

New traits: `IntoXML`, `FromXML`.
  • Loading branch information
ctrlcctrlv committed Jan 10, 2022
1 parent 7c5fe52 commit 46a7540
Show file tree
Hide file tree
Showing 30 changed files with 492 additions and 225 deletions.
5 changes: 4 additions & 1 deletion src/anchor.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod xml;

use std::fmt::Debug;
#[cfg(feature = "glifserde")]
use serde::{Serialize, Deserialize};
Expand All @@ -14,6 +16,7 @@ pub struct Anchor<PD: PointData> {
pub data: PD,
}

/// Only Undefined is used, for now.
#[cfg_attr(feature = "glifserde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum AnchorType {
Expand All @@ -22,7 +25,7 @@ pub enum AnchorType {
Base,
MarkMark,
MarkBase,
} // Undefined used everywhere for now as getting type requires parsing OpenType features, which we will be using nom to do since I have experience w/it.
}

impl<PD: PointData> Anchor<PD> {
pub fn new() -> Self {
Expand Down
14 changes: 14 additions & 0 deletions src/anchor/xml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::glif::IntoXML;
use crate::xml::Element;

use super::{Anchor, PointData};

impl<PD: PointData> IntoXML for Anchor<PD> {
fn xml(&self) -> Element {
let mut anchor_node = xmltree::Element::new("anchor");
anchor_node.attributes.insert("x".to_owned(), self.x.to_string());
anchor_node.attributes.insert("y".to_owned(), self.y.to_string());
anchor_node.attributes.insert("name".to_owned(), self.class.to_string());
anchor_node
}
}
11 changes: 11 additions & 0 deletions src/codepoint.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use crate::glif::IntoXML;
use crate::xml::Element;

pub trait Codepoint {
fn display(&self) -> String;
}
Expand All @@ -7,3 +10,11 @@ impl Codepoint for char {
format!("{:X}", *self as u32)
}
}

impl IntoXML for dyn Codepoint {
fn xml(&self) -> Element {
let mut unicode = xmltree::Element::new("unicode");
unicode.attributes.insert("hex".to_owned(), self.display());
unicode
}
}
2 changes: 2 additions & 0 deletions src/component.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod xml;

use crate::error::GlifParserError;
use crate::glif::{self, Glif};
#[cfg(feature = "mfek")]
Expand Down
15 changes: 15 additions & 0 deletions src/component/xml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::matrix;
use crate::xml::{Element, IntoXML};

use super::GlifComponent;

impl IntoXML for GlifComponent {
fn xml(&self) -> Element {
let mut component_node = Element::new("component");
component_node
.attributes
.insert("base".to_string(), self.base.clone());
matrix::write!(component_node, self);
component_node
}
}
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use xmltree::{ParseError, Error as XMLTreeError};
#[cfg(feature = "glifserde")]
use plist::Error as PlistError;

pub type GlifParserResult<T> = Result<T, GlifParserError>;

#[derive(Debug, Clone)]
pub enum GlifParserError {
/// OS error when reading glif
Expand Down
17 changes: 9 additions & 8 deletions src/glif.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use plist;

use std::path;

use crate::anchor::Anchor;
Expand All @@ -12,15 +10,18 @@ use crate::point::PointData;
use crate::outline::{Outline, OutlineType};

mod conv;
mod lib;
pub use lib::Lib;
mod read;
pub use self::read::read_ufo_glif as read;
pub use self::read::read_ufo_glif_from_filename as read_from_filename;
mod write;
pub use self::write::write_ufo_glif as write;
pub use self::write::write_ufo_glif_to_filename as write_to_filename;
#[cfg(feature = "mfek")]
pub mod mfek;

pub use read::read_ufo_glif as read;
pub use read::read_ufo_glif_from_filename as read_from_filename;
pub use write::write_ufo_glif as write;
pub use write::write_ufo_glif_to_filename as write_to_filename;
pub mod xml;
pub use self::{read::FromXML, write::IntoXML, xml::XMLConversion};

#[cfg(feature = "glifserde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer, ser::SerializeStruct, ser::Error as SerdeError, de::Error as SerdeDeError};
Expand Down Expand Up @@ -59,7 +60,7 @@ pub struct Glif<PD: PointData> {
/// It's up to the API consumer to set this.
pub filename: Option<path::PathBuf>,
/// glif private library
pub lib: Option<plist::Dictionary>,
pub lib: Lib,
}

#[cfg(feature = "glifserde")]
Expand Down
17 changes: 17 additions & 0 deletions src/glif/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::xml;

#[derive(Clone, Debug, PartialEq)]
pub enum Lib {
None,
Plist(plist::Dictionary),
/// This variant is highly undesirable to see as output and means that the user's glif file has
/// validity issues. However, to prevent data loss, we attempt to store the broken plist as
/// XML, as XML is the parent of plist.
Xml(xml::Element),
}

impl Default for Lib {
fn default() -> Self {
Self::None
}
}
17 changes: 14 additions & 3 deletions src/glif/read.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
mod xml;
pub use self::xml::FromXML;

use std::convert::TryInto;
use std::path;
use std::rc::Rc;

use integer_or_float::IntegerOrFloat;

use super::Glif;
use super::{Glif, Lib};
use crate::error::GlifParserError::{self, GlifInputError};
use crate::component::GlifComponent;
use crate::guideline::Guideline;
Expand Down Expand Up @@ -260,8 +263,16 @@ pub fn read_ufo_glif<PD: PointData>(glif: &str) -> Result<Glif<PD>, GlifParserEr
#[cfg(feature = "glifserde")]
if let Some(lib) = glif.take_child("lib") {
let mut plist_temp: Vec<u8> = vec![];
lib.write(&mut plist_temp)?;
ret.lib = plist::from_bytes(&plist_temp).ok();
match lib.write(&mut plist_temp).map(|()|plist::from_bytes(&plist_temp)) {
Ok(Ok(lib_p)) => ret.lib = Lib::Plist(lib_p),
Err(e) => {
log::error!("Failed to serialize .glif lib as XML? Error: {:?}", e);
ret.lib = Lib::Xml(lib)
},
Ok(Err(e)) => {
log::error!("Failed to deserialize .glif lib XML as plist? Error: {:?}", e);
}
}
}
#[cfg(not(feature = "glifserde"))]
if let Some(_) = glif.take_child("lib") {
Expand Down
8 changes: 8 additions & 0 deletions src/glif/read/xml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use crate::error::GlifParserResult;

pub trait FromXML: super::super::write::IntoXML + Sized {
fn from_xml(xml: &[u8]) -> GlifParserResult<Self>;
fn from_xml_string(xml: &String) -> GlifParserResult<Self> {
Self::from_xml(xml.as_bytes())
}
}
Loading

0 comments on commit 46a7540

Please sign in to comment.