use batch_impl::{batch_impl, batch_impl_only, batch_trait};
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;
#[batch_impl(usize, isize, f32, f64)]
trait Numeric {}
fn demos_basic() {
fn check<T: Numeric>(_: &T) {}
check(&0usize);
check(&0isize);
check(&0.0f32);
check(&0.0f64);
println!(" 1. basic (4 concrete types): OK");
}
#[batch_impl(<T> Vec<T>)]
trait Collection {}
fn demos_generic() {
fn check<T: Collection>(_: &T) {}
check(&vec![1, 2, 3]);
check(&vec!["a", "b"]);
println!(" 2. generic (`<T> Vec<T>`): OK");
}
#[batch_impl(
[usize { fn name() -> &'static str { "usize" } },
isize { fn name() -> &'static str { "isize" } }]
{ fn zero() -> Self { 0 } }
)]
trait Zero {
fn zero() -> Self;
fn name() -> &'static str;
}
fn demos_shared_independent_body() {
assert_eq!(usize::zero(), 0);
assert_eq!(isize::zero(), 0);
assert_eq!(usize::name(), "usize");
assert_eq!(isize::name(), "isize");
println!(" 3. shared + independent body merge: OK");
}
#[batch_impl([&, Box, Rc, Arc]^u32)]
trait RefOrOwned {}
fn demos_caret() {
fn check<T: RefOrOwned>(_: &T) {}
let v: u32 = 7;
check(&(&v));
check(&Box::new(v));
check(&Rc::new(v));
check(&Arc::new(v));
println!(" 4. `^` cartesian product ([&, Box, Rc, Arc]^u32): OK");
}
#[batch_impl(()^3)]
trait Tuple {}
#[batch_impl((u8, u16, u32) {
fn sum(&self) -> u32 { self.0 as u32 + self.1 as u32 + self.2 }
})]
trait TupleSum {
fn sum(&self) -> u32;
}
fn demos_tuple_gen() {
fn _check<T: Tuple>() {}
_check::<(u8, u16, u32)>();
_check::<(i8, i16, i32)>();
_check::<(u32, u32, u32)>();
let t: (u8, u16, u32) = (1, 2, 3);
assert_eq!(<(u8, u16, u32) as TupleSum>::sum(&t), 6);
println!(" 5. tuple gen + concrete tuple body: OK");
}
#[batch_impl(<T> Iter<Item=T> Vec<T> {
fn count(&self) -> usize { self.len() }
})]
trait Iter {
type Item;
fn count(&self) -> usize;
}
fn demos_assoc_binding() {
let v: Vec<i32> = vec![1, 2, 3];
assert_eq!(v.count(), 3);
println!(" 6. associated type binding: OK");
}
#[batch_impl(unsafe^usize, isize)]
unsafe trait PartialUnsafe {}
#[batch_impl(u8, u16, u32)]
unsafe trait AllUnsafe {}
fn demos_unsafe() {
fn check_partial<T: PartialUnsafe>(_: &T) {}
fn check_all<T: AllUnsafe>(_: &T) {}
check_partial(&0usize);
check_partial(&0isize);
check_all(&0u8);
check_all(&0u16);
check_all(&0u32);
println!(" 7. unsafe impl (per-spec + trait-level): OK");
}
#[batch_impl(fn^(i32, u32))]
trait FnProbe {}
#[batch_impl(fn(i32, u32)-String)]
trait FnProbeWithRet {}
fn demos_fn_types() {
fn check<T: FnProbe>(_: &T) {}
fn check_ret<T: FnProbeWithRet>(_: &T) {}
let f: fn(i32, u32) = |_, _| {};
check(&f);
let fr: fn(i32, u32) -> String = |_, _| String::new();
check_ret(&fr);
println!(" 8. fn types + return type: OK");
}
#[batch_impl(#[allow(dead_code)]^usize, isize)]
trait AttrProbe {}
fn demos_attr() {
fn check<T: AttrProbe>(_: &T) {}
check(&0usize);
check(&0isize);
println!(" 9. attribute injection: OK");
}
#[batch_impl(
usize #to_str{"usize"},
isize #to_str{"isize"}
)]
trait ReadSig {
fn to_str(&self) -> &'static str;
}
#[batch_impl(
Vec<u32> #d_len{self.len()},
Box^Vec^u32 #delegate(d_len){**self}
)]
trait DelegatedLen {
fn d_len(&self) -> usize;
}
fn demos_directives() {
assert_eq!(0usize.to_str(), "usize");
assert_eq!(0isize.to_str(), "isize");
let v: Vec<u32> = vec![1, 2, 3];
assert_eq!(v.d_len(), 3);
let b: Box<Vec<u32>> = Box::new(vec![1, 2, 3, 4]);
assert_eq!(b.d_len(), 4);
println!(" 10. #name{{body}} + #delegate: OK");
}
trait SegA {}
trait SegB<T> {}
unsafe trait SegUnsafe {}
mod deep {
pub trait SegC {}
}
batch_trait!(
SegA: u8, u16, u32;
SegB: <T> SegB<T> Vec<T>;
unsafe SegUnsafe: u32;
deep::SegC: u32
);
fn demos_batch_trait_macro() {
fn check_a<T: SegA>(_: &T) {}
fn check_b<T: SegB<i32>>(_: &T) {}
fn check_c<T: deep::SegC>(_: &T) {}
fn check_u<T: SegUnsafe>(_: &T) {}
check_a(&0u8);
check_a(&0u16);
check_a(&0u32);
check_b(&vec![1i32, 2, 3]);
check_c(&0u32);
check_u(&0u32);
println!(" 11. batch_trait! multi-segment + path + unsafe: OK");
}
trait DropTrait {
fn val(&self) -> u32;
}
#[batch_impl_only(usize #val{42})]
trait DropTrait {
fn val(&self) -> u32;
}
fn demos_batch_impl_only() {
assert_eq!(0usize.val(), 42);
println!(" 12. batch_impl_only drops trait def: OK");
}
#[batch_impl(
&str,
Box<dyn std::fmt::Display>,
fn(i32) -> bool,
(i32, String)
)]
trait ComplexMarker {}
fn demos_complex_passthrough() {
fn check<T: ComplexMarker + ?Sized>(_: &T) {}
check(&"hi");
let b: Box<dyn std::fmt::Display> = Box::new(1i32);
check(&b);
let f: fn(i32) -> bool = |_| true;
check(&f);
check(&(1i32, String::from("x")));
println!(" 13. complex passthrough: OK");
}
#[batch_impl(<T> Describe<T> [Vec<T>, <U> HashMap<T, U>] {
fn describe(&self) -> String { format!("len={}", self.len()) }
})]
trait Describe<T> {
fn describe(&self) -> String;
}
fn demos_nested_generic_merge() {
let v: Vec<i32> = vec![1, 2, 3];
assert_eq!(v.describe(), "len=3");
let m: HashMap<i32, String> = HashMap::from([(1, String::from("a"))]);
assert_eq!(m.describe(), "len=1");
println!(" 14. nested generic merge (<A>[<B>T1,<C>T2]): OK");
}
fn main() {
println!("=== batch-impl quickstart ===");
demos_basic();
demos_generic();
demos_shared_independent_body();
demos_caret();
demos_tuple_gen();
demos_assoc_binding();
demos_unsafe();
demos_fn_types();
demos_attr();
demos_directives();
demos_batch_trait_macro();
demos_batch_impl_only();
demos_complex_passthrough();
demos_nested_generic_merge();
println!("=== all demos ok ===");
}