From faa9f7d4efbfd2da46c153d2e022f06ae9d74d41 Mon Sep 17 00:00:00 2001 From: Xu Shaohua Date: Sun, 9 Jun 2024 23:28:58 +0800 Subject: [PATCH] string: Add sub_str command --- src/cmd/string.rs | 7 +++++++ src/mem/string/get_range.rs | 13 +++++++++++++ src/mem/string/mod.rs | 2 ++ src/mem/string/sub_str.rs | 10 ++++++++-- src/util/prune_range.rs | 16 +++++----------- 5 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 src/mem/string/get_range.rs diff --git a/src/cmd/string.rs b/src/cmd/string.rs index 0ac4896..b6223fe 100644 --- a/src/cmd/string.rs +++ b/src/cmd/string.rs @@ -12,6 +12,7 @@ pub enum StringCommand { Append(String, Bytes), Get(String), GetDel(String), + GetRange(String, i64, i64), GetSet(String, Bytes), Set(String, Bytes), StrLen(String), @@ -37,6 +38,12 @@ impl StringCommand { let key = parser.next_string()?; Self::GetDel(key) } + "getrange" => { + let key = parser.next_string()?; + let start = parser.next_i64()?; + let end = parser.next_i64()?; + Self::GetRange(key, start, end) + } "getset" => { let key = parser.next_string()?; let value = parser.next_bytes()?; diff --git a/src/mem/string/get_range.rs b/src/mem/string/get_range.rs new file mode 100644 index 0000000..15bb359 --- /dev/null +++ b/src/mem/string/get_range.rs @@ -0,0 +1,13 @@ +// Copyright (c) 2024 Xu Shaohua . All rights reserved. +// Use of this source is governed by GNU Affero General Public License +// that can be found in the LICENSE file. + +use crate::cmd::frame::Frame; +use crate::mem::db::Db; +use crate::mem::string::sub_str::sub_str; + +#[must_use] +#[inline] +pub fn get_range(db: &Db, key: &str, start: i64, end: i64) -> Frame { + sub_str(db, key, start, end) +} \ No newline at end of file diff --git a/src/mem/string/mod.rs b/src/mem/string/mod.rs index c9c0590..b92243d 100644 --- a/src/mem/string/mod.rs +++ b/src/mem/string/mod.rs @@ -16,6 +16,7 @@ mod append; mod get_del; mod get_set; mod sub_str; +mod get_range; #[derive(Debug, Clone)] pub enum StrObject { @@ -73,6 +74,7 @@ impl Mem { StringCommand::Append(key, value) => append::append(&mut self.db, key, value), StringCommand::Get(key) => get::get(&self.db, &key), StringCommand::GetDel(key) => get_del::get_del(&mut self.db, &key), + StringCommand::GetRange(key, start, end) => get_range::get_range(&self.db, &key, start, end), StringCommand::GetSet(key, value) => get_set::get_set(&mut self.db, key, value), StringCommand::Set(key, value) => set::set(&mut self.db, key, value), StringCommand::StrLen(key) => strlen::strlen(&self.db, &key), diff --git a/src/mem/string/sub_str.rs b/src/mem/string/sub_str.rs index 2b537bd..85e57a5 100644 --- a/src/mem/string/sub_str.rs +++ b/src/mem/string/sub_str.rs @@ -2,10 +2,12 @@ // Use of this source is governed by GNU Affero General Public License // that can be found in the LICENSE file. +use bytes::Bytes; + use crate::cmd::frame::Frame; use crate::mem::db::{Db, MemObject}; use crate::mem::string::StrObject; -use crate::util::prune_range::slice_range_to_bytes; +use crate::util::prune_range::prune_range; /// Returns the substring of the string value stored at key, /// determined by the offsets start and end (both are inclusive). @@ -19,7 +21,11 @@ pub fn sub_str(db: &Db, key: &str, start: i64, end: i64) -> Frame { Some(MemObject::Str(value)) => match value { StrObject::Integer(_) => todo!(), StrObject::Vec(vec) => { - let bytes = slice_range_to_bytes(vec, start, end); + let bytes = if let Some((start, end)) = prune_range(vec.len(), start, end) { + Bytes::copy_from_slice(&vec[start..=end]) + } else { + Bytes::new() + }; Frame::Bulk(bytes) } } diff --git a/src/util/prune_range.rs b/src/util/prune_range.rs index 967b243..df0c2bb 100644 --- a/src/util/prune_range.rs +++ b/src/util/prune_range.rs @@ -2,20 +2,14 @@ // Use of this source is governed by GNU Affero General Public License // that can be found in the LICENSE file. -use bytes::Bytes; - -pub fn slice_range_to_bytes(slice: &[u8], start: i64, end: i64) -> Bytes { - if let Some((start, end)) = prune_range(slice.len(), start, end) { - Bytes::copy_from_slice(&slice[start..=end]) - } else { - Bytes::new() - } -} - +#[allow(clippy::cast_possible_truncation)] +#[allow(clippy::cast_possible_wrap)] +#[allow(clippy::cast_sign_loss)] pub fn prune_range(len: usize, mut start: i64, mut end: i64) -> Option<(usize, usize)> { + // TODO(Shaohua): Handle cast error let len_i64 = len as i64; if start < 0 { - start += len_i64 + start + start += len_i64; } if end < 0 { end += len_i64;