Skip to content

Commit

Permalink
Merge 0bdd7ad into 06fadc6
Browse files Browse the repository at this point in the history
  • Loading branch information
Pushkarm029 authored Aug 22, 2024
2 parents 06fadc6 + 0bdd7ad commit ff228d7
Show file tree
Hide file tree
Showing 6 changed files with 941 additions and 17 deletions.
5 changes: 4 additions & 1 deletion fs-storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ serde_json = "1.0.82"
serde = { version = "1.0.138", features = ["derive"] }
jni = { version = "0.21.1", optional = true }
jnix = { version = "0.5.1", features = ["derive"], optional = true }

bincode = "1.3"
data-error = { path = "../data-error" }


[dev-dependencies]
anyhow = "1.0.81"
quickcheck = { version = "1.0.3", features = ["use_logging"] }
quickcheck_macros = "1.0.0"
tempdir = "0.3.7"
test-log = "0.2.16"

[features]
default = ["jni-bindings"]
Expand Down
128 changes: 114 additions & 14 deletions fs-storage/examples/cli.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use anyhow::{Context, Result};
use fs_storage::{base_storage::BaseStorage, file_storage::FileStorage};
use fs_storage::{
base_storage::BaseStorage, file_storage::FileStorage,
folder_storage::FolderStorage,
};
use serde_json::Value;
use std::{env, fs, path::Path};

Expand All @@ -13,26 +16,41 @@ fn run() -> Result<()> {
let args: Vec<String> = env::args().collect();
if args.len() < 3 {
println!("Usage:");
println!(" cargo run --example cli write <path> [JSON_FILE_PATH | KEY_VALUE_PAIRS]");
println!(" cargo run --example cli read <path> <key1,key2,...>");
println!(" cargo run --example cli (file | folder) write <path> [JSON_FILE_PATH | KEY_VALUE_PAIRS]");
println!(" cargo run --example cli (file | folder) read <path> <key1,key2,...>");
return Ok(());
}

let command = &args[1];
let path = &args[2];
match command.as_str() {
"read" => read_command(&args, path),
"write" => write_command(&args, path),
let storage_type = &args[1];
let command = &args[2];
let path = &args[3];
match storage_type.as_str() {
"file" => match command.as_str() {
"read" => file_read_command(&args, path),
"write" => file_write_command(&args, path),
_ => {
eprintln!("Invalid command. Use 'read' or 'write'.");
Ok(())
}
},
"folder" => match command.as_str() {
"read" => folder_read_command(&args, path),
"write" => folder_write_command(&args, path),
_ => {
eprintln!("Invalid command. Use 'read' or 'write'.");
Ok(())
}
},
_ => {
eprintln!("Invalid command. Use 'read' or 'write'.");
eprintln!("Invalid storage. Use 'file' or 'folder'.");
Ok(())
}
}
}

fn read_command(args: &[String], path: &str) -> Result<()> {
fn file_read_command(args: &[String], path: &str) -> Result<()> {
let keys = if args.len() > 3 {
args[3]
args[4]
.split(',')
.map(|s| s.to_string())
.collect::<Vec<String>>()
Expand Down Expand Up @@ -63,13 +81,13 @@ fn read_command(args: &[String], path: &str) -> Result<()> {
Ok(())
}

fn write_command(args: &[String], path: &str) -> Result<()> {
fn file_write_command(args: &[String], path: &str) -> Result<()> {
if args.len() < 4 {
println!("Usage: cargo run --example cli write <path> [JSON_FILE_PATH | KEY_VALUE_PAIRS]");
println!("Usage: cargo run --example cli file write <path> [JSON_FILE_PATH | KEY_VALUE_PAIRS]");
return Ok(());
}

let content = &args[3];
let content = &args[4];
// Check if the content is a JSON file path
let content_json = Path::new(content)
.extension()
Expand Down Expand Up @@ -107,5 +125,87 @@ fn write_command(args: &[String], path: &str) -> Result<()> {
}
}
}
fs.write_fs().expect("Failed to write to file");
Ok(())
}

fn folder_read_command(args: &[String], path: &str) -> Result<()> {
let keys = if args.len() > 3 {
args[4]
.split(',')
.map(|s| s.to_string())
.collect::<Vec<String>>()
} else {
vec![]
};

let mut fs: FolderStorage<String, String> =
FolderStorage::new("cli".to_string(), Path::new(path))
.context("Failed to create FolderStorage")?;

let map = fs
.read_fs()
.expect("No Data is present on this path");
if keys.is_empty() {
for (key, value) in map {
println!("{}: {}", key, value);
}
}
for key in &keys {
if let Some(value) = map.get(key) {
println!("{}: {}", key, value);
} else {
eprintln!("Key '{}' not found", key);
}
}

Ok(())
}

fn folder_write_command(args: &[String], path: &str) -> Result<()> {
if args.len() < 4 {
println!("Usage: cargo run --example cli folder write <path> [JSON_FILE_PATH | KEY_VALUE_PAIRS]");
return Ok(());
}

let content = &args[4];
// Check if the content is a JSON file path
let content_json = Path::new(content)
.extension()
.map_or(false, |ext| ext == "json");

let mut fs: FolderStorage<String, String> =
FolderStorage::new("cli".to_string(), Path::new(path))
.context("Failed to create FolderStorage")?;
if content_json {
let content =
fs::read_to_string(content).context("Failed to read JSON file")?;
let json: Value =
serde_json::from_str(&content).context("Failed to parse JSON")?;
if let Value::Object(object) = json {
for (key, value) in object {
if let Value::String(value_str) = value {
fs.set(key, value_str);
} else {
println!(
"Warning: Skipping non-string value for key '{}'",
key
);
}
}
} else {
println!("JSON value is not an object");
return Ok(());
}
} else {
let pairs = content.split(',');
for pair in pairs {
let kv: Vec<&str> = pair.split(':').collect();
if kv.len() == 2 {
fs.set(kv[0].to_string(), kv[1].to_string());
}
}
}
fs.write_fs().expect("Failed to write to folder");
Ok(())
}
2 changes: 1 addition & 1 deletion fs-storage/src/base_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub trait BaseStorage<K, V>: AsRef<BTreeMap<K, V>> {
fn remove(&mut self, id: &K) -> Result<()>;

/// Get [`SyncStatus`] of the storage
fn sync_status(&self) -> Result<SyncStatus>;
fn sync_status(&mut self) -> Result<SyncStatus>;

/// Sync the in-memory storage with the storage on disk
fn sync(&mut self) -> Result<()>;
Expand Down
2 changes: 1 addition & 1 deletion fs-storage/src/file_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ where
/// Compare the timestamp of the storage file
/// with the timestamp of the in-memory storage and the last written
/// to time to determine if either of the two requires syncing.
fn sync_status(&self) -> Result<SyncStatus> {
fn sync_status(&mut self) -> Result<SyncStatus> {
let file_updated = fs::metadata(&self.path)?.modified()?;

// Determine the synchronization status based on the modification times
Expand Down
Loading

0 comments on commit ff228d7

Please sign in to comment.