Use toml_config in all applicable crates; add toml_config enum support

This commit is contained in:
Joakim Frostegård
2021-12-23 16:56:17 +01:00
parent 7892a23c8f
commit 2242bedf92
23 changed files with 160 additions and 88 deletions
Generated
+9
View File
@@ -62,6 +62,7 @@ dependencies = [
"serde",
"simplelog",
"toml",
"toml_config",
]
[[package]]
@@ -80,6 +81,7 @@ dependencies = [
"privdrop",
"rand",
"serde",
"toml_config",
]
[[package]]
@@ -109,6 +111,7 @@ dependencies = [
"signal-hook",
"slab",
"smartstring",
"toml_config",
]
[[package]]
@@ -130,6 +133,7 @@ dependencies = [
"rand_distr",
"rustls",
"serde",
"toml_config",
]
[[package]]
@@ -179,6 +183,7 @@ dependencies = [
"slab",
"socket2 0.4.2",
"tinytemplate",
"toml_config",
]
[[package]]
@@ -196,6 +201,7 @@ dependencies = [
"rand",
"rand_distr",
"serde",
"toml_config",
]
[[package]]
@@ -215,6 +221,7 @@ dependencies = [
"rand_distr",
"serde",
"socket2 0.4.2",
"toml_config",
]
[[package]]
@@ -259,6 +266,7 @@ dependencies = [
"signal-hook",
"slab",
"socket2 0.4.2",
"toml_config",
"tungstenite",
]
@@ -284,6 +292,7 @@ dependencies = [
"rustls",
"serde",
"serde_json",
"toml_config",
"tungstenite",
]
+1
View File
@@ -12,3 +12,4 @@ anyhow = "1"
serde = { version = "1", features = ["derive"] }
simplelog = "0.11"
toml = "0.5"
toml_config = "0.1.0"
+5 -4
View File
@@ -4,8 +4,9 @@ use std::io::Read;
use anyhow::Context;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use simplelog::{ColorChoice, ConfigBuilder, LevelFilter, TermLogger, TerminalMode};
use toml_config::TomlConfig;
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, TomlConfig, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LogLevel {
Off,
@@ -22,7 +23,7 @@ impl Default for LogLevel {
}
}
pub trait Config: Default + Serialize + DeserializeOwned {
pub trait Config: Default + TomlConfig + DeserializeOwned {
fn get_log_level(&self) -> Option<LogLevel> {
None
}
@@ -169,9 +170,9 @@ where
fn default_config_as_toml<T>() -> String
where
T: Default + Serialize,
T: Default + TomlConfig,
{
toml::to_string_pretty(&T::default()).expect("Could not serialize default config to toml")
<T as TomlConfig>::default_to_string()
}
fn start_logger(log_level: LogLevel) -> ::anyhow::Result<()> {
+1
View File
@@ -24,6 +24,7 @@ log = "0.4"
privdrop = "0.5"
rand = { version = "0.8", features = ["small_rng"] }
serde = { version = "1", features = ["derive"] }
toml_config = "0.1.0"
# cpu-pinning
hwloc = { version = "0.5", optional = true }
+3 -2
View File
@@ -7,8 +7,9 @@ use anyhow::Context;
use arc_swap::{ArcSwap, Cache};
use hashbrown::HashSet;
use serde::{Deserialize, Serialize};
use toml_config::TomlConfig;
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
#[derive(Clone, Copy, Debug, TomlConfig, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AccessListMode {
/// Only serve torrents with info hash present in file
@@ -25,7 +26,7 @@ impl AccessListMode {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
pub struct AccessListConfig {
pub mode: AccessListMode,
/// Path to access list file consisting of newline-separated hex-encoded info hashes.
+3 -2
View File
@@ -1,7 +1,8 @@
use hwloc::{CpuSet, ObjectType, Topology, CPUBIND_THREAD};
use serde::{Deserialize, Serialize};
use toml_config::TomlConfig;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CpuPinningMode {
Ascending,
@@ -14,7 +15,7 @@ impl Default for CpuPinningMode {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
pub struct CpuPinningConfig {
pub active: bool,
pub mode: CpuPinningMode,
+3 -2
View File
@@ -7,9 +7,10 @@ use std::{
};
use privdrop::PrivDrop;
use serde::{Deserialize, Serialize};
use serde::{Deserialize};
use toml_config::TomlConfig;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct PrivilegeConfig {
/// Chroot and switch user after binding to sockets
+1
View File
@@ -38,6 +38,7 @@ serde = { version = "1", features = ["derive"] }
signal-hook = { version = "0.3" }
slab = "0.4"
smartstring = "0.2"
toml_config = "0.1.0"
[dev-dependencies]
quickcheck = "1"
+6 -5
View File
@@ -1,11 +1,12 @@
use std::{net::SocketAddr, path::PathBuf};
use aquatic_common::{access_list::AccessListConfig, privileges::PrivilegeConfig};
use serde::{Deserialize, Serialize};
use serde::{Deserialize};
use toml_config::TomlConfig;
use aquatic_cli_helpers::LogLevel;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct Config {
/// Socket workers receive requests from the socket, parse them and send
@@ -31,7 +32,7 @@ impl aquatic_cli_helpers::Config for Config {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct NetworkConfig {
/// Bind to this address
@@ -42,7 +43,7 @@ pub struct NetworkConfig {
pub keep_alive: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct ProtocolConfig {
/// Maximum number of torrents to accept in scrape request
@@ -53,7 +54,7 @@ pub struct ProtocolConfig {
pub peer_announce_interval: usize,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct CleaningConfig {
/// Clean peers this often (seconds)
+1
View File
@@ -26,6 +26,7 @@ rand = { version = "0.8", features = ["small_rng"] }
rand_distr = "0.4"
rustls = { version = "0.20", features = ["dangerous_configuration"] }
serde = { version = "1", features = ["derive"] }
toml_config = "0.1.0"
[dev-dependencies]
quickcheck = "1"
+4 -3
View File
@@ -1,9 +1,10 @@
use std::net::SocketAddr;
use aquatic_cli_helpers::LogLevel;
use serde::{Deserialize, Serialize};
use serde::{Deserialize};
use toml_config::TomlConfig;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct Config {
pub server_address: SocketAddr,
@@ -28,7 +29,7 @@ impl aquatic_cli_helpers::Config for Config {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct TorrentConfig {
pub number_of_torrents: usize,
+1
View File
@@ -36,6 +36,7 @@ slab = "0.4"
signal-hook = { version = "0.3" }
socket2 = { version = "0.4", features = ["all"] }
tinytemplate = "1"
toml_config = "0.1.0"
[dev-dependencies]
quickcheck = "1"
+7 -6
View File
@@ -1,11 +1,12 @@
use std::{net::SocketAddr, path::PathBuf};
use aquatic_common::{access_list::AccessListConfig, privileges::PrivilegeConfig};
use serde::{Deserialize, Serialize};
use serde::{Deserialize};
use aquatic_cli_helpers::LogLevel;
use toml_config::TomlConfig;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct Config {
/// Socket workers receive requests from the socket, parse them and send
@@ -62,7 +63,7 @@ impl aquatic_cli_helpers::Config for Config {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct NetworkConfig {
/// Bind to this address
@@ -108,7 +109,7 @@ impl Default for NetworkConfig {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct ProtocolConfig {
/// Maximum number of torrents to accept in scrape request
@@ -129,7 +130,7 @@ impl Default for ProtocolConfig {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct StatisticsConfig {
/// Collect and print/write statistics this often (seconds)
@@ -159,7 +160,7 @@ impl Default for StatisticsConfig {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct CleaningConfig {
/// Clean connections this often (seconds)
+1
View File
@@ -21,3 +21,4 @@ num-format = "0.4"
rand = { version = "0.8", features = ["small_rng"] }
rand_distr = "0.4"
serde = { version = "1", features = ["derive"] }
toml_config = "0.1.0"
+3 -2
View File
@@ -1,6 +1,7 @@
use serde::{Deserialize, Serialize};
use serde::{Deserialize};
use toml_config::TomlConfig;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
pub struct BenchConfig {
pub num_rounds: usize,
pub num_threads: usize,
+1
View File
@@ -24,6 +24,7 @@ rand = { version = "0.8", features = ["small_rng"] }
rand_distr = "0.4"
serde = { version = "1", features = ["derive"] }
socket2 = { version = "0.4", features = ["all"] }
toml_config = "0.1.0"
[dev-dependencies]
quickcheck = "1"
+5 -4
View File
@@ -1,12 +1,13 @@
use std::net::SocketAddr;
use serde::{Deserialize, Serialize};
use serde::{Deserialize};
use aquatic_cli_helpers::LogLevel;
#[cfg(feature = "cpu-pinning")]
use aquatic_common::cpu_pinning::CpuPinningConfig;
use toml_config::TomlConfig;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct Config {
/// Server address
@@ -39,7 +40,7 @@ impl Default for Config {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct NetworkConfig {
/// True means bind to one localhost IP per socket.
@@ -84,7 +85,7 @@ impl Default for NetworkConfig {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct RequestConfig {
/// Number of torrents to simulate
+1
View File
@@ -36,6 +36,7 @@ rustls-pemfile = "0.2"
serde = { version = "1", features = ["derive"] }
signal-hook = { version = "0.3" }
slab = "0.4"
toml_config = "0.1.0"
tungstenite = "0.16"
# mio
+8 -7
View File
@@ -4,11 +4,12 @@ use std::path::PathBuf;
#[cfg(feature = "cpu-pinning")]
use aquatic_common::cpu_pinning::CpuPinningConfig;
use aquatic_common::{access_list::AccessListConfig, privileges::PrivilegeConfig};
use serde::{Deserialize, Serialize};
use serde::{Deserialize};
use aquatic_cli_helpers::LogLevel;
use toml_config::TomlConfig;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct Config {
/// Socket workers receive requests from the socket, parse them and send
@@ -38,7 +39,7 @@ impl aquatic_cli_helpers::Config for Config {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct NetworkConfig {
/// Bind to this address
@@ -56,7 +57,7 @@ pub struct NetworkConfig {
pub poll_timeout_microseconds: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct ProtocolConfig {
/// Maximum number of torrents to accept in scrape request
@@ -68,7 +69,7 @@ pub struct ProtocolConfig {
}
#[cfg(feature = "with-mio")]
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct HandlerConfig {
/// Maximum number of requests to receive from channel before locking
@@ -77,7 +78,7 @@ pub struct HandlerConfig {
pub channel_recv_timeout_microseconds: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct CleaningConfig {
/// Clean peers this often (seconds)
@@ -98,7 +99,7 @@ pub struct CleaningConfig {
}
#[cfg(feature = "with-mio")]
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct StatisticsConfig {
/// Print statistics this often (seconds). Don't print when set to zero.
+1
View File
@@ -29,6 +29,7 @@ rand_distr = "0.4"
rustls = { version = "0.20", features = ["dangerous_configuration"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
toml_config = "0.1.0"
tungstenite = "0.16"
[dev-dependencies]
+4 -3
View File
@@ -3,9 +3,10 @@ use std::net::SocketAddr;
use aquatic_cli_helpers::LogLevel;
#[cfg(feature = "cpu-pinning")]
use aquatic_common::cpu_pinning::CpuPinningConfig;
use serde::{Deserialize, Serialize};
use serde::{Deserialize};
use toml_config::TomlConfig;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct Config {
pub server_address: SocketAddr,
@@ -41,7 +42,7 @@ impl Default for Config {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, TomlConfig, Deserialize)]
#[serde(default)]
pub struct TorrentConfig {
pub offers_per_request: usize,
+20 -1
View File
@@ -1,3 +1,4 @@
pub use toml;
pub use toml_config_derive::TomlConfig;
/// Run this on your struct implementing TomlConfig to generate a test for it
@@ -69,8 +70,9 @@ pub trait TomlConfig: Default {
pub mod __private {
use std::path::PathBuf;
use std::net::SocketAddr;
pub trait Private: Default {
pub trait Private {
fn __to_string(&self, comment: Option<String>, field_name: String) -> String;
}
@@ -94,8 +96,25 @@ pub mod __private {
};
}
impl_trait!(isize);
impl_trait!(i8);
impl_trait!(i16);
impl_trait!(i32);
impl_trait!(i64);
impl_trait!(usize);
impl_trait!(u8);
impl_trait!(u16);
impl_trait!(u32);
impl_trait!(u64);
impl_trait!(f32);
impl_trait!(f64);
impl_trait!(bool);
impl_trait!(String);
impl_trait!(PathBuf);
impl_trait!(SocketAddr);
}
+71 -47
View File
@@ -1,6 +1,6 @@
use proc_macro2::{TokenStream, TokenTree};
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Type, Attribute, Ident, Data, Fields};
use syn::{parse_macro_input, DeriveInput, Type, Attribute, Ident, Data, Fields, DataStruct};
#[proc_macro_derive(TomlConfig)]
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
@@ -9,72 +9,96 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let comment = extract_comment_string(input.attrs);
let ident = input.ident;
let mut output_stream = quote! {
let mut output = String::new();
};
extract_from_struct(ident.clone(), input.data, &mut output_stream);
let expanded = quote! {
impl ::toml_config::TomlConfig for #ident {
fn default_to_string() -> String {
match input.data {
Data::Struct(struct_data) => {
let mut output_stream = quote! {
let mut output = String::new();
};
let comment: Option<String> = #comment;
extract_from_struct(ident.clone(), struct_data, &mut output_stream);
if let Some(comment) = comment {
output.push_str(&comment);
output.push('\n');
let expanded = quote! {
impl ::toml_config::TomlConfig for #ident {
fn default_to_string() -> String {
let mut output = String::new();
let comment: Option<String> = #comment;
if let Some(comment) = comment {
output.push_str(&comment);
output.push('\n');
}
let body = {
#output_stream
output
};
output.push_str(&body);
output
}
}
impl ::toml_config::__private::Private for #ident {
fn __to_string(&self, comment: Option<String>, field_name: String) -> String {
let mut output = String::new();
let body = {
#output_stream
output.push('\n');
output
};
if let Some(comment) = comment {
output.push_str(&comment);
}
output.push_str(&format!("[{}]\n", field_name));
output.push_str(&body);
let body = {
#output_stream
output
}
}
impl ::toml_config::__private::Private for #ident {
fn __to_string(&self, comment: Option<String>, field_name: String) -> String {
let mut output = String::new();
output
};
output.push('\n');
output.push_str(&body);
if let Some(comment) = comment {
output.push_str(&comment);
output
}
}
output.push_str(&format!("[{}]\n", field_name));
};
let body = {
#output_stream
output
};
output.push_str(&body);
output
}
proc_macro::TokenStream::from(expanded)
}
};
Data::Enum(_) => {
let expanded = quote! {
impl ::toml_config::__private::Private for #ident {
fn __to_string(&self, comment: Option<String>, field_name: String) -> String {
let mut output = String::new();
proc_macro::TokenStream::from(expanded)
if let Some(comment) = comment {
output.push_str(&comment);
}
let value = match ::toml_config::toml::ser::to_string(self) {
Ok(value) => value,
Err(err) => panic!("Couldn't serialize enum to toml: {:#}", err),
};
output.push_str(&format!("{} = {}\n", field_name, value));
output
}
}
};
proc_macro::TokenStream::from(expanded)
}
Data::Union(_) => panic!("Unions are not supported"),
}
}
fn extract_from_struct(
struct_ty_ident: Ident,
struct_data: Data,
struct_data: DataStruct,
output_stream: &mut TokenStream
) {
let struct_data = if let Data::Struct(data) = struct_data {
data
} else {
panic!("Not a struct");
};
let fields = if let Fields::Named(fields) = struct_data.fields {
fields
} else {