use std::mem;

enum WeekO { Mon, Tue, Wed, Thu, Fri, Sat, Sun }
#[derive(Debug, Clone, Copy)]
enum Week { Mon, Tue, Wed = 2, Thu = 10, Fri, Sat, Sun }

#[derive(Debug)]
struct S {
	i : isize, j : isize,
}
#[repr(u8)]
#[derive(Debug)]
enum ADT {
	I(isize) = 5,
	F(f64) = 10,
	S(S) = 0,
}

#[derive(Debug)]
enum Animal {
	Dog( String, f64 ),
	Cat{ name: String, weight: f64 },
}

#[derive(Debug)]
enum Direction { North, South, East, West }

impl Direction {
    const VALUES: [Self; 4] = [Self::North, Self::South, Self::East, Self::West];
}
#[repr(u8)]
enum Fieldless {
    Tuple() = 5,
    Struct{} = 10,
    Unit = 12,
}
impl Fieldless {
    fn discriminant(&self) -> u8 {
        // SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)` `union`
        // between `repr(C)` structs, each of which has the `u8` discriminant as its first
        // field, so we can read the discriminant without offsetting the pointer.
        unsafe { *<*const _>::from(self).cast::<u8>() }
    }
}
fn main() {
	let arr : [i32; 7];

	let mut s = S{ i : 3, j : 4 };
	let mut adt : ADT;
	adt = ADT::I(3);  println!( "{:?}", adt );
	adt = ADT::F(3.5);  println!( "{:?}", adt );
	adt = ADT::S(s);  println!( "{:?}", adt );
	match adt {
		ADT::I(i) => println!( "{:}", i ),
		ADT::F(f) => println!( "{:}", f ),
		ADT::S(s) => println!( "{:} {:}", s.i, s.j ),
	}

	let mut wo : WeekO = WeekO::Mon;
	match wo {
		WeekO::Mon => println!( "Mon" ),
		_ => (),
	}
	
	let mut fl : Fieldless;
	fl = Fieldless::Struct{};
	match fl {
		Fieldless::Struct{} => println!( "Struct" ),
		_ => (),
	}
	if fl.discriminant() == 10 {
		println!( "Struct" );
	}
	let mut week: Week = Week::Sat;
	match week {
		Week::Mon => println!( "X {:?}", Week::Mon as isize ),
		Week::Tue => println!( "X {:?}", Week::Tue as isize ),
		Week::Wed => println!( "X {:?}", Week::Wed as isize ),
		Week::Thu => println!( "X {:?}", Week::Thu as isize ),
		Week::Fri => println!( "X {:?}", Week::Fri as isize ),
		Week::Sat => println!( "X {:?}", Week::Sat as isize ),
		Week::Sun => println!( "X {:?}", Week::Sun as isize ),
	}
	match week {
		Week::Mon | Week:: Tue | Week::Wed | Week::Thu | Week::Fri => println!( "weekday" ),
		Week::Sat | Week:: Sun => println!( "weekend" ),
	}
	println!( "{:?} {:?}", week as isize, Week::Fri as isize );
	if mem::discriminant(&week) == mem::discriminant(&Week::Mon) {
		println!( "{:?}", week );
	}
	if week as isize == Week::Mon as isize {
		println!( "{:?}", week );
	}
	for d in Week::Mon as isize ..= Week::Sun as isize {
		print!( "{:?} ", d );
	}
	println!( "" );
	let mut mon : isize = Week::Mon as isize;

	week = Week::Fri;
	println!( "{:?}", week );

	let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2);
	println!( "{:?}", a );
	a = Animal::Cat{ name: "Spotty".to_string(), weight: 2.7 };
//	println!( "{:?} {:?}", a, a.name );

 	for direction in Direction::VALUES {
        println!("{direction:?}");
    }
}

// Local Variables: //
// tab-width: 4 //
// End: //
