veddb_client/
lib.rs

1//! # VedDB Rust Client
2//!
3//! [![Crates.io](https://img.shields.io/crates/v/veddb-client.svg)](https://crates.io/crates/veddb-client)
4//! [![Documentation](https://docs.rs/veddb-client/badge.svg)](https://docs.rs/veddb-client)
5//! [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6//!
7//! **Official Rust client library and CLI for VedDB** - A fast, lightweight in-memory key-value database.
8//!
9//! This crate provides both a **Rust library** for embedding in your applications and a **CLI tool** 
10//! (`veddb-cli`) for interactive database operations.
11//!
12//! ## 🚀 Quick Start
13//!
14//! Add this to your `Cargo.toml`:
15//!
16//! ```toml
17//! [dependencies]
18//! veddb-client = "0.0.11"
19//! tokio = { version = "1", features = ["full"] }
20//! ```
21//!
22//! ### Basic Example
23//!
24//! ```no_run
25//! use veddb_client::{Client, Result};
26//!
27//! #[tokio::main]
28//! async fn main() -> Result<()> {
29//!     // Connect to VedDB server
30//!     let client = Client::connect("127.0.0.1:50051").await?;
31//!     
32//!     // Ping the server
33//!     client.ping().await?;
34//!     println!("Server is alive!");
35//!     
36//!     // Set a key-value pair
37//!     client.set("name", "Alice").await?;
38//!     
39//!     // Get a value
40//!     let value = client.get("name").await?;
41//!     println!("Value: {}", String::from_utf8_lossy(&value));
42//!     
43//!     // List all keys
44//!     let keys = client.list_keys().await?;
45//!     println!("Keys: {:?}", keys);
46//!     
47//!     // Delete a key
48//!     client.delete("name").await?;
49//!     
50//!     Ok(())
51//! }
52//! ```
53//!
54//! ## ✨ Features
55//!
56//! - **Async/Await** - Built on Tokio for high-performance async I/O
57//! - **Connection Pooling** - Efficient connection management and reuse
58//! - **Type-Safe** - Full Rust type safety and error handling
59//! - **All Operations** - PING, SET, GET, DELETE, LIST commands
60//! - **CLI Tool** - Command-line interface included (`veddb-cli`)
61//!
62//! ## 📖 Usage Examples
63//!
64//! ### Connection Pooling
65//!
66//! ```no_run
67//! use veddb_client::Client;
68//!
69//! #[tokio::main]
70//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
71//!     // Create client with connection pool (10 connections)
72//!     let client = Client::with_pool_size("127.0.0.1:50051", 10).await?;
73//!     
74//!     // Connections are automatically managed
75//!     client.set("key1", "value1").await?;
76//!     client.set("key2", "value2").await?;
77//!     
78//!     Ok(())
79//! }
80//! ```
81//!
82//! ### Working with Binary Data
83//!
84//! ```no_run
85//! use veddb_client::Client;
86//!
87//! #[tokio::main]
88//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
89//!     let client = Client::connect("127.0.0.1:50051").await?;
90//!     
91//!     // Store binary data
92//!     let data = vec![0x01, 0x02, 0x03, 0x04];
93//!     client.set("binary_key", &data).await?;
94//!     
95//!     // Retrieve binary data
96//!     let retrieved = client.get("binary_key").await?;
97//!     assert_eq!(retrieved, data);
98//!     
99//!     Ok(())
100//! }
101//! ```
102//!
103//! ### Error Handling
104//!
105//! ```no_run
106//! use veddb_client::{Client, Error};
107//!
108//! #[tokio::main]
109//! async fn main() {
110//!     let client = Client::connect("127.0.0.1:50051").await.unwrap();
111//!     
112//!     match client.get("nonexistent_key").await {
113//!         Ok(value) => println!("Found: {:?}", value),
114//!         Err(Error::Server(msg)) if msg.contains("NotFound") => {
115//!             println!("Key not found");
116//!         }
117//!         Err(e) => eprintln!("Error: {}", e),
118//!     }
119//! }
120//! ```
121//!
122//! ## 🖥️ CLI Tool
123//!
124//! This crate includes `veddb-cli`, a command-line interface for VedDB:
125//!
126//! ```bash
127//! # Ping server
128//! veddb-cli ping
129//!
130//! # Set a key
131//! veddb-cli kv set name Alice
132//!
133//! # Get a key
134//! veddb-cli kv get name
135//!
136//! # List all keys
137//! veddb-cli kv list
138//!
139//! # Delete a key
140//! veddb-cli kv del name
141//! ```
142//!
143//! ## 🔌 Protocol
144//!
145//! VedDB uses a simple binary protocol over TCP:
146//!
147//! - **Little-endian** encoding for all integers
148//! - **Command format**: 24-byte header + payload
149//! - **Response format**: 20-byte header + payload
150//!
151//! ### Supported Operations
152//!
153//! | OpCode | Command | Description |
154//! |--------|---------|-------------|
155//! | `0x01` | PING | Health check |
156//! | `0x02` | SET | Store key-value pair |
157//! | `0x03` | GET | Retrieve value by key |
158//! | `0x04` | DELETE | Remove key |
159//! | `0x09` | LIST | List all keys |
160//!
161//! ## 🔗 Related
162//!
163//! - **Server**: [ved-db-server](https://github.com/Mihir-Rabari/ved-db-server) - VedDB Server v0.1.21
164//! - **Repository**: [GitHub](https://github.com/Mihir-Rabari/ved-db-rust-client)
165//!
166//! ## 📄 License
167//!
168//! This project is licensed under the MIT License - see the [LICENSE](https://github.com/Mihir-Rabari/ved-db-rust-client/blob/main/LICENSE) file for details.
169
170#![warn(missing_docs)]
171#![warn(rustdoc::missing_crate_level_docs)]
172#![forbid(unsafe_code)]
173
174mod connection;
175mod error;
176mod types;
177
178pub use connection::{Client, ClientBuilder, Connection, ConnectionPool};
179pub use error::Error;
180pub use types::{Command, Response, StatusCode};
181
182/// Custom result type for VedDB operations
183pub type Result<T> = std::result::Result<T, Error>;
184
185/// Re-export of the `bytes` crate for convenience
186pub use bytes;
187
188/// Re-export of the `tracing` crate for convenience
189#[cfg(feature = "tracing")]
190pub use tracing;
191
192#[cfg(test)]
193mod tests {
194    use super::*;
195
196    #[tokio::test]
197    async fn test_error_conversion() {
198        // Test that we can convert from io::Error
199        let io_error = std::io::Error::new(std::io::ErrorKind::Other, "test");
200        let error: Error = io_error.into();
201        assert!(matches!(error, Error::Io(_)));
202        
203        // Test that we can convert from string
204        let error: Error = "test error".into();
205        assert!(matches!(error, Error::Other(_)));
206    }
207}