diff --git a/Cargo.toml b/Cargo.toml index 812f4ac..6f348ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ confique-macro = { version = "=0.0.9", path = "macro" } json5 = { version = "0.4.1", optional = true } serde = { version = "1", features = ["derive"] } serde_yaml = { version = "0.9", optional = true } -toml = { version = "0.5", optional = true } +toml = { version = "0.8", optional = true } [dev-dependencies] pretty_assertions = "1.2.1" diff --git a/src/file.rs b/src/file.rs index b83e0e7..962d7ab 100644 --- a/src/file.rs +++ b/src/file.rs @@ -77,8 +77,10 @@ impl File { match self.format { #[cfg(feature = "toml")] - FileFormat::Toml => toml::from_slice(&file_content) - .map_err(|e| error(Box::new(e))), + FileFormat::Toml => { + let s = std::str::from_utf8(&file_content).map_err(|e| error(Box::new(e)))?; + toml::from_str(s).map_err(|e| error(Box::new(e))) + } #[cfg(feature = "yaml")] FileFormat::Yaml => serde_yaml::from_slice(&file_content) diff --git a/src/meta.rs b/src/meta.rs index fbe53dc..7e852be 100644 --- a/src/meta.rs +++ b/src/meta.rs @@ -140,6 +140,16 @@ impl From for Expr { } } +impl Float { + #[cfg(feature = "toml")] + pub(crate) fn is_nan(&self) -> bool { + match self { + Float::F32(f) => f.is_nan(), + Float::F64(f) => f.is_nan(), + } + } +} + fn serialize_map(map: &&'static [MapEntry], serializer: S) -> Result where S: serde::Serializer, diff --git a/src/toml.rs b/src/toml.rs index 37a3ec7..720d386 100644 --- a/src/toml.rs +++ b/src/toml.rs @@ -189,11 +189,20 @@ impl fmt::Display for PrintExpr<'_> { Ok(()) }, + // We special case floats as the TOML serializer below doesn't work + // well with floats, not rounding them appropriately. See: + // https://github.com/toml-rs/toml/issues/494 + // + // For all non-NAN floats, the `Display` output is compatible with + // TOML. + Expr::Float(fv) if !fv.is_nan() => fv.fmt(f), + // All these other types can simply be serialized as is. Expr::Str(_) | Expr::Float(_) | Expr::Integer(_) | Expr::Bool(_) | Expr::Array(_) => { - toml::to_string(&self.0) - .expect("string serialization to TOML failed") - .fmt(f) + let mut s = String::new(); + serde::Serialize::serialize(&self.0, toml::ser::ValueSerializer::new(&mut s)) + .expect("string serialization to TOML failed"); + s.fmt(f) } } }