Got Config parsed from yaml file

This commit is contained in:
AlexanderHD27
2025-05-20 01:59:41 +02:00
commit 877cf71413
6 changed files with 369 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

21
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,21 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "cargo",
"command": "run",
"problemMatcher": [
"$rustc"
],
"label": "rust: cargo run",
"presentation": {
"echo": true,
"reveal": "always",
"focus": true,
"panel": "dedicated",
"showReuseMessage": true,
"clear": true
}
}
]
}

180
Cargo.lock generated Normal file
View File

@@ -0,0 +1,180 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "configotron"
version = "0.1.0"
dependencies = [
"pad",
"serde",
"serde_yml",
"thiserror",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "hashbrown"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
[[package]]
name = "indexmap"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "libyml"
version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980"
dependencies = [
"anyhow",
"version_check",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "pad"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3"
dependencies = [
"unicode-width",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_yml"
version = "0.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd"
dependencies = [
"indexmap",
"itoa",
"libyml",
"memchr",
"ryu",
"serde",
"version_check",
]
[[package]]
name = "syn"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"

10
Cargo.toml Normal file
View File

@@ -0,0 +1,10 @@
[package]
name = "configotron"
version = "0.1.0"
edition = "2021"
[dependencies]
pad = "0.1.6"
serde = { version = "1.0", features = ["derive"] }
serde_yml = "0.0.12"
thiserror = "1"

34
example.yml Normal file
View File

@@ -0,0 +1,34 @@
name: ssbc_remote
config_items:
- !Submenu
name: network settings
config_items:
- !IPv4
name: ip
- !IPv4
name: subnet_mask
- !IPv4
name: gateway
- !String
name: wifi_ssid
description: The SSID of the Wi-Fi network.
max_length: 64
- !String
name: wifi_password
description: The password for the Wi-Fi network.
max_length: 64
- !Boolean
name: dhcp_enabled
- !IPv4
name: hub_ip
- !Number
name: hub_port
max: 65535
min: 1

123
src/main.rs Normal file
View File

@@ -0,0 +1,123 @@
use serde::{Deserialize, Serialize};
use serde_yml;
use std::fs;
use pad::PadStr;
#[derive(Deserialize, Serialize, Debug)]
enum UserConfigItem {
String {
name: String,
max_length: u64
},
IPv4 {
name: String,
},
Boolean {
name: String
},
Number {
name: String,
max: Option<i32>,
min: Option<i32>
},
Submenu(UserConfigData)
}
#[derive(Deserialize, Serialize, Debug)]
struct UserConfigData {
name: String,
config_items: Vec<UserConfigItem>
}
#[derive(thiserror::Error, Debug)]
pub enum ConfigotronError {
#[error("IO Operation failed: {}", ._0.to_string())]
IoError(#[from] std::io::Error),
#[error("Failed to parse YAML File: {}", ._0.to_string())]
YamlParsingError(#[from] serde_yml::Error),
#[error("Missing field {} (line {} col {}) {}", .missing_filed, .line, .col, .context)]
MissingFieldError{
col: i32,
line: i32,
missing_filed: Box<str>,
context: Box<str>
}
}
fn read_and_parse_yaml_file(input_file: &str) -> Result<UserConfigData, ConfigotronError> {
let file_content = fs::read_to_string(&input_file)?;
let config: UserConfigData = serde_yml::from_str(&file_content)?;
return Ok(config);
}
fn generate_text_report_from_item(item: &UserConfigItem) -> Vec<String> {
return match item {
UserConfigItem::Boolean {name} => vec![String::from(name), String::from("[y/n]")] ,
UserConfigItem::IPv4 { name } => vec![String::from(name), format!("[ipv4]")],
UserConfigItem::String { name, max_length } => vec![String::from(name), format!("[text, max length {}]", max_length)],
UserConfigItem::Number { name, min, max } => match (min, max) {
(None, None) => vec![String::from(name), String::from("[number]")],
(None, Some(maximum)) => vec![String::from(name), format!("[number, ..{}]", maximum)],
(Some(minmum), None) => vec![String::from(name), format!("[number, {}..]", minmum)],
(Some(minmum), Some(maximum)) => vec![String::from(name), format!("[number, {}..{}]", minmum, maximum)],
},
UserConfigItem::Submenu(c) => generate_text_report(c)
}
}
fn generate_text_report(config: &UserConfigData) -> Vec<String> {
let lines: Vec<Vec<String>> = config.config_items
.iter()
.map(|i| generate_text_report_from_item(i))
.collect();
let block_width = lines
.iter()
.map(|l: &Vec<String>|
l
.iter()
.map(|s: &String| s.chars().count())
.max().unwrap_or(0)
)
.max().unwrap_or(0);
let line_seperator = format!("+{}+", "-".repeat(block_width + 2));
let config_name_width = config.name.chars().count() + 2;
let mut lines_flattend: Vec<String> = lines
.iter()
.map(|i| i
.iter()
.map(|s| format!("| {} |", s.pad_to_width(block_width)))
.collect::<Vec<String>>()
)
.flat_map(|seg| [seg, vec![String::from(&line_seperator)]])
.flatten()
.into_iter()
.map(|e| format!("{}{}", " ".repeat(config_name_width), e))
.collect();
lines_flattend.insert(0, format!("{}{}", config.name.pad_to_width(config_name_width), line_seperator));
return lines_flattend;
}
fn main() {
let data = match read_and_parse_yaml_file("example.yml") {
Ok(d) => d,
Err(error) => {
println!("{}", error);
return;
}
};
let res = generate_text_report(&data).join("\n");
println!("{}", res);
println!("Hello, world!");
}