1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! LibreDR is an open-source ray-tracing differentiable renderer
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]

use std::path::Path;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use configparser::ini::Ini;
use anyhow::{Error, Result};
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
use tikv_jemallocator::Jemalloc;

/// Constants to configure `Render`
pub mod render;
/// `Message` type shared by Client, Server, and Worker
pub mod message;
/// `Connection` type shared by Client, Server, and Worker
pub mod connection;
/// `Geometry` type shared by Client, Server, and Worker
pub mod geometry;

#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc;

/// Global allocator for display
pub const ALLOCATOR: &str = if cfg!(all(not(target_env = "msvc"), feature = "jemalloc")) {
  "jemalloc"
} else {
  "default"
};

/// `CLAP_LONG_VERSION` for display
pub const CLAP_LONG_VERSION: &str = const_format::concatcp!(
  "LibreDR ", self::connection::build::CLAP_LONG_VERSION,
  "\nallocator:", ALLOCATOR);

/// Load an ini config file and merge it to the current config HashMap
pub fn add_config(config: &mut HashMap<String, HashMap<String, String>>,
    new_config_file: &Path) -> Result<()> {
  let new_config = Ini::new()
    .load(new_config_file)
    .map_err(|err| format!("add_config: Error loading `{}`: {err}", new_config_file.display()))
    .map_err(Error::msg)?;
  for (section_key, new_section) in new_config {
    let Entry::Occupied(mut section) = config.entry(section_key.to_owned()) else {
      eprintln!("add_config: Warning: unexpected section `{section_key}`");
      continue;
    };
    let section = section.get_mut();
    for (entry_key, value) in new_section {
      let Some(value) = value else {
        continue;
      };
      match section.entry(entry_key) {
        Entry::Occupied(mut entry) => entry.insert(value),
        Entry::Vacant(vacant) => {
          let entry_key = vacant.into_key();
          eprintln!("add_config: Warning: unexpected entry `{entry_key}` in section `{section_key}`");
          continue;
        },
      };
    }
  }
  Ok(())
}