From 6410f91bd1269ad3a50289a37506ec052a5e6dbc Mon Sep 17 00:00:00 2001
From: Hristo Venev <hristo@venev.name>
Date: Mon, 30 Sep 2019 14:55:11 +0300
Subject: Don't use `#[serde(flatten)]`.

It breaks the error line numbers.
---
 src/config.rs      | 100 +++++++++++++++++++++-----
 src/manager/mod.rs |   6 +-
 src/proto.rs       | 208 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 275 insertions(+), 39 deletions(-)

(limited to 'src')

diff --git a/src/config.rs b/src/config.rs
index b755739..6269525 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -7,8 +7,8 @@ use serde_derive;
 use std::collections::HashMap;
 use std::path::PathBuf;
 
-#[serde(deny_unknown_fields)]
 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+#[serde(deny_unknown_fields)]
 pub struct Source {
     pub url: String,
     pub psk: Option<Key>,
@@ -18,21 +18,17 @@ pub struct Source {
     pub required: bool,
 }
 
-#[serde(deny_unknown_fields)]
 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+#[serde(deny_unknown_fields)]
 pub struct Peer {
     pub source: Option<String>,
     pub psk: Option<Key>,
 }
 
-#[serde(deny_unknown_fields)]
-#[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 pub struct GlobalConfig {
-    #[serde(default = "default_min_keepalive")]
     pub min_keepalive: u32,
-    #[serde(default = "default_max_keepalive")]
     pub max_keepalive: u32,
-    #[serde(default, rename = "peer")]
     pub peers: HashMap<Key, Peer>,
 }
 
@@ -59,13 +55,11 @@ impl GlobalConfig {
     }
 }
 
-#[serde(deny_unknown_fields)]
-#[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 pub struct UpdaterConfig {
     pub cache_directory: Option<PathBuf>,
 
     // Number of seconds between regular updates.
-    #[serde(default = "default_refresh_sec")]
     pub refresh_sec: u32,
 }
 
@@ -79,21 +73,93 @@ impl Default for UpdaterConfig {
     }
 }
 
-#[serde(deny_unknown_fields)]
 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Default, Clone, Debug)]
+#[serde(from = "ConfigRepr", into = "ConfigRepr")]
 pub struct Config {
     pub runtime_directory: Option<PathBuf>,
-
-    #[serde(flatten)]
     pub global: GlobalConfig,
-
-    #[serde(flatten)]
     pub updater: UpdaterConfig,
-
-    #[serde(rename = "source")]
     pub sources: HashMap<String, Source>,
 }
 
+#[derive(serde_derive::Serialize, serde_derive::Deserialize)]
+#[serde(deny_unknown_fields)]
+struct ConfigRepr {
+    runtime_directory: Option<PathBuf>,
+    cache_directory: Option<PathBuf>,
+
+    #[serde(default = "default_min_keepalive")]
+    min_keepalive: u32,
+    #[serde(default = "default_max_keepalive")]
+    max_keepalive: u32,
+    #[serde(default, rename = "peer")]
+    peers: HashMap<Key, Peer>,
+
+    #[serde(default = "default_refresh_sec")]
+    refresh_sec: u32,
+
+    #[serde(default, rename = "source")]
+    sources: HashMap<String, Source>,
+}
+
+impl From<Config> for ConfigRepr {
+    #[inline]
+    fn from(v: Config) -> Self {
+        let Config {
+            runtime_directory,
+            global,
+            updater,
+            sources,
+        } = v;
+        let GlobalConfig {
+            min_keepalive,
+            max_keepalive,
+            peers,
+        } = global;
+        let UpdaterConfig {
+            cache_directory,
+            refresh_sec,
+        } = updater;
+        Self {
+            runtime_directory,
+            cache_directory,
+            min_keepalive,
+            max_keepalive,
+            peers,
+            refresh_sec,
+            sources,
+        }
+    }
+}
+
+impl From<ConfigRepr> for Config {
+    #[inline]
+    fn from(v: ConfigRepr) -> Self {
+        let ConfigRepr {
+            runtime_directory,
+            cache_directory,
+            min_keepalive,
+            max_keepalive,
+            peers,
+            refresh_sec,
+            sources,
+        } = v;
+        Self {
+            runtime_directory,
+            global: GlobalConfig {
+                min_keepalive,
+                max_keepalive,
+                peers,
+            },
+            updater: UpdaterConfig {
+                cache_directory,
+                refresh_sec,
+            },
+            sources,
+        }
+    }
+}
+
 #[inline]
 const fn default_min_keepalive() -> u32 {
     10
diff --git a/src/manager/mod.rs b/src/manager/mod.rs
index 20ec061..8df4d23 100644
--- a/src/manager/mod.rs
+++ b/src/manager/mod.rs
@@ -139,10 +139,10 @@ impl Manager {
                 .next
                 .as_ref()
                 .and_then(|next| {
-                    if ts >= next.update_at {
-                        Some(&next.config)
+                    if ts >= next.0 {
+                        Some(&next.1)
                     } else {
-                        t_cfg = t_cfg.min(next.update_at);
+                        t_cfg = t_cfg.min(next.0);
                         None
                     }
                 })
diff --git a/src/proto.rs b/src/proto.rs
index 9421e53..e546b2f 100644
--- a/src/proto.rs
+++ b/src/proto.rs
@@ -6,55 +6,146 @@ use crate::model::{Endpoint, Ipv4Net, Ipv6Net, Key};
 use serde_derive;
 use std::time::SystemTime;
 
-#[serde(deny_unknown_fields)]
-#[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 pub struct Peer {
     pub public_key: Key,
-    #[serde(default)]
     pub ipv4: Vec<Ipv4Net>,
-    #[serde(default)]
     pub ipv6: Vec<Ipv6Net>,
 }
 
-#[serde(deny_unknown_fields)]
+#[serde(from = "ServerRepr", into = "ServerRepr")]
 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
 pub struct Server {
-    #[serde(flatten)]
     pub peer: Peer,
     pub endpoint: Endpoint,
-    #[serde(default)]
     pub keepalive: u32,
 }
 
+#[derive(serde_derive::Serialize, serde_derive::Deserialize)]
 #[serde(deny_unknown_fields)]
+struct ServerRepr {
+    public_key: Key,
+    #[serde(default)]
+    ipv4: Vec<Ipv4Net>,
+    #[serde(default)]
+    ipv6: Vec<Ipv6Net>,
+    endpoint: Endpoint,
+    #[serde(default)]
+    keepalive: u32,
+}
+
+impl From<Server> for ServerRepr {
+    #[inline]
+    fn from(v: Server) -> Self {
+        let Server {
+            peer,
+            endpoint,
+            keepalive,
+        } = v;
+        let Peer {
+            public_key,
+            ipv4,
+            ipv6,
+        } = peer;
+        Self {
+            public_key,
+            ipv4,
+            ipv6,
+            endpoint,
+            keepalive,
+        }
+    }
+}
+
+impl From<ServerRepr> for Server {
+    #[inline]
+    fn from(v: ServerRepr) -> Self {
+        let ServerRepr {
+            public_key,
+            ipv4,
+            ipv6,
+            endpoint,
+            keepalive,
+        } = v;
+        Self {
+            peer: Peer {
+                public_key,
+                ipv4,
+                ipv6,
+            },
+            endpoint,
+            keepalive,
+        }
+    }
+}
+
 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+#[serde(from = "RoadWarriorRepr", into = "RoadWarriorRepr")]
 pub struct RoadWarrior {
-    #[serde(flatten)]
     pub peer: Peer,
     pub base: Key,
 }
 
 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
-pub struct SourceConfig {
+#[serde(deny_unknown_fields)]
+pub struct RoadWarriorRepr {
+    public_key: Key,
     #[serde(default)]
-    pub servers: Vec<Server>,
+    ipv4: Vec<Ipv4Net>,
     #[serde(default)]
-    pub road_warriors: Vec<RoadWarrior>,
+    ipv6: Vec<Ipv6Net>,
+    pub base: Key,
 }
 
-#[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
-pub struct SourceNextConfig {
-    #[serde(with = "serde_utc")]
-    pub update_at: SystemTime,
-    #[serde(flatten)]
-    pub config: SourceConfig,
+impl From<RoadWarrior> for RoadWarriorRepr {
+    #[inline]
+    fn from(v: RoadWarrior) -> Self {
+        let RoadWarrior { peer, base } = v;
+        let Peer {
+            public_key,
+            ipv4,
+            ipv6,
+        } = peer;
+        Self {
+            public_key,
+            ipv4,
+            ipv6,
+            base,
+        }
+    }
+}
+
+impl From<RoadWarriorRepr> for RoadWarrior {
+    #[inline]
+    fn from(v: RoadWarriorRepr) -> Self {
+        let RoadWarriorRepr {
+            public_key,
+            ipv4,
+            ipv6,
+            base,
+        } = v;
+        Self {
+            peer: Peer {
+                public_key,
+                ipv4,
+                ipv6,
+            },
+            base,
+        }
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct SourceConfig {
+    pub servers: Vec<Server>,
+    pub road_warriors: Vec<RoadWarrior>,
 }
 
 #[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+#[serde(from = "SourceRepr", into = "SourceRepr")]
 pub struct Source {
-    #[serde(flatten)]
     pub config: SourceConfig,
-    pub next: Option<SourceNextConfig>,
+    pub next: Option<(SystemTime, SourceConfig)>,
 }
 
 impl Source {
@@ -69,6 +160,85 @@ impl Source {
     }
 }
 
+#[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+struct SourceNextRepr {
+    #[serde(default)]
+    servers: Vec<Server>,
+    #[serde(default)]
+    road_warriors: Vec<RoadWarrior>,
+    #[serde(with = "serde_utc")]
+    update_at: SystemTime,
+}
+
+#[derive(serde_derive::Serialize, serde_derive::Deserialize, Clone, PartialEq, Eq, Debug)]
+struct SourceRepr {
+    #[serde(default)]
+    servers: Vec<Server>,
+    #[serde(default)]
+    road_warriors: Vec<RoadWarrior>,
+    next: Option<SourceNextRepr>,
+}
+
+impl From<Source> for SourceRepr {
+    #[inline]
+    fn from(v: Source) -> Self {
+        let Source { config, next } = v;
+        let SourceConfig {
+            servers,
+            road_warriors,
+        } = config;
+        Self {
+            servers,
+            road_warriors,
+            next: next.map(
+                #[inline]
+                |next| {
+                    let (update_at, next) = next;
+                    SourceNextRepr {
+                        servers: next.servers,
+                        road_warriors: next.road_warriors,
+                        update_at,
+                    }
+                },
+            ),
+        }
+    }
+}
+
+impl From<SourceRepr> for Source {
+    #[inline]
+    fn from(v: SourceRepr) -> Self {
+        let SourceRepr {
+            servers,
+            road_warriors,
+            next,
+        } = v;
+        Self {
+            config: SourceConfig {
+                servers,
+                road_warriors,
+            },
+            next: next.map(
+                #[inline]
+                |next| {
+                    let SourceNextRepr {
+                        servers,
+                        road_warriors,
+                        update_at,
+                    } = next;
+                    (
+                        update_at,
+                        SourceConfig {
+                            servers,
+                            road_warriors,
+                        },
+                    )
+                },
+            ),
+        }
+    }
+}
+
 mod serde_utc {
     use chrono::{DateTime, SecondsFormat, TimeZone, Utc};
     use serde::*;
-- 
cgit