Welcome to Valu3 - the ultimate, flexible, and powerful library for manipulating diverse data types in your Rust projects. Say goodbye to the complexity of handling numbers, strings, arrays, objects, and datetime values. Valu3 is here to make your life easier!
- Universal Type Handling: No more juggling with different data types! Valu3's generic type support enables smooth management of all data types under one roof.
- Intuitive API: Experience effortless data manipulation with Valu3's user-friendly API, designed to provide consistency across diverse data types.
- All-in-One Data Manipulation: Valu3 has it all - numeric, string, object, array, and date/time manipulation. No need to look anywhere else!
- Effortless Data Conversion: Convert your data to and from popular formats like JSON, YAML, and XML with ease, thanks to Valu3's built-in support.
- Serde Integration: Serialize and deserialize your data seamlessly with Valu3's out-of-the-box integration with the Serde library.
- Native Struct Parsing & Validation: Valu3 and Pest join forces to offer native parsing, conversion, and validation of data to structs, ensuring data integrity at every step.
- Payload Interpretation & Transformation: Valu3 interprets and transforms payload strings like a champ, handling JSON from HTTP request bodies and more.
Valu3 is designed to make data manipulation tasks in Rust a breeze. By combining a wide range of features and a consistent API, it simplifies data handling in Rust projects while maximizing productivity.
Join the Valu3 revolution and experience the future of data manipulation in Rust! π
β‘ Get Started with Valu3 Today! β‘
Here are some examples of how to use the Valu3:
use valu3::prelude::*;
let string_value = "hello".to_value();
let number_value = 42.to_value();
let boolean_value = true.to_value();
let null_value = Value::Null;
let undefined_value = Value::Undefined;
let mut datetime_value = DateTime::from("2023-04-05T00:00:00Z").to_value();
string_value.as_string();
number_value.get_i32();
assert_eq!(boolean_value, true);
assert_eq!(null_value, Value::Null);
assert_eq!(undefined_value, Value::Undefined);
datetime_value.add_days(1);
To start using the Valu3 in your Rust project, simply add the following line to your Cargo.toml
file:
[dependencies]
valu3 = "0.8"
Then, you can import the library in your code like this:
use valu3::prelude::*;
//...
let pi = 3.14.to_value();
Valu3 provides a comprehensive type system through the Value
enum, which can represent eight fundamental data types:
- String - Text data with extended manipulation methods
- Number - All numeric types (integers and floats)
- Boolean - True/false values
- Array - Ordered collections of values
- Object - Key-value mappings (HashMap or BTreeMap)
- DateTime - Date, time, or datetime values
- Null - Absence of value
- Undefined - Uninitialized value
The String type in Valu3 provides enhanced string manipulation capabilities.
Key Methods:
as_string()
- Get the String valueto_uppercase()
- Convert to uppercaseto_lowercase()
- Convert to lowercasetrim()
- Remove whitespacereplace()
- Replace substringsconcat()
- Concatenate stringslen()
- Get string length
Example:
use valu3::prelude::*;
fn main() {
// Creating strings
let text = "Hello, World!".to_value();
let mut name = Value::String(StringB::from("Alice"));
// String operations
if let Value::String(s) = &text {
println!("Original: {}", s.as_string());
println!("Uppercase: {}", s.to_uppercase().as_string());
println!("Lowercase: {}", s.to_lowercase().as_string());
}
// More operations
let trimmed = " spaces ".to_value();
if let Value::String(s) = &trimmed {
println!("Trimmed: '{}'", s.trim().as_string());
}
// Replace and concat
let greeting = "Hello, NAME!".to_value();
if let Value::String(s) = &greeting {
let personalized = s.replace("NAME", "Bob");
println!("Replaced: {}", personalized.as_string());
let extended = personalized.concat(" How are you?");
println!("Concatenated: {}", extended.as_string());
}
}
Supports all Rust numeric types with automatic type detection and conversion.
Supported Types:
- Unsigned integers:
u8
,u16
,u32
,u64
,u128
- Signed integers:
i8
,i16
,i32
,i64
,i128
- Floating point:
f32
,f64
Key Methods:
get_[type]()
- Get value as specific type (returnsOption
)set_[type]()
- Set value as specific typeis_[type]()
- Check if value is specific typeis_integer()
- Check if integeris_float()
- Check if floatis_positive()
/is_negative()
- Check sign
Example:
use valu3::prelude::*;
fn main() {
// Creating numbers
let int_value = 42.to_value();
let float_value = 3.14159.to_value();
let negative = (-100).to_value();
// Type checking
println!("42 is integer: {}", int_value.as_number().unwrap().is_integer());
println!("3.14 is float: {}", float_value.as_number().unwrap().is_float());
// Getting values
if let Some(num) = int_value.as_number() {
println!("As i32: {:?}", num.get_i32());
println!("As f64: {:?}", num.get_f64());
}
// Setting values
let mut dynamic_num = Value::Number(Number::default());
dynamic_num.set_u64(1000000);
println!("Set to u64: {:?}", dynamic_num.get_u64());
// Sign checking
if let Some(num) = negative.as_number() {
println!("-100 is negative: {}", num.is_negative());
}
}
Simple true/false values.
Example:
use valu3::prelude::*;
fn main() {
let is_active = true.to_value();
let is_complete = Value::Boolean(false);
// Checking boolean values
if let Value::Boolean(b) = is_active {
println!("Active status: {}", b);
}
// Using in conditions
match is_complete {
Value::Boolean(true) => println!("Task completed!"),
Value::Boolean(false) => println!("Task pending..."),
_ => println!("Not a boolean"),
}
}
Ordered collection of Value
items.
Key Methods:
push()
- Add element to endpop()
- Remove and return last elementget()
- Get element by indexget_mut()
- Get mutable reference by indexlen()
- Get array lengthis_empty()
- Check if empty
Example:
use valu3::prelude::*;
fn main() {
// Creating arrays
let mut numbers = vec![1, 2, 3, 4, 5].to_value();
let mixed = json!(["text", 42, true, null]);
// Array operations
if let Value::Array(arr) = &mut numbers {
arr.push(6.to_value());
println!("Array length: {}", arr.len());
// Accessing elements
if let Some(first) = arr.get(0) {
println!("First element: {}", first);
}
// Removing elements
if let Some(last) = arr.pop() {
println!("Popped: {}", last);
}
}
// Iterating
if let Value::Array(arr) = &mixed {
for (index, value) in arr.values.iter().enumerate() {
println!("Index {}: {}", index, value);
}
}
}
Key-value mappings using either HashMap
or BTreeMap
.
Key Methods:
insert()
- Insert key-value pairget()
- Get value by keyget_mut()
- Get mutable reference by keyremove()
- Remove key-value paircontains_key()
- Check if key existskeys()
- Get all keysvalues()
- Get all valueslen()
- Get number of pairs
Example:
use valu3::prelude::*;
fn main() {
// Creating objects
let mut person = json!({
"name": "Alice",
"age": 30,
"email": "alice@example.com"
});
// Accessing values
if let Some(name) = person.get("name") {
println!("Name: {}", name);
}
// Modifying objects
person.insert("city", "New York".to_value());
person.insert("age", 31.to_value()); // Update existing
// Checking keys
if let Value::Object(obj) = &person {
println!("Has email: {}", obj.contains_key(&"email"));
println!("Object size: {}", obj.len());
// Iterate over keys
for key in obj.keys() {
println!("Key: {}", key);
}
}
// Remove values
if let Value::Object(obj) = &mut person {
if let Some(removed) = obj.remove(&"email") {
println!("Removed email: {}", removed);
}
}
}
Represents dates, times, or combined datetime values.
Variants:
Date(NaiveDate)
- Date without timezoneTime(NaiveTime)
- Time without dateDateTime(ChDateTime<Utc>)
- Full datetime with timezone
Key Methods:
year()
,month()
,day()
- Date componentshour()
,minute()
,second()
- Time componentsto_iso8601()
- Format as ISO 8601to_rfc3339()
- Format as RFC 3339add_duration()
- Add time durationnow()
- Current datetime
Example:
use valu3::prelude::*;
fn main() {
// Creating datetime values
let now = DateTime::now().to_value();
let specific_date = DateTime::from("2024-01-15T10:30:00Z").to_value();
let date_only = DateTime::from_ymd_opt(2024, 12, 25).to_value();
// Accessing components
if let Value::DateTime(dt) = &specific_date {
println!("Year: {:?}", dt.year());
println!("Month: {:?}", dt.month());
println!("Hour: {:?}", dt.hour());
println!("ISO 8601: {}", dt.to_iso8601());
}
// Date arithmetic
if let Value::DateTime(dt) = &date_only {
let tomorrow = dt.add_duration(chrono::Duration::days(1));
if let Some(next_day) = tomorrow {
println!("Tomorrow: {}", next_day);
}
}
}
Represent absence or uninitialized values.
Example:
use valu3::prelude::*;
fn main() {
let null_value = Value::Null;
let undefined_value = Value::Undefined;
// Checking for null/undefined
println!("Is null: {}", null_value.is_null());
println!("Is undefined: {}", undefined_value.is_undefined());
// Pattern matching
match null_value {
Value::Null => println!("Value is null"),
Value::Undefined => println!("Value is undefined"),
_ => println!("Value has content"),
}
// JSON representation
println!("Null as JSON: {}", null_value.to_json(JsonMode::Compact));
println!("Display: {}", undefined_value);
}
use valu3::prelude::*;
fn main() {
// Building a complex data structure
let mut database = json!({
"users": [
{
"id": 1,
"name": "Alice",
"active": true,
"roles": ["admin", "user"],
"metadata": {
"created_at": "2024-01-01T00:00:00Z",
"last_login": null
}
},
{
"id": 2,
"name": "Bob",
"active": false,
"roles": ["user"],
"metadata": {
"created_at": "2024-01-15T00:00:00Z",
"last_login": "2024-01-20T10:30:00Z"
}
}
],
"settings": {
"max_users": 100,
"allow_registration": true
}
});
// Accessing nested data
if let Some(users) = database.get("users") {
if let Value::Array(user_array) = users {
println!("Total users: {}", user_array.len());
// Process each user
for user in &user_array.values {
if let Some(name) = user.get("name") {
println!("User: {}", name);
}
}
}
}
// Modifying nested data
if let Some(settings) = database.get_mut("settings") {
settings.insert("maintenance_mode", false.to_value());
}
}
use valu3::prelude::*;
fn main() {
// Converting between different representations
let data = json!({
"temperature": "23.5",
"count": "42",
"enabled": "true",
"items": "[1,2,3]"
});
// Parse string values to appropriate types
if let Some(temp_str) = data.get("temperature") {
if let Value::String(s) = temp_str {
let temp_float: f64 = s.as_string().parse().unwrap();
println!("Temperature: {}Β°C", temp_float);
}
}
// Convert JSON string to Value
let json_str = r#"{"name":"Product","price":29.99}"#;
let parsed = Value::payload_to_value(json_str).unwrap();
println!("Parsed: {}", parsed.to_json(JsonMode::Compact));
// Value to different formats
let product = json!({
"id": 123,
"name": "Widget",
"price": 19.99,
"in_stock": true
});
// To JSON
println!("JSON: {}", product.to_json(JsonMode::Indented));
// To YAML (if feature enabled)
// println!("YAML: {}", product.to_yaml());
}
use valu3::prelude::*;
fn validate_user(user: &Value) -> Result<(), String> {
// Check required fields
if !user.is_object() {
return Err("User must be an object".to_string());
}
// Validate email
match user.get("email") {
Some(email) if email.is_string() => {
let email_str = email.as_string_b().unwrap().as_string();
if !email_str.contains('@') {
return Err("Invalid email format".to_string());
}
},
_ => return Err("Email is required and must be a string".to_string()),
}
// Validate age
if let Some(age) = user.get("age") {
if let Some(num) = age.as_number() {
if let Some(age_val) = num.get_i32() {
if age_val < 0 || age_val > 150 {
return Err("Age must be between 0 and 150".to_string());
}
}
}
}
Ok(())
}
fn main() {
let valid_user = json!({
"email": "user@example.com",
"age": 25,
"name": "John Doe"
});
let invalid_user = json!({
"email": "not-an-email",
"age": 200
});
match validate_user(&valid_user) {
Ok(_) => println!("β Valid user"),
Err(e) => println!("β Invalid user: {}", e),
}
match validate_user(&invalid_user) {
Ok(_) => println!("β Valid user"),
Err(e) => println!("β Invalid user: {}", e),
}
}
use valu3::prelude::*;
fn merge_objects(base: &mut Value, updates: &Value) {
if let (Value::Object(base_obj), Value::Object(updates_obj)) = (base, updates) {
for (key, value) in updates_obj.keys().zip(updates_obj.values()) {
base_obj.insert(key.clone(), value.clone());
}
}
}
fn filter_array(array: &Value, predicate: impl Fn(&Value) -> bool) -> Value {
if let Value::Array(arr) = array {
let filtered: Vec<Value> = arr.values.iter()
.filter(|v| predicate(v))
.cloned()
.collect();
return filtered.to_value();
}
Value::Array(Array::new())
}
fn main() {
// Merging objects
let mut config = json!({
"host": "localhost",
"port": 8080
});
let overrides = json!({
"port": 3000,
"debug": true
});
merge_objects(&mut config, &overrides);
println!("Merged config: {}", config);
// Filtering arrays
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10].to_value();
let evens = filter_array(&numbers, |v| {
if let Some(num) = v.as_number() {
if let Some(n) = num.get_i32() {
return n % 2 == 0;
}
}
false
});
println!("Even numbers: {}", evens);
}
use valu3::prelude::*;
fn main() {
// The json! macro supports all JSON syntax
let config = json!({
"application": {
"name": "MyApp",
"version": "1.0.0",
"features": [
"auth",
"api",
"dashboard"
],
"settings": {
"theme": "dark",
"language": "en",
"notifications": true
}
},
"database": {
"host": "localhost",
"port": 5432,
"ssl": false,
"pools": {
"min": 5,
"max": 20
}
},
"cache": null,
"debug": true
});
// Variables in json! macro
let app_name = "MyService";
let version = 2;
let is_production = false;
let service = json!({
"service": app_name,
"version": version,
"production": is_production,
"endpoints": [
"/api/v1",
"/api/v2"
]
});
println!("Service config: {}", service.to_json(JsonMode::Compact));
}
Valu3 natively has conversions for famous data types like json, yaml and xml. Furthermore with valu3-derive
you are able to transform struct
to Value
by applying the to_value()
method generated by the ToValue
derive macros. This is an example on converting struct
to Value
and Value
to other payload data types.
use valu3::prelude:*;
#[derive(ToValue, FromValue, Default)]
struct MyStruct {
id: u32,
name: String,
tags: Vec<String>
}
fn main(){
let my_struct = MyStruct::default();
let value = my_struct.to_value();
assert_eq!(my_struct, MyStruct::from_value(value));
}
If your focus is only on using Valu3
for conversion only, use the ToJson
macro.
use valu3::prelude:*;
#[derive(ToJson, Default)]
struct MyStruct {
id: u32,
name: String,
tags: Vec<String>
}
fn main(){
let my_struct = MyStruct::default();
let json = my_struct.to_json();
println!("{}", json); // print json string
}
Vale3
is able to recognize a payload string, identify and convert it to Value
, follow the example:
use valu3::prelude:*;
fn main(){
let boolean = Value::payload_to_value("true").unwrap();
let float = Value::payload_to_value("3.14").unwrap();
let json = Value::payload_to_value(r#"{"item": 3.14}"#).unwrap();
let array = Value::payload_to_value(r#"[1,2,3]"#).unwrap();
let null = Value::payload_to_value("null").unwrap();
let string = Value::payload_to_value(r#""123""#).unwrap();
assert_eq!(boolean, true.to_value());
assert_eq!(float, 3.14.to_value());
assert_eq!(json, Value::from(vec![("item", 3.14)]));
assert_eq!(array, vec![1, 2, 3].to_value());
assert_eq!(null, Value::Null);
assert_eq!(string, "123".to_value());
}
If you find a bug or have a suggestion for a new feature, please open an issue on the GitHub repository.
If you would like to contribute to the project, please feel free to submit a pull request. Before submitting a pull request, please make sure that your code adheres to the project's style guidelines and passes all tests.
~ We're constantly working to improve and expand the capabilities of Valu3, making it even more powerful and versatile.
By keeping track of the project's progress, you can stay informed about new features in development and planned improvements. This will allow you to make the most of Valu3 in your Rust projects and prepare for future updates.
Our commitment is to make Valu3 the ultimate data manipulation solution in Rust. Your input is invaluable! Feel free to join the discussions, share your ideas, and contribute to the project as it evolves.
Join us in the ongoing journey to refine and expand Valu3! π
This project is licensed under the Apache 2.0 License. See the LICENSE file for more information.