Skip to content

Commit 802cdbd

Browse files
committed
Added support for struct variants, using generate structs
1 parent e30d33e commit 802cdbd

File tree

9 files changed

+1032
-390
lines changed

9 files changed

+1032
-390
lines changed

README.md

Lines changed: 333 additions & 215 deletions
Large diffs are not rendered by default.

dtype_variant/src/lib.rs

Lines changed: 103 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@ pub trait EnumVariantDowncast<VariantToken> {
1010
}
1111

1212
pub trait EnumVariantDowncastRef<VariantToken> {
13-
type Target<'target> where Self: 'target;
13+
type Target<'target>
14+
where
15+
Self: 'target;
1416

1517
/// Returns a reference wrapper for the target field if the enum is the target variant
1618
fn downcast_ref(&self) -> Option<Self::Target<'_>>;
1719
}
1820

1921
pub trait EnumVariantDowncastMut<VariantToken> {
20-
type Target<'target> where Self: 'target;
22+
type Target<'target>
23+
where
24+
Self: 'target;
2125

2226
/// Returns a mutable reference wrapper for the target field if the enum is the target variant
2327
fn downcast_mut(&mut self) -> Option<Self::Target<'_>>;
@@ -232,39 +236,46 @@ mod tests {
232236
name: "Alice".to_string(),
233237
age: 30,
234238
};
235-
239+
236240
let location_data = StructVariantData::Location {
237241
lat: 37.7749,
238242
lng: -122.4194,
239243
};
240-
244+
241245
let score_data = StructVariantData::Score(95);
242-
246+
243247
// Test owned downcasting (struct variants only support owned downcasting for now)
244-
if let Some(person_fields) = person_data.clone().downcast::<PersonVariant>() {
248+
if let Some(person_fields) =
249+
person_data.clone().downcast::<PersonVariant>()
250+
{
245251
assert_eq!(person_fields.name, "Alice");
246252
assert_eq!(person_fields.age, 30);
247253
} else {
248254
panic!("Failed to downcast person variant");
249255
}
250-
251-
if let Some(location_fields) = location_data.clone().downcast::<LocationVariant>() {
256+
257+
if let Some(location_fields) =
258+
location_data.clone().downcast::<LocationVariant>()
259+
{
252260
assert_eq!(location_fields.lat, 37.7749);
253261
assert_eq!(location_fields.lng, -122.4194);
254262
} else {
255263
panic!("Failed to downcast location variant");
256264
}
257-
265+
258266
if let Some(score) = score_data.downcast_ref::<ScoreVariant>() {
259267
assert_eq!(*score, 95);
260268
} else {
261269
panic!("Failed to downcast score variant");
262270
}
263-
271+
264272
// Test From implementations with struct types
265-
let person_struct = PersonFields { name: "Bob".to_string(), age: 25 };
273+
let person_struct = StructVariantDataPersonFields {
274+
name: "Bob".to_string(),
275+
age: 25,
276+
};
266277
let data_from_struct = StructVariantData::from(person_struct);
267-
278+
268279
if let StructVariantData::Person { name, age } = data_from_struct {
269280
assert_eq!(name, "Bob");
270281
assert_eq!(age, 25);
@@ -293,12 +304,12 @@ mod tests {
293304
name: "Alice".to_string(),
294305
age: 30,
295306
};
296-
307+
297308
let location_data = StructVariantData::Location {
298309
lat: 37.7749,
299310
lng: -122.4194,
300311
};
301-
312+
302313
let score_data = StructVariantData::Score(95);
303314

304315
// Test basic matcher functionality for all variants
@@ -338,7 +349,7 @@ mod tests {
338349
name: "Alice".to_string(),
339350
age: 30,
340351
};
341-
352+
342353
let location_data = StructVariantData::Location {
343354
lat: 37.7749,
344355
lng: -122.4194,
@@ -367,15 +378,17 @@ mod tests {
367378
name: "Bob".to_string(),
368379
age: 25,
369380
};
370-
381+
371382
let person_mut_ref = person_data_mut.downcast_mut::<PersonVariant>();
372383
if let Some(person_fields_mut) = person_mut_ref {
373384
// We can modify the fields through the mutable references
374385
*person_fields_mut.age = 26;
375386
// Note: The original enum is not modified because we're working with a wrapper struct
376387
// This is expected behavior for this design
377388
} else {
378-
panic!("Mutable reference downcasting should work for struct variants now");
389+
panic!(
390+
"Mutable reference downcasting should work for struct variants now"
391+
);
379392
}
380393
}
381394

@@ -391,24 +404,25 @@ mod tests {
391404
assert!(location_ref.is_none());
392405

393406
let mut person_data_clone = person_data.clone();
394-
let location_mut_ref = person_data_clone.downcast_mut::<LocationVariant>();
407+
let location_mut_ref =
408+
person_data_clone.downcast_mut::<LocationVariant>();
395409
assert!(location_mut_ref.is_none());
396410
}
397411

398412
#[test]
399413
fn test_new_trait_structure() {
400414
// Test that the new three-trait structure works correctly
401415
let score_data = StructVariantData::Score(95);
402-
416+
403417
// Test each trait separately
404418
// Owned downcasting should work for tuple variants
405419
let score_owned = score_data.clone().downcast::<ScoreVariant>();
406420
assert_eq!(score_owned, Some(95));
407-
421+
408422
// Reference downcasting should work for tuple variants
409423
let score_ref = score_data.downcast_ref::<ScoreVariant>();
410424
assert_eq!(score_ref, Some(&95));
411-
425+
412426
// Mutable reference downcasting should work for tuple variants
413427
let mut score_data_mut = StructVariantData::Score(42);
414428
let score_mut_ref = score_data_mut.downcast_mut::<ScoreVariant>();
@@ -423,67 +437,122 @@ mod tests {
423437
age: 30,
424438
};
425439

426-
// Test that downcast_ref returns PersonRef<'_>
427-
let person_ref: Option<PersonRef<'_>> = person_data.downcast_ref::<PersonVariant>();
440+
// Test that downcast_ref returns StructVariantDataPersonRef<'_>
441+
let person_ref: Option<StructVariantDataPersonRef<'_>> =
442+
person_data.downcast_ref::<PersonVariant>();
428443
assert!(person_ref.is_some());
429444
let person_ref = person_ref.unwrap();
430445
assert_eq!(person_ref.name, "Alice");
431446
assert_eq!(*person_ref.age, 30);
432447

433-
// Test that downcast_mut returns PersonMut<'_>
448+
// Test that downcast_mut returns StructVariantDataPersonMut<'_>
434449
let mut person_data_mut = StructVariantData::Person {
435450
name: "Bob".to_string(),
436451
age: 25,
437452
};
438-
let person_mut: Option<PersonMut<'_>> = person_data_mut.downcast_mut::<PersonVariant>();
453+
let person_mut: Option<StructVariantDataPersonMut<'_>> =
454+
person_data_mut.downcast_mut::<PersonVariant>();
439455
assert!(person_mut.is_some());
440456
let person_mut = person_mut.unwrap();
441457
assert_eq!(person_mut.name, "Bob");
442458
*person_mut.age = 26; // Demonstrate mutable access
443459
assert_eq!(*person_mut.age, 26);
444460
}
445461

462+
#[test]
463+
fn test_struct_from_conversions() {
464+
// Test From conversions for struct reference types
465+
let person_data = StructVariantData::Person {
466+
name: "Alice".to_string(),
467+
age: 30,
468+
};
469+
470+
// Test Ref -> Fields conversion
471+
if let Some(person_ref) = person_data.downcast_ref::<PersonVariant>() {
472+
let person_fields: StructVariantDataPersonFields =
473+
person_ref.into();
474+
assert_eq!(person_fields.name, "Alice");
475+
assert_eq!(person_fields.age, 30);
476+
} else {
477+
panic!("Failed to downcast to PersonRef");
478+
}
479+
480+
// Test Mut -> Fields conversion
481+
let mut person_data_mut = StructVariantData::Person {
482+
name: "Bob".to_string(),
483+
age: 25,
484+
};
485+
486+
if let Some(person_mut) =
487+
person_data_mut.downcast_mut::<PersonVariant>()
488+
{
489+
let person_fields: StructVariantDataPersonFields =
490+
person_mut.into();
491+
assert_eq!(person_fields.name, "Bob");
492+
assert_eq!(person_fields.age, 25);
493+
} else {
494+
panic!("Failed to downcast to PersonMut");
495+
}
496+
497+
// Test reference-to-reference conversion
498+
let location_data = StructVariantData::Location {
499+
lat: 37.7749,
500+
lng: -122.4194,
501+
};
502+
503+
if let Some(location_ref) =
504+
location_data.downcast_ref::<LocationVariant>()
505+
{
506+
let location_fields: StructVariantDataLocationFields =
507+
(&location_ref).into();
508+
assert_eq!(location_fields.lat, 37.7749);
509+
assert_eq!(location_fields.lng, -122.4194);
510+
} else {
511+
panic!("Failed to downcast to LocationRef");
512+
}
513+
}
514+
446515
#[test]
447516
fn test_complete_reference_downcasting_functionality() {
448517
// Comprehensive test demonstrating the complete functionality
449-
518+
450519
// Test struct variants with reference downcasting
451520
let person = StructVariantData::Person {
452521
name: "Alice".to_string(),
453522
age: 30,
454523
};
455-
524+
456525
// Test owned downcasting (returns PersonFields)
457526
let person_owned = person.clone().downcast::<PersonVariant>().unwrap();
458527
assert_eq!(person_owned.name, "Alice");
459528
assert_eq!(person_owned.age, 30);
460-
529+
461530
// Test reference downcasting (returns PersonRef<'_>)
462531
let person_ref = person.downcast_ref::<PersonVariant>().unwrap();
463532
assert_eq!(person_ref.name, "Alice");
464533
assert_eq!(*person_ref.age, 30);
465-
534+
466535
// Test mutable reference downcasting (returns PersonMut<'_>)
467536
let mut person_mut = StructVariantData::Person {
468537
name: "Bob".to_string(),
469538
age: 25,
470539
};
471-
let person_mut_ref = person_mut.downcast_mut::<PersonVariant>().unwrap();
540+
let person_mut_ref =
541+
person_mut.downcast_mut::<PersonVariant>().unwrap();
472542
assert_eq!(person_mut_ref.name, "Bob");
473543
*person_mut_ref.age = 26;
474544
assert_eq!(*person_mut_ref.age, 26);
475-
545+
476546
// Test tuple variants still work
477547
let score = StructVariantData::Score(95);
478548
assert_eq!(score.clone().downcast::<ScoreVariant>(), Some(95));
479549
assert_eq!(score.downcast_ref::<ScoreVariant>(), Some(&95));
480-
550+
481551
let mut score_mut = StructVariantData::Score(42);
482552
assert_eq!(score_mut.downcast_mut::<ScoreVariant>(), Some(&mut 42));
483-
553+
484554
// Test wrong type downcasting returns None
485555
assert!(person.downcast_ref::<LocationVariant>().is_none());
486556
assert!(person.downcast_ref::<ScoreVariant>().is_none());
487557
}
488-
489558
}

0 commit comments

Comments
 (0)