From f4d14841b06d17983fa69cf0b896abd97ccba38f Mon Sep 17 00:00:00 2001 From: Chethan Date: Wed, 20 Mar 2024 22:35:18 +0530 Subject: [PATCH] add typestate pattern --- Cargo.lock | 65 +++++++++++++ Cargo.toml | 5 +- src/main.rs | 260 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 306 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1082236..f5c940e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,6 +109,12 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "camino" version = "1.1.6" @@ -213,6 +219,47 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +[[package]] +name = "diesel" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "diesel_derives", + "pq-sys", +] + +[[package]] +name = "diesel_derives" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "enum_dispatch" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "errno" version = "0.3.8" @@ -524,6 +571,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pq-sys" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c0052426df997c0cbd30789eb44ca097e3541717a7b8fa36b1c464ee7edebd" +dependencies = [ + "vcpkg", +] + [[package]] name = "proc-macro2" version = "1.0.67" @@ -593,6 +649,9 @@ version = "0.1.0" dependencies = [ "base64", "chrono", + "diesel", + "dotenv", + "enum_dispatch", "error-stack", "hex", "moka", @@ -882,6 +941,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 9d1b19e..fb29ec9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -error-stack = "0.3.1" +error-stack = "*" thiserror = "1.0.40" serde_json = "1.0.96" serde = { version = "1.0.163", features = ["derive"] } @@ -17,3 +17,6 @@ moka = { version = "0.12.1", features = ["future"] } tokio = { version = "1.33.0", features = ["macros", "rt-multi-thread"] } base64 = "*" hex = "*" +enum_dispatch = "*" +diesel = { version = "1.4", features = ["postgres"] } +dotenv = "0.15" diff --git a/src/main.rs b/src/main.rs index 2cd8b6b..09a7b90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1598,40 +1598,254 @@ //////////////////////////////////////////////////////////////////////////////////// -use base64::Engine; +// use enum_dispatch::enum_dispatch; -fn main() { - // Base-64: Groups binary into 6 bits (2^6 = 64 characters) and encodes to its own character from BASE-64 chart - let a = b"And"; // or let a = "And".as_bytes() +// #[enum_dispatch] +// trait KnobControl { +// fn get_value(&self) -> f64; +// } + +// #[derive(Debug)] +// struct LinearKnob; + +// impl KnobControl for LinearKnob { +// fn get_value(&self) -> f64 { +// 1.0 +// } +// } + +// #[derive(Debug)] +// struct LogarithmicKnob; + +// impl KnobControl for LogarithmicKnob { +// fn get_value(&self) -> f64 { +// 2.0 +// } +// } + +// #[enum_dispatch(KnobControl)] +// #[derive(Debug)] - let en = base64::engine::general_purpose::STANDARD.encode(a); // You can even pass direct String, it will get converted to bytes internally +// enum Knob { +// LinearKnob, +// LogarithmicKnob, +// } - let de = base64::engine::general_purpose::STANDARD - .decode(en.clone()) - .unwrap(); // Gives UTF-8 values of "And" +// fn main() { +// let a = Knob::from(LinearKnob); - let de = String::from_utf8(de); // Generate String from utf-8 which is "And" +// println!("{:?}", a) +// } - println!("{en:?} {de:?}"); +//////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////// +// TypeState pattern + +// struct Settings { +// db_password: String, +// } +// struct Decryptable { +// state: Settings, +// marker: std::marker::PhantomData, +// } + +// /// decrypt valid only in Encrypted state. +// impl Decryptable { +// fn decrypt(self) -> Decryptable { +// Decryptable { +// state: Settings { +// db_password: "decrypted".to_string(), +// }, +// marker: std::marker::PhantomData, +// } +// } +// } + +// impl Decryptable { +// fn inner_value(self) -> Settings { +// self.state +// } +// } - // Hex encoding: Groups binary into 4 bits (2^4 = 16 characters) and encodes to its own character from Hex chart - // let String = "he" - // Binary = (h)01101000 (e)01100101 - // Group into 4 bits - // 0110 1000 0110 0101 - // 6 8 6 5 +// enum Encrypted {} +// enum Raw {} - let a = "he"; +// trait State {} +// impl State for Encrypted {} +// impl State for Raw {} - let hex_en = hex::encode(a); +// fn main() { +// // parsed as encrypted value +// let parsed_config: Decryptable = Decryptable { +// state: Settings { +// db_password: "encrypted".to_string(), +// }, +// marker: std::marker::PhantomData, +// }; - let hex_de = hex::decode(hex_en.clone()).unwrap(); // Gives UTF-8 values of "he" +// let raw_decryptable = parsed_config.decrypt(); - let hex_de = String::from_utf8(hex_de); // Generate String from utf-8 which is "he" +// let decrypted_settings = raw_decryptable.inner_value(); - println!("{hex_en:?} {hex_de:?}"); // 6865 "he" -} +// println!("{:?}", decrypted_settings.db_password); // decrypted +// } //////////////////////////////////////////////////////////////////////////////////// + +// use std::marker::PhantomData; + +// trait EncryptionState {} +// #[derive(Clone, Debug)] + +// struct Decrypted {} + +// #[derive(Clone, Debug)] +// struct Encrypted {} + +// impl EncryptionState for Decrypted {} +// impl EncryptionState for Encrypted {} + +// // Placeholder KMS client +// struct KMSClient {} + +// impl KMSClient { +// fn decrypt(&self, _: String) -> String { +// "decrypted".to_string() +// } +// } + +// #[derive(Debug, Clone)] +// struct Decryptable { +// inner: T, +// marker: PhantomData, +// } + +// impl Decryptable { +// fn decrypt(mut self, decryptor_fn: impl FnOnce(T) -> T) -> Decryptable { +// self.inner = decryptor_fn(self.inner); +// Decryptable { +// inner: self.inner, +// marker: PhantomData, +// } +// } +// } + +// trait Decryption +// where +// Self: Sized, +// { +// fn decrypt( +// value: Decryptable, +// kms_client: &KMSClient, +// ) -> Decryptable; +// } + +// #[derive(Clone, Debug)] +// struct Database { +// dbname: String, +// password: String, +// } + +// impl Decryption for Database { +// fn decrypt( +// value: Decryptable, +// kms_client: &KMSClient, +// ) -> Decryptable { +// value.decrypt(|a| Database { +// dbname: a.dbname, +// password: kms_client.decrypt(a.password), +// }) +// } +// } + +// #[derive(Debug)] +// struct Settings { +// db: Decryptable, +// } + +// fn main() { +// let db = Database { +// dbname: "hyper".to_string(), +// password: "encrypted".to_string(), +// }; + +// let decryptable_db: Decryptable = Decryptable { +// inner: db.clone(), +// marker: PhantomData, +// }; + +// let mut state = Settings { +// db: decryptable_db.clone(), +// }; + +// let decrypted_val = Database::decrypt(decryptable_db, &KMSClient {}); + +// let decrypted_settings = Settings { db: decrypted_val }; +// } + +//////////////////////////////////////////////////////////// + +// struct AwsKmsClient; + +// impl AwsKmsClient { +// fn encrypt(&self, data: String) {} + +// fn decrypt(&self, data: String) {} +// } + +// struct HcVaultClient; + +// impl HcVaultClient { +// fn fetch(&self, data: String) {} +// } + +// pub trait SecretsManagementInterface { +// fn store_secret(&self, input: String); + +// fn get_secret(&self, input: String); +// } + +// impl SecretsManagementInterface for AwsKmsClient { +// fn store_secret(&self, input: String) { +// self.encrypt(input) +// } + +// fn get_secret(&self, input: String) { +// self.decrypt(input) +// } +// } + +// impl SecretsManagementInterface for HcVaultClient { +// fn store_secret(&self, input: String) { +// unimplemented!() +// } + +// fn get_secret(&self, input: String) { +// self.fetch(input) +// } +// } + +// pub trait EncryptionManagementInterface { +// fn encrypt(&self, input: String); + +// fn decrypt(&self, input: String); +// } + +// impl EncryptionManagementInterface for AwsKmsClient { +// fn encrypt(&self, input: String) { +// self.encrypt(input) +// } + +// fn decrypt(&self, input: String) { +// self.decrypt(input) +// } +// } + +// struct AppState { +// pub encryption_client: Box, +// } + +// fn main() {} + +/////////////////////////////////////////////////////////////////////////// +