From 751812f45141a7b2022d0dba138457f3c21950b0 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 4 Feb 2020 21:36:29 +0100 Subject: [PATCH] =?UTF-8?q?Serialize=20layouts=20with=20serde=20?= =?UTF-8?q?=F0=9F=94=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 6 ++-- src/func.rs | 10 +++---- src/layout/actions.rs | 37 ++++++++++++++++++------ src/layout/mod.rs | 33 ++-------------------- src/lib.rs | 7 +++-- src/size.rs | 10 ++++--- src/syntax/func/values.rs | 6 ++-- tests/coma.typ | 2 +- tests/src/render.py | 59 +++++++++++++++++---------------------- tests/src/typeset.rs | 31 ++++++++++---------- 10 files changed, 95 insertions(+), 106 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e21438400..d4552e3a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ name = "typstc" version = "0.1.0" authors = ["Laurenz Mädje "] edition = "2018" -# build = "build.rs" [dependencies] toddle = { path = "../toddle", features = ["query"], default-features = false } @@ -13,10 +12,11 @@ smallvec = "1" unicode-xid = "0.2" async-trait = "0.1" serde = { version = "1", features = ["derive"] } +serde_json = { version = "1", optional = true } futures-executor = { version = "0.3", optional = true } [features] -default = ["fs-provider", "futures-executor"] +default = ["fs-provider", "futures-executor", "serde_json"] fs-provider = ["toddle/fs-provider"] [[bin]] @@ -28,4 +28,4 @@ required-features = ["fs-provider", "futures-executor"] name = "typeset" path = "tests/src/typeset.rs" harness = false -required-features = ["fs-provider", "futures-executor"] +required-features = ["fs-provider", "futures-executor", "serde_json"] diff --git a/src/func.rs b/src/func.rs index 215de60f3..88d08d2dd 100644 --- a/src/func.rs +++ b/src/func.rs @@ -53,16 +53,16 @@ pub trait ParseFunc { /// body: Option, /// } /// -/// parse(header, body, ctx, errors, decos) { -/// let body = body!(opt: body, ctx, errors, decos); -/// let hidden = header.args.pos.get::(errors) -/// .or_missing(errors, header.name.span, "hidden") +/// parse(header, body, ctx, f) { +/// let body = body!(opt: body, ctx, f); +/// let hidden = header.args.pos.get::(&mut f.errors) +/// .or_missing(&mut f.errors, header.name.span, "hidden") /// .unwrap_or(false); /// /// HiderFunc { body: if hidden { None } else { body } } /// } /// -/// layout(self, ctx, errors) { +/// layout(self, ctx, f) { /// match &self.body { /// Some(model) => vec![LayoutSyntaxModel(model)], /// None => vec![], diff --git a/src/layout/actions.rs b/src/layout/actions.rs index 314084e5f..0abef5f9e 100644 --- a/src/layout/actions.rs +++ b/src/layout/actions.rs @@ -1,11 +1,11 @@ //! Drawing and configuration actions composing layouts. -use std::io::{self, Write}; use std::fmt::{self, Debug, Formatter}; +use serde::ser::{Serialize, Serializer, SerializeTuple}; use toddle::query::FontIndex; use crate::size::{Size, Size2D}; -use super::{Layout, Serialize}; +use super::Layout; use self::LayoutAction::*; @@ -24,12 +24,33 @@ pub enum LayoutAction { } impl Serialize for LayoutAction { - fn serialize(&self, f: &mut W) -> io::Result<()> { + fn serialize(&self, serializer: S) -> Result where S: Serializer { match self { - MoveAbsolute(s) => write!(f, "m {:.4} {:.4}", s.x.to_pt(), s.y.to_pt()), - SetFont(i, s) => write!(f, "f {} {} {}", i.id, i.variant, s.to_pt()), - WriteText(s) => write!(f, "w {}", s), - DebugBox(s) => write!(f, "b {} {}", s.x.to_pt(), s.y.to_pt()), + LayoutAction::MoveAbsolute(pos) => { + let mut tup = serializer.serialize_tuple(2)?; + tup.serialize_element(&0u8)?; + tup.serialize_element(&pos)?; + tup.end() + } + LayoutAction::SetFont(index, size) => { + let mut tup = serializer.serialize_tuple(4)?; + tup.serialize_element(&1u8)?; + tup.serialize_element(index)?; + tup.serialize_element(size)?; + tup.end() + } + LayoutAction::WriteText(text) => { + let mut tup = serializer.serialize_tuple(2)?; + tup.serialize_element(&2u8)?; + tup.serialize_element(text)?; + tup.end() + } + LayoutAction::DebugBox(size) => { + let mut tup = serializer.serialize_tuple(2)?; + tup.serialize_element(&3u8)?; + tup.serialize_element(&size)?; + tup.end() + } } } } @@ -40,7 +61,7 @@ impl Debug for LayoutAction { match self { MoveAbsolute(s) => write!(f, "move {} {}", s.x, s.y), SetFont(i, s) => write!(f, "font {}_{} {}", i.id, i.variant, s), - WriteText(s) => write!(f, "write \"{}\"", s), + WriteText(s) => write!(f, "write {:?}", s), DebugBox(s) => write!(f, "box {} {}", s.x, s.y), } } diff --git a/src/layout/mod.rs b/src/layout/mod.rs index b29d87e3a..01d402db4 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,8 +1,8 @@ //! Layouting types and engines. -use std::io::{self, Write}; use std::fmt::{self, Display, Formatter}; use smallvec::SmallVec; +use serde::Serialize; use toddle::query::FontIndex; use crate::size::{Size, Size2D, SizeBox}; @@ -32,11 +32,12 @@ pub mod prelude { pub type MultiLayout = Vec; /// A finished box with content at fixed positions. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize)] pub struct Layout { /// The size of the box. pub dimensions: Size2D, /// How to align this layout in a parent container. + #[serde(skip)] pub alignment: LayoutAlignment, /// The actions composing this layout. pub actions: Vec, @@ -57,34 +58,6 @@ impl Layout { } } -/// Layout components that can be serialized. -pub trait Serialize { - /// Serialize the data structure into an output writable. - fn serialize(&self, f: &mut W) -> io::Result<()>; -} - -impl Serialize for Layout { - fn serialize(&self, f: &mut W) -> io::Result<()> { - writeln!(f, "{:.4} {:.4}", self.dimensions.x.to_pt(), self.dimensions.y.to_pt())?; - writeln!(f, "{}", self.actions.len())?; - for action in &self.actions { - action.serialize(f)?; - writeln!(f)?; - } - Ok(()) - } -} - -impl Serialize for MultiLayout { - fn serialize(&self, f: &mut W) -> io::Result<()> { - writeln!(f, "{}", self.len())?; - for layout in self { - layout.serialize(f)?; - } - Ok(()) - } -} - /// A vector of layout spaces, that is stack allocated as long as it only /// contains at most 2 spaces. pub type LayoutSpaces = SmallVec<[LayoutSpace; 2]>; diff --git a/src/lib.rs b/src/lib.rs index b74837fe8..7136b2bde 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,8 @@ use async_trait::async_trait; use smallvec::smallvec; use toddle::{Font, OwnedData}; -use toddle::query::{FontLoader, FontProvider, SharedFontLoader, FontDescriptor}; +use toddle::query::{FontLoader, SharedFontLoader}; +use toddle::query::{FontProvider, FontIndex, FontDescriptor}; use crate::error::Error; use crate::layout::MultiLayout; @@ -223,8 +224,8 @@ where P: FontProvider, P::Error: Debug + 'static { type Data = P::Data; type Error = Box; - async fn load(&self, index: usize, variant: usize) -> Result, Self::Error> { - self.provider.load(index, variant).await + async fn load(&self, index: FontIndex) -> Result, Self::Error> { + self.provider.load(index).await .map_err(|d| Box::new(d) as Box) } } diff --git a/src/size.rs b/src/size.rs index 79b987746..e97b92485 100644 --- a/src/size.rs +++ b/src/size.rs @@ -4,12 +4,14 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::iter::Sum; use std::ops::*; use std::str::FromStr; +use serde::Serialize; use crate::layout::prelude::*; /// A general spacing type. -#[derive(Default, Copy, Clone, PartialEq, PartialOrd)] +#[derive(Default, Copy, Clone, PartialEq, PartialOrd, Serialize)] +#[serde(transparent)] pub struct Size { /// The size in typographic points (1/72 inches). pub points: f32, @@ -137,7 +139,7 @@ pub type FSize = ScaleSize; pub type PSize = ScaleSize; /// A value in two dimensions. -#[derive(Default, Copy, Clone, Eq, PartialEq)] +#[derive(Default, Copy, Clone, Eq, PartialEq, Serialize)] pub struct Value2D { /// The horizontal component. pub x: T, @@ -299,7 +301,7 @@ impl Neg for Size2D { /// A value that is stretchable in an interval from a minimal through an optimal /// to a maximal value. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Serialize)] pub struct StretchValue { /// The minimum this value can be stretched to. pub min: T, @@ -320,7 +322,7 @@ impl StretchValue { pub type StretchSize = StretchValue; /// A value in four dimensions. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Serialize)] pub struct ValueBox { /// The left extent. pub left: T, diff --git a/src/syntax/func/values.rs b/src/syntax/func/values.rs index d2b54a0b7..8e0c24b4f 100644 --- a/src/syntax/func/values.rs +++ b/src/syntax/func/values.rs @@ -100,9 +100,9 @@ impl From for String { } } -/// A value type that matches the string `"default"` or a value type `V` and -/// returns `Option::Some(V::Output)` for a value and `Option::None` for -/// `"default"`. +/// A value type that matches the identifier `default` or a value type `V` and +/// implements `Into