commit c4465088293950c12807c9714cc33ebc315f46e4 Author: Edward Shen Date: Wed Feb 3 20:40:06 2021 -0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b60de5b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +**/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..fd42802 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,495 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "anyhow" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bytes" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "futures-core" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" + +[[package]] +name = "lock_api" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "mio" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e50ae3f04d169fcc9bde0b547d1c205219b7157e07ded9c5aff03e0637cb3ed7" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +dependencies = [ + "socket2", + "winapi", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" + +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" + +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "signal-hook-registry" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" +dependencies = [ + "libc", +] + +[[package]] +name = "simple_logger" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd57f17c093ead1d4a1499dc9acaafdd71240908d64775465543b8d9a9f1d198" +dependencies = [ + "atty", + "chrono", + "colored", + "log", + "winapi", +] + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + +[[package]] +name = "socket2" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +dependencies = [ + "cfg-if", + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "thiserror" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "tokio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6714d663090b6b0acb0fa85841c6d66233d150cdb2602c8f9b8abb03370beb3f" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42517d2975ca3114b22a16192634e8241dc5cc1f130be194645970cc1c371494" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76066865172052eb8796c686f0b441a93df8b08d40a950b062ffb9a426f00edd" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "vtse-client" +version = "0.1.0" + +[[package]] +name = "vtse-common" +version = "0.1.0" +dependencies = [ + "serde", + "thiserror", +] + +[[package]] +name = "vtse-server" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "log", + "serde", + "serde_json", + "simple_logger", + "tokio", + "tokio-stream", + "uuid", + "vtse-common", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..033c869 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["vtse-client", "vtse-common", "vtse-server"] \ No newline at end of file diff --git a/vtse-client/Cargo.toml b/vtse-client/Cargo.toml new file mode 100644 index 0000000..756dc63 --- /dev/null +++ b/vtse-client/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "vtse-client" +version = "0.1.0" +authors = ["Edward Shen "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/vtse-client/src/main.rs b/vtse-client/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/vtse-client/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/vtse-common/Cargo.toml b/vtse-common/Cargo.toml new file mode 100644 index 0000000..edd07c6 --- /dev/null +++ b/vtse-common/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "vtse-common" +version = "0.1.0" +authors = ["Edward Shen "] +edition = "2018" + +[dependencies] +serde = { version = "1", features = ["derive"] } +thiserror = "1" \ No newline at end of file diff --git a/vtse-common/src/lib.rs b/vtse-common/src/lib.rs new file mode 100644 index 0000000..0a00bd3 --- /dev/null +++ b/vtse-common/src/lib.rs @@ -0,0 +1,10 @@ +pub mod operations; +pub mod stock; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/vtse-common/src/operations.rs b/vtse-common/src/operations.rs new file mode 100644 index 0000000..887b7e1 --- /dev/null +++ b/vtse-common/src/operations.rs @@ -0,0 +1,6 @@ +use crate::stock::StockName; + +pub(crate) enum MarketOperation { + Buy, + Sell, +} diff --git a/vtse-common/src/stock.rs b/vtse-common/src/stock.rs new file mode 100644 index 0000000..e18ed94 --- /dev/null +++ b/vtse-common/src/stock.rs @@ -0,0 +1,19 @@ +use serde::Deserialize; +use std::str::FromStr; +use thiserror::Error; + +#[derive(Deserialize, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)] +pub struct StockName(String); + +#[derive(Error, Debug)] +pub enum StockNameParseError {} + +impl FromStr for StockName { + type Err = StockNameParseError; + + fn from_str(s: &str) -> Result { + Ok(Self(s.to_string())) + } +} + +pub(crate) struct Stock {} diff --git a/vtse-server/Cargo.toml b/vtse-server/Cargo.toml new file mode 100644 index 0000000..d311860 --- /dev/null +++ b/vtse-server/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "vtse-server" +version = "0.1.0" +authors = ["Edward Shen "] +edition = "2018" + +[dependencies] +vtse-common = { path = "../vtse-common" } +log = "0.4" +simple_logger = "1.11" +tokio = { version = "1", features = ["full"] } +tokio-stream = { version = "0.1", features = ["net"] } +anyhow = "1" +uuid = { version = "0.8", features = ["v4"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +bytes = "1" \ No newline at end of file diff --git a/vtse-server/src/main.rs b/vtse-server/src/main.rs new file mode 100644 index 0000000..3f1748e --- /dev/null +++ b/vtse-server/src/main.rs @@ -0,0 +1,60 @@ +use crate::operations::ServerOperation; +use anyhow::anyhow; +use bytes::BytesMut; +use log::{error, info}; +use tokio::io::AsyncReadExt; +use tokio::net::{TcpListener, TcpStream}; +use tokio_stream::{wrappers::TcpListenerStream, StreamExt}; + +mod operations; + +pub(crate) type Result = std::result::Result; + +#[tokio::main] +async fn main() -> Result<()> { + simple_logger::SimpleLogger::default().init()?; + + let mut listener_stream = TcpListener::bind("localhost:8080") + .await + .map(TcpListenerStream::new)?; + + info!("Successfully bound to port"); + + while let Some(Ok(stream)) = listener_stream.next().await { + tokio::task::spawn(async { + match handle_stream(stream).await { + Ok(_) => (), + Err(e) => error!("{}", e), + } + }); + } + + info!("Cleanly shut down. Goodbye!"); + + Ok(()) +} + +async fn handle_stream(mut socket: TcpStream) -> Result<()> { + // only accept data that can fit in 256 bytes + let mut buffer = BytesMut::with_capacity(256); + loop { + let bytes_read = socket.read_buf(&mut buffer).await?; + match bytes_read { + 0 => return Err(anyhow!("Failed to read bytes, assuming socket is closed.")), + n => { + let data = buffer.split_to(n); // O(1) + let parsed = serde_json::from_slice::(&data)?; + match parsed { + ServerOperation::Query(op) => { + dbg!(op); + } + ServerOperation::Meta(op) => { + dbg!(op); + } + } + buffer.unsplit(data); // O(1) + } + } + buffer.clear(); + } +} diff --git a/vtse-server/src/operations.rs b/vtse-server/src/operations.rs new file mode 100644 index 0000000..3a43bda --- /dev/null +++ b/vtse-server/src/operations.rs @@ -0,0 +1,56 @@ +use serde::Deserialize; +use vtse_common::stock::StockName; + +#[derive(Deserialize, Debug, PartialEq)] +#[serde(untagged)] +pub(crate) enum ServerOperation { + Query(QueryOperation), + Meta(MetaOperation), +} + +#[derive(Deserialize, Debug, PartialEq)] +#[serde(tag = "type", rename_all = "snake_case")] +pub(crate) enum QueryOperation { + StockInfo { stock: StockName }, +} + +#[derive(Deserialize, Debug, PartialEq)] +#[serde(tag = "type", rename_all = "snake_case")] +pub(crate) enum MetaOperation { + Register { username: String, password: String }, +} + +#[cfg(test)] +mod deserialize { + use super::*; + use serde_json::json; + use std::str::FromStr; + + #[test] + fn server_op_is_transparent() { + assert_eq!( + serde_json::from_value::(json!({ + "type": "stock_info", + "stock": "Gura", + })) + .unwrap(), + ServerOperation::Query(QueryOperation::StockInfo { + stock: StockName::from_str("Gura").unwrap() + }) + ) + } + + #[test] + fn query_op() { + assert_eq!( + serde_json::from_value::(json!({ + "type": "stock_info", + "stock": "Gura", + })) + .unwrap(), + QueryOperation::StockInfo { + stock: StockName::from_str("Gura").unwrap() + } + ) + } +} diff --git a/vtse-server/src/user.rs b/vtse-server/src/user.rs new file mode 100644 index 0000000..2204f2d --- /dev/null +++ b/vtse-server/src/user.rs @@ -0,0 +1 @@ +pub(crate) struct ApiKey(String);