From d3186fb2b6646af248ba136ba1460e857032e9d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Willy=20Rom=C3=A3o?= Date: Sun, 21 Jan 2024 21:16:37 +0000 Subject: [PATCH] feat(setup_states): new yaml reader, new read_config_state and types adjusts for generalization --- .github/workflows/checks.yml | 2 +- Cargo.lock | 57 ++-- mfm_core/Cargo.toml | 1 + mfm_core/src/config/authentication/wallet.rs | 2 +- mfm_core/src/config/dexes.rs | 1 + mfm_core/src/config/network.rs | 10 +- mfm_core/src/config/token.rs | 9 +- mfm_core/src/contexts/mod.rs | 8 +- mfm_core/src/lib.rs | 16 +- mfm_core/src/{tasks => operations}/mod.rs | 0 mfm_core/src/states/mod.rs | 69 +++- mfm_core/test_config.yml | 323 +++++++++++++++++++ mfm_machine/src/state/mod.rs | 15 +- test_config.yml | 286 ++++++++++++++++ 14 files changed, 738 insertions(+), 61 deletions(-) rename mfm_core/src/{tasks => operations}/mod.rs (100%) create mode 100644 mfm_core/test_config.yml create mode 100644 test_config.yml diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 4caf57b..65ac57b 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,4 +1,4 @@ -name: Rust +name: Rust build & tests on: [push] diff --git a/Cargo.lock b/Cargo.lock index f966ff1..8f4405e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,12 +30,6 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - [[package]] name = "cfg-if" version = "1.0.0" @@ -51,6 +45,12 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "gethostname" version = "0.2.3" @@ -74,17 +74,17 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "indexmap" -version = "1.9.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ - "autocfg", + "equivalent", "hashbrown", ] @@ -150,6 +150,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "serde_yaml", "zeroize", ] @@ -215,18 +216,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -313,22 +314,22 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -344,9 +345,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.21" +version = "0.9.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c" +checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" dependencies = [ "indexmap", "itoa", @@ -383,9 +384,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -451,7 +452,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -530,9 +531,9 @@ checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unsafe-libyaml" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "valuable" @@ -591,7 +592,7 @@ checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] diff --git a/mfm_core/Cargo.toml b/mfm_core/Cargo.toml index f72b1bb..881284c 100644 --- a/mfm_core/Cargo.toml +++ b/mfm_core/Cargo.toml @@ -13,3 +13,4 @@ zeroize = "1.7.0" serde_json = "1.0.108" serde_derive = "1.0.193" anyhow = "1.0.75" +serde_yaml = "0.9.30" diff --git a/mfm_core/src/config/authentication/wallet.rs b/mfm_core/src/config/authentication/wallet.rs index db4b964..04e9179 100644 --- a/mfm_core/src/config/authentication/wallet.rs +++ b/mfm_core/src/config/authentication/wallet.rs @@ -6,6 +6,6 @@ use crate::password::{deserialize_safe_password, SafePassword}; pub struct Wallet { #[serde(deserialize_with = "deserialize_safe_password")] pub private_key: SafePassword, - pub not_encrypted: bool, + pub not_encrypted: Option, pub env_password: Option, } diff --git a/mfm_core/src/config/dexes.rs b/mfm_core/src/config/dexes.rs index 620f9af..ea32e56 100644 --- a/mfm_core/src/config/dexes.rs +++ b/mfm_core/src/config/dexes.rs @@ -2,6 +2,7 @@ use serde_derive::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] pub enum Kind { UniswapV2, } diff --git a/mfm_core/src/config/network.rs b/mfm_core/src/config/network.rs index 25e1d86..e8d1822 100644 --- a/mfm_core/src/config/network.rs +++ b/mfm_core/src/config/network.rs @@ -1,10 +1,10 @@ -use super::token::Token; use serde_derive::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] pub enum Kind { - EVM, + Evm, } #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -14,11 +14,11 @@ pub struct Network { pub symbol: String, pub decimals: Option, pub chain_id: u32, - pub node_url: String, - pub node_url_failover: Option, + pub node_url_http: Option, + pub node_url_grpc: Option, pub blockexplorer_url: Option, pub min_balance_coin: f64, - pub wrapped_asset: Option, + pub wrapped_token: Option, } #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] diff --git a/mfm_core/src/config/token.rs b/mfm_core/src/config/token.rs index f4019a0..8bde78c 100644 --- a/mfm_core/src/config/token.rs +++ b/mfm_core/src/config/token.rs @@ -2,17 +2,19 @@ use serde_derive::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] pub enum Kind { - ERC20, + Erc20, } #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct TokenNetwork { pub name: String, + pub kind: Kind, pub network_id: String, pub address: String, pub slippage: f64, - pub path_asset: String, + pub path_token: String, } #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -20,7 +22,8 @@ pub struct TokenNetworks(HashMap); #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct Token { - pub kind: Kind, + // TODO: rethink tokens to be any kind of token, but each + // chain/network will may have an different token kind. pub networks: TokenNetworks, } diff --git a/mfm_core/src/contexts/mod.rs b/mfm_core/src/contexts/mod.rs index 318cecd..05905f5 100644 --- a/mfm_core/src/contexts/mod.rs +++ b/mfm_core/src/contexts/mod.rs @@ -1,15 +1,17 @@ use crate::config::Config; +use mfm_machine::state::Label; use serde_derive::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub enum ConfigSource { - TomlFile(String), + YamlFile(String), } +pub const CONFIG_SOURCE_CTX: Label = Label("config_source_ctx"); #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct ReadConfig { +pub struct ConfigCtx { pub config_source: ConfigSource, pub config: Config, } -pub const READ_CONFIG: &str = "read_config"; +pub const CONFIG_CTX: Label = Label("config_ctx"); diff --git a/mfm_core/src/lib.rs b/mfm_core/src/lib.rs index 69b7fbd..fc38a5c 100644 --- a/mfm_core/src/lib.rs +++ b/mfm_core/src/lib.rs @@ -1,6 +1,20 @@ +use std::{fs::File, io::Read}; + pub mod config; pub mod contexts; pub mod hidden; +pub mod operations; pub mod password; pub mod states; -pub mod tasks; + +use anyhow::Error; +use serde::de::DeserializeOwned; + +fn read_yaml(path: String) -> Result { + let mut file = File::open(path)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + + let instance: T = serde_yaml::from_str(&contents)?; + Ok(instance) +} diff --git a/mfm_core/src/tasks/mod.rs b/mfm_core/src/operations/mod.rs similarity index 100% rename from mfm_core/src/tasks/mod.rs rename to mfm_core/src/operations/mod.rs diff --git a/mfm_core/src/states/mod.rs b/mfm_core/src/states/mod.rs index 35767b2..b96b06d 100644 --- a/mfm_core/src/states/mod.rs +++ b/mfm_core/src/states/mod.rs @@ -4,8 +4,13 @@ use mfm_machine::state::{ context::ContextWrapper, DependencyStrategy, Label, StateHandler, StateMetadata, StateResult, Tag, }; +use serde_json::json; -use crate::contexts::{self, READ_CONFIG}; +use crate::{ + config::Config, + contexts::{ConfigCtx, ConfigSource, CONFIG_CTX, CONFIG_SOURCE_CTX}, + read_yaml, +}; #[derive(Debug, Clone, PartialEq, StateMetadataReqs)] pub struct ReadConfig { @@ -15,32 +20,59 @@ pub struct ReadConfig { depends_on_strategy: DependencyStrategy, } +pub static READ_CONFIG: Label = Label("read_config"); + impl ReadConfig { - pub fn new() -> Self { + pub fn new( + tags: Vec, + depends_on: Vec, + depends_on_strategy: DependencyStrategy, + ) -> Self { Self { - label: Label::new("read_config").unwrap(), - tags: vec![Tag::new("setup").unwrap()], - depends_on: vec![Tag::new("config").unwrap()], - depends_on_strategy: DependencyStrategy::Latest, + label: READ_CONFIG, + tags, + depends_on, + depends_on_strategy, } } } impl Default for ReadConfig { fn default() -> Self { - Self::new() + Self { + label: READ_CONFIG, + tags: vec![Tag::new("setup").unwrap()], + depends_on: vec![Tag::new("config").unwrap()], + depends_on_strategy: DependencyStrategy::Latest, + } } } +// TODO: implement error froms to be able to use `?` for context ops. impl StateHandler for ReadConfig { fn handler(&self, context: ContextWrapper) -> StateResult { - let value = context + let config_ctx = context .lock() .unwrap() - .read(READ_CONFIG.to_string()) + .read(CONFIG_SOURCE_CTX.into()) + .unwrap(); + + let config_source: ConfigSource = serde_json::from_value(config_ctx).unwrap(); + + let ConfigSource::YamlFile(path) = config_source.clone(); + + let config: Config = read_yaml(path).unwrap(); + + let config_ctx = ConfigCtx { + config_source, + config, + }; + + context + .lock() + .unwrap() + .write(CONFIG_CTX.into(), &json!(config_ctx)) .unwrap(); - let data: contexts::ConfigSource = serde_json::from_value(value).unwrap(); - println!("data: {:?}", data); Ok(()) } } @@ -55,19 +87,22 @@ mod test { }; use serde_json::json; - use crate::contexts::{ConfigSource, READ_CONFIG}; + use crate::contexts::{ConfigSource, CONFIG_SOURCE_CTX}; use super::ReadConfig; #[test] fn test_readconfig_from_source_file() { - let state = ReadConfig::new(); + let state = ReadConfig::default(); let ctx_input = wrap_context(Local::new(HashMap::from([( - READ_CONFIG.to_string(), - json!(ConfigSource::TomlFile("test_config.toml".to_string())), + CONFIG_SOURCE_CTX.into(), + json!(ConfigSource::YamlFile("test_config.yml".to_string())), )]))); - let result = state.handler(ctx_input); - assert!(result.is_ok()) + let result = state.handler(ctx_input.clone()); + + let dump = ctx_input.lock().unwrap().dump().unwrap(); + assert!(result.is_ok()); + assert_eq!(dump, json!("")); } // TODO: add a test transitioning between states and contexts. diff --git a/mfm_core/test_config.yml b/mfm_core/test_config.yml new file mode 100644 index 0000000..a154227 --- /dev/null +++ b/mfm_core/test_config.yml @@ -0,0 +1,323 @@ +auth_methods: + - { type: wallet, private_key: YOUR_PRIVATE_KEY } + +networks: + bsc: + kind: evm + name: bsc + symbol: bnb + chain_id: 56 + node_url_http: https://bsc-dataseed.binance.org + # node_url_grpc: + # node_url_failover: + blockexplorer_url: https://bscscan.com + min_balance_coin: 0.1 + wrapped_token: wbnb + decimals: 18 + polygon: + kind: evm + name: polygon + symbol: matic + chain_id: 137 + node_url_http: https://polygon-rpc.com/ + # node_url_grpc: + # node_url_failover: + blockexplorer_url: https://polygonscan.com/ + min_balance_coin: 1 + wrapped_token: wmatic + decimals: 18 + +dexes: + pancake_swap_v2: + name: pancake_swap_v2 + kind: uniswap_v2 + router_address: 0x10ED43C718714eb63d5aA57B78B54704E256024E + factory_address: 0xca143ce32fe78f1f7019d7d551a6402fc5350c73 + network_id: bsc + quickswap_v2: + name: quickswap_v2 + kind: uniswap_v2 + router_address: 0xa5e0829caced8ffdd4de3c43696c57f7d7a678ff + factory_address: 0x5757371414417b8c6caad45baef941abc7d3ab32 + network_id: polygon + sushi_swap_polygon: + name: sushi_swap_polygon + kind: uniswap_v2 + router_address: 0x1b02da8cb0d097eb8d57a175b88c7d8b47997506 + factory_address: 0xc35dadb65012ec5796536bd9864ed8773abc74c4 + network_id: polygon + biswap: + name: biswap + kind: uniswap_v2 + router_address: 0x3a6d8ca21d1cf76f653a67577fa0d27453350dd8 + factory_address: 0x858e3312ed3a876947ea49d572a7c42de08af7ee + network_id: bsc + +tokens: + qidao: + networks: + polygon: + name: qidao + kind: erc20 + network_id: polygon + address: 0x580a84c73811e1839f75d86d75d88cca0c241ff4 + slippage: 2 + path_token: weth + dquick: + kind: token + networks: + polygon: + name: dquick + kind: erc20 + network_id: polygon + address: 0xf28164a485b0b2c90639e47b0f377b4a438a16b1 + slippage: 2 + path_token: weth + xrp: + kind: token + networks: + bsc: + name: xrp + kind: erc20 + network_id: bsc + address: 0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE + slippage: 2 + path_token: wbnb + link: + kind: token + networks: + bsc: + name: link + kind: erc20 + network_id: bsc + address: 0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD + slippage: 2 + path_token: wbnb + gala: + kind: token + networks: + bsc: + name: gala + kind: erc20 + network_id: bsc + address: 0x7dDEE176F665cD201F93eEDE625770E2fD911990 + slippage: 2 + path_token: wbnb + near: + kind: token + networks: + bsc: + name: near + kind: erc20 + network_id: bsc + address: 0x1Fa4a73a3F0133f0025378af00236f3aBDEE5D63 + slippage: 2 + path_token: wbnb + luna: + kind: token + networks: + bsc: + name: luna + kind: erc20 + network_id: bsc + address: 0x156ab3346823B651294766e23e6Cf87254d68962 + slippage: 2 + path_token: wbnb + wmatic: + kind: token + networks: + bsc: + name: wmatic + kind: erc20 + network_id: bsc + address: 0xcc42724c6683b7e57334c4e856f4c9965ed682bd + slippage: 2 + path_token: wbnb + polygon: + name: wmatic + kind: erc20 + network_id: polygon + address: 0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270 + slippage: 2 + path_token: weth + anonq: + kind: token + networks: + bsc: + name: anonq + kind: erc20 + network_id: bsc + address: 0xf393138616cd6DD367171eaA59c2eaEE420a32b9 + slippage: 2 + path_token: wbnb + busd: + kind: token + networks: + bsc: + name: busd + kind: erc20 + network_id: bsc + address: 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56 + slippage: 2 + path_token: wbnb + wbnb: + kind: token + networks: + bsc: + name: wbnb + kind: erc20 + network_id: bsc + address: 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c + slippage: 2 + path_token: wbnb + weth: + kind: token + networks: + bsc: + name: weth + kind: erc20 + network_id: bsc + address: 0x2170ed0880ac9a755fd29b2688956bd959f933f8 + slippage: 2 + path_token: wbnb + polygon: + name: weth + kind: erc20 + network_id: polygon + address: 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619 + slippage: 2 + path_token: weth + btc: + kind: token + networks: + bsc: + name: btc + kind: erc20 + network_id: bsc + address: 0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c + slippage: 2 + path_token: wbnb + sol: + kind: token + networks: + bsc: + name: sol + kind: erc20 + network_id: bsc + address: 0x570A5D26f7765Ecb712C0924E4De545B89fD43dF + slippage: 2 + path_token: wbnb + polygon: + name: sol + kind: erc20 + network_id: polygon + address: 0x7dff46370e9ea5f0bad3c4e29711ad50062ea7a4 + slippage: 2 + path_token: weth + posi: + kind: token + networks: + bsc: + name: posi + kind: erc20 + network_id: bsc + address: 0x5ca42204cdaa70d5c773946e69de942b85ca6706 + slippage: 2 + path_token: wbnb + cake: + kind: token + networks: + bsc: + name: cake + kind: erc20 + network_id: bsc + address: 0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82 + slippage: 2 + path_token: wbnb + pacoca: + kind: token + networks: + bsc: + name: pacoca + kind: erc20 + network_id: bsc + address: 0x55671114d774ee99d653d6c12460c780a67f1d18 + slippage: 1 + path_token: wbnb + safemoon: + kind: token + networks: + bsc: + name: safemoon + kind: erc20 + network_id: bsc + address: 0x42981d0bfbAf196529376EE702F2a9Eb9092fcB5 + slippage: 1 + path_token: wbnb + grt: + kind: token + networks: + polygon: + name: grt + kind: erc20 + network_id: polygon + address: 0x5fe2b58c013d7601147dcdd68c143a77499f5531 + slippage: 1 + path_token: weth + usdc: + kind: token + networks: + polygon: + name: usdc + kind: erc20 + network_id: polygon + address: 0x2791bca1f2de4661ed88a30c99a7a9449aa84174 + slippage: 1 + path_token: wmatic + bsc: + name: usdc + kind: erc20 + network_id: bsc + address: 0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d + slippage: 1 + path_token: wbnb + usdt: + kind: token + networks: + bsc: + name: usdt + kind: erc20 + network_id: bsc + address: 0x55d398326f99059ff775485246999027b3197955 + slippage: 1 + path_token: wbnb + baby: + kind: token + networks: + bsc: + name: baby + kind: erc20 + network_id: bsc + address: 0x53e562b9b7e5e94b81f10e96ee70ad06df3d2657 + slippage: 1 + path_token: usdt + bal: + kind: token + networks: + polygon: + name: bal + kind: erc20 + network_id: polygon + address: 0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3 + slippage: 3 + path_token: weth + avax: + kind: token + networks: + polygon: + name: avax + kind: erc20 + network_id: polygon + address: 0x2c89bbc92bd86f8075d1decc58c7f4e0107f286b + slippage: 2 + path_token: weth diff --git a/mfm_machine/src/state/mod.rs b/mfm_machine/src/state/mod.rs index e491fba..acd2692 100644 --- a/mfm_machine/src/state/mod.rs +++ b/mfm_machine/src/state/mod.rs @@ -5,11 +5,16 @@ pub mod context; use self::context::ContextWrapper; +// TODO: rethink this pub on the private field of `Tag` and `Label`: +// I'm making it public just to address the idea of having const/static Label +// by context and/or states. +// It may be better solved using procedural macros that can validate the string +// at compiler time, and translate in a safe to `From` to `Label` using const fn. #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] -pub struct Tag(&'static str); +pub struct Tag(pub &'static str); #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] -pub struct Label(&'static str); +pub struct Label(pub &'static str); fn ensure_nonempty_ascii_lowercase_underscore(input: &'static str) -> Result<&'static str, Error> { if input.is_empty() { @@ -41,6 +46,12 @@ impl Label { } } +impl From