chore: restore examples after thread safety feature

This commit is contained in:
2025-10-29 11:29:36 +01:00
parent 645e7560b3
commit e1178f7126
2 changed files with 397 additions and 388 deletions

View File

@@ -1,160 +1,161 @@
fn main() {}
// use heave::*;
//
// // Define a struct named `Component` to represent an electronic component.
// #[derive(Debug, Clone, PartialEq)]
// struct Component {
// pub id: String,
// pub part_number: String,
// pub kind: String,
// pub value: u64,
// pub package: String,
// pub in_stock: bool,
// }
// // Implement the `EAV` trait for the `Component` struct.
// impl EAV for Component {
// // `class` is a function that returns the class name of the entity.
// fn class() -> &'static str {
// "component"
// }
// }
// // Implement the `From<Component>` trait for the `Entity` struct.
// impl From<Component> for Entity {
// // `from` is a function that converts a `Component` into an `Entity`.
// fn from(value: Component) -> Entity {
// Entity::new::<Component>()
// .with_id(&value.id)
// .with_attribute("part_number", value.part_number)
// .with_attribute("kind", value.kind)
// .with_attribute("value", value.value)
// .with_attribute("package", value.package)
// .with_attribute("in_stock", value.in_stock)
// }
// }
// // Implement the `From<Entity>` trait for the `Component` struct.
// impl From<Entity> for Component {
// // `from` is a function that converts an `Entity` into a `Component`.
// fn from(value: Entity) -> Self {
// Self {
// id: value.id.clone(),
// part_number: value
// .unwrap("part_number")
// .expect("part_number is always present"),
// kind: value.unwrap("kind").expect("kind is always present"),
// value: value.unwrap("value").expect("value is always present"),
// package: value.unwrap("package").expect("package is always present"),
// in_stock: value
// .unwrap("in_stock")
// .expect("in_stock is always present"),
// }
// }
// }
//
// fn main() {
// // Define the path for the SQLite database file.
// let db_path = "./using_filters.sqlite3";
// // Create a new `Catalog` instance with the specified database path.
// let mut catalog = Catalog::new(db_path);
// // Initialize the catalog, which sets up the database.
// catalog.init().unwrap();
// // Create some component instances.
// let components_to_add = vec![
// // This one should be found
// Component {
// id: "R1".to_string(),
// part_number: "R-10K-0805".to_string(),
// kind: "resistor".to_string(),
// value: 10000,
// package: "smd-0805".to_string(),
// in_stock: true,
// },
// // This one should be found
// Component {
// id: "R2".to_string(),
// part_number: "R-4K7-0805".to_string(),
// kind: "resistor".to_string(),
// value: 4700,
// package: "smd-0805".to_string(),
// in_stock: true,
// },
// // This one should NOT be found (wrong kind)
// Component {
// id: "C1".to_string(),
// part_number: "C-100n-0603".to_string(),
// kind: "capacitor".to_string(),
// value: 100,
// package: "smd-0603".to_string(),
// in_stock: true,
// },
// // This one should NOT be found (value too low)
// Component {
// id: "R3".to_string(),
// part_number: "R-100-0805".to_string(),
// kind: "resistor".to_string(),
// value: 100,
// package: "smd-0805".to_string(),
// in_stock: true,
// },
// // This one should NOT be found (not in stock)
// Component {
// id: "R4".to_string(),
// part_number: "R-22K-TH".to_string(),
// kind: "resistor".to_string(),
// value: 22000,
// package: "through-hole".to_string(),
// in_stock: false,
// },
// // This one should NOT be found (wrong kind, even if other fields match)
// Component {
// id: "L1".to_string(),
// part_number: "L-10mH-TH".to_string(),
// kind: "inductor".to_string(),
// value: 10000,
// package: "through-hole".to_string(),
// in_stock: true,
// },
// ];
// // Insert the components into the catalog.
// catalog.insert_many(components_to_add.clone()).unwrap();
// // Persist the changes to the database.
// catalog.persist().unwrap();
// // Create a new catalog to ensure we are loading from the database.
// let mut new_catalog = Catalog::new(db_path);
// // Create a composite filter.
// // We are looking for resistors with a value greater than 1000 that are in stock.
// let filter = Filter::new()
// .with_text("kind", Comparison::IsExactly, "resistor")
// .with_unsigned_int("value", Comparison::Greater, 1000)
// .with_bool("in_stock", true);
// // Load entities from the database using the filter.
// new_catalog.load_by_filter(&filter).unwrap();
// // Get the list of loaded components.
// let loaded_components: Vec<Component> = new_catalog
// .list_by_class::<Component>()
// .map(|c| c.unwrap())
// .collect();
// // Print the loaded components
// println!(
// "Found {} components matching the filter:",
// loaded_components.len()
// );
// for component in &loaded_components {
// println!(
// "- ID: {}, Part Number: {}, Kind: {}, Value: {}, Package: {}, In Stock: {}",
// component.id,
// component.part_number,
// component.kind,
// component.value,
// component.package,
// component.in_stock
// );
// }
// // Verify that we have loaded the correct number of components.
// assert_eq!(loaded_components.len(), 2);
// // Verify that the correct components were loaded.
// let ids: Vec<String> = loaded_components.iter().map(|c| c.id.clone()).collect();
// assert!(ids.contains(&"R1".to_string()));
// assert!(ids.contains(&"R2".to_string()));
// // Clean up the database file.
// std::fs::remove_file(db_path).unwrap();
// }
use heave::*;
// Define a struct named `Component` to represent an electronic component.
#[derive(Debug, Clone, PartialEq)]
struct Component {
pub id: String,
pub part_number: String,
pub kind: String,
pub value: u64,
pub package: String,
pub in_stock: bool,
}
// Implement the `EAV` trait for the `Component` struct.
impl EAV for Component {
// `class` is a function that returns the class name of the entity.
fn class() -> &'static str {
"component"
}
}
// Implement the `From<Component>` trait for the `Entity` struct.
impl From<Component> for Entity {
// `from` is a function that converts a `Component` into an `Entity`.
fn from(value: Component) -> Entity {
Entity::new::<Component>()
.with_id(&value.id)
.with_attribute("part_number", value.part_number)
.with_attribute("kind", value.kind)
.with_attribute("value", value.value)
.with_attribute("package", value.package)
.with_attribute("in_stock", value.in_stock)
}
}
// Implement the `From<Entity>` trait for the `Component` struct.
impl From<Entity> for Component {
// `from` is a function that converts an `Entity` into a `Component`.
fn from(value: Entity) -> Self {
Self {
id: value.id.clone(),
part_number: value
.unwrap("part_number")
.expect("part_number is always present"),
kind: value.unwrap("kind").expect("kind is always present"),
value: value.unwrap("value").expect("value is always present"),
package: value.unwrap("package").expect("package is always present"),
in_stock: value
.unwrap("in_stock")
.expect("in_stock is always present"),
}
}
}
fn main() {
// Define the path for the SQLite database file.
let db_path = "./using_filters.sqlite3";
// Create a new `Catalog` instance with the specified database path.
let mut catalog = Catalog::new(db_path);
// Initialize the catalog, which sets up the database.
catalog.init().unwrap();
// Create some component instances.
let components_to_add = vec![
// This one should be found
Component {
id: "R1".to_string(),
part_number: "R-10K-0805".to_string(),
kind: "resistor".to_string(),
value: 10000,
package: "smd-0805".to_string(),
in_stock: true,
},
// This one should be found
Component {
id: "R2".to_string(),
part_number: "R-4K7-0805".to_string(),
kind: "resistor".to_string(),
value: 4700,
package: "smd-0805".to_string(),
in_stock: true,
},
// This one should NOT be found (wrong kind)
Component {
id: "C1".to_string(),
part_number: "C-100n-0603".to_string(),
kind: "capacitor".to_string(),
value: 100,
package: "smd-0603".to_string(),
in_stock: true,
},
// This one should NOT be found (value too low)
Component {
id: "R3".to_string(),
part_number: "R-100-0805".to_string(),
kind: "resistor".to_string(),
value: 100,
package: "smd-0805".to_string(),
in_stock: true,
},
// This one should NOT be found (not in stock)
Component {
id: "R4".to_string(),
part_number: "R-22K-TH".to_string(),
kind: "resistor".to_string(),
value: 22000,
package: "through-hole".to_string(),
in_stock: false,
},
// This one should NOT be found (wrong kind, even if other fields match)
Component {
id: "L1".to_string(),
part_number: "L-10mH-TH".to_string(),
kind: "inductor".to_string(),
value: 10000,
package: "through-hole".to_string(),
in_stock: true,
},
];
// Insert the components into the catalog.
catalog.insert_many(components_to_add.clone()).unwrap();
// Persist the changes to the database.
catalog.persist().unwrap();
// Create a new catalog to ensure we are loading from the database.
let mut new_catalog = Catalog::new(db_path);
// Create a composite filter.
// We are looking for resistors with a value greater than 1000 that are in stock.
let filter = Filter::new()
.with_text("kind", Comparison::IsExactly, "resistor")
.with_unsigned_int("value", Comparison::Greater, 1000)
.with_bool("in_stock", true);
// Load entities from the database using the filter.
new_catalog.load_by_filter(&filter).unwrap();
// Get the list of loaded components.
let loaded_components: Vec<Component> = new_catalog
.list_by_class::<Component>()
.unwrap()
.into_iter()
.map(|c| c.unwrap())
.collect();
// Print the loaded components
println!(
"Found {} components matching the filter:",
loaded_components.len()
);
for component in &loaded_components {
println!(
"- ID: {}, Part Number: {}, Kind: {}, Value: {}, Package: {}, In Stock: {}",
component.id,
component.part_number,
component.kind,
component.value,
component.package,
component.in_stock
);
}
// Verify that we have loaded the correct number of components.
assert_eq!(loaded_components.len(), 2);
// Verify that the correct components were loaded.
let ids: Vec<String> = loaded_components.iter().map(|c| c.id.clone()).collect();
assert!(ids.contains(&"R1".to_string()));
assert!(ids.contains(&"R2".to_string()));
// Clean up the database file.
std::fs::remove_file(db_path).unwrap();
}

View File

@@ -1,228 +1,236 @@
fn main() {}
// use heave::*;
// use std::path::Path;
//
// struct Laptop {
// pub id: String,
// pub model: String,
// pub price: u64,
// }
// struct Display {
// pub id: String,
// pub model: String,
// pub resolution: f64,
// pub price: u64,
// }
// struct Mouse {
// pub id: String,
// pub model: String,
// pub wireless: bool,
// pub price: u64,
// }
// enum Product {
// None,
// Laptop(Laptop),
// Display(Display),
// Mouse(Mouse),
// }
// impl EAV for Product {
// fn class() -> &'static str {
// "product"
// }
// }
// impl From<Entity> for Product {
// fn from(value: Entity) -> Self {
// if let Some(ref subclass) = value.subclass {
// match subclass.as_ref() {
// "laptop" => Product::Laptop(Laptop {
// id: value.id.clone(),
// model: value.unwrap("model").expect("model is mandatory"),
// price: value.unwrap("price").expect("price is mandatory"),
// }),
// "display" => Product::Display(Display {
// id: value.id.clone(),
// model: value.unwrap("model").expect("model is mandatory"),
// price: value.unwrap("price").expect("price is mandatory"),
// resolution: value.unwrap("resolution").expect("resolution is mandatory"),
// }),
// "mouse" => Product::Mouse(Mouse {
// id: value.id.clone(),
// model: value.unwrap("model").expect("model is mandatory"),
// price: value.unwrap("price").expect("price is mandatory"),
// wireless: value.unwrap("wireless").expect("wireless is mandatory"),
// }),
// _ => unreachable!(),
// }
// } else {
// Product::None
// }
// }
// }
// impl From<Product> for Entity {
// fn from(value: Product) -> Self {
// match value {
// Product::Laptop(value) => Entity::new::<Product>()
// .with_id(&value.id)
// .with_subclass("laptop")
// .with_attribute("model", value.model)
// .with_attribute("price", value.price),
// Product::Display(value) => Entity::new::<Product>()
// .with_id(&value.id)
// .with_subclass("display")
// .with_attribute("model", value.model)
// .with_attribute("resolution", value.resolution)
// .with_attribute("price", value.price),
// Product::Mouse(value) => Entity::new::<Product>()
// .with_id(&value.id)
// .with_subclass("mouse")
// .with_attribute("model", value.model)
// .with_attribute("wireless", value.wireless)
// .with_attribute("price", value.price),
// _ => unreachable!(),
// }
// }
// }
// fn main() -> Result<(), FailedTo> {
// let db_path = "working_with_many_types.db";
//
// // Clean up previous runs if file exists
// if Path::new(db_path).exists() {
// std::fs::remove_file(db_path).unwrap();
// }
//
// // 1. Initialize and Persist Data
// println!("== 1. Storing different product types ==");
// let mut catalog = Catalog::new(db_path);
// catalog.init()?;
//
// let products_to_add = vec![
// Product::Laptop(Laptop {
// id: "laptop_01".to_string(),
// model: "Titan".to_string(),
// price: 1500,
// }),
// Product::Display(Display {
// id: "display_01".to_string(),
// model: "CrystalClear".to_string(),
// resolution: 4.0, // 4K
// price: 600,
// }),
// Product::Mouse(Mouse {
// id: "mouse_01".to_string(),
// model: "SwiftClick".to_string(),
// wireless: true,
// price: 80,
// }),
// Product::Laptop(Laptop {
// id: "laptop_02".to_string(),
// model: "Nomad".to_string(),
// price: 950,
// }),
// ];
//
// catalog.insert_many(products_to_add)?;
// catalog.persist()?;
// println!("✅ 4 products saved to the database.\n");
//
// // 2. Load data using filters
// println!("== 2. Loading products using class and subclass filters ==");
//
// // Load only laptops
// let mut laptop_catalog = Catalog::new(db_path);
// let laptop_filter = Filter::new()
// .with_class(Product::class())
// .with_subclass("laptop");
//
// laptop_catalog.load_by_filter(&laptop_filter)?;
//
// let laptops: Vec<Product> = laptop_catalog.list_by_class().map(|p| p.unwrap()).collect();
//
// println!("✅ Loaded {} laptop(s) using filter.", laptops.len());
// assert_eq!(laptops.len(), 2);
// for p in laptops {
// if let Product::Laptop(laptop) = p {
// println!(
// " - Laptop: {} ({}) - ${}",
// laptop.id, laptop.model, laptop.price
// );
// }
// }
// println!();
//
// println!("== 3. Loading products using attribute filters ==");
// // Load expensive products (price > 1000)
// let mut expensive_catalog = Catalog::new(db_path);
// let expensive_filter = Filter::new()
// .with_class(Product::class())
// .with_unsigned_int("price", Comparison::Greater, 1000);
//
// expensive_catalog.load_by_filter(&expensive_filter)?;
//
// let expensive_products: Vec<Product> = expensive_catalog
// .list_by_class()
// .map(|p| p.unwrap())
// .collect();
//
// println!(
// "✅ Loaded {} product(s) with price > $1000.",
// expensive_products.len()
// );
// assert_eq!(expensive_products.len(), 1);
//
// for p in expensive_products {
// match p {
// Product::Laptop(laptop) => {
// println!(
// " - Found Laptop: {} ({}) - ${}",
// laptop.id, laptop.model, laptop.price
// );
// assert_eq!(laptop.id, "laptop_01");
// }
// _ => panic!("Expected a laptop!"),
// }
// }
// println!();
//
// println!("== 4. Loading all product types ==");
// let mut all_products_catalog = Catalog::new(db_path);
// let all_products_filter = Filter::new().with_class(Product::class());
// all_products_catalog.load_by_filter(&all_products_filter)?;
//
// let all_products: Vec<Product> = all_products_catalog
// .list_by_class()
// .map(|p| p.unwrap())
// .collect();
//
// println!("✅ Loaded {} total products.", all_products.len());
// assert_eq!(all_products.len(), 4);
//
// for p in all_products {
// match p {
// Product::Laptop(laptop) => {
// println!(
// " - Found Laptop: {} ({}) - ${}",
// laptop.id, laptop.model, laptop.price
// );
// }
// Product::Display(display) => {
// println!(
// " - Found Display: {} ({}) - ${}",
// display.id, display.model, display.price
// );
// }
// Product::Mouse(mouse) => {
// println!(
// " - Found Mouse: {} ({}) - ${}",
// mouse.id, mouse.model, mouse.price
// );
// }
// Product::None => panic!("Product::None should not be loaded"),
// }
// }
// println!();
//
// // Clean up the created database file
// std::fs::remove_file(db_path).unwrap();
//
// Ok(())
// }
use heave::*;
use std::path::Path;
struct Laptop {
pub id: String,
pub model: String,
pub price: u64,
}
struct Display {
pub id: String,
pub model: String,
pub resolution: f64,
pub price: u64,
}
struct Mouse {
pub id: String,
pub model: String,
pub wireless: bool,
pub price: u64,
}
enum Product {
None,
Laptop(Laptop),
Display(Display),
Mouse(Mouse),
}
impl EAV for Product {
fn class() -> &'static str {
"product"
}
}
impl From<Entity> for Product {
fn from(value: Entity) -> Self {
if let Some(ref subclass) = value.subclass {
match subclass.as_ref() {
"laptop" => Product::Laptop(Laptop {
id: value.id.clone(),
model: value.unwrap("model").expect("model is mandatory"),
price: value.unwrap("price").expect("price is mandatory"),
}),
"display" => Product::Display(Display {
id: value.id.clone(),
model: value.unwrap("model").expect("model is mandatory"),
price: value.unwrap("price").expect("price is mandatory"),
resolution: value.unwrap("resolution").expect("resolution is mandatory"),
}),
"mouse" => Product::Mouse(Mouse {
id: value.id.clone(),
model: value.unwrap("model").expect("model is mandatory"),
price: value.unwrap("price").expect("price is mandatory"),
wireless: value.unwrap("wireless").expect("wireless is mandatory"),
}),
_ => unreachable!(),
}
} else {
Product::None
}
}
}
impl From<Product> for Entity {
fn from(value: Product) -> Self {
match value {
Product::Laptop(value) => Entity::new::<Product>()
.with_id(&value.id)
.with_subclass("laptop")
.with_attribute("model", value.model)
.with_attribute("price", value.price),
Product::Display(value) => Entity::new::<Product>()
.with_id(&value.id)
.with_subclass("display")
.with_attribute("model", value.model)
.with_attribute("resolution", value.resolution)
.with_attribute("price", value.price),
Product::Mouse(value) => Entity::new::<Product>()
.with_id(&value.id)
.with_subclass("mouse")
.with_attribute("model", value.model)
.with_attribute("wireless", value.wireless)
.with_attribute("price", value.price),
_ => unreachable!(),
}
}
}
fn main() -> Result<(), FailedTo> {
let db_path = "working_with_many_types.db";
// Clean up previous runs if file exists
if Path::new(db_path).exists() {
std::fs::remove_file(db_path).unwrap();
}
// 1. Initialize and Persist Data
println!("== 1. Storing different product types ==");
let mut catalog = Catalog::new(db_path);
catalog.init()?;
let products_to_add = vec![
Product::Laptop(Laptop {
id: "laptop_01".to_string(),
model: "Titan".to_string(),
price: 1500,
}),
Product::Display(Display {
id: "display_01".to_string(),
model: "CrystalClear".to_string(),
resolution: 4.0, // 4K
price: 600,
}),
Product::Mouse(Mouse {
id: "mouse_01".to_string(),
model: "SwiftClick".to_string(),
wireless: true,
price: 80,
}),
Product::Laptop(Laptop {
id: "laptop_02".to_string(),
model: "Nomad".to_string(),
price: 950,
}),
];
catalog.insert_many(products_to_add)?;
catalog.persist()?;
println!("✅ 4 products saved to the database.\n");
// 2. Load data using filters
println!("== 2. Loading products using class and subclass filters ==");
// Load only laptops
let mut laptop_catalog = Catalog::new(db_path);
let laptop_filter = Filter::new()
.with_class(Product::class())
.with_subclass("laptop");
laptop_catalog.load_by_filter(&laptop_filter)?;
let laptops: Vec<Product> = laptop_catalog
.list_by_class()
.unwrap()
.into_iter()
.map(|p| p.unwrap())
.collect();
println!("✅ Loaded {} laptop(s) using filter.", laptops.len());
assert_eq!(laptops.len(), 2);
for p in laptops {
if let Product::Laptop(laptop) = p {
println!(
" - Laptop: {} ({}) - ${}",
laptop.id, laptop.model, laptop.price
);
}
}
println!();
println!("== 3. Loading products using attribute filters ==");
// Load expensive products (price > 1000)
let mut expensive_catalog = Catalog::new(db_path);
let expensive_filter = Filter::new()
.with_class(Product::class())
.with_unsigned_int("price", Comparison::Greater, 1000);
expensive_catalog.load_by_filter(&expensive_filter)?;
let expensive_products: Vec<Product> = expensive_catalog
.list_by_class()
.unwrap()
.into_iter()
.map(|p| p.unwrap())
.collect();
println!(
"✅ Loaded {} product(s) with price > $1000.",
expensive_products.len()
);
assert_eq!(expensive_products.len(), 1);
for p in expensive_products {
match p {
Product::Laptop(laptop) => {
println!(
" - Found Laptop: {} ({}) - ${}",
laptop.id, laptop.model, laptop.price
);
assert_eq!(laptop.id, "laptop_01");
}
_ => panic!("Expected a laptop!"),
}
}
println!();
println!("== 4. Loading all product types ==");
let mut all_products_catalog = Catalog::new(db_path);
let all_products_filter = Filter::new().with_class(Product::class());
all_products_catalog.load_by_filter(&all_products_filter)?;
let all_products: Vec<Product> = all_products_catalog
.list_by_class()
.unwrap()
.into_iter()
.map(|p| p.unwrap())
.collect();
println!("✅ Loaded {} total products.", all_products.len());
assert_eq!(all_products.len(), 4);
for p in all_products {
match p {
Product::Laptop(laptop) => {
println!(
" - Found Laptop: {} ({}) - ${}",
laptop.id, laptop.model, laptop.price
);
}
Product::Display(display) => {
println!(
" - Found Display: {} ({}) - ${}",
display.id, display.model, display.price
);
}
Product::Mouse(mouse) => {
println!(
" - Found Mouse: {} ({}) - ${}",
mouse.id, mouse.model, mouse.price
);
}
Product::None => panic!("Product::None should not be loaded"),
}
}
println!();
// Clean up the created database file
std::fs::remove_file(db_path).unwrap();
Ok(())
}