From 8599d4af6b47ba5fbdd4b2153bfea8cdc2684e68 Mon Sep 17 00:00:00 2001 From: upupnoah Date: Sun, 28 Jul 2024 17:51:35 +0700 Subject: [PATCH] feat(network): support network for simple redis --- Cargo.lock | 447 +++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 21 ++- src/cmd/map.rs | 4 +- src/cmd/mod.rs | 25 ++- src/lib.rs | 8 +- src/main.rs | 28 ++- src/network.rs | 81 +++++++++ src/resp/mod.rs | 7 + 8 files changed, 609 insertions(+), 12 deletions(-) create mode 100644 src/network.rs diff --git a/Cargo.lock b/Cargo.lock index e6be4e1..2416537 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,30 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.82" @@ -14,6 +38,21 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bitflags" version = "2.6.0" @@ -26,6 +65,12 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +[[package]] +name = "cc" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" + [[package]] name = "cfg-if" version = "1.0.0" @@ -64,12 +109,85 @@ dependencies = [ "syn", ] +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "lazy_static" version = "1.5.0" @@ -92,12 +210,79 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "object" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot_core" version = "0.9.10" @@ -111,6 +296,18 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "proc-macro2" version = "1.0.86" @@ -138,12 +335,71 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "simple-redis" version = "0.1.0" @@ -152,8 +408,14 @@ dependencies = [ "bytes", "dashmap", "enum_dispatch", - "lazy_static", + "futures", "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "tracing-subscriber", + "winnow", ] [[package]] @@ -162,6 +424,16 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "syn" version = "2.0.71" @@ -193,12 +465,176 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" +dependencies = [ + "backtrace", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[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" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -262,3 +698,12 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml index cdf92bc..ec2a407 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,5 +11,24 @@ anyhow = "^1.0" bytes = "^1.6.1" dashmap = "6.0.1" enum_dispatch = "^0.3.13" -lazy_static = "^1.5.0" +futures = { version = "^0.3.30", default-features = false } +# lazy_static = "^1.5.0" thiserror = "^1.0.62" +tokio = { version = "^1.37.0", features = [ + "rt", + "rt-multi-thread", + "macros", + "net", +] } +tokio-stream = "^0.1.15" +tokio-util = { version = "^0.7.10", features = ["codec"] } +tracing = "^0.1.40" +tracing-subscriber = { version = "^0.3.18", features = ["env-filter"] } +winnow = { version = "^0.6.8", features = ["simd"] } + +# [dev-dependencies] +# criterion = { version = "^0.5.1", features = ["html_reports"] } + +# [[bench]] +# name = "resp" +# harness = false diff --git a/src/cmd/map.rs b/src/cmd/map.rs index 0e7341c..680dcc1 100644 --- a/src/cmd/map.rs +++ b/src/cmd/map.rs @@ -1,9 +1,9 @@ use crate::{ cmd::{extract_args, validate_command, Get, Set}, - CommandError, RespArray, RespFrame, RespNull, + RespArray, RespFrame, RespNull, }; -use super::{CommandExecutor, RESP_OK}; +use super::{CommandError, CommandExecutor, RESP_OK}; impl CommandExecutor for Get { fn execute(self, backend: &crate::Backend) -> RespFrame { diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 207acb0..12da088 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -1,5 +1,6 @@ +use std::sync::LazyLock; + use enum_dispatch::enum_dispatch; -use lazy_static::lazy_static; use thiserror::Error; use crate::{Backend, RespArray, RespError, RespFrame, SimpleString}; @@ -12,9 +13,13 @@ mod map; // 1. init in runtime // 2. thread safe // 3. improve performance -lazy_static! { - static ref RESP_OK: RespFrame = SimpleString::new("OK").into(); -} +// lazy_static! { +// static ref RESP_OK: RespFrame = SimpleString::new("OK").into(); +// } + +// > Rust 1.80.0 +// https://blog.rust-lang.org/2024/07/25/Rust-1.80.0.html +static RESP_OK: LazyLock = LazyLock::new(|| SimpleString::new("OK").into()); // region: --- Traits #[enum_dispatch] @@ -108,6 +113,18 @@ impl TryFrom for Command { } } } + +impl TryFrom for Command { + type Error = CommandError; + fn try_from(v: RespFrame) -> Result { + match v { + RespFrame::Array(array) => array.try_into(), + _ => Err(CommandError::InvalidCommand( + "Command must be an Array".to_string(), + )), + } + } +} // endregion: --- impls // region: --- functions diff --git a/src/lib.rs b/src/lib.rs index 195a8a3..d5776ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,11 @@ mod backend; -mod cmd; + mod resp; +pub mod cmd; +pub mod network; + pub use backend::*; -pub use cmd::*; +// pub use cmd::*; +// pub use network::*; pub use resp::*; diff --git a/src/main.rs b/src/main.rs index e7a11a9..ef80ad8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,27 @@ -fn main() { - println!("Hello, world!"); +use anyhow::Result; +use simple_redis::{network, Backend}; +use tokio::net::TcpListener; +use tracing::info; + +#[tokio::main] +async fn main() -> Result<()> { + tracing_subscriber::fmt::init(); + + let addr = "0.0.0.0:6389"; + let listener = TcpListener::bind(addr).await?; + info!("Simple-Redis-Server is listening on {}", addr); + + let backend = Backend::new(); + loop { + let (stream, remote_addr) = listener.accept().await?; + info!("Accepted connection from {}", remote_addr); + let cloned_backend = backend.clone(); + tokio::spawn(async move { + // handling of stream + match network::stream_handler(stream, cloned_backend).await { + Ok(_) => info!("Connection from {} closed", remote_addr), + Err(e) => info!("Connection from {} closed with error: {}", remote_addr, e), + } + }); + } } diff --git a/src/network.rs b/src/network.rs new file mode 100644 index 0000000..29a1656 --- /dev/null +++ b/src/network.rs @@ -0,0 +1,81 @@ +use anyhow::Result; +use futures::SinkExt; +use tokio::net::TcpStream; +use tokio_stream::StreamExt; +use tokio_util::codec::{Decoder, Encoder, Framed}; +use tracing::info; + +use crate::{ + cmd::{Command, CommandExecutor}, + Backend, RespDecode, RespEncode, RespError, RespFrame, +}; + +#[derive(Debug)] +struct RedisRequest { + frame: RespFrame, + backend: Backend, +} + +#[derive(Debug)] +struct RedisResponse { + frame: RespFrame, +} + +#[derive(Debug)] +struct RespFrameCodec; + +pub async fn stream_handler(stream: TcpStream, backend: Backend) -> Result<()> { + // how to get a frame from the stream? + let mut framed = Framed::new(stream, RespFrameCodec); + loop { + match framed.next().await { + Some(Ok(frame)) => { + info!("Received frame: {:?}", frame); + let request = RedisRequest { + frame, + backend: backend.clone(), + }; + let response = request_handler(request).await?; + info!("Sending response: {:?}", response.frame); + framed.send(response.frame).await?; + } + Some(Err(e)) => return Err(e), + None => return Ok(()), + } + } +} + +// NOTE: need a backend to process the frame +// async fn request_handler(request: RespFrame) -> Result { +// todo!() +// } +async fn request_handler(request: RedisRequest) -> Result { + let (frame, backend) = (request.frame, request.backend); + let cmd = Command::try_from(frame)?; + info!("Executing command: {:?}", cmd); + let frame = cmd.execute(&backend); + Ok(RedisResponse { frame }) +} + +impl Encoder for RespFrameCodec { + type Error = anyhow::Error; + + fn encode(&mut self, item: RespFrame, dst: &mut bytes::BytesMut) -> Result<()> { + let encoded = item.encode(); + dst.extend_from_slice(&encoded); + Ok(()) + } +} + +impl Decoder for RespFrameCodec { + type Item = RespFrame; + type Error = anyhow::Error; + + fn decode(&mut self, src: &mut bytes::BytesMut) -> Result> { + match RespFrame::decode(src) { + Ok(frame) => Ok(Some(frame)), + Err(RespError::NotComplete) => Ok(None), + Err(e) => Err(e.into()), + } + } +} diff --git a/src/resp/mod.rs b/src/resp/mod.rs index ba940ec..4edf46d 100644 --- a/src/resp/mod.rs +++ b/src/resp/mod.rs @@ -58,6 +58,13 @@ pub enum RespError { // fn expect_length(buf: &[u8]) -> Result; // } +// 关于 enum 的知识点 +// 枚举变体: 直接包含数据, 结构体类型, 无数据 + +// 元组变体: 当枚举变体直接包含一组命名未指定的值时-> SimpleString(String) 和 Integer(i64), +// 结构体变体: 枚举的变体被定义为包含具有名称的字段-> StructVariant { name: String, id: i32 } +// 单元变体: RespNull + // 之所以要定义一些新的结构体, 是因为要在实现 trait 的时候, 要区分开这些类型 #[enum_dispatch(RespEncode)] #[derive(Debug, Clone, PartialEq)]