# Comprehensive Usage Examples
This document provides detailed examples for using `rok-utils`.
## Table of Contents
1. [String Utilities](#string-utilities)
2. [Fluent Builder](#fluent-builder)
3. [Array/Collection Utilities](#arraycollection-utilities)
4. [Error Handling](#error-handling)
5. [Functional Patterns](#functional-patterns)
6. [Data Utilities](#data-utilities)
7. [File System Helpers](#file-system-helpers)
8. [Type Guards](#type-guards)
---
## String Utilities
### Case Conversion
```rust
use rok_utils::{to_snake_case, to_camel_case, to_kebab_case, to_pascal_case};
let snake = to_snake_case("HelloWorld"); // "hello_world"
let camel = to_camel_case("hello_world"); // "helloWorld"
let kebab = to_kebab_case("HelloWorld"); // "hello-world"
let pascal = to_pascal_case("hello_world"); // "HelloWorld"
```
### Truncation
```rust
use rok_utils::truncate;
let short = truncate("Hello World", 5); // "Hello..."
let complete = truncate("Hello World", 5); // Already short, unchanged
```
### Slug Generation
```rust
use rok_utils::slug;
let slug = slug("Hello World!"); // "hello-world"
let custom = slug("Hello World!", '_'); // "hello_world"
```
### Pluralization (feature: "unicode")
```rust
use rok_utils::pluralize;
assert_eq!(pluralize("cat", 1), "cat");
assert_eq!(pluralize("cat", 2), "cats");
assert_eq!(pluralize("box", 3), "boxes");
```
### Base64 Encoding
```rust
use rok_utils::to_base64;
let encoded = to_base64("Hello"); // "SGVsbG8="
```
### String Inspection
```rust
use rok_utils::{
is_empty, is_ascii, is_url, starts_with, ends_with, contains,
word_count, length
};
assert!(!is_empty("hello"));
assert!(is_ascii("hello"));
assert!(is_url("https://example.com"));
assert!(starts_with("hello world", "hello"));
assert!(ends_with("hello world", "world"));
assert!(contains("hello world", "lo"));
assert_eq!(word_count("hello world"), 2);
assert_eq!(length("hello"), 5);
```
---
## Fluent Builder
The `Str::of()` builder provides a chainable API for complex string transformations.
### Basic Chaining
```rust
use rok_utils::str::Str;
let result = Str::of(" Hello World ")
.trim()
.to_snake_case()
.value();
assert_eq!(result, "hello_world");
```
### Conditional Transformations
```rust
use rok_utils::str::Str;
let result = Str::of("hello")
.when(true, |s| s.append(" world"))
.when(false, |s| s.append(" hidden"))
.value();
assert_eq!(result, "hello world");
```
### Empty Handling
```rust
use rok_utils::str::Str;
let result = Str::of("")
.when_empty(|s| s.append("default"))
.value();
assert_eq!(result, "default");
```
### Content-Based Conditionals
```rust
use rok_utils::str::Str;
let result = Str::of("user@example.com")
.when_contains("@", |s| s.replace("@", " [at] "))
.value();
assert_eq!(result, "user [at] example.com");
```
### Prefix/Suffix Operations
```rust
use rok_utils::str::Str;
let result = Str::of("world")
.ensure_start("hello ")
.finish("!")
.value();
assert_eq!(result, "hello world!");
```
### Text Wrapping
```rust
use rok_utils::str::Str;
let result = Str::of("content")
.wrap("[", "]")
.value();
assert_eq!(result, "[content]");
```
### Side Effects with Tap
```rust
use rok_utils::str::Str;
let mut collected = Vec::new();
let _ = Str::of("hello")
.tap(|s| collected.push(s.len()))
.tap(|s| collected.push(s.chars().count()))
.value();
// collected: [5, 5]
```
### Custom Transformations with Pipe
```rust
use rok_utils::str::Str;
let result = Str::of("hello")
.pipe(|s| s.to_uppercase())
.pipe(|s| format!("{s}!"))
.value();
assert_eq!(result, "HELLO!");
```
### Complete Real-World Example
```rust
use rok_utils::str::Str;
fn format_username(name: &str) -> String {
Str::of(name)
.trim()
.lower()
.when_empty(|s| s.append("anonymous"))
.replace(" ", "_")
.prepend("@")
.value()
}
assert_eq!(format_username(" John Doe "), "@john_doe");
assert_eq!(format_username(" "), "@anonymous");
```
---
## Array/Collection Utilities
### Mapping and Filtering
```rust
use rok_utils::arr::{map, filter};
let numbers = [1, 2, 3, 4, 5];
```
### Finding Elements
```rust
use rok_utils::arr::{first, last, find};
let items = ["a", "b", "c"];
assert_eq!(first(&items), Some(&"a"));
assert_eq!(last(&items), Some(&"c"));
```rust
use rok_utils::arr::{unique, diff, intersect, without};
let a = [1, 2, 3, 2, 1];
let uniq = unique(&a);
assert_eq!(uniq, vec![1, 2, 3]);
let difference = diff(&[1, 2, 3], &[2]);
assert_eq!(difference, vec![1, 3]);
let intersection = intersect(&[1, 2, 3], &[2, 3, 4]);
assert_eq!(intersection, vec![2, 3]);
let filtered = without(&[1, 2, 3, 4], &[2, 4]);
assert_eq!(filtered, vec![1, 3]);
```
### Membership Testing
```rust
use rok_utils::arr::contains;
let items = ["a", "b", "c"];
assert!(contains(&items, &"b"));
assert!(!contains(&items, &"d"));
```
### Reducing
```rust
use rok_utils::arr::reduce;
let numbers = [1, 2, 3, 4];
```
---
## Error Handling
### Basic Error Creation
```rust
use rok_utils::RokError;
let err = RokError::NotFound("User #42".into());
assert_eq!(err.code(), "E_NOT_FOUND");
assert_eq!(err.status(), 404);
assert!(err.is_self_handled());
```
### Result Extension
```rust
use rok_utils::{RokResultExt, RokError};
fn find_user(id: u64) -> Result<String, RokError> {
if id == 42 {
Ok("Alice".to_string())
} else {
Err(RokError::NotFound(format!("User #{id}")))
}
}
let result = find_user(42).context("Database query failed");
assert!(result.is_ok());
let result = find_user(0).or_not_found("User");
assert!(matches!(result, Err(RokError::NotFound(_))));
```
### Contextual Errors
```rust
use rok_utils::{RokResultExt, RokError};
let data = vec![1, 2, 3];
let result = data.get(10)
.ok_or(RokError::NotFound("Element not found".into()))
.context("Array access failed");
```
### Validation Errors
```rust
use rok_utils::RokError;
fn validate_email(email: &str) -> Result<(), RokError> {
if email.contains('@') {
Ok(())
} else {
Err(RokError::ValidationFailure {
field: "email".to_string(),
reason: "Must contain @".to_string(),
})
}
}
let result = validate_email("invalid");
assert!(matches!(result, Err(RokError::ValidationFailure { .. })));
```
### Handling Different Error Types
```rust
use rok_utils::RokError;
fn handle_error(err: &RokError) -> String {
match err {
RokError::NotFound(msg) => format!("404: {}", msg),
RokError::ValidationFailure { field, reason } => {
format!("Validation error on {}: {}", field, reason)
}
RokError::Unauthorized(msg) => format!("401: {}", msg),
_ => format!("Error: {}", err.code()),
}
}
```
---
## Functional Patterns
### Pipe
```rust
use rok_utils::fp::pipe;
let result = pipe(5, vec![
|x| x + 1,
|x| x * 2,
|x| x - 3,
]);
assert_eq!(result, 9); // (5 + 1) * 2 - 3 = 9
```
### Compose
```rust
use rok_utils::fp::compose;
let add_one = |x: i32| x + 1;
assert_eq!(add_then_double(5), 12); // (5 + 1) * 2
```
### Tap (Side Effects)
```rust
use rok_utils::fp::tap;
let mut log = Vec::new();
```rust
use rok_utils::fp::memoize;
let call_count = std::cell::Cell::new(0);
x * x
});
assert_eq!(expensive(5), 25);
assert_eq!(expensive(5), 25); // Uses cached result
assert_eq!(call_count.get(), 1);
```
### Lazy Initialization
```rust
use rok_utils::fp::Lazy;
"config_value".to_string()
});
println!("Before access");
let value = config.get();
println!("After access: {}", value);
let value2 = config.get(); // No re-initialization
```
---
## Data Utilities
### Number Formatting (feature: default)
```rust
use rok_utils::data::numbers::{format_number, format_currency, format_percentage};
assert_eq!(format_number(1234567.89, 2, ','), "1,234,567.89");
assert_eq!(format_currency(1234.50, "USD"), "$1,234.50");
assert_eq!(format_percentage(0.1234, 1), "12.3%");
```
### Rounding
```rust
use rok_utils::data::numbers::{round, ceil, floor};
assert_eq!(round(3.14159, 2), 3.14);
assert_eq!(ceil(3.001, 0), 4.0);
assert_eq!(floor(3.999, 0), 3.0);
```
### Date/Time (feature: "dates")
```rust
use rok_utils::{now, today, format_date, add_days};
let today = today();
let tomorrow = add_days(&today, 1);
let now = now();
let formatted = format_date(&now, "%Y-%m-%d %H:%M");
```
### UUID/ULID Generation (feature: "ids")
```rust
use rok_utils::{uuid_v4, uuid_v7, ulid, is_uuid, is_ulid};
let uuid = uuid_v4();
let uuid7 = uuid_v7();
let id = ulid();
assert!(is_uuid(&uuid));
assert!(is_ulid(&id));
```
### Hashing (feature: "crypto")
```rust
use rok_utils::{hash_sha256, verify_sha256, generate_token, secure_compare};
let hash = hash_sha256("password");
assert!(verify_sha256("password", &hash));
let token = generate_token(32);
assert_eq!(token.len(), 32); // 32 bytes as hex
assert!(secure_compare("secret", "secret"));
assert!(!secure_compare("secret", "Secret"));
```
### Random Strings (feature: "random")
```rust
use rok_utils::{random, password};
let rand_str = random(16); // 16 character random string
let pass = password(16, true); // with symbols
```
---
## File System Helpers
### Directory Operations
```rust
use rok_utils::fs::{ensure_dir, is_dir, is_file, find_files};
ensure_dir("./data/output").expect("Failed to create directory");
if is_dir("./data") {
let files = find_files("./data", "*.txt").unwrap();
}
```
### File Operations
```rust
use rok_utils::fs::{read_to_string, write_atomic, copy_dir_all};
let content = read_to_string("config.toml").unwrap();
write_atomic("output.txt", "Hello, World!").unwrap();
```
### Directory Copying
```rust
use rok_utils::fs::copy_dir_all;
copy_dir_all("source", "destination").expect("Copy failed");
```
---
## Type Guards (feature: "json")
```rust
use rok_utils::types::{is_string, is_number, is_array, is_object};
use serde_json::json;
let value = json!({
"name": "Alice",
"age": 30,
"scores": [95, 87, 92]
});
assert!(is_string(&value["name"]));
assert!(is_number(&value["age"]));
assert!(is_array(&value["scores"]));
assert!(is_object(&value));
```
### Deep Path Access
```rust
use rok_utils::types::get_path;
use serde_json::json;
let data = json!({
"user": {
"address": {
"city": "New York"
}
}
});
assert_eq!(get_path(&data, "user.address.city"), Some(&json!("New York")));
assert_eq!(get_path(&data, "user.missing"), None);
```
### Deep Path Setting
```rust
use rok_utils::types::set_path;
use serde_json::json;
let mut data = json!({"a": 1});
data = set_path(data, "b", json!(2));
assert_eq!(data.get("b"), Some(&json!(2)));
```
### Deep Equality
```rust
use rok_utils::types::deep_equal;
use serde_json::json;
assert!(deep_equal(&json!({"a": 1}), &json!({"a": 1})));
assert!(!deep_equal(&json!({"a": 1}), &json!({"a": 2})));
```
---
## Complete Examples
### Web API Input Validation
```rust
use rok_utils::{RokError, RokResultExt, Str, truncate};
fn validate_username(username: &str) -> Result<String, RokError> {
let normalized = Str::of(username)
.trim()
.lower()
.when_empty(|_| panic!("Username required"))
.value();
if normalized.len() < 3 {
return Err(RokError::ValidationFailure {
field: "username".to_string(),
reason: "Must be at least 3 characters".to_string(),
});
}
if normalized.len() > 20 {
return Err(RokError::ValidationFailure {
field: "username".to_string(),
reason: "Must be at most 20 characters".to_string(),
});
}
Ok(normalized)
}
```
### Slug Generation for URLs
```rust
use rok_utils::{Str, slug, to_snake_case};
fn generate_url_slug(title: &str) -> String {
Str::of(title)
.trim()
.lower()
.replace("'", "")
.squish()
.value()
}
assert_eq!(generate_url_slug(" Hello World !"), "hello world");
```
### API Response Formatting
```rust
use rok_utils::{Str, truncate};
fn format_error_message(error: &str) -> String {
Str::of(error)
.trim()
.truncate(100)
.finish("...")
.wrap("[Error] ", "")
.value()
}
assert_eq!(format_error_message(" Something went wrong "), "[Error] Something went wrong...");
```