profile
viewpoint

rtic-rs/cortex-m-rtic 563

Real-Time Interrupt-driven Concurrency (RTIC) framework for ARM Cortex-M microcontrollers

stm32-rs/stm32f1xx-hal 212

A Rust embedded-hal HAL impl for the STM32F1 family based on japarics stm32f103xx-hal

stm32-rs/stm32f4xx-hal 139

A Rust embedded-hal HAL for all MCUs in the STM32 F4 family

japaric/stm32f103xx-hal 111

HAL for the STM32F103xx family of microcontrollers

TeXitoi/blue-pill-quickstart 75

Quickstart a Rust project for the blue pill board

TeXitoi/benchmarksgame-rs 60

The Computer Language Benchmarks Game: Rust implementations

KardinalAI/coin_cbc 2

Rust bindings to the CoinOR CBC MILP Solveur using the C API.

TeXitoi/awesome-mechanical-keyboard 1

⌨️ A curated list of awesome Mechanical Keyboard resources.

pull request commentgeorust/geojson

Display GeoJSON string for geojson::Value

Thanks for clarifying! In my understanding the GitHub token included in a fork only has read access to the source repo, so even if someone modifies the workflow in a malicious fork they aren't able to modify the source. I'm basing that on some posts in the GitHub support forum.

I made the PR from a fork out of habit here, but if we want to stick with this workflow that's fine with me

pjsier

comment created time in 37 minutes

Pull request review commentgeorust/geo

#533 Add Debug for implementations for all structs

 impl<'a, T: CoordinateType> Iterator for GeometryCoordsIter<'a, T> {     } } +impl<'a, T: CoordinateType> fmt::Debug for GeometryCoordsIter<'a, T> {+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {

I think I'd expect something akin to impl Debug for Vec::Iter which includes details about the vec contents, which is more likely what you're interested in rather than just the type.

fn main() {
    let v = vec!["a", "b", "c"];
    println!("v.iter() debug: {:?}", v.iter());
    println!("v debug: {:?}", v);
}

Which outputs:

v.iter() debug: Iter(["a", "b", "c"])
v debug: ["a", "b", "c"]
martinfrances107

comment created time in 44 minutes

PR merged georust/geo

#548 Clippy: Remove the "clone on Copy type" warnings
  • [x] I agree to follow the project's code of conduct.
  • [ ] I added an entry to CHANGES.md if knowledge of this change could be valuable to users.

This is the PR associated with #548

+2 -2

1 comment

2 changed files

martinfrances107

pr closed time in an hour

push eventgeorust/geo

Martin

commit sha 6847f2504b67f17fc77e29a70ef261338aec1eae

#548 Clippy: Remove the "clone on Copy type" warnings

view details

bors[bot]

commit sha 46688687c32ff2ceaa45f8f0ea36878f5191a61a

Merge #549 549: #548 Clippy: Remove the "clone on Copy type" warnings r=michaelkirk a=martinfrances107 - [x] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md). - [ ] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users. --- This is the PR associated with #548 Co-authored-by: Martin <martinfrances107@hotmail.com>

view details

push time in an hour

issue commentgeorust/geo

Add Debug implementations for all structs

Thanks for taking a look at this @martinfrances107!

I think I'd expect something akin to impl Debug for Vec::Iter which includes details about the vec contents, which is more likely what you're interested in rather than just the type.

fn main() {
    let v = vec!["a", "b", "c"];
    println!("v.iter() debug: {:?}", v.iter());
    println!("v debug: {:?}", v);
}

Which outputs:

v.iter() debug: Iter(["a", "b", "c"])
v debug: ["a", "b", "c"]
frewsxcv

comment created time in an hour

push eventgeorust/geo

Martin

commit sha 6847f2504b67f17fc77e29a70ef261338aec1eae

#548 Clippy: Remove the "clone on Copy type" warnings

view details

bors[bot]

commit sha 46688687c32ff2ceaa45f8f0ea36878f5191a61a

Merge #549 549: #548 Clippy: Remove the "clone on Copy type" warnings r=michaelkirk a=martinfrances107 - [x] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md). - [ ] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users. --- This is the PR associated with #548 Co-authored-by: Martin <martinfrances107@hotmail.com>

view details

push time in an hour

delete branch georust/geo

delete branch : staging.tmp

delete time in an hour

push eventgeorust/geo

Martin

commit sha 6847f2504b67f17fc77e29a70ef261338aec1eae

#548 Clippy: Remove the "clone on Copy type" warnings

view details

bors[bot]

commit sha 3e8c29703d1d7b31a451cbb42430224095e9e102

[ci skip][skip ci][skip netlify] -bors-staging-tmp-549

view details

push time in an hour

create barnchgeorust/geo

branch : staging.tmp

created branch time in an hour

PR merged georust/geo

approx: Increase the minor version number #550
  • [x] I agree to follow the project's code of conduct.
  • [ ] I added an entry to CHANGES.md if knowledge of this change could be valuable to users.

Locally tests pass with this minor patch update.

+2 -2

1 comment

1 changed file

martinfrances107

pr closed time in an hour

push eventgeorust/geo

Martin

commit sha 74ea4cacf29a29f9912890d9b684d3104fd6e687

approx: Increase the minor version number #550

view details

bors[bot]

commit sha 9463016ea9ee14b5efbd273eec3e8dc3e27ecc19

Merge #551 551: approx: Increase the minor version number #550 r=michaelkirk a=martinfrances107 - [x] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md). - [ ] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users. --- Locally tests pass with this minor patch update. Co-authored-by: Martin <martinfrances107@hotmail.com>

view details

push time in an hour

pull request commentgeorust/geo

approx: Increase the minor version number #550

Build succeeded:

martinfrances107

comment created time in an hour

pull request commentgeorust/geojson

Display GeoJSON string for geojson::Value

try

Build succeeded:

pjsier

comment created time in an hour

create barnchgeorust/geojson

branch : trying

created branch time in an hour

delete branch georust/geojson

delete branch : trying.tmp

delete time in an hour

push eventgeorust/geojson

pjsier

commit sha a43f251bf8ef442d08867cd76349c373d034b108

Display GeoJSON string for geojson::Value

view details

bors[bot]

commit sha cef9afb1e02214110b28cf952b4c10625f92bbef

[ci skip][skip ci][skip netlify] -bors-staging-tmp-151

view details

push time in an hour

create barnchgeorust/geojson

branch : trying.tmp

created branch time in an hour

pull request commentgeorust/geojson

Display GeoJSON string for geojson::Value

Also noticed that this didn't trigger CI because it's only set to run on push. Is updating that to run on pull requests something that would make sense for another issue?

I haven't ever actually tested this theory or read more than cursorily, but my understanding is by running CI automatically when anyone runs a PR, we're effectively giving everyone with a GH account write access to our repository, since they can edit the workflow file in the PR (and the actions runner has a read/write GH token).

So, mostly for that reason I prefer the current workflow for this project and most of my public projects, but if there's a broad preference for an alternative (or if I'm misunderstanding), I'd be open to discussing it.

Since you already have write access to this repository, you could push up your feature branch to georust/geo rather than your fork and CI will run automatically.

People who aren't in the georust/core cannot, and so need someone with bors access for this repository to manually trigger their CI, after, presumably verifying that the PR is sane:

bors try

pjsier

comment created time in an hour

push eventgeorust/geo

Michael Kirk

commit sha ffd5c6651f04e2242dc5e4beda998bbe9b634b16

cargo fmt

view details

Michael Kirk

commit sha 48292b6e5631a8849931e535bd61aa60760f370f

Releasing geo-types-0.6.2 and geo-0.16.0

view details

Michael Kirk

commit sha fa8931be7f973f590e639b02e5c7d63fbde94673

prep for next release

view details

Michael Kirk

commit sha 63a05dd9cd6923ac10273ab5413377b817655fbd

add pr template

view details

Michael Kirk

commit sha 4125240779c3ce38cc47b130c4acff8b2867251b

Update .github/pull_request_template.md Co-authored-by: Corey Farwell <coreyf@rwell.org>

view details

Michael Kirk

commit sha 0341d3c551bb5be9a1d1d4a886ad0e066988333e

fixup! add pr template

view details

Michael Kirk

commit sha c992957ec13bb9e1106afd3e0f7e8e3840a421a9

absolute url

view details

Michael Kirk

commit sha 7ab13788d9f6c50a86cb378780ffe7584453250b

Merge pull request #545 from georust/mkirk/pr-template add pr template

view details

Martin

commit sha 74ea4cacf29a29f9912890d9b684d3104fd6e687

approx: Increase the minor version number #550

view details

bors[bot]

commit sha 9463016ea9ee14b5efbd273eec3e8dc3e27ecc19

Merge #551 551: approx: Increase the minor version number #550 r=michaelkirk a=martinfrances107 - [x] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md). - [ ] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users. --- Locally tests pass with this minor patch update. Co-authored-by: Martin <martinfrances107@hotmail.com>

view details

push time in an hour

delete branch georust/geo

delete branch : staging.tmp

delete time in an hour

push eventgeorust/geo

Martin

commit sha 74ea4cacf29a29f9912890d9b684d3104fd6e687

approx: Increase the minor version number #550

view details

bors[bot]

commit sha 7eff0ff84be8ac272f68f4bb9e9bd05d348257fc

[ci skip][skip ci][skip netlify] -bors-staging-tmp-551

view details

push time in an hour

create barnchgeorust/geo

branch : staging.tmp

created branch time in an hour

Pull request review commentCanalTP/mimirsbrunn

Osm2mimir configuration

+use config::{Config, ConfigError, File, FileFormat, Source, Value};+use failure::ResultExt;+use serde::Deserialize;+use slog_scope::{info, warn};+use std::collections::HashMap;+use std::convert::TryFrom;+use std::path::PathBuf;+use structopt::StructOpt;++use crate::osm_reader::poi;+use crate::Error;++#[derive(Debug, Clone, Deserialize)]+pub struct StreetExclusion {+    pub highways: Option<Vec<String>>,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Street {+    pub import: bool,+    pub exclusion: StreetExclusion,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Admin {+    pub import: bool,+    pub levels: Vec<u32>,+    pub city_level: u32,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Poi {+    pub import: bool,+    pub config: Option<poi::PoiConfig>,+}++#[cfg(feature = "db-storage")]+#[derive(Debug, Clone, Deserialize)]+pub struct Database {+    pub file: PathBuf,+    pub buffer_size: usize,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Elasticsearch {+    pub connection_string: String,+    pub insert_thread_count: usize,+    pub streets_shards: usize,+    pub streets_replicas: usize,+    pub admins_shards: usize,+    pub admins_replicas: usize,+    pub pois_shards: usize,+    pub pois_replicas: usize,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Settings {+    pub dataset: String,+    #[cfg(feature = "db-storage")]+    pub database: Option<Database>,+    pub elasticsearch: Elasticsearch,+    pub street: Option<Street>,+    pub poi: Option<Poi>,+    pub admin: Option<Admin>,+}++impl Settings {+    // To create settings, we first retrieve default settings, merge in specific settings if+    // needed, and finally override them with command line arguments.+    pub fn new(args: Args) -> Result<Self, Error> {+        let config_dir = args.config_dir.clone();+        let settings = args.settings.clone();++        let mut config = Config::new();+        // let config_dir = config_dir.clone();+        match config_dir {+            Some(mut dir) => {+                // Start off by merging in the "default" configuration file+                dir.push("osm2mimir-default");++                if let Some(path) = dir.to_str() {+                    info!("using configuration from {}", path);+                    // Now if the file exists, we read it, otherwise, we+                    // read from the compiled version.+                    if dir.exists() {+                        config.merge(File::with_name(path)).with_context(|e| {+                            format!(+                                "Could not merge default configuration from file {}: {}",+                                path, e+                            )+                        })?;+                    } else {+                        config+                            .merge(File::from_str(+                                include_str!("../../config/osm2mimir-default.toml"),+                                FileFormat::Toml,+                            ))+                            .with_context(|e| {+                                format!(+                                    "Could not merge default configuration from file {}: {}",+                                    path, e+                                )+                            })?;+                    }+                } else {+                    return Err(failure::err_msg(format!(+                        "Could not read default settings in '{}'",+                        dir.display()+                    )));+                }++                dir.pop(); // remove the default+                           // If we provided a special configuration, merge it.+                if let Some(settings) = settings {+                    dir.push(&settings);++                    if let Some(path) = dir.to_str() {+                        info!("using configuration from {}", path);+                        config+                            .merge(File::with_name(path).required(true))+                            .with_context(|e| {+                                format!(+                                    "Could not merge {} configuration in file {}: {}",+                                    settings, path, e+                                )+                            })?;+                    } else {+                        return Err(failure::err_msg(format!(+                            "Could not read configuration for '{}'",+                            settings,+                        )));+                    }+                    dir.pop();+                }+            }+            None => {+                if settings.is_some() {+                    // If the user set the 'settings' at the command line, he should+                    // also have used the 'config_dir' option. So we issue a warning,+                    // and leave with an error because the expected configuration can+                    // not be read.+                    warn!("settings option used without the 'config_dir' option. Please set the config directory with --config-dir.");+                    return Err(failure::err_msg(String::from(+                        "Could not build program settings",+                    )));+                }+                config+                    .merge(File::from_str(+                        include_str!("../../config/osm2mimir-default.toml"),+                        FileFormat::Toml,+                    ))+                    .with_context(|e| {+                        format!(+                            "Could not merge default configuration from file at compile time: {}",+                            e+                        )+                    })?;+            }+        }++        // Now override with command line values+        config+            .merge(args)+            .with_context(|e| format!("Could not merge arguments into configuration: {}", e))?;++        // You can deserialize (and thus freeze) the entire configuration as+        config.try_into().map_err(|e| {+            failure::err_msg(format!(+                "Could not generate settings from configuration: {}",+                e+            ))+        })+    }+}++#[derive(StructOpt, Clone, Debug)]+pub struct Args {+    /// OSM PBF file.+    #[structopt(short = "i", long = "input", parse(from_os_str))]+    pub input: PathBuf,+    /// Admin levels to keep.+    #[structopt(short = "l", long = "level")]+    level: Option<Vec<u32>>,+    /// City level to  calculate weight.+    #[structopt(short = "C", long = "city-level")]+    city_level: Option<u32>,+    /// Elasticsearch parameters.+    #[structopt(short = "c", long = "connection-string")]+    connection_string: Option<String>,+    /// Import ways.+    #[structopt(short = "w", long = "import-way")]+    import_way: bool,+    /// Import admins.+    #[structopt(short = "a", long = "import-admin")]+    import_admin: bool,+    /// Import POIs.+    #[structopt(short = "p", long = "import-poi")]+    import_poi: bool,+    /// Name of the dataset.+    #[structopt(short = "d", long = "dataset")]+    pub dataset: Option<String>,+    /// Number of shards for the admin es index+    #[structopt(long = "nb-admin-shards")]+    nb_admin_shards: Option<usize>,+    /// Number of replicas for the es index+    #[structopt(long = "nb-admin-replicas")]+    nb_admin_replicas: Option<usize>,+    /// Number of shards for the street es index+    #[structopt(long = "nb-street-shards")]+    nb_street_shards: Option<usize>,+    /// Number of replicas for the street es index+    #[structopt(long = "nb-street-replicas")]+    nb_street_replicas: Option<usize>,+    /// Number of shards for the es index+    #[structopt(long = "nb-poi-shards")]+    nb_poi_shards: Option<usize>,+    /// Number of replicas for the es index+    #[structopt(long = "nb-poi-replicas")]+    nb_poi_replicas: Option<usize>,+    /// If you use this option by providing a filename, then we+    /// will use a SQlite database that will be persisted. You+    /// can only do that if osm2mimir was compiled with the+    /// 'db-storage' feature. If you don't provide a value, then+    /// we will use in memory storage.+    #[cfg(feature = "db-storage")]+    #[structopt(long = "db-file", parse(from_os_str))]+    pub db_file: Option<PathBuf>,++    /// DB buffer size.+    #[cfg(feature = "db-storage")]+    #[structopt(long = "db-buffer-size")]+    pub db_buffer_size: Option<usize>,+    /// Number of threads to use to insert into Elasticsearch. Note that Elasticsearch is not able+    /// to handle values that are too high.+    #[structopt(short = "T", long = "nb-insert-threads")]+    nb_insert_threads: Option<usize>,++    /// Path to the config directory+    /// osm2mimir will read the default configuration in there, and maybe+    /// more depending on the settings option.+    /// If no option is given, we'll just read the ./config/osm2mimir-default.toml+    /// at compile time.+    #[structopt(short = "D", long = "config-dir")]+    config_dir: Option<PathBuf>,++    /// Specific configuration, on top of the default ones.+    /// You should provide the basename of the file, eg acme, so that+    /// osm2mimir will use {config-dir}/acme.toml. (Requires config_dir to+    /// be set)+    #[structopt(short = "s", long = "settings")]+    settings: Option<String>,+}++impl Source for Args {+    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {+        Box::new((*self).clone())+    }++    fn collect(&self) -> Result<HashMap<String, Value>, ConfigError> {+        let mut m = HashMap::new();++        // DATASET+        if let Some(dataset) = self.dataset.clone() {+            m.insert(String::from("dataset"), Value::new(None, dataset));+        }++        // ADMIN+        m.insert(+            String::from("admin.import"),+            Value::new(None, self.import_admin),+        );+        if let Some(city_level) = self.city_level {+            m.insert(+                String::from("admin.city_level"),+                Value::new(+                    None,+                    i64::try_from(city_level).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert admin city_level to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }+        if let Some(level) = self.level.clone() {+            m.insert(+                String::from("admin.levels"),+                Value::new(+                    None,+                    level.into_iter().try_fold(Vec::new(), |mut acc, l| {+                        let i = i64::try_from(l).map_err(|e| {+                            ConfigError::Message(format!(+                                "Could not convert admin city_level to integer: {}",+                                e+                            ))+                        })?;+                        acc.push(i);+                        Ok(acc)+                    })?,+                ),+            );+        }++        // WAY+        m.insert(+            String::from("street.import"),+            Value::new(None, self.import_way),+        );++        // POI+        m.insert(+            String::from("poi.import"),+            Value::new(None, self.import_poi),+        );++        // ELASTICSEARCH SETTINGS++        if let Some(connection_string) = self.connection_string.clone() {+            m.insert(+                String::from("elasticsearch.connection_string"),+                Value::new(None, connection_string),+            );+        }++        if let Some(nb_way_shards) = self.nb_street_shards {+            m.insert(+                String::from("elasticsearch.way_shards"),

:+1:

crocme10

comment created time in 2 hours

PR opened georust/geo

approx: Increase the minor version number #550
  • [ ] I agree to follow the project's code of conduct.
  • [ ] I added an entry to CHANGES.md if knowledge of this change could be valuable to users.

Locally tests pass with this minor patch update.

+2 -2

0 comment

1 changed file

pr created time in 2 hours

issue openedgeorust/geo

approx: Increase the minor version number

Looking at the packages in

geo-types/Cargo.toml

approx should be increased from 0.3.0 to 0.4.0 to reflect the latest minor release.

locally I can say tests pass...I am about to generate a PR

created time in 2 hours

Pull request review commentCanalTP/mimirsbrunn

Osm2mimir configuration

     clippy::never_loop,     clippy::option_map_unit_fn )]+ use crate::Error; use osmpbfreader::{OsmId, OsmObj, StoreObjs}; use slog_scope::info; -#[cfg(not(feature = "db-storage"))]-use slog_scope::warn;+#[cfg(feature = "db-storage")]+use crate::settings::osm2mimir::Database;++// #[cfg(not(feature = "db-storage"))]+// use slog_scope::warn;

done, thanks

crocme10

comment created time in 3 hours

Pull request review commentCanalTP/mimirsbrunn

Osm2mimir configuration

+use config::{Config, ConfigError, File, FileFormat, Source, Value};+use failure::ResultExt;+use serde::Deserialize;+use slog_scope::{info, warn};+use std::collections::HashMap;+use std::convert::TryFrom;+use std::path::PathBuf;+use structopt::StructOpt;++use crate::osm_reader::poi;+use crate::Error;++#[derive(Debug, Clone, Deserialize)]+pub struct StreetExclusion {+    pub highways: Option<Vec<String>>,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Street {+    pub import: bool,+    pub exclusion: StreetExclusion,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Admin {+    pub import: bool,+    pub levels: Vec<u32>,+    pub city_level: u32,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Poi {+    pub import: bool,+    pub config: Option<poi::PoiConfig>,+}++#[cfg(feature = "db-storage")]+#[derive(Debug, Clone, Deserialize)]+pub struct Database {+    pub file: PathBuf,+    pub buffer_size: usize,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Elasticsearch {+    pub connection_string: String,+    pub insert_thread_count: usize,+    pub streets_shards: usize,+    pub streets_replicas: usize,+    pub admins_shards: usize,+    pub admins_replicas: usize,+    pub pois_shards: usize,+    pub pois_replicas: usize,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Settings {+    pub dataset: String,+    #[cfg(feature = "db-storage")]+    pub database: Option<Database>,+    pub elasticsearch: Elasticsearch,+    pub street: Option<Street>,+    pub poi: Option<Poi>,+    pub admin: Option<Admin>,+}++impl Settings {+    // To create settings, we first retrieve default settings, merge in specific settings if+    // needed, and finally override them with command line arguments.+    pub fn new(args: Args) -> Result<Self, Error> {+        let config_dir = args.config_dir.clone();+        let settings = args.settings.clone();++        let mut config = Config::new();+        // let config_dir = config_dir.clone();+        match config_dir {+            Some(mut dir) => {+                // Start off by merging in the "default" configuration file+                dir.push("osm2mimir-default");++                if let Some(path) = dir.to_str() {+                    info!("using configuration from {}", path);+                    // Now if the file exists, we read it, otherwise, we+                    // read from the compiled version.+                    if dir.exists() {+                        config.merge(File::with_name(path)).with_context(|e| {+                            format!(+                                "Could not merge default configuration from file {}: {}",+                                path, e+                            )+                        })?;+                    } else {+                        config+                            .merge(File::from_str(+                                include_str!("../../config/osm2mimir-default.toml"),+                                FileFormat::Toml,+                            ))+                            .with_context(|e| {+                                format!(+                                    "Could not merge default configuration from file {}: {}",+                                    path, e+                                )+                            })?;+                    }+                } else {+                    return Err(failure::err_msg(format!(+                        "Could not read default settings in '{}'",+                        dir.display()+                    )));+                }++                dir.pop(); // remove the default+                           // If we provided a special configuration, merge it.+                if let Some(settings) = settings {+                    dir.push(&settings);++                    if let Some(path) = dir.to_str() {+                        info!("using configuration from {}", path);+                        config+                            .merge(File::with_name(path).required(true))+                            .with_context(|e| {+                                format!(+                                    "Could not merge {} configuration in file {}: {}",+                                    settings, path, e+                                )+                            })?;+                    } else {+                        return Err(failure::err_msg(format!(+                            "Could not read configuration for '{}'",+                            settings,+                        )));+                    }+                    dir.pop();+                }+            }+            None => {+                if settings.is_some() {+                    // If the user set the 'settings' at the command line, he should+                    // also have used the 'config_dir' option. So we issue a warning,+                    // and leave with an error because the expected configuration can+                    // not be read.+                    warn!("settings option used without the 'config_dir' option. Please set the config directory with --config-dir.");+                    return Err(failure::err_msg(String::from(+                        "Could not build program settings",+                    )));+                }+                config+                    .merge(File::from_str(+                        include_str!("../../config/osm2mimir-default.toml"),+                        FileFormat::Toml,+                    ))+                    .with_context(|e| {+                        format!(+                            "Could not merge default configuration from file at compile time: {}",+                            e+                        )+                    })?;+            }+        }++        // Now override with command line values+        config+            .merge(args)+            .with_context(|e| format!("Could not merge arguments into configuration: {}", e))?;++        // You can deserialize (and thus freeze) the entire configuration as+        config.try_into().map_err(|e| {+            failure::err_msg(format!(+                "Could not generate settings from configuration: {}",+                e+            ))+        })+    }+}++#[derive(StructOpt, Clone, Debug)]+pub struct Args {+    /// OSM PBF file.+    #[structopt(short = "i", long = "input", parse(from_os_str))]+    pub input: PathBuf,+    /// Admin levels to keep.+    #[structopt(short = "l", long = "level")]+    level: Option<Vec<u32>>,+    /// City level to  calculate weight.+    #[structopt(short = "C", long = "city-level")]+    city_level: Option<u32>,+    /// Elasticsearch parameters.+    #[structopt(short = "c", long = "connection-string")]+    connection_string: Option<String>,+    /// Import ways.+    #[structopt(short = "w", long = "import-way")]+    import_way: bool,+    /// Import admins.+    #[structopt(short = "a", long = "import-admin")]+    import_admin: bool,+    /// Import POIs.+    #[structopt(short = "p", long = "import-poi")]+    import_poi: bool,+    /// Name of the dataset.+    #[structopt(short = "d", long = "dataset")]+    pub dataset: Option<String>,+    /// Number of shards for the admin es index+    #[structopt(long = "nb-admin-shards")]+    nb_admin_shards: Option<usize>,+    /// Number of replicas for the es index+    #[structopt(long = "nb-admin-replicas")]+    nb_admin_replicas: Option<usize>,+    /// Number of shards for the street es index+    #[structopt(long = "nb-street-shards")]+    nb_street_shards: Option<usize>,+    /// Number of replicas for the street es index+    #[structopt(long = "nb-street-replicas")]+    nb_street_replicas: Option<usize>,+    /// Number of shards for the es index+    #[structopt(long = "nb-poi-shards")]+    nb_poi_shards: Option<usize>,+    /// Number of replicas for the es index+    #[structopt(long = "nb-poi-replicas")]+    nb_poi_replicas: Option<usize>,+    /// If you use this option by providing a filename, then we+    /// will use a SQlite database that will be persisted. You+    /// can only do that if osm2mimir was compiled with the+    /// 'db-storage' feature. If you don't provide a value, then+    /// we will use in memory storage.+    #[cfg(feature = "db-storage")]+    #[structopt(long = "db-file", parse(from_os_str))]+    pub db_file: Option<PathBuf>,++    /// DB buffer size.+    #[cfg(feature = "db-storage")]+    #[structopt(long = "db-buffer-size")]+    pub db_buffer_size: Option<usize>,+    /// Number of threads to use to insert into Elasticsearch. Note that Elasticsearch is not able+    /// to handle values that are too high.+    #[structopt(short = "T", long = "nb-insert-threads")]+    nb_insert_threads: Option<usize>,++    /// Path to the config directory+    /// osm2mimir will read the default configuration in there, and maybe+    /// more depending on the settings option.+    /// If no option is given, we'll just read the ./config/osm2mimir-default.toml+    /// at compile time.+    #[structopt(short = "D", long = "config-dir")]+    config_dir: Option<PathBuf>,++    /// Specific configuration, on top of the default ones.+    /// You should provide the basename of the file, eg acme, so that+    /// osm2mimir will use {config-dir}/acme.toml. (Requires config_dir to+    /// be set)+    #[structopt(short = "s", long = "settings")]+    settings: Option<String>,+}++impl Source for Args {+    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {+        Box::new((*self).clone())+    }++    fn collect(&self) -> Result<HashMap<String, Value>, ConfigError> {+        let mut m = HashMap::new();++        // DATASET+        if let Some(dataset) = self.dataset.clone() {+            m.insert(String::from("dataset"), Value::new(None, dataset));+        }++        // ADMIN+        m.insert(+            String::from("admin.import"),+            Value::new(None, self.import_admin),+        );+        if let Some(city_level) = self.city_level {+            m.insert(+                String::from("admin.city_level"),+                Value::new(+                    None,+                    i64::try_from(city_level).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert admin city_level to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }+        if let Some(level) = self.level.clone() {+            m.insert(+                String::from("admin.levels"),+                Value::new(+                    None,+                    level.into_iter().try_fold(Vec::new(), |mut acc, l| {+                        let i = i64::try_from(l).map_err(|e| {+                            ConfigError::Message(format!(+                                "Could not convert admin city_level to integer: {}",+                                e+                            ))+                        })?;+                        acc.push(i);+                        Ok(acc)+                    })?,+                ),+            );+        }++        // WAY+        m.insert(+            String::from("street.import"),+            Value::new(None, self.import_way),+        );++        // POI+        m.insert(+            String::from("poi.import"),+            Value::new(None, self.import_poi),+        );++        // ELASTICSEARCH SETTINGS++        if let Some(connection_string) = self.connection_string.clone() {+            m.insert(+                String::from("elasticsearch.connection_string"),+                Value::new(None, connection_string),+            );+        }++        if let Some(nb_way_shards) = self.nb_street_shards {+            m.insert(+                String::from("elasticsearch.way_shards"),+                Value::new(+                    None,+                    i64::try_from(nb_way_shards).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of way shards to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_way_replicas) = self.nb_street_replicas {+            m.insert(+                String::from("elasticsearch.way_replicas"),+                Value::new(+                    None,+                    i64::try_from(nb_way_replicas).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of way replicas to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_poi_shards) = self.nb_poi_shards {+            m.insert(+                String::from("elasticsearch.poi_shards"),+                Value::new(+                    None,+                    i64::try_from(nb_poi_shards).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of poi shards to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_poi_replicas) = self.nb_poi_replicas {+            m.insert(+                String::from("elasticsearch.poi_replicas"),+                Value::new(+                    None,+                    i64::try_from(nb_poi_replicas).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of poi replicas to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_admin_shards) = self.nb_admin_shards {+            m.insert(+                String::from("elasticsearch.admin_shards"),
                String::from("elasticsearch.admins_shards"),
crocme10

comment created time in 3 hours

Pull request review commentCanalTP/mimirsbrunn

Osm2mimir configuration

+use config::{Config, ConfigError, File, FileFormat, Source, Value};+use failure::ResultExt;+use serde::Deserialize;+use slog_scope::{info, warn};+use std::collections::HashMap;+use std::convert::TryFrom;+use std::path::PathBuf;+use structopt::StructOpt;++use crate::osm_reader::poi;+use crate::Error;++#[derive(Debug, Clone, Deserialize)]+pub struct StreetExclusion {+    pub highways: Option<Vec<String>>,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Street {+    pub import: bool,+    pub exclusion: StreetExclusion,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Admin {+    pub import: bool,+    pub levels: Vec<u32>,+    pub city_level: u32,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Poi {+    pub import: bool,+    pub config: Option<poi::PoiConfig>,+}++#[cfg(feature = "db-storage")]+#[derive(Debug, Clone, Deserialize)]+pub struct Database {+    pub file: PathBuf,+    pub buffer_size: usize,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Elasticsearch {+    pub connection_string: String,+    pub insert_thread_count: usize,+    pub streets_shards: usize,+    pub streets_replicas: usize,+    pub admins_shards: usize,+    pub admins_replicas: usize,+    pub pois_shards: usize,+    pub pois_replicas: usize,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Settings {+    pub dataset: String,+    #[cfg(feature = "db-storage")]+    pub database: Option<Database>,+    pub elasticsearch: Elasticsearch,+    pub street: Option<Street>,+    pub poi: Option<Poi>,+    pub admin: Option<Admin>,+}++impl Settings {+    // To create settings, we first retrieve default settings, merge in specific settings if+    // needed, and finally override them with command line arguments.+    pub fn new(args: Args) -> Result<Self, Error> {+        let config_dir = args.config_dir.clone();+        let settings = args.settings.clone();++        let mut config = Config::new();+        // let config_dir = config_dir.clone();+        match config_dir {+            Some(mut dir) => {+                // Start off by merging in the "default" configuration file+                dir.push("osm2mimir-default");++                if let Some(path) = dir.to_str() {+                    info!("using configuration from {}", path);+                    // Now if the file exists, we read it, otherwise, we+                    // read from the compiled version.+                    if dir.exists() {+                        config.merge(File::with_name(path)).with_context(|e| {+                            format!(+                                "Could not merge default configuration from file {}: {}",+                                path, e+                            )+                        })?;+                    } else {+                        config+                            .merge(File::from_str(+                                include_str!("../../config/osm2mimir-default.toml"),+                                FileFormat::Toml,+                            ))+                            .with_context(|e| {+                                format!(+                                    "Could not merge default configuration from file {}: {}",+                                    path, e+                                )+                            })?;+                    }+                } else {+                    return Err(failure::err_msg(format!(+                        "Could not read default settings in '{}'",+                        dir.display()+                    )));+                }++                dir.pop(); // remove the default+                           // If we provided a special configuration, merge it.+                if let Some(settings) = settings {+                    dir.push(&settings);++                    if let Some(path) = dir.to_str() {+                        info!("using configuration from {}", path);+                        config+                            .merge(File::with_name(path).required(true))+                            .with_context(|e| {+                                format!(+                                    "Could not merge {} configuration in file {}: {}",+                                    settings, path, e+                                )+                            })?;+                    } else {+                        return Err(failure::err_msg(format!(+                            "Could not read configuration for '{}'",+                            settings,+                        )));+                    }+                    dir.pop();+                }+            }+            None => {+                if settings.is_some() {+                    // If the user set the 'settings' at the command line, he should+                    // also have used the 'config_dir' option. So we issue a warning,+                    // and leave with an error because the expected configuration can+                    // not be read.+                    warn!("settings option used without the 'config_dir' option. Please set the config directory with --config-dir.");+                    return Err(failure::err_msg(String::from(+                        "Could not build program settings",+                    )));+                }+                config+                    .merge(File::from_str(+                        include_str!("../../config/osm2mimir-default.toml"),+                        FileFormat::Toml,+                    ))+                    .with_context(|e| {+                        format!(+                            "Could not merge default configuration from file at compile time: {}",+                            e+                        )+                    })?;+            }+        }++        // Now override with command line values+        config+            .merge(args)+            .with_context(|e| format!("Could not merge arguments into configuration: {}", e))?;++        // You can deserialize (and thus freeze) the entire configuration as+        config.try_into().map_err(|e| {+            failure::err_msg(format!(+                "Could not generate settings from configuration: {}",+                e+            ))+        })+    }+}++#[derive(StructOpt, Clone, Debug)]+pub struct Args {+    /// OSM PBF file.+    #[structopt(short = "i", long = "input", parse(from_os_str))]+    pub input: PathBuf,+    /// Admin levels to keep.+    #[structopt(short = "l", long = "level")]+    level: Option<Vec<u32>>,+    /// City level to  calculate weight.+    #[structopt(short = "C", long = "city-level")]+    city_level: Option<u32>,+    /// Elasticsearch parameters.+    #[structopt(short = "c", long = "connection-string")]+    connection_string: Option<String>,+    /// Import ways.+    #[structopt(short = "w", long = "import-way")]+    import_way: bool,+    /// Import admins.+    #[structopt(short = "a", long = "import-admin")]+    import_admin: bool,+    /// Import POIs.+    #[structopt(short = "p", long = "import-poi")]+    import_poi: bool,+    /// Name of the dataset.+    #[structopt(short = "d", long = "dataset")]+    pub dataset: Option<String>,+    /// Number of shards for the admin es index+    #[structopt(long = "nb-admin-shards")]+    nb_admin_shards: Option<usize>,+    /// Number of replicas for the es index+    #[structopt(long = "nb-admin-replicas")]+    nb_admin_replicas: Option<usize>,+    /// Number of shards for the street es index+    #[structopt(long = "nb-street-shards")]+    nb_street_shards: Option<usize>,+    /// Number of replicas for the street es index+    #[structopt(long = "nb-street-replicas")]+    nb_street_replicas: Option<usize>,+    /// Number of shards for the es index+    #[structopt(long = "nb-poi-shards")]+    nb_poi_shards: Option<usize>,+    /// Number of replicas for the es index+    #[structopt(long = "nb-poi-replicas")]+    nb_poi_replicas: Option<usize>,+    /// If you use this option by providing a filename, then we+    /// will use a SQlite database that will be persisted. You+    /// can only do that if osm2mimir was compiled with the+    /// 'db-storage' feature. If you don't provide a value, then+    /// we will use in memory storage.+    #[cfg(feature = "db-storage")]+    #[structopt(long = "db-file", parse(from_os_str))]+    pub db_file: Option<PathBuf>,++    /// DB buffer size.+    #[cfg(feature = "db-storage")]+    #[structopt(long = "db-buffer-size")]+    pub db_buffer_size: Option<usize>,+    /// Number of threads to use to insert into Elasticsearch. Note that Elasticsearch is not able+    /// to handle values that are too high.+    #[structopt(short = "T", long = "nb-insert-threads")]+    nb_insert_threads: Option<usize>,++    /// Path to the config directory+    /// osm2mimir will read the default configuration in there, and maybe+    /// more depending on the settings option.+    /// If no option is given, we'll just read the ./config/osm2mimir-default.toml+    /// at compile time.+    #[structopt(short = "D", long = "config-dir")]+    config_dir: Option<PathBuf>,++    /// Specific configuration, on top of the default ones.+    /// You should provide the basename of the file, eg acme, so that+    /// osm2mimir will use {config-dir}/acme.toml. (Requires config_dir to+    /// be set)+    #[structopt(short = "s", long = "settings")]+    settings: Option<String>,+}++impl Source for Args {+    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {+        Box::new((*self).clone())+    }++    fn collect(&self) -> Result<HashMap<String, Value>, ConfigError> {+        let mut m = HashMap::new();++        // DATASET+        if let Some(dataset) = self.dataset.clone() {+            m.insert(String::from("dataset"), Value::new(None, dataset));+        }++        // ADMIN+        m.insert(+            String::from("admin.import"),+            Value::new(None, self.import_admin),+        );+        if let Some(city_level) = self.city_level {+            m.insert(+                String::from("admin.city_level"),+                Value::new(+                    None,+                    i64::try_from(city_level).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert admin city_level to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }+        if let Some(level) = self.level.clone() {+            m.insert(+                String::from("admin.levels"),+                Value::new(+                    None,+                    level.into_iter().try_fold(Vec::new(), |mut acc, l| {+                        let i = i64::try_from(l).map_err(|e| {+                            ConfigError::Message(format!(+                                "Could not convert admin city_level to integer: {}",+                                e+                            ))+                        })?;+                        acc.push(i);+                        Ok(acc)+                    })?,+                ),+            );+        }++        // WAY+        m.insert(+            String::from("street.import"),+            Value::new(None, self.import_way),+        );++        // POI+        m.insert(+            String::from("poi.import"),+            Value::new(None, self.import_poi),+        );++        // ELASTICSEARCH SETTINGS++        if let Some(connection_string) = self.connection_string.clone() {+            m.insert(+                String::from("elasticsearch.connection_string"),+                Value::new(None, connection_string),+            );+        }++        if let Some(nb_way_shards) = self.nb_street_shards {+            m.insert(+                String::from("elasticsearch.way_shards"),

Inconsistent with the Settings struct:

                String::from("elasticsearch.streets_shards"),
crocme10

comment created time in 3 hours

Pull request review commentCanalTP/mimirsbrunn

Osm2mimir configuration

+use config::{Config, ConfigError, File, FileFormat, Source, Value};+use failure::ResultExt;+use serde::Deserialize;+use slog_scope::{info, warn};+use std::collections::HashMap;+use std::convert::TryFrom;+use std::path::PathBuf;+use structopt::StructOpt;++use crate::osm_reader::poi;+use crate::Error;++#[derive(Debug, Clone, Deserialize)]+pub struct StreetExclusion {+    pub highways: Option<Vec<String>>,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Street {+    pub import: bool,+    pub exclusion: StreetExclusion,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Admin {+    pub import: bool,+    pub levels: Vec<u32>,+    pub city_level: u32,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Poi {+    pub import: bool,+    pub config: Option<poi::PoiConfig>,+}++#[cfg(feature = "db-storage")]+#[derive(Debug, Clone, Deserialize)]+pub struct Database {+    pub file: PathBuf,+    pub buffer_size: usize,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Elasticsearch {+    pub connection_string: String,+    pub insert_thread_count: usize,+    pub streets_shards: usize,+    pub streets_replicas: usize,+    pub admins_shards: usize,+    pub admins_replicas: usize,+    pub pois_shards: usize,+    pub pois_replicas: usize,+}++#[derive(Debug, Clone, Deserialize)]+pub struct Settings {+    pub dataset: String,+    #[cfg(feature = "db-storage")]+    pub database: Option<Database>,+    pub elasticsearch: Elasticsearch,+    pub street: Option<Street>,+    pub poi: Option<Poi>,+    pub admin: Option<Admin>,+}++impl Settings {+    // To create settings, we first retrieve default settings, merge in specific settings if+    // needed, and finally override them with command line arguments.+    pub fn new(args: Args) -> Result<Self, Error> {+        let config_dir = args.config_dir.clone();+        let settings = args.settings.clone();++        let mut config = Config::new();+        // let config_dir = config_dir.clone();+        match config_dir {+            Some(mut dir) => {+                // Start off by merging in the "default" configuration file+                dir.push("osm2mimir-default");++                if let Some(path) = dir.to_str() {+                    info!("using configuration from {}", path);+                    // Now if the file exists, we read it, otherwise, we+                    // read from the compiled version.+                    if dir.exists() {+                        config.merge(File::with_name(path)).with_context(|e| {+                            format!(+                                "Could not merge default configuration from file {}: {}",+                                path, e+                            )+                        })?;+                    } else {+                        config+                            .merge(File::from_str(+                                include_str!("../../config/osm2mimir-default.toml"),+                                FileFormat::Toml,+                            ))+                            .with_context(|e| {+                                format!(+                                    "Could not merge default configuration from file {}: {}",+                                    path, e+                                )+                            })?;+                    }+                } else {+                    return Err(failure::err_msg(format!(+                        "Could not read default settings in '{}'",+                        dir.display()+                    )));+                }++                dir.pop(); // remove the default+                           // If we provided a special configuration, merge it.+                if let Some(settings) = settings {+                    dir.push(&settings);++                    if let Some(path) = dir.to_str() {+                        info!("using configuration from {}", path);+                        config+                            .merge(File::with_name(path).required(true))+                            .with_context(|e| {+                                format!(+                                    "Could not merge {} configuration in file {}: {}",+                                    settings, path, e+                                )+                            })?;+                    } else {+                        return Err(failure::err_msg(format!(+                            "Could not read configuration for '{}'",+                            settings,+                        )));+                    }+                    dir.pop();+                }+            }+            None => {+                if settings.is_some() {+                    // If the user set the 'settings' at the command line, he should+                    // also have used the 'config_dir' option. So we issue a warning,+                    // and leave with an error because the expected configuration can+                    // not be read.+                    warn!("settings option used without the 'config_dir' option. Please set the config directory with --config-dir.");+                    return Err(failure::err_msg(String::from(+                        "Could not build program settings",+                    )));+                }+                config+                    .merge(File::from_str(+                        include_str!("../../config/osm2mimir-default.toml"),+                        FileFormat::Toml,+                    ))+                    .with_context(|e| {+                        format!(+                            "Could not merge default configuration from file at compile time: {}",+                            e+                        )+                    })?;+            }+        }++        // Now override with command line values+        config+            .merge(args)+            .with_context(|e| format!("Could not merge arguments into configuration: {}", e))?;++        // You can deserialize (and thus freeze) the entire configuration as+        config.try_into().map_err(|e| {+            failure::err_msg(format!(+                "Could not generate settings from configuration: {}",+                e+            ))+        })+    }+}++#[derive(StructOpt, Clone, Debug)]+pub struct Args {+    /// OSM PBF file.+    #[structopt(short = "i", long = "input", parse(from_os_str))]+    pub input: PathBuf,+    /// Admin levels to keep.+    #[structopt(short = "l", long = "level")]+    level: Option<Vec<u32>>,+    /// City level to  calculate weight.+    #[structopt(short = "C", long = "city-level")]+    city_level: Option<u32>,+    /// Elasticsearch parameters.+    #[structopt(short = "c", long = "connection-string")]+    connection_string: Option<String>,+    /// Import ways.+    #[structopt(short = "w", long = "import-way")]+    import_way: bool,+    /// Import admins.+    #[structopt(short = "a", long = "import-admin")]+    import_admin: bool,+    /// Import POIs.+    #[structopt(short = "p", long = "import-poi")]+    import_poi: bool,+    /// Name of the dataset.+    #[structopt(short = "d", long = "dataset")]+    pub dataset: Option<String>,+    /// Number of shards for the admin es index+    #[structopt(long = "nb-admin-shards")]+    nb_admin_shards: Option<usize>,+    /// Number of replicas for the es index+    #[structopt(long = "nb-admin-replicas")]+    nb_admin_replicas: Option<usize>,+    /// Number of shards for the street es index+    #[structopt(long = "nb-street-shards")]+    nb_street_shards: Option<usize>,+    /// Number of replicas for the street es index+    #[structopt(long = "nb-street-replicas")]+    nb_street_replicas: Option<usize>,+    /// Number of shards for the es index+    #[structopt(long = "nb-poi-shards")]+    nb_poi_shards: Option<usize>,+    /// Number of replicas for the es index+    #[structopt(long = "nb-poi-replicas")]+    nb_poi_replicas: Option<usize>,+    /// If you use this option by providing a filename, then we+    /// will use a SQlite database that will be persisted. You+    /// can only do that if osm2mimir was compiled with the+    /// 'db-storage' feature. If you don't provide a value, then+    /// we will use in memory storage.+    #[cfg(feature = "db-storage")]+    #[structopt(long = "db-file", parse(from_os_str))]+    pub db_file: Option<PathBuf>,++    /// DB buffer size.+    #[cfg(feature = "db-storage")]+    #[structopt(long = "db-buffer-size")]+    pub db_buffer_size: Option<usize>,+    /// Number of threads to use to insert into Elasticsearch. Note that Elasticsearch is not able+    /// to handle values that are too high.+    #[structopt(short = "T", long = "nb-insert-threads")]+    nb_insert_threads: Option<usize>,++    /// Path to the config directory+    /// osm2mimir will read the default configuration in there, and maybe+    /// more depending on the settings option.+    /// If no option is given, we'll just read the ./config/osm2mimir-default.toml+    /// at compile time.+    #[structopt(short = "D", long = "config-dir")]+    config_dir: Option<PathBuf>,++    /// Specific configuration, on top of the default ones.+    /// You should provide the basename of the file, eg acme, so that+    /// osm2mimir will use {config-dir}/acme.toml. (Requires config_dir to+    /// be set)+    #[structopt(short = "s", long = "settings")]+    settings: Option<String>,+}++impl Source for Args {+    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {+        Box::new((*self).clone())+    }++    fn collect(&self) -> Result<HashMap<String, Value>, ConfigError> {+        let mut m = HashMap::new();++        // DATASET+        if let Some(dataset) = self.dataset.clone() {+            m.insert(String::from("dataset"), Value::new(None, dataset));+        }++        // ADMIN+        m.insert(+            String::from("admin.import"),+            Value::new(None, self.import_admin),+        );+        if let Some(city_level) = self.city_level {+            m.insert(+                String::from("admin.city_level"),+                Value::new(+                    None,+                    i64::try_from(city_level).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert admin city_level to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }+        if let Some(level) = self.level.clone() {+            m.insert(+                String::from("admin.levels"),+                Value::new(+                    None,+                    level.into_iter().try_fold(Vec::new(), |mut acc, l| {+                        let i = i64::try_from(l).map_err(|e| {+                            ConfigError::Message(format!(+                                "Could not convert admin city_level to integer: {}",+                                e+                            ))+                        })?;+                        acc.push(i);+                        Ok(acc)+                    })?,+                ),+            );+        }++        // WAY+        m.insert(+            String::from("street.import"),+            Value::new(None, self.import_way),+        );++        // POI+        m.insert(+            String::from("poi.import"),+            Value::new(None, self.import_poi),+        );++        // ELASTICSEARCH SETTINGS++        if let Some(connection_string) = self.connection_string.clone() {+            m.insert(+                String::from("elasticsearch.connection_string"),+                Value::new(None, connection_string),+            );+        }++        if let Some(nb_way_shards) = self.nb_street_shards {+            m.insert(+                String::from("elasticsearch.way_shards"),+                Value::new(+                    None,+                    i64::try_from(nb_way_shards).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of way shards to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_way_replicas) = self.nb_street_replicas {+            m.insert(+                String::from("elasticsearch.way_replicas"),+                Value::new(+                    None,+                    i64::try_from(nb_way_replicas).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of way replicas to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_poi_shards) = self.nb_poi_shards {+            m.insert(+                String::from("elasticsearch.poi_shards"),+                Value::new(+                    None,+                    i64::try_from(nb_poi_shards).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of poi shards to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_poi_replicas) = self.nb_poi_replicas {+            m.insert(+                String::from("elasticsearch.poi_replicas"),+                Value::new(+                    None,+                    i64::try_from(nb_poi_replicas).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of poi replicas to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_admin_shards) = self.nb_admin_shards {+            m.insert(+                String::from("elasticsearch.admin_shards"),+                Value::new(+                    None,+                    i64::try_from(nb_admin_shards).map_err(|e| {+                        ConfigError::Message(format!(+                            "Could not convert count of admin shards to integer: {}",+                            e+                        ))+                    })?,+                ),+            );+        }++        if let Some(nb_admin_replicas) = self.nb_admin_replicas {+            m.insert(+                String::from("elasticsearch.admin_replicas"),
                String::from("elasticsearch.admins_replicas"),
crocme10

comment created time in 3 hours

more