From 81addda9ecd3c93e54cf45ad196627537ea44f11 Mon Sep 17 00:00:00 2001
From: Kubat <mael.martin31@gmail.com>
Date: Wed, 25 Jan 2023 00:15:54 +0100
Subject: [PATCH] RUST: Continue C <-> Rust bindings + we will handle the
 config on the rust side of the force

---
 .vscode/settings.json                |  22 ++---
 CMakeLists.txt                       |   1 -
 inc/liblektor-rs/config.h            |  18 ++++
 inc/liblektor-rs/queue.h             |   2 +-
 src/main/server.c                    |  10 +-
 src/rust/Cargo.toml                  |   1 +
 src/rust/lektor_config/Cargo.toml    |  13 +++
 src/rust/lektor_config/src/config.rs | 139 +++++++++++++++++++++++++++
 src/rust/lektor_config/src/lib.rs    |   2 +
 src/rust/lektor_unsafe/Cargo.toml    |   3 +
 src/rust/lektor_unsafe/src/config.rs |  57 +++++++++++
 src/rust/lektor_unsafe/src/lib.rs    |   1 +
 12 files changed, 252 insertions(+), 17 deletions(-)
 create mode 100644 inc/liblektor-rs/config.h
 create mode 100644 src/rust/lektor_config/Cargo.toml
 create mode 100644 src/rust/lektor_config/src/config.rs
 create mode 100644 src/rust/lektor_config/src/lib.rs
 create mode 100644 src/rust/lektor_unsafe/src/config.rs

diff --git a/.vscode/settings.json b/.vscode/settings.json
index f4203265..14c36fbf 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,13 +1,11 @@
 {
-    "settings": {
-        "ltex.language": "en",
-        "languageTool.language": "en",
-        "editor.formatOnSave": true,
-        "json.format.enable": true,
-        "rust-analyzer.checkOnSave.command": "clippy",
-        "rust-analyzer.inlayHints.parameterHints.enable": false,
-        "rust-analyzer.diagnostics.enable": true,
-        "rust-analyzer.procMacro.enable": true,
-        "rust-analyzer.procMacro.attributes.enable": true,
-    }
-}
+    "ltex.language": "en",
+    "languageTool.language": "en",
+    "editor.formatOnSave": true,
+    "json.format.enable": true,
+    "rust-analyzer.checkOnSave.command": "clippy",
+    "rust-analyzer.inlayHints.parameterHints.enable": false,
+    "rust-analyzer.diagnostics.enable": true,
+    "rust-analyzer.procMacro.enable": true,
+    "rust-analyzer.procMacro.attributes.enable": true,
+}
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 725a16d6..54974088 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -187,7 +187,6 @@ set(lektor_db_SOURCES
 
 set(lektor_module_SOURCES
     src/base/reg.c
-    src/module/module_repo.c
     src/module/module_repo_rs.c
     src/module/mpv.c
     src/module/thread.c
diff --git a/inc/liblektor-rs/config.h b/inc/liblektor-rs/config.h
new file mode 100644
index 00000000..61c5840b
--- /dev/null
+++ b/inc/liblektor-rs/config.h
@@ -0,0 +1,18 @@
+
+#if !defined(LIBLEKTOR_RS_DATABASE___)
+#define LIBLEKTOR_RS_DATABASE___
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+bool lkt_config_write_default_to_file(const char *);
+bool lkt_config_write_default_to_default_file(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // LIBLEKTOR_RS_DATABASE___
diff --git a/inc/liblektor-rs/queue.h b/inc/liblektor-rs/queue.h
index 8d32c302..48f0abe8 100644
--- a/inc/liblektor-rs/queue.h
+++ b/inc/liblektor-rs/queue.h
@@ -22,7 +22,7 @@ typedef struct lkt_database_queue lkt_database_queue;
  */
 typedef void (*lkt_search_cb)(int64_t, void *restrict);
 
-lkt_database_queue *lkt_database_queue_new();
+lkt_database_queue *lkt_database_queue_new(void);
 void lkt_database_queue_delete(lkt_database_queue *);
 
 bool lkt_database_queue_current(lkt_database_queue *, int64_t *restrict);
diff --git a/src/main/server.c b/src/main/server.c
index 865cdea4..44ebedd4 100644
--- a/src/main/server.c
+++ b/src/main/server.c
@@ -9,8 +9,10 @@
 #include <lektor/launch.h>
 #include <lektor/logfile.h>
 
-#include <liblektor-rs/database.h>
 #include <liblektor-rs/loging.h>
+#include <liblektor-rs/config.h>
+#include <liblektor-rs/database.h>
+#include <liblektor-rs/queue.h>
 
 #include <wait.h>
 #include <spawn.h>
@@ -20,7 +22,6 @@
 
 #if defined(LKT_STATIC_MODULE)
 REG_DECLARE(qt_window_reg)
-REG_DECLARE(repo_reg)
 REG_DECLARE(repo_rs_reg)
 #endif
 
@@ -42,7 +43,6 @@ main(int argc, char *argv[])
     REG_ADD(database_upgrade_scheme)
 #if defined(LKT_STATIC_MODULE)
     REG_REGISTER("repo_rs", repo_rs_reg)
-    REG_REGISTER("repo", repo_reg)
     REG_REGISTER("qt", qt_window_reg)
 #endif
     REG_END()
@@ -92,6 +92,7 @@ main(int argc, char *argv[])
     FAIL_IF(lkt_queue_new(&srv.queue), "Failed to create server queue");
     FAIL_UNLESS(database_new(&srv.db), "Failed to init memory database");
     FAIL_IF(config_open(srv.db, conf_file, PATH_MAX), "Failed to open or create the config file");
+    lkt_config_write_default_to_default_file();
 
     /* Dump and abort here, if we are dumping informations about the server */
     if (dump_and_abort) {
@@ -108,6 +109,9 @@ main(int argc, char *argv[])
     lkt_set_log_logfile(logfile);
     lektor_init_rust_logging();
 
+    /* Create objects from the rust part of the code */
+    lkt_database_queue *const UNUSED queue = lkt_database_queue_new();
+
     /* Read the configuration. We already know that the config is valid */
     database_config_get_int(srv.db, "player", "autoclear", &autoclear);
     database_config_get_text(srv.db, "database", "kara_dir", kara_dir, PATH_MAX);
diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml
index 80ffe6fa..fd3c5609 100644
--- a/src/rust/Cargo.toml
+++ b/src/rust/Cargo.toml
@@ -6,6 +6,7 @@ members = [
     "lektor_db",
     "lektor_repo",
     "lektor_unsafe",
+    "lektor_config",
 
     # Common things
     "kurisu_api",
diff --git a/src/rust/lektor_config/Cargo.toml b/src/rust/lektor_config/Cargo.toml
new file mode 100644
index 00000000..92cbcd10
--- /dev/null
+++ b/src/rust/lektor_config/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "lektor_config"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+
+[dependencies]
+log.workspace = true
+serde.workspace = true
+thiserror.workspace = true
+
+lektor_c_compat = { path = "../lektor_c_compat" }
diff --git a/src/rust/lektor_config/src/config.rs b/src/rust/lektor_config/src/config.rs
new file mode 100644
index 00000000..43b01cc6
--- /dev/null
+++ b/src/rust/lektor_config/src/config.rs
@@ -0,0 +1,139 @@
+use serde::{Deserialize, Serialize};
+use std::path::PathBuf;
+
+#[derive(Debug, Serialize, Deserialize)]
+pub enum RepoApiVersion {
+    V1,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub enum LogLevel {
+    #[serde(rename = "DEBUG")]
+    Debug,
+
+    #[serde(rename = "INFO")]
+    Info,
+
+    #[serde(rename = "WARN")]
+    Warn,
+
+    #[serde(rename = "ERROR")]
+    Error,
+}
+
+#[derive(Debug, Serialize, Deserialize, Default)]
+pub struct LektorConfig {
+    pub log: LektorLogConfig,
+    pub database: LektorDatabaseConfig,
+    pub player: LektorPlayerConfig,
+    pub repo: LektorRepoConfig,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct LektorLogConfig {
+    pub level: LogLevel,
+    pub folder: PathBuf,
+    pub file_count: u64,
+    pub line_count: u64,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct LektorDatabaseConfig {
+    pub kara_dir: PathBuf,
+    pub dir_permission: u64,
+    pub db_path: PathBuf,
+    pub autoclear_queue: bool,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct LektorPlayerConfig {
+    pub module: String,
+    pub fond_size: u64,
+    pub font_name: String,
+    pub msg_duration: u64,
+    pub force_x11: bool,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct LektorRepoConfig {
+    pub module: String,
+    pub workers: usize,
+    pub server: Vec<RepoConfig>,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct RepoConfig {
+    pub name: String,
+    pub api: RepoApiVersion,
+    pub urls: Vec<String>,
+}
+
+impl Default for LogLevel {
+    fn default() -> Self {
+        LogLevel::Debug
+    }
+}
+
+impl Default for LektorLogConfig {
+    fn default() -> Self {
+        Self {
+            level: Default::default(),
+            folder: PathBuf::from("/home/kara/logs"),
+            file_count: 10,
+            line_count: 1000,
+        }
+    }
+}
+
+impl Default for LektorDatabaseConfig {
+    fn default() -> Self {
+        Self {
+            kara_dir: PathBuf::from("/home/kara"),
+            dir_permission: 0o700,
+            db_path: PathBuf::from("/home/kara/lektor.db"),
+            autoclear_queue: true,
+        }
+    }
+}
+
+impl Default for LektorPlayerConfig {
+    fn default() -> Self {
+        Self {
+            module: String::from("qt"),
+            fond_size: 12,
+            font_name: String::from("monospace"),
+            msg_duration: 4,
+            force_x11: true,
+        }
+    }
+}
+
+impl Default for LektorRepoConfig {
+    fn default() -> Self {
+        Self {
+            module: String::from("repo_rs"),
+            workers: 2,
+            server: vec![
+                Default::default(),
+                RepoConfig {
+                    name: String::from("Dummy"),
+                    api: RepoApiVersion::V1,
+                    urls: Default::default(),
+                },
+            ],
+        }
+    }
+}
+
+impl Default for RepoConfig {
+    fn default() -> Self {
+        Self {
+            name: String::from("Kurisu"),
+            api: RepoApiVersion::V1,
+            urls: vec![
+                String::from("https://kurisu.iiens.net/api"),
+                String::from("http://kurisu.iiens.net/api"),
+            ],
+        }
+    }
+}
diff --git a/src/rust/lektor_config/src/lib.rs b/src/rust/lektor_config/src/lib.rs
new file mode 100644
index 00000000..12f374cf
--- /dev/null
+++ b/src/rust/lektor_config/src/lib.rs
@@ -0,0 +1,2 @@
+mod config;
+pub use config::*;
diff --git a/src/rust/lektor_unsafe/Cargo.toml b/src/rust/lektor_unsafe/Cargo.toml
index 5bbff867..8aae3c2f 100644
--- a/src/rust/lektor_unsafe/Cargo.toml
+++ b/src/rust/lektor_unsafe/Cargo.toml
@@ -8,8 +8,11 @@ crate-type = ["staticlib"]
 
 [dependencies]
 log.workspace = true
+toml.workspace = true
 lazy_static.workspace = true
 
 lektor_c_compat = { path = "../lektor_c_compat", features = ["c_types"] }
+lektor_config = { path = "../lektor_config" }
 lektor_repo = { path = "../lektor_repo" }
 lektor_db = { path = "../lektor_db" }
+commons = { path = "../commons" }
diff --git a/src/rust/lektor_unsafe/src/config.rs b/src/rust/lektor_unsafe/src/config.rs
new file mode 100644
index 00000000..0d83938a
--- /dev/null
+++ b/src/rust/lektor_unsafe/src/config.rs
@@ -0,0 +1,57 @@
+//! An unsafe interface around the rust implementation of the config read/write
+//! things to be able to call it from C or C++ code.
+//!
+//! Be carefull when naming things because those names might collide with things
+//! defined in lektor's C code...
+
+use crate::*;
+use lektor_config::*;
+
+#[no_mangle]
+pub unsafe extern "C" fn lkt_config_write_default_to_file(file: *const u8) -> bool {
+    let mut len = 0;
+    while *file.offset(len) != 0 {
+        len += 1
+    }
+    let file = ManuallyDrop::new(String::from_raw_parts(
+        file as *mut _,
+        len as usize,
+        len as usize,
+    ));
+
+    let conf = match toml::to_string_pretty(&LektorConfig::default()) {
+        Ok(conf) => conf,
+        Err(err) => {
+            log::error!(target: "CONF", "failed to serialize default config: {err}");
+            return false;
+        }
+    };
+
+    match std::fs::write(PathBuf::from(&file[..]), conf) {
+        Ok(()) => true,
+        Err(err) => {
+            log::error!(target: "CONF", "failed to write default config to {}: {err}", &file[..]);
+            false
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn lkt_config_write_default_to_default_file() -> bool {
+    let path = commons::user_config_directory("lektor").join("lektor.toml");
+    let conf = match toml::to_string_pretty(&LektorConfig::default()) {
+        Ok(conf) => conf,
+        Err(err) => {
+            log::error!(target: "CONF", "failed to serialize default config: {err}");
+            return false;
+        }
+    };
+
+    match std::fs::write(&path, conf) {
+        Ok(()) => true,
+        Err(err) => {
+            log::error!(target: "CONF", "failed to write default config to {}: {err}", path.to_string_lossy());
+            false
+        }
+    }
+}
diff --git a/src/rust/lektor_unsafe/src/lib.rs b/src/rust/lektor_unsafe/src/lib.rs
index 39a589fe..476ce351 100644
--- a/src/rust/lektor_unsafe/src/lib.rs
+++ b/src/rust/lektor_unsafe/src/lib.rs
@@ -1,6 +1,7 @@
 //! Create C functions to calls things defined in the rust language from C code.
 //! See the headers inside the liblektor-rs folder from the C include directory.
 
+pub mod config;
 pub mod db;
 pub mod loging;
 pub mod queue;
-- 
GitLab