Skip to content

Commit fc43e46

Browse files
committed
Remove serde-derive dependency
Musl target does not work with proc-macro. See rust-lang/rust#40174 Removing serde-derive allows building tectonic for musl targets.
1 parent d645924 commit fc43e46

File tree

4 files changed

+147
-51
lines changed

4 files changed

+147
-51
lines changed

Cargo.lock

-47
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ tempfile = "^3.0"
5252
md-5 = "^0.8"
5353
sha2 = "^0.8"
5454
serde = "^1.0"
55-
serde_derive = "^1.0"
5655
tectonic_xdv = { path = "xdv", version = "0.1.9-dev" }
5756
termcolor = "^1.0"
5857
toml = "^0.4"

src/config.rs

+147-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ use std::ffi::OsStr;
1616
use std::fs::File;
1717
use std::path::PathBuf;
1818
use std::sync::atomic::{AtomicBool, Ordering};
19+
use std::result;
20+
use std::fmt;
1921

2022
use app_dirs::{app_dir, app_root, get_app_root, sanitized, AppDataType};
2123
use toml;
2224

25+
use serde::de::{self, Deserialize, Deserializer, Visitor, MapAccess};
26+
2327
use errors::{ErrorKind, Result};
2428
use io::itarbundle::{HttpITarIoFactory, ITarBundle};
2529
use io::local_cache::LocalCache;
@@ -47,16 +51,157 @@ url = "https://archive.org/services/purl/net/pkgwpub/tectonic-default"
4751
"#;
4852

4953

50-
#[derive(Deserialize)]
5154
pub struct PersistentConfig {
5255
default_bundles: Vec<BundleInfo>,
5356
}
5457

55-
#[derive(Deserialize)]
58+
// Manual implementation of Deserialize because serde_derive does not work with musl
59+
// See https://github.com/rust-lang/rust/issues/40174
60+
// Implementation based on https://serde.rs/deserialize-struct.html
61+
impl<'de> Deserialize<'de> for PersistentConfig {
62+
fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
63+
where
64+
D: Deserializer<'de>,
65+
{
66+
enum Field { DefaultBundles };
67+
68+
impl<'de> Deserialize<'de> for Field {
69+
fn deserialize<D>(deserializer: D) -> result::Result<Field, D::Error>
70+
where
71+
D: Deserializer<'de>,
72+
{
73+
struct FieldVisitor;
74+
75+
impl<'de> Visitor<'de> for FieldVisitor {
76+
type Value = Field;
77+
78+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
79+
formatter.write_str("`default_bundles`")
80+
}
81+
82+
fn visit_str<E>(self, value: &str) -> result::Result<Field, E>
83+
where
84+
E: de::Error,
85+
{
86+
match value {
87+
"default_bundles" => Ok(Field::DefaultBundles),
88+
_ => Err(de::Error::unknown_field(value, FIELDS)),
89+
}
90+
}
91+
}
92+
93+
deserializer.deserialize_identifier(FieldVisitor)
94+
}
95+
}
96+
97+
struct PersistentConfigVisitor;
98+
99+
impl<'de> Visitor<'de> for PersistentConfigVisitor {
100+
type Value = PersistentConfig;
101+
102+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
103+
formatter.write_str("struct PersistentConfig")
104+
}
105+
106+
fn visit_map<V>(self, mut map: V) -> result::Result<PersistentConfig, V::Error>
107+
where
108+
V: MapAccess<'de>,
109+
{
110+
let mut default_bundles = None;
111+
while let Some(key) = map.next_key()? {
112+
match key {
113+
Field::DefaultBundles => {
114+
if default_bundles.is_some() {
115+
return Err(de::Error::duplicate_field("default_bundles"));
116+
}
117+
default_bundles = Some(map.next_value()?);
118+
}
119+
}
120+
}
121+
let default_bundles = default_bundles.ok_or_else(|| de::Error::missing_field("default_bundles"))?;
122+
Ok(PersistentConfig { default_bundles })
123+
}
124+
}
125+
126+
const FIELDS: &'static [&'static str] = &["default_bundles"];
127+
deserializer.deserialize_struct("PersistentConfig", FIELDS, PersistentConfigVisitor)
128+
}
129+
}
130+
56131
pub struct BundleInfo {
57132
url: String,
58133
}
59134

135+
impl<'de> Deserialize<'de> for BundleInfo {
136+
fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
137+
where
138+
D: Deserializer<'de>,
139+
{
140+
enum Field { Url };
141+
142+
impl<'de> Deserialize<'de> for Field {
143+
fn deserialize<D>(deserializer: D) -> result::Result<Field, D::Error>
144+
where
145+
D: Deserializer<'de>,
146+
{
147+
struct FieldVisitor;
148+
149+
impl<'de> Visitor<'de> for FieldVisitor {
150+
type Value = Field;
151+
152+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
153+
formatter.write_str("`url`")
154+
}
155+
156+
fn visit_str<E>(self, value: &str) -> result::Result<Field, E>
157+
where
158+
E: de::Error,
159+
{
160+
match value {
161+
"url" => Ok(Field::Url),
162+
_ => Err(de::Error::unknown_field(value, FIELDS)),
163+
}
164+
}
165+
}
166+
167+
deserializer.deserialize_identifier(FieldVisitor)
168+
}
169+
}
170+
171+
struct BundleInfoVisitor;
172+
173+
impl<'de> Visitor<'de> for BundleInfoVisitor {
174+
type Value = BundleInfo;
175+
176+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
177+
formatter.write_str("struct BundleInfo")
178+
}
179+
180+
fn visit_map<V>(self, mut map: V) -> result::Result<BundleInfo, V::Error>
181+
where
182+
V: MapAccess<'de>,
183+
{
184+
let mut url = None;
185+
while let Some(key) = map.next_key()? {
186+
match key {
187+
Field::Url => {
188+
if url.is_some() {
189+
return Err(de::Error::duplicate_field("url"));
190+
}
191+
url = Some(map.next_value()?);
192+
}
193+
}
194+
}
195+
let url = url.ok_or_else(|| de::Error::missing_field("url"))?;
196+
Ok(BundleInfo { url })
197+
}
198+
}
199+
200+
const FIELDS: &'static [&'static str] = &["url"];
201+
deserializer.deserialize_struct("BundleInfo", FIELDS, BundleInfoVisitor)
202+
}
203+
}
204+
60205
impl PersistentConfig {
61206
pub fn open(auto_create_config_file: bool) -> Result<PersistentConfig> {
62207
let mut cfg_path = if auto_create_config_file {

src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ extern crate hyper_native_tls;
5959
extern crate libc;
6060
extern crate md5;
6161
extern crate tempfile;
62-
#[macro_use] extern crate serde_derive;
6362
extern crate serde;
6463
extern crate sha2;
6564
extern crate tectonic_xdv;

0 commit comments

Comments
 (0)