#![allow(unused, clippy::unnecessary_operation, clippy::no_effect)]
use serde::Deserialize;
use serde::Serialize;
use static_assertions::assert_impl_all;
use static_assertions::assert_not_impl_all;
use std::fmt::Debug;
use subdef::subdef;
struct Uuid;
#[subdef(derive(Serialize, Deserialize))]
#[serde(deny_unknown_fields)]
struct Profile {
id: u32,
info: [_; {
struct Info {
age: u8,
email: String,
}
}],
}
#[test]
fn r#struct() {
#[subdef]
struct Profile {
id: u32,
info: [_; {
struct Info {
age: u8,
email: String,
}
}],
}
Profile {
id: 1,
info: Info {
age: 30,
email: String::from("a@b.com"),
},
};
#[subdef]
struct Config {
settings: [Option<_>; {
struct Settings {
timeout_ms: u64,
}
}],
}
Config {
settings: Some(Settings { timeout_ms: 5000 }),
};
#[subdef]
struct Level1 {
level2: [_; {
pub struct Level2 {
level3: [Vec<Option<_>>; {
pub struct Level3 {
id: u8,
}
}],
}
}],
}
Level1 {
level2: Level2 {
level3: vec![Some(Level3 { id: 1 }), None],
},
};
}
#[test]
fn r#enum() {
#[subdef]
pub enum Event {
User(
[_; {
struct UserData {
name: String,
id: u32,
}
}],
),
Session(
[u64; {
struct SessionId(u64);
}],
),
StateChange(
[_; {
enum State {
Active,
Inactive,
}
}],
),
Ping,
}
Event::User(UserData {
name: String::new(),
id: 1,
});
Event::Session(64);
Event::StateChange(State::Active);
}
#[test]
fn union() {
#[subdef]
union Data {
i: [std::mem::ManuallyDrop<_>; {
struct IntData {
value: i32,
}
}],
f: [f32; { 1 }],
}
Data {
i: std::mem::ManuallyDrop::new(IntData { value: 10 }),
};
}
#[test]
fn attribute_propagation() {
#[subdef(derive(PartialEq, Eq))]
struct DataReport {
#[cfg(false)]
uuid: Uuid,
kind: [_; {
#[subdef(derive(PartialOrd, Ord))]
struct Kind {
value: String,
}
}],
}
assert_impl_all!(DataReport: PartialEq, Eq);
assert_impl_all!(Kind: PartialEq, Eq, PartialOrd, Ord);
DataReport {
kind: Kind {
value: String::new(),
},
};
}
#[test]
fn fine_tuned_attribute_propagation() {
#[subdef(
debug = derive(Debug),
eq = derive(PartialEq, Eq)
)]
#[subdef(skip(debug), skip(eq))]
struct TopLevel {
nested1: [_; {
#[subdef(skip_recursively(eq))]
struct Nested1 {
inner: [_; {
struct Inner1 {
data: u32,
}
}],
}
}],
nested2: [_; {
#[subdef(apply_recursively(eq))]
struct Nested2 {
inner: [_; {
#[subdef(apply(debug))]
struct Inner2;
}],
}
}],
}
assert_not_impl_all!(TopLevel: Debug, Eq);
assert_impl_all!(Nested1: Debug);
assert_not_impl_all!(Nested1: PartialEq, Eq);
assert_not_impl_all!(Inner1: PartialEq, Eq);
assert_impl_all!(Inner1: Debug);
assert_impl_all!(Nested2: Eq, PartialEq);
assert_impl_all!(Inner2: Debug, Eq, PartialEq);
}
#[test]
fn expect_no_expansion() {
#[subdef]
struct NoSubdef {
field1: String,
field2: [u8; 8],
field3: [u32; {
const X: usize = 10;
X + 1
}],
field4: [f64; {
struct S;
let _ = S {};
0
}],
}
NoSubdef {
field1: String::new(),
field2: [0; 8],
field3: [0; 11],
field4: [0.0; 0],
};
}
#[test]
fn edge_case_generics_and_inference() {
#[subdef]
struct GenericContainer<T, const N: usize>
where
T: Debug,
{
item: [Option<std::sync::Arc<Item<T, N>>>; {
struct Item<T, const N: usize>
where
T: Debug,
{
payload: T,
size: [u8; N],
}
}],
phantom: std::marker::PhantomData<T>,
}
GenericContainer::<u32, 5> {
item: Some(std::sync::Arc::new(Item {
payload: 10,
size: [0; 5],
})),
phantom: std::marker::PhantomData,
};
}