wallrnd 1.2.2

A generator of random abstract wallpapers
Documentation
use crate::prelude::*;
use crate::scene::*;
use std::fmt;
use std::fs::File;
use std::io::{Read, Write};
use std::rc::Rc;

pub struct Logger {
    pub frame: Frame,
    pub bg: ColorItem,
    pub objects: Vec<Rc<dyn Contains>>,
}

impl fmt::Display for Frame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {} {} {} #", self.x, self.y, self.w, self.h)
    }
}

impl fmt::Display for ColorItem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {} {} ", self.shade.0, self.shade.1, self.shade.2)?;
        write!(f, "{} {} {} ", self.theme.0, self.theme.1, self.theme.2)?;
        write!(f, "{} ", self.salt)?;
        write!(f, "{} {} #", self.deviation, self.distance)
    }
}

impl fmt::Display for SaltItem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {} {} ", self.color.0, self.color.1, self.color.2)?;
        write!(f, "{} {} ", self.likeliness, self.variability)
    }
}

impl fmt::Display for Salt {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for item in self.0.iter() {
            write!(f, "{} ", item)?;
        }
        write!(f, "#")
    }
}

impl fmt::Display for Disc {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Disc {} {} {} ",
            self.center.0, self.center.1, self.radius
        )?;
        write!(f, "{} #", self.color)
    }
}

impl fmt::Display for HalfPlane {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "HalfPlane {} {} {} {} ",
            self.limit.0, self.limit.1, self.reference.0, self.reference.1
        )?;
        write!(f, "{} #", self.color)
    }
}

impl fmt::Display for Triangle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Triangle {} {} ", self.a.0, self.a.1)?;
        write!(f, "{} {} ", self.b.0, self.b.1)?;
        write!(f, "{} {} ", self.c.0, self.c.1)?;
        write!(f, "{} #", self.color)
    }
}

impl fmt::Display for Spiral {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Spiral {} {} {} {} ",
            self.center.0, self.center.1, self.width, self.tightness
        )?;
        write!(f, "{} #", self.color)
    }
}

impl fmt::Display for Stripe {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Stripe {} {} {} {} ",
            self.limit.0, self.limit.1, self.reference.0, self.reference.1
        )?;
        write!(f, "{} #", self.color)
    }
}

impl fmt::Display for Wave {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Wave {} {} {} {} ",
            self.limit.0, self.limit.1, self.reference.0, self.reference.1
        )?;
        write!(f, "{} {} ", self.amplitude, self.frequency)?;
        write!(f, "{} #", self.color)
    }
}

impl fmt::Display for Sawtooth {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Sawtooth {} {} {} {} ",
            self.limit.0, self.limit.1, self.reference.0, self.reference.1
        )?;
        write!(f, "{} {} ", self.amplitude, self.frequency)?;
        write!(f, "{} #", self.color)
    }
}

impl fmt::Display for Logger {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} ", self.frame)?;
        write!(f, "{} ", self.bg)?;
        write!(f, "{} ", self.objects.len())?;
        for o in &self.objects {
            write!(f, "{} ", o)?;
        }
        Ok(())
    }
}

impl Logger {
    pub fn save(&self, dest: &str) -> std::io::Result<()> {
        let mut buffer = File::create(dest)?;
        buffer.write_all(&format!("{}", &self).into_bytes())
    }

    pub fn load(src: &str) -> Self {
        let mut s = String::new();
        let mut file = File::open(src).unwrap();
        file.read_to_string(&mut s).unwrap();
        let mut items = s.split(' ');
        Logger::restore(&mut items)
    }
}

trait Restore {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self;
}

impl Restore for usize {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        items.next().unwrap().parse::<Self>().unwrap()
    }
}

impl Restore for f64 {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        items.next().unwrap().parse::<Self>().unwrap()
    }
}

impl Restore for Pos {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        Self(f64::restore(items), f64::restore(items))
    }
}

impl Restore for Color {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        Self(
            usize::restore(items),
            usize::restore(items),
            usize::restore(items),
        )
    }
}

impl Restore for Logger {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let frame = Frame::restore(items);
        let bg = ColorItem::restore(items);
        let len = items.next().unwrap().parse::<usize>().unwrap();
        let mut objects = Vec::new();
        for _ in 0..len {
            objects.push(match items.next().unwrap() {
                "Disc" => Rc::new(Disc::restore(items)) as Rc<dyn Contains>,
                "HalfPlane" => Rc::new(HalfPlane::restore(items)) as Rc<dyn Contains>,
                "Stripe" => Rc::new(Stripe::restore(items)) as Rc<dyn Contains>,
                "Triangle" => Rc::new(Triangle::restore(items)) as Rc<dyn Contains>,
                "Spiral" => Rc::new(Spiral::restore(items)) as Rc<dyn Contains>,
                "Wave" => Rc::new(Wave::restore(items)) as Rc<dyn Contains>,
                "Sawtooth" => Rc::new(Sawtooth::restore(items)) as Rc<dyn Contains>,
                _ => panic!("Unknown item"),
            });
        }
        Self { frame, bg, objects }
    }
}

impl Restore for Frame {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let x = usize::restore(items);
        let y = usize::restore(items);
        let w = usize::restore(items);
        let h = usize::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self { x, y, w, h }
    }
}

impl Restore for Salt {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let nb = usize::restore(items);
        let mut salt = Salt::default();
        for _ in 0..nb {
            salt.0.push(SaltItem::restore(items));
        }
        assert_eq!(items.next().unwrap(), "#");
        salt
    }
}

impl Restore for SaltItem {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let color = Color::restore(items);
        let likeliness = f64::restore(items);
        let variability = usize::restore(items);
        Self {
            color,
            likeliness,
            variability,
        }
    }
}

impl Restore for ColorItem {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let shade = Color::restore(items);
        let theme = Color::restore(items);
        let salt = Salt::restore(items);
        let deviation = usize::restore(items);
        let distance = usize::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self {
            shade,
            theme,
            deviation,
            distance,
            salt,
        }
    }
}

impl Restore for Disc {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let center = Pos::restore(items);
        let radius = f64::restore(items);
        let color = ColorItem::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self {
            center,
            radius,
            color,
        }
    }
}

impl Restore for HalfPlane {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let limit = Pos::restore(items);
        let reference = Pos::restore(items);
        let color = ColorItem::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self {
            limit,
            reference,
            color,
        }
    }
}

impl Restore for Stripe {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let limit = Pos::restore(items);
        let reference = Pos::restore(items);
        let color = ColorItem::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self {
            limit,
            reference,
            color,
        }
    }
}

impl Restore for Triangle {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let a = Pos::restore(items);
        let b = Pos::restore(items);
        let c = Pos::restore(items);
        let color = ColorItem::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self { a, b, c, color }
    }
}

impl Restore for Spiral {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let center = Pos::restore(items);
        let width = f64::restore(items);
        let tightness = f64::restore(items);
        let color = ColorItem::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self {
            center,
            width,
            color,
            tightness,
        }
    }
}

impl Restore for Wave {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let limit = Pos::restore(items);
        let reference = Pos::restore(items);
        let amplitude = f64::restore(items);
        let frequency = f64::restore(items);
        let color = ColorItem::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self {
            limit,
            reference,
            amplitude,
            frequency,
            color,
        }
    }
}

impl Restore for Sawtooth {
    fn restore<'a>(items: &mut impl Iterator<Item = &'a str>) -> Self {
        let limit = Pos::restore(items);
        let reference = Pos::restore(items);
        let amplitude = f64::restore(items);
        let frequency = f64::restore(items);
        let color = ColorItem::restore(items);
        assert_eq!(items.next().unwrap(), "#");
        Self {
            limit,
            reference,
            amplitude,
            frequency,
            color,
        }
    }
}