chiark / gitweb /
wip toml
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 17 Nov 2020 18:42:34 +0000 (18:42 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 18 Nov 2020 11:30:48 +0000 (11:30 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/lib.rs
src/toml.rs [new file with mode: 0644]

index 8bf731e77db1a6583d1d9ed7218370c0dac87e5b..95f543068c21e74eb5b1b225603b7e8425247ced 100644 (file)
@@ -27,4 +27,5 @@ pub mod shapelib;
 pub mod tz;
 pub mod accounts;
 pub mod config;
+pub mod toml;
 #[path="slotmap-slot-idx.rs"] pub mod slotmap_slot_idx;
diff --git a/src/toml.rs b/src/toml.rs
new file mode 100644 (file)
index 0000000..8a60562
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright 2020 Ian Jackson
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// There is NO WARRANTY.
+
+use std::fmt::{self, Display};
+use std::iter::Peekable;
+
+use fehler::throws;
+use serde::de::{Deserializer, DeserializeSeed, MapAccess, SeqAccess, Visitor};
+use thiserror::Error;
+
+#[derive(Error,Debug)]
+enum Error {
+  Custom(Box<dyn Display>),
+}
+
+impl Display for Error {
+  #[throws(fmt::Error)]
+  fn fmt(&self, f: &mut fmt::Formatter) {
+    type E = Error;
+    match self {
+      E::Custom(x) => write!(f, "toml::TomlDe::Error::Custom:{}", x)?,
+    }
+  }
+}
+
+impl serde::de::Error for Error {
+  fn custom<X: Display>(x: X) -> Self { Error::Custom(Box::new(x)) }
+}
+
+pub struct TomlDe<'de>(pub &'de toml::Value);
+
+struct SA<'de> (&'de [toml::Value]);
+
+impl<'de> SeqAccess<'de> for SA<'de> {
+  type Error = Error;
+  #[throws(Error)]
+  fn next_element_seed<T: DeserializeSeed<'de>>
+    (&mut self, seed: T) -> Option<T::Value>
+  {
+    let elem = (self.0).next()?;
+    Some(seed.deserialize(elem)?)
+  }
+  fn size_hint(&self) -> Option<usize> {
+    Some(self.0.len())
+  }
+}
+
+struct MA<'de> (Peekable<toml::map::Iter<'de>>);
+
+impl<'de> MapAccess<'de> for MA<'de> {
+  type Error = Error;
+  #[throws(Error)]
+  fn next_key_seed<K: DeserializeSeed<'de>>
+    (&mut self, seed: K) -> Option<K::Value>
+  {
+    let (k, _v) = self.0.peek()?;
+    Some(seed.deserialize(k)?)
+  }
+  #[throws(Error)]
+  fn next_value_seed<V: DeserializeSeed<'de>>
+    (&mut self, seed: V) -> V::Value
+  {
+    let (_k, v) = self.0.next().unwrap();
+    seed.deserialize(v)?
+  }
+}
+
+#[throws(Error)]
+fn visit<'de, V: Visitor<'de>>(v: &V, tv: &toml::Value) -> V::Value {
+  type TV = toml::Value;
+  match tv {
+    TV::String(s) => v.visit_borrowed_str(s)?,
+    TV::Array(a) => v.visit_seq(SA(a.as_slice()))?,
+    TV::Table(t) => v.visit_table(MA(t.iter().peekable()))?,
+  }
+}
+
+impl<'de> Deserializer<'de> for TomlDe<'de> {
+  type Error = Error;
+  #[throws(Error)]
+  fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> V::Value {
+    visit(visitor, &self.0);
+  }
+}