<commit_before>// A reference to a wire in a relatively located tile
#[derive(Clone)]
pub struct RelWire {
    pub rel_x: i32,   // (bel.x + rel_x == tile.x)
    pub rel_y: i32,   // (bel.y + rel_y == tile.y)
    pub name: String, // wire name in tile
}

impl RelWire {
    pub fn rel_name(&self) -> String {
        let mut name = String::new();
        if self.rel_y < 0 {
            name.push_str(&format!("N{}", -self.rel_y));
        }
        if self.rel_y > 0 {
            name.push_str(&format!("S{}", self.rel_y));
        }
        if self.rel_x < 0 {
            name.push_str(&format!("W{}", -self.rel_x));
        }
        if self.rel_x > 0 {
            name.push_str(&format!("E{}", self.rel_x));
        }
        if !name.is_empty() {
            name.push(':');
        }
        name.push_str(&self.name);
        name
    }
}

#[derive(Eq, PartialEq, Clone)]
pub enum PinDir {
    INPUT = 0,
    OUTPUT = 1,
    INOUT = 2,
}

#[derive(Clone)]
pub struct BelPin {
    pub name: String,  // name of pin on bel
    pub desc: String,  // description for documentation
    pub dir: PinDir,   // direction
    pub wire: RelWire, // reference to wire in tile
}

impl BelPin {
    pub fn new(
        name: &str,
        desc: &str,
        dir: PinDir,
        wirename: &str,
        rel_x: i32,
        rel_y: i32,
    ) -> BelPin {
        BelPin {
            name: name.to_string(),
            desc: desc.to_string(),
            dir: dir,
            wire: RelWire {
                rel_x: rel_x,
                rel_y: rel_y,
                name: wirename.to_string(),
            },
        }
    }

    // Standard postfixed wirename scheme
    pub fn new_p(
        name: &str,
        desc: &str,
        dir: PinDir,
        postfix: &str,
        rel_x: i32,
        rel_y: i32,
    ) -> BelPin {
        BelPin {
            name: name.to_string(),
            desc: desc.to_string(),
            dir: dir,
            wire: RelWire {
                rel_x: rel_x,
                rel_y: rel_y,
                name: format!("J{}_{}", name, postfix),
            },
        }
    }
    // Logical->physical mapped postfixed wirename scheme
    pub fn new_mapped(
        name: &str,
        desc: &str,
        dir: PinDir,
        physpin: &str,
        postfix: &str,
        rel_x: i32,
        rel_y: i32,
    ) -> BelPin {
        BelPin {
            name: name.to_string(),
            desc: desc.to_string(),
            dir: dir,
            wire: RelWire {
                rel_x: rel_x,
                rel_y: rel_y,
                name: format!("J{}_{}", physpin, postfix),
            },
        }
    }
}

pub struct Bel {
    pub name: String,
    pub beltype: String,
    pub pins: Vec<BelPin>,
    pub z: u32,
}

// Macros for common cases
macro_rules! input {
	($($rest:expr),*) =>
		( def_pin!(PinDir::INPUT, $($rest),*) );
}

macro_rules! output {
	($($rest:expr),*) =>
		( def_pin!(PinDir::OUTPUT, $($rest),*) );
}

macro_rules! def_pin {
    ($dir: expr, $postfix: expr, $name: expr) => {
        BelPin::new_p($name, "", $dir, $postfix, 0, 0)
    };

    ($dir: expr,$postfix: expr, $name: expr, $desc: expr) => {
        BelPin::new_p($name, $desc, $dir, $postfix, 0, 0)
    };
    ($dir: expr,$postfix: expr, $name: expr, $desc: expr, $rel_x: expr, $rel_y: expr) => {
        BelPin::new_p($name, $desc, $dir, $postfix, $rel_x, $rel_y)
    };
}

macro_rules! input_m {
    ($($rest:expr),*) =>
        ( def_pin_mapped!(PinDir::INPUT, $($rest),*) );
}

macro_rules! output_m {
    ($($rest:expr),*) =>
        ( def_pin_mapped!(PinDir::OUTPUT, $($rest),*) );
}

macro_rules! inout_m {
    ($($rest:expr),*) =>
        ( def_pin_mapped!(PinDir::INOUT, $($rest),*) );
}

macro_rules! def_pin_mapped {
    ($dir: expr, $postfix: expr, $name: expr) => {
        BelPin::new_p($name, "", $dir, $physpin, $postfix, 0, 0)
    };

    ($dir: expr,$postfix: expr, $name: expr, $physpin: expr, $desc: expr) => {
        BelPin::new_mapped($name, $desc, $dir, $physpin, $postfix, 0, 0)
    };
}

const Z_TO_CHAR: [char; 4] = ['A', 'B', 'C', 'D'];

impl Bel {
    pub fn make_oxide_ff(slice: usize, ff: usize) -> Bel {
        let ch = Z_TO_CHAR[slice];
        let postfix = format!("SLICE{}", ch);
        let pins = vec![
            input!(&postfix, "CLK", "FF clock"),
            input!(&postfix, "CE", "FF clock enable"),
            input!(&postfix, "LSR", "FF local set/reset"),
            input_m!(
                &postfix,
                "DI",
                &format!("DI{}", ff),
                "FF input from LUT/MUX output"
            ),
            input_m!(
                &postfix,
                "M",
                &format!("M{}", ff),
                "FF direct input from fabric M signal"
            ),
            output_m!(&postfix, "Q", &format!("Q{}", ff), "FF output"),
        ];
        Bel {
            name: format!("{}_FF{}", &postfix, ff),
            beltype: String::from("OXIDE_FF"),
            pins: pins,
            z: (slice << 3 | (ff + 2)) as u32,
        }
    }

    pub fn make_oxide_comb(slice: usize, lut: usize) -> Bel {
        let ch = Z_TO_CHAR[slice];
        let postfix = format!("SLICE{}", ch);
        let mut pins = vec![
            input_m!(&postfix, "A", &format!("A{}", lut), "LUT A input"),
            input_m!(&postfix, "B", &format!("B{}", lut), "LUT B input"),
            input_m!(&postfix, "C", &format!("C{}", lut), "LUT C input"),
            input_m!(&postfix, "D", &format!("D{}", lut), "LUT D input"),
            input_m!(
                &postfix,
                "FCI",
                if lut == 0 { "FCI" } else { "INT_CARRY" },
                "CCU2 fast carry input"
            ),
            output_m!(&postfix, "F", &format!("F{}", lut), "LUT/sum output"),
            output_m!(
                &postfix,
                "FCO",
                if lut == 1 { "FCO" } else { "INT_CARRY" },
                "CCU2 fast carry output"
            ),
        ];
        if lut == 0 {
            // MUX2 in LUT0 COMB only
            pins.append(&mut vec![
                input!(&postfix, "SEL", "MUX2 select input"),
                input!(&postfix, "F1", "input from second LUT to MUX2"),
                output_m!(&postfix, "OFX", "OFX0", "MUX2 output"),
            ]);
        }
        if slice == 0 || slice == 1 {
            // DPRAM in lower two SLICEs only
            pins.append(&mut vec![
                input!(&postfix, "WAD0", "LUTRAM write address 0 (from RAMW)"),
                input!(&postfix, "WAD1", "LUTRAM write address 1 (from RAMW)"),
                input!(&postfix, "WAD2", "LUTRAM write address 2 (from RAMW)"),
                input!(&postfix, "WAD3", "LUTRAM write address 3 (from RAMW)"),
                input_m!(
                    &postfix,
                    "WD",
                    &format!("WD{}", lut),
                    "LUTRAM write data (from RAMW)"
                ),
                input!(&postfix, "WCK", "LUTRAM write clock (from RAMW)"),
                input!(&postfix, "WRE", "LUTRAM write enable (from RAMW)"),
            ]);
        }
        Bel {
            name: format!("{}_LUT{}", &postfix, lut),
            beltype: String::from("OXIDE_COMB"),
            pins: pins,
            z: (slice << 3 | lut) as u32,
        }
    }

    pub fn make_oxide_ramw(slice: usize) -> Bel {
        assert_eq!(slice, 2);
        let ch = Z_TO_CHAR[slice];
        let postfix = format!("SLICE{}", ch);
        let pins = vec![
            input!(&postfix, "A0", "buffered to WADO3"),
            input!(&postfix, "A1", "buffered to WDO2"),
            input!(&postfix, "B0", "buffered to WADO1"),
            input!(&postfix, "B1", "buffered to WDO3"),
            input!(&postfix, "C0", "buffered to WADO2"),
            input!(&postfix, "C1", "buffered to WDO1"),
            input!(&postfix, "D0", "buffered to WADO0"),
            input!(&postfix, "D1", "buffered to WDO0"),
            input!(&postfix, "CLK", "buffered to WCKO"),
            input!(&postfix, "LSR", "buffered to WREO"),
            output!(&postfix, "WADO0", "LUTRAM write address 0 (to SLICEA/B)"),
            output!(&postfix, "WADO1", "LUTRAM write address 1 (to SLICEA/B)"),
            output!(&postfix, "WADO2", "LUTRAM write address 2 (to SLICEA/B)"),
            output!(&postfix, "WADO3", "LUTRAM write address 3 (to SLICEA/B)"),
            output!(&postfix, "WCKO", "LUTRAM write clock (to SLICEA/B)"),
            output!(&postfix, "WREO", "LUTRAM write enable (to SLICEA/B)"),
            output!(&postfix, "WDO0", "LUTRAM write data 0 (to SLICEA)"),
            output!(&postfix, "WDO1", "LUTRAM write data 1 (to SLICEA)"),
            output!(&postfix, "WDO2", "LUTRAM write data 2 (to SLICEB)"),
            output!(&postfix, "WDO3", "LUTRAM write data 3 (to SLICEB)"),
        ];
        Bel {
            name: format!("{}_RAMW", &postfix),
            beltype: String::from("RAMW"),
            pins: pins,
            z: (slice << 3 | 4) as u32,
        }
    }

    pub fn make_seio33(z: usize) -> Bel {
        let ch = Z_TO_CHAR[z];
        let postfix = format!("SEIO33_CORE_IO{}", ch);
        Bel {
            name: format!("PIO{}", ch),
            beltype: String::from("SEIO33_CORE"),
            pins: vec![
                inout_m!(&postfix, "B", "PAD", "top level pad signal"),
                input_m!(
                    &postfix,
                    "I",
                    "PADDO",
                    "output buffer input from fabric/IOLOGIC"
                ),
                input_m!(
                    &postfix,
                    "T",
                    "PADDT",
                    "output buffer tristate (0=driven, 1=hi-z)"
                ),
                output_m!(
                    &postfix,
                    "O",
                    "PADDI",
                    "input buffer output to fabric/IOLOGIC"
                ),
                input!(&postfix, "I3CRESEN", "I3C strong pullup enable"),
                input!(&postfix, "I3CWKPU", "I3C weak pullup enable"),
            ],
            z: z as u32,
        }
    }

    pub fn make_seio18(z: usize) -> Bel {
        let ch = Z_TO_CHAR[z];
        let postfix = format!("SEIO18_CORE_IO{}", ch);
        Bel {
            name: format!("PIO{}", ch),
            beltype: String::from("SEIO18_CORE"),
            pins: vec![
                inout_m!(&postfix, "B", "IOPAD", "top level pad signal"),
                input_m!(
                    &postfix,
                    "I",
                    "PADDO",
                    "output buffer input from fabric/IOLOGIC"
                ),
                input_m!(
                    &postfix,
                    "T",
                    "PADDT",
                    "output buffer tristate (0=driven, 1=hi-z)"
                ),
                output_m!(
                    &postfix,
                    "O",
                    "PADDI",
                    "input buffer output to fabric/IOLOGIC"
                ),
                input!(&postfix, "DOLP", "DPHY LP mode output buffer input"),
                output!(&postfix, "INLP", "DPHY LP mode input buffer output"),
                output!(&postfix, "INADC", "analog signal out to ADC"),
            ],
            z: z as u32,
        }
    }
}

pub fn get_tile_bels(tiletype: &str) -> Vec<Bel> {
    match tiletype {
        "PLC" => (0..4)
            .map(|slice| {
                let mut bels = vec![
                    Bel::make_oxide_comb(slice, 0),
                    Bel::make_oxide_comb(slice, 1),
                    Bel::make_oxide_ff(slice, 0),
                    Bel::make_oxide_ff(slice, 1),
                ];
                if slice == 2 {
                    bels.push(Bel::make_oxide_ramw(slice));
                }
                bels
            })
            .flatten()
            .collect(),
        "SYSIO_B0_0" | "SYSIO_B1_0" | "SYSIO_B1_0_C" | "SYSIO_B2_0" | "SYSIO_B2_0_C"
        | "SYSIO_B6_0" | "SYSIO_B6_0_C" | "SYSIO_B7_0" | "SYSIO_B7_0_C" => {
            (0..2).map(Bel::make_seio33).collect()
        }
        "SYSIO_B3_0" | "SYSIO_B4_0" | "SYSIO_B5_0" => (0..2).map(Bel::make_seio18).collect(),
        _ => vec![],
    }
}
<commit_msg>Add oscillator bel<commit_after>// A reference to a wire in a relatively located tile
#[derive(Clone)]
pub struct RelWire {
    pub rel_x: i32,   // (bel.x + rel_x == tile.x)
    pub rel_y: i32,   // (bel.y + rel_y == tile.y)
    pub name: String, // wire name in tile
}

impl RelWire {
    pub fn rel_name(&self) -> String {
        let mut name = String::new();
        if self.rel_y < 0 {
            name.push_str(&format!("N{}", -self.rel_y));
        }
        if self.rel_y > 0 {
            name.push_str(&format!("S{}", self.rel_y));
        }
        if self.rel_x < 0 {
            name.push_str(&format!("W{}", -self.rel_x));
        }
        if self.rel_x > 0 {
            name.push_str(&format!("E{}", self.rel_x));
        }
        if !name.is_empty() {
            name.push(':');
        }
        name.push_str(&self.name);
        name
    }
}

#[derive(Eq, PartialEq, Clone)]
pub enum PinDir {
    INPUT = 0,
    OUTPUT = 1,
    INOUT = 2,
}

#[derive(Clone)]
pub struct BelPin {
    pub name: String,  // name of pin on bel
    pub desc: String,  // description for documentation
    pub dir: PinDir,   // direction
    pub wire: RelWire, // reference to wire in tile
}

impl BelPin {
    pub fn new(
        name: &str,
        desc: &str,
        dir: PinDir,
        wirename: &str,
        rel_x: i32,
        rel_y: i32,
    ) -> BelPin {
        BelPin {
            name: name.to_string(),
            desc: desc.to_string(),
            dir: dir,
            wire: RelWire {
                rel_x: rel_x,
                rel_y: rel_y,
                name: wirename.to_string(),
            },
        }
    }

    // Standard postfixed wirename scheme
    pub fn new_p(
        name: &str,
        desc: &str,
        dir: PinDir,
        postfix: &str,
        rel_x: i32,
        rel_y: i32,
    ) -> BelPin {
        BelPin {
            name: name.to_string(),
            desc: desc.to_string(),
            dir: dir,
            wire: RelWire {
                rel_x: rel_x,
                rel_y: rel_y,
                name: format!("J{}_{}", name, postfix),
            },
        }
    }
    // Logical->physical mapped postfixed wirename scheme
    pub fn new_mapped(
        name: &str,
        desc: &str,
        dir: PinDir,
        physpin: &str,
        postfix: &str,
        rel_x: i32,
        rel_y: i32,
    ) -> BelPin {
        BelPin {
            name: name.to_string(),
            desc: desc.to_string(),
            dir: dir,
            wire: RelWire {
                rel_x: rel_x,
                rel_y: rel_y,
                name: format!("J{}_{}", physpin, postfix),
            },
        }
    }
}

pub struct Bel {
    pub name: String,
    pub beltype: String,
    pub pins: Vec<BelPin>,
    pub z: u32,
}

// Macros for common cases
macro_rules! input {
	($($rest:expr),*) =>
		( def_pin!(PinDir::INPUT, $($rest),*) );
}

macro_rules! output {
	($($rest:expr),*) =>
		( def_pin!(PinDir::OUTPUT, $($rest),*) );
}

macro_rules! def_pin {
    ($dir: expr, $postfix: expr, $name: expr) => {
        BelPin::new_p($name, "", $dir, $postfix, 0, 0)
    };

    ($dir: expr,$postfix: expr, $name: expr, $desc: expr) => {
        BelPin::new_p($name, $desc, $dir, $postfix, 0, 0)
    };
    ($dir: expr,$postfix: expr, $name: expr, $desc: expr, $rel_x: expr, $rel_y: expr) => {
        BelPin::new_p($name, $desc, $dir, $postfix, $rel_x, $rel_y)
    };
}

macro_rules! input_m {
    ($($rest:expr),*) =>
        ( def_pin_mapped!(PinDir::INPUT, $($rest),*) );
}

macro_rules! output_m {
    ($($rest:expr),*) =>
        ( def_pin_mapped!(PinDir::OUTPUT, $($rest),*) );
}

macro_rules! inout_m {
    ($($rest:expr),*) =>
        ( def_pin_mapped!(PinDir::INOUT, $($rest),*) );
}

macro_rules! def_pin_mapped {
    ($dir: expr, $postfix: expr, $name: expr) => {
        BelPin::new_p($name, "", $dir, $physpin, $postfix, 0, 0)
    };

    ($dir: expr,$postfix: expr, $name: expr, $physpin: expr, $desc: expr) => {
        BelPin::new_mapped($name, $desc, $dir, $physpin, $postfix, 0, 0)
    };
}

const Z_TO_CHAR: [char; 4] = ['A', 'B', 'C', 'D'];

impl Bel {
    pub fn make_oxide_ff(slice: usize, ff: usize) -> Bel {
        let ch = Z_TO_CHAR[slice];
        let postfix = format!("SLICE{}", ch);
        let pins = vec![
            input!(&postfix, "CLK", "FF clock"),
            input!(&postfix, "CE", "FF clock enable"),
            input!(&postfix, "LSR", "FF local set/reset"),
            input_m!(
                &postfix,
                "DI",
                &format!("DI{}", ff),
                "FF input from LUT/MUX output"
            ),
            input_m!(
                &postfix,
                "M",
                &format!("M{}", ff),
                "FF direct input from fabric M signal"
            ),
            output_m!(&postfix, "Q", &format!("Q{}", ff), "FF output"),
        ];
        Bel {
            name: format!("{}_FF{}", &postfix, ff),
            beltype: String::from("OXIDE_FF"),
            pins: pins,
            z: (slice << 3 | (ff + 2)) as u32,
        }
    }

    pub fn make_oxide_comb(slice: usize, lut: usize) -> Bel {
        let ch = Z_TO_CHAR[slice];
        let postfix = format!("SLICE{}", ch);
        let mut pins = vec![
            input_m!(&postfix, "A", &format!("A{}", lut), "LUT A input"),
            input_m!(&postfix, "B", &format!("B{}", lut), "LUT B input"),
            input_m!(&postfix, "C", &format!("C{}", lut), "LUT C input"),
            input_m!(&postfix, "D", &format!("D{}", lut), "LUT D input"),
            input_m!(
                &postfix,
                "FCI",
                if lut == 0 { "FCI" } else { "INT_CARRY" },
                "CCU2 fast carry input"
            ),
            output_m!(&postfix, "F", &format!("F{}", lut), "LUT/sum output"),
            output_m!(
                &postfix,
                "FCO",
                if lut == 1 { "FCO" } else { "INT_CARRY" },
                "CCU2 fast carry output"
            ),
        ];
        if lut == 0 {
            // MUX2 in LUT0 COMB only
            pins.append(&mut vec![
                input!(&postfix, "SEL", "MUX2 select input"),
                input!(&postfix, "F1", "input from second LUT to MUX2"),
                output_m!(&postfix, "OFX", "OFX0", "MUX2 output"),
            ]);
        }
        if slice == 0 || slice == 1 {
            // DPRAM in lower two SLICEs only
            pins.append(&mut vec![
                input!(&postfix, "WAD0", "LUTRAM write address 0 (from RAMW)"),
                input!(&postfix, "WAD1", "LUTRAM write address 1 (from RAMW)"),
                input!(&postfix, "WAD2", "LUTRAM write address 2 (from RAMW)"),
                input!(&postfix, "WAD3", "LUTRAM write address 3 (from RAMW)"),
                input_m!(
                    &postfix,
                    "WD",
                    &format!("WD{}", lut),
                    "LUTRAM write data (from RAMW)"
                ),
                input!(&postfix, "WCK", "LUTRAM write clock (from RAMW)"),
                input!(&postfix, "WRE", "LUTRAM write enable (from RAMW)"),
            ]);
        }
        Bel {
            name: format!("{}_LUT{}", &postfix, lut),
            beltype: String::from("OXIDE_COMB"),
            pins: pins,
            z: (slice << 3 | lut) as u32,
        }
    }

    pub fn make_oxide_ramw(slice: usize) -> Bel {
        assert_eq!(slice, 2);
        let ch = Z_TO_CHAR[slice];
        let postfix = format!("SLICE{}", ch);
        let pins = vec![
            input!(&postfix, "A0", "buffered to WADO3"),
            input!(&postfix, "A1", "buffered to WDO2"),
            input!(&postfix, "B0", "buffered to WADO1"),
            input!(&postfix, "B1", "buffered to WDO3"),
            input!(&postfix, "C0", "buffered to WADO2"),
            input!(&postfix, "C1", "buffered to WDO1"),
            input!(&postfix, "D0", "buffered to WADO0"),
            input!(&postfix, "D1", "buffered to WDO0"),
            input!(&postfix, "CLK", "buffered to WCKO"),
            input!(&postfix, "LSR", "buffered to WREO"),
            output!(&postfix, "WADO0", "LUTRAM write address 0 (to SLICEA/B)"),
            output!(&postfix, "WADO1", "LUTRAM write address 1 (to SLICEA/B)"),
            output!(&postfix, "WADO2", "LUTRAM write address 2 (to SLICEA/B)"),
            output!(&postfix, "WADO3", "LUTRAM write address 3 (to SLICEA/B)"),
            output!(&postfix, "WCKO", "LUTRAM write clock (to SLICEA/B)"),
            output!(&postfix, "WREO", "LUTRAM write enable (to SLICEA/B)"),
            output!(&postfix, "WDO0", "LUTRAM write data 0 (to SLICEA)"),
            output!(&postfix, "WDO1", "LUTRAM write data 1 (to SLICEA)"),
            output!(&postfix, "WDO2", "LUTRAM write data 2 (to SLICEB)"),
            output!(&postfix, "WDO3", "LUTRAM write data 3 (to SLICEB)"),
        ];
        Bel {
            name: format!("{}_RAMW", &postfix),
            beltype: String::from("RAMW"),
            pins: pins,
            z: (slice << 3 | 4) as u32,
        }
    }

    pub fn make_seio33(z: usize) -> Bel {
        let ch = Z_TO_CHAR[z];
        let postfix = format!("SEIO33_CORE_IO{}", ch);
        Bel {
            name: format!("PIO{}", ch),
            beltype: String::from("SEIO33_CORE"),
            pins: vec![
                inout_m!(&postfix, "B", "PAD", "top level pad signal"),
                input_m!(
                    &postfix,
                    "I",
                    "PADDO",
                    "output buffer input from fabric/IOLOGIC"
                ),
                input_m!(
                    &postfix,
                    "T",
                    "PADDT",
                    "output buffer tristate (0=driven, 1=hi-z)"
                ),
                output_m!(
                    &postfix,
                    "O",
                    "PADDI",
                    "input buffer output to fabric/IOLOGIC"
                ),
                input!(&postfix, "I3CRESEN", "I3C strong pullup enable"),
                input!(&postfix, "I3CWKPU", "I3C weak pullup enable"),
            ],
            z: z as u32,
        }
    }

    pub fn make_seio18(z: usize) -> Bel {
        let ch = Z_TO_CHAR[z];
        let postfix = format!("SEIO18_CORE_IO{}", ch);
        Bel {
            name: format!("PIO{}", ch),
            beltype: String::from("SEIO18_CORE"),
            pins: vec![
                inout_m!(&postfix, "B", "IOPAD", "top level pad signal"),
                input_m!(
                    &postfix,
                    "I",
                    "PADDO",
                    "output buffer input from fabric/IOLOGIC"
                ),
                input_m!(
                    &postfix,
                    "T",
                    "PADDT",
                    "output buffer tristate (0=driven, 1=hi-z)"
                ),
                output_m!(
                    &postfix,
                    "O",
                    "PADDI",
                    "input buffer output to fabric/IOLOGIC"
                ),
                input!(&postfix, "DOLP", "DPHY LP mode output buffer input"),
                output!(&postfix, "INLP", "DPHY LP mode input buffer output"),
                output!(&postfix, "INADC", "analog signal out to ADC"),
            ],
            z: z as u32,
        }
    }

    pub fn make_osc_core() -> Bel {
        let postfix = format!("OSC_CORE");
        Bel {
            name: format!("OSC_CORE"),
            beltype: String::from("OSC_CORE"),
            pins: vec![
                output!(&postfix, "HFCLKOUT", "HF oscillator output", 0, 1),
                output!(&postfix, "LFCLKOUT", "LF oscillator output", 0, 1),
                input!(&postfix, "HFOUTEN", "HF oscillator output enable", 0, 1),
            ],
            z: 0,
        }
    }
}

pub fn get_tile_bels(tiletype: &str) -> Vec<Bel> {
    match tiletype {
        "PLC" => (0..4)
            .map(|slice| {
                let mut bels = vec![
                    Bel::make_oxide_comb(slice, 0),
                    Bel::make_oxide_comb(slice, 1),
                    Bel::make_oxide_ff(slice, 0),
                    Bel::make_oxide_ff(slice, 1),
                ];
                if slice == 2 {
                    bels.push(Bel::make_oxide_ramw(slice));
                }
                bels
            })
            .flatten()
            .collect(),
        "SYSIO_B0_0" | "SYSIO_B1_0" | "SYSIO_B1_0_C" | "SYSIO_B2_0" | "SYSIO_B2_0_C"
        | "SYSIO_B6_0" | "SYSIO_B6_0_C" | "SYSIO_B7_0" | "SYSIO_B7_0_C" => {
            (0..2).map(Bel::make_seio33).collect()
        }
        "SYSIO_B3_0" | "SYSIO_B4_0" | "SYSIO_B5_0" => (0..2).map(Bel::make_seio18).collect(),
        "EFB_1_OSC" => vec![Bel::make_osc_core()],
        _ => vec![],
    }
}
<|endoftext|>


<commit_before>use std::mem;
use libc::size_t;
use num_complex::Complex;
use fnv::FnvHashMap;

use super::PI;
use sitevector::SiteVector;
use blochfunc::{BlochFunc, BlochFuncSet};

// c compatible complex type for export to numpy at the end
#[repr(C)]
pub struct CComplex<T> {
    pub re: T,
    pub im: T
}

impl<T> CComplex<T> {
    pub fn from_num_complex(c: Complex<T>) -> CComplex<T> {
        let re = c.re;
        let im = c.im;
        CComplex { re, im }
    }
}

#[repr(C)]
pub struct Vector<T> {
    ptr: *const T,
    len: size_t
}

impl<T> Vector<T> {
    fn new(ptr: *const T, len: size_t) -> Vector<T> {
        Vector { ptr, len }
    }
}

#[repr(C)]
pub struct CoordMatrix<T> {
    data: Vector<T>,
    col: Vector<u32>,
    row: Vector<u32>
}

impl<T> CoordMatrix<T> {
    pub fn new(mut data: Vec<T>, mut col: Vec<u32>, mut row: Vec<u32>) -> CoordMatrix<T> {
        let data_ptr = data.as_mut_ptr();
        let data_len = data.len() as size_t;

        let col_ptr = col.as_mut_ptr();
        let col_len = col.len() as size_t;

        let row_ptr = row.as_mut_ptr();
        let row_len = row.len() as size_t;

        mem::forget(data);
        mem::forget(col);
        mem::forget(row);
        let data = Vector::new(data_ptr, data_len);
        let col = Vector::new(col_ptr, col_len);
        let row = Vector::new(row_ptr, row_len);
        CoordMatrix { data, col, row }
    }
}

pub struct InteractingSites {
    pub first: (Vec<u32>, Vec<u32>),
    pub second: (Vec<u32>, Vec<u32>),
    pub third: (Vec<u32>, Vec<u32>)
}

pub fn translate_x(dec: u32, nx: u32, ny: u32) -> u32 {
    let n = (0..ny).map(|x| x * nx).collect::<Vec<u32>>();
    let s = n.iter()
        .map(|&x| dec % 2_u32.pow(x + nx) / 2_u32.pow(x))
        .map(|x| (x * 2_u32) % 2_u32.pow(nx) + x / 2_u32.pow(nx - 1));

    n.iter().map(|&x| 2_u32.pow(x))
        .zip(s)
        .map(|(a, b)| a * b)  // basically a dot product here
        .sum()
}

pub fn translate_y(dec: u32, nx: u32, ny: u32) -> u32 {
    let xdim = 2_u32.pow(nx);
    let pred_totdim = 2_u32.pow(nx * (ny - 1));
    let tail = dec % xdim;
    dec / xdim + tail * pred_totdim
}

pub fn exchange_spin_flips(dec: u32, s1: u32, s2: u32) -> (bool, bool) {
    let updown = (dec | s1 == dec) && (dec | s2 != dec);
    let downup = (dec | s1 != dec) && (dec | s2 == dec);
    (updown, downup)
}

pub fn repeated_spins(dec: u32, s1: u32, s2: u32) -> (bool, bool) {
    let upup = (dec | s1 == dec) && (dec | s2 == dec);
    let downdown = (dec | s1 != dec) && (dec | s2 != dec);
    (upup, downdown)
}

pub fn generate_bonds(nx: u32, ny: u32) -> Vec<Vec<Vec<SiteVector>>> {
    let n = nx * ny;
    let mut vec = SiteVector::new((0, 0), nx, ny);
    let mut bonds_by_range = vec![Vec::new(); 3];
    for _ in 0..n {
        let nearest_neighbor = vec.nearest_neighboring_sites(false);
        let second_neighbor = vec.second_neighboring_sites(false);
        let third_neighbor = vec.third_neighboring_sites(false);
        let neighbors = vec![nearest_neighbor, second_neighbor, third_neighbor];
        for (leap, bonds) in bonds_by_range.iter_mut().enumerate() {
            for n in neighbors[leap].iter() {
                let mut bond = vec![vec.clone(), n.clone()];
                bond.sort();
                bonds.push(bond);
            }
        }
        vec = vec.next_site();
    }
    bonds_by_range
}

pub fn gamma(nx: u32, ny: u32, s1: u32, s2: u32) -> Complex<f64> {
    let m = (s1 as f64).log2().round() as u32;
    let n = (s2 as f64).log2().round() as u32;
    let vec1 = SiteVector::from_index(m, nx, ny);
    let vec2 = SiteVector::from_index(n, nx, ny );
    let ang = vec1.angle_with(&vec2);

    Complex::from_polar(&1.0, &ang)
}

pub fn interacting_sites(nx: u32, ny: u32, l: u32) -> (Vec<u32>, Vec<u32>) {
    let mut site1 = Vec::new();
    let mut site2 = Vec::new();
    let bonds_by_range = generate_bonds(nx, ny);
    let bonds = &bonds_by_range[l as usize - 1];
    for bond in bonds.iter() {
        site1.push(bond[0].lattice_index());
        site2.push(bond[1].lattice_index());
    }

    (
    site1.into_iter().map(|x| 2_u32.pow(x)).collect::<Vec<_>>(),
    site2.into_iter().map(|x| 2_u32.pow(x)).collect::<Vec<_>>(),
    )
}

pub fn bloch_states<'a>(nx: u32, ny: u32, kx: u32, ky: u32) -> BlochFuncSet {
    let n = nx * ny;
    let mut sieve = vec![true; 2_usize.pow(n)];
    let mut bfuncs: Vec<BlochFunc> = Vec::new();
    let phase = |i, j| {
        let r = 1.;
        let ang1 = 2. * PI * (i * kx) as f64 / nx as f64;
        let ang2 = 2. * PI * (j * ky) as f64 / ny as f64;
        Complex::from_polar(&r, &(ang1 + ang2))
    };

    for dec in 0..2_usize.pow(n) {
        if sieve[dec]
        {   // if the corresponding entry of dec in "sieve" is not false,
            // we find all translations of dec and put them in a BlochFunc
            // then mark all corresponding entries in "sieve" as false.

            // "decs" is a hashtable that holds vectors whose entries
            // correspond to Bloch function constituent configurations which
            // are mapped to single decimals that represent the leading states.
            let mut decs: FnvHashMap<u32, Complex<f64>> = FnvHashMap::default();
            // "new_dec" represents the configuration we are currently iterating
            // over.
            let mut new_dec = dec as u32;
            for j in 0..ny {
                for i in 0..nx {
                    sieve[new_dec as usize] = false;
                    let new_p = match decs.get(&new_dec) {
                        Some(&p) => p + phase(i, j),
                        None     => phase(i, j)
                    };
                    decs.insert(new_dec, new_p);
                    new_dec = translate_x(new_dec, nx, ny);
                }
                new_dec = translate_y(new_dec, nx, ny);
            }

            let lead = dec as u32;
            let norm = decs.values()
                .into_iter()
                .map(|&x| x.norm_sqr())
                .sum::<f64>()
                .sqrt();

            if norm > 1e-8 {
                let mut bfunc = BlochFunc { lead, decs, norm };
                bfuncs.push(bfunc);
            }
        }
    }

    let mut table = BlochFuncSet::create(bfuncs);
    table.sort();
    table
}

pub fn find_leading_state<'a>(dec: u32,
                           hashtable: &'a FnvHashMap<&u32, &BlochFunc>
                           ) -> Option<(&'a BlochFunc, Complex<f64>)> {

    match hashtable.get(&dec) {
        None => None,
        Some(&cntd_state) => match cntd_state.decs.get(&dec) {
            None     => None,
            Some(&p) => {
                let mut phase = p.conj();
                phase /= phase.norm();
                Some((cntd_state, phase))
            },
        }
    }
}

pub fn gen_ind_dec_conv_dicts<'a>(bfuncs: &'a BlochFuncSet)
    -> (FnvHashMap<u32, &'a BlochFunc>, FnvHashMap<u32, u32>) {
    let dec = bfuncs.iter()
        .map(|x| x.lead)
        .collect::<Vec<_>>();
    let nstates = dec.len();
    let inds = (0..nstates as u32).collect::<Vec<u32>>();

    // build the hashtables
    let dec_to_ind = dec.into_iter()
        .zip(inds.clone())
        .collect::<FnvHashMap<u32, u32>>();
    let ind_to_dec = inds.into_iter()
        .zip(bfuncs.iter())
        .collect::<FnvHashMap<u32, &BlochFunc>>();

    (ind_to_dec, dec_to_ind)
}

pub fn coeff(orig_state: &BlochFunc, cntd_state: &BlochFunc) -> f64 {
    cntd_state.norm / orig_state.norm
}
<commit_msg>Minor code clean up<commit_after>use std::mem;
use libc::size_t;
use num_complex::Complex;
use fnv::FnvHashMap;

use super::PI;
use sitevector::SiteVector;
use blochfunc::{BlochFunc, BlochFuncSet};

// c compatible complex type for export to numpy at the end
#[repr(C)]
pub struct CComplex<T> {
    pub re: T,
    pub im: T
}

impl<T> CComplex<T> {
    pub fn from_num_complex(c: Complex<T>) -> CComplex<T> {
        let re = c.re;
        let im = c.im;
        CComplex { re, im }
    }
}

#[repr(C)]
pub struct Vector<T> {
    ptr: *const T,
    len: size_t
}

impl<T> Vector<T> {
    fn new(ptr: *const T, len: size_t) -> Vector<T> {
        Vector { ptr, len }
    }
}

#[repr(C)]
pub struct CoordMatrix<T> {
    data: Vector<T>,
    col: Vector<u32>,
    row: Vector<u32>
}

impl<T> CoordMatrix<T> {
    pub fn new(mut data: Vec<T>, mut col: Vec<u32>, mut row: Vec<u32>) -> CoordMatrix<T> {
        let data_ptr = data.as_mut_ptr();
        let data_len = data.len() as size_t;

        let col_ptr = col.as_mut_ptr();
        let col_len = col.len() as size_t;

        let row_ptr = row.as_mut_ptr();
        let row_len = row.len() as size_t;

        mem::forget(data);
        mem::forget(col);
        mem::forget(row);
        let data = Vector::new(data_ptr, data_len);
        let col = Vector::new(col_ptr, col_len);
        let row = Vector::new(row_ptr, row_len);
        CoordMatrix { data, col, row }
    }
}

pub struct InteractingSites {
    pub first: (Vec<u32>, Vec<u32>),
    pub second: (Vec<u32>, Vec<u32>),
    pub third: (Vec<u32>, Vec<u32>)
}

pub fn translate_x(dec: u32, nx: u32, ny: u32) -> u32 {
    let n = (0..ny).map(|x| x * nx).collect::<Vec<u32>>();
    let s = n.iter()
        .map(|&x| dec % 2_u32.pow(x + nx) / 2_u32.pow(x))
        .map(|x| (x * 2_u32) % 2_u32.pow(nx) + x / 2_u32.pow(nx - 1));

    n.iter().map(|&x| 2_u32.pow(x))
        .zip(s)
        .map(|(a, b)| a * b)  // basically a dot product here
        .sum()
}

pub fn translate_y(dec: u32, nx: u32, ny: u32) -> u32 {
    let xdim = 2_u32.pow(nx);
    let pred_totdim = 2_u32.pow(nx * (ny - 1));
    let tail = dec % xdim;
    dec / xdim + tail * pred_totdim
}

pub fn exchange_spin_flips(dec: u32, s1: u32, s2: u32) -> (bool, bool) {
    let updown = (dec | s1 == dec) && (dec | s2 != dec);
    let downup = (dec | s1 != dec) && (dec | s2 == dec);
    (updown, downup)
}

pub fn repeated_spins(dec: u32, s1: u32, s2: u32) -> (bool, bool) {
    let upup = (dec | s1 == dec) && (dec | s2 == dec);
    let downdown = (dec | s1 != dec) && (dec | s2 != dec);
    (upup, downdown)
}

pub fn generate_bonds(nx: u32, ny: u32) -> Vec<Vec<Vec<SiteVector>>> {
    let n = nx * ny;
    let mut vec = SiteVector::new((0, 0), nx, ny);
    let mut bonds_by_range = vec![Vec::new(); 3];
    for _ in 0..n {
        let nearest_neighbor = vec.nearest_neighboring_sites(false);
        let second_neighbor = vec.second_neighboring_sites(false);
        let third_neighbor = vec.third_neighboring_sites(false);
        let neighbors = vec![nearest_neighbor, second_neighbor, third_neighbor];
        for (leap, bonds) in bonds_by_range.iter_mut().enumerate() {
            for n in neighbors[leap].iter() {
                let mut bond = vec![vec.clone(), n.clone()];
                bond.sort();
                bonds.push(bond);
            }
        }
        vec = vec.next_site();
    }
    bonds_by_range
}

pub fn gamma(nx: u32, ny: u32, s1: u32, s2: u32) -> Complex<f64> {
    let m = (s1 as f64).log2().round() as u32;
    let n = (s2 as f64).log2().round() as u32;
    let vec1 = SiteVector::from_index(m, nx, ny);
    let vec2 = SiteVector::from_index(n, nx, ny );
    let ang = vec1.angle_with(&vec2);

    Complex::from_polar(&1.0, &ang)
}

pub fn interacting_sites(nx: u32, ny: u32, l: u32) -> (Vec<u32>, Vec<u32>) {
    let mut site1 = Vec::new();
    let mut site2 = Vec::new();
    let bonds_by_range = generate_bonds(nx, ny);
    let bonds = &bonds_by_range[l as usize - 1];
    for bond in bonds.iter() {
        site1.push(bond[0].lattice_index());
        site2.push(bond[1].lattice_index());
    }

    (
    site1.into_iter().map(|x| 2_u32.pow(x)).collect::<Vec<_>>(),
    site2.into_iter().map(|x| 2_u32.pow(x)).collect::<Vec<_>>(),
    )
}

pub fn bloch_states<'a>(nx: u32, ny: u32, kx: u32, ky: u32) -> BlochFuncSet {
    let n = nx * ny;
    let mut sieve = vec![true; 2_usize.pow(n)];
    let mut bfuncs: Vec<BlochFunc> = Vec::new();
    let phase = |i, j| {
        let r = 1.;
        let ang1 = 2. * PI * (i * kx) as f64 / nx as f64;
        let ang2 = 2. * PI * (j * ky) as f64 / ny as f64;
        Complex::from_polar(&r, &(ang1 + ang2))
    };

    for dec in 0..2_usize.pow(n) {
        if sieve[dec]
        {   // if the corresponding entry of dec in "sieve" is not false,
            // we find all translations of dec and put them in a BlochFunc
            // then mark all corresponding entries in "sieve" as false.

            // "decs" is a hashtable that holds vectors whose entries
            // correspond to Bloch function constituent configurations which
            // are mapped to single decimals that represent the leading states.
            let mut decs: FnvHashMap<u32, Complex<f64>> = FnvHashMap::default();
            // "new_dec" represents the configuration we are currently iterating
            // over.
            let mut new_dec = dec as u32;
            for j in 0..ny {
                for i in 0..nx {
                    sieve[new_dec as usize] = false;
                    let new_p = match decs.get(&new_dec) {
                        Some(&p) => p + phase(i, j),
                        None     => phase(i, j)
                    };
                    decs.insert(new_dec, new_p);
                    new_dec = translate_x(new_dec, nx, ny);
                }
                new_dec = translate_y(new_dec, nx, ny);
            }

            let lead = dec as u32;
            let norm = decs.values()
                .into_iter()
                .map(|&x| x.norm_sqr())
                .sum::<f64>()
                .sqrt();

            if norm > 1e-8 {
                let mut bfunc = BlochFunc { lead, decs, norm };
                bfuncs.push(bfunc);
            }
        }
    }

    let mut table = BlochFuncSet::create(bfuncs);
    table.sort();
    table
}

pub fn find_leading_state<'a>(dec: u32,
                              hashtable: &'a FnvHashMap<&u32, &BlochFunc>
                              ) -> Option<(&'a BlochFunc, Complex<f64>)> {

    match hashtable.get(&dec) {
        None => None,
        Some(&cntd_state) => match cntd_state.decs.get(&dec) {
            None     => None,
            Some(&p) => {
                let mut phase = p.conj();
                phase /= phase.norm();
                Some((cntd_state, phase))
            },
        }
    }
}

pub fn gen_ind_dec_conv_dicts<'a>(bfuncs: &'a BlochFuncSet)
    -> (FnvHashMap<u32, &'a BlochFunc>, FnvHashMap<u32, u32>) {
    let dec = bfuncs.iter()
        .map(|x| x.lead)
        .collect::<Vec<_>>();
    let nstates = dec.len();
    let inds = (0..nstates as u32).collect::<Vec<u32>>();

    // build the hashtables
    let dec_to_ind = dec.into_iter()
        .zip(inds.clone())
        .collect::<FnvHashMap<u32, u32>>();
    let ind_to_dec = inds.into_iter()
        .zip(bfuncs.iter())
        .collect::<FnvHashMap<u32, &BlochFunc>>();

    (ind_to_dec, dec_to_ind)
}

pub fn coeff(orig_state: &BlochFunc, cntd_state: &BlochFunc) -> f64 {
    cntd_state.norm / orig_state.norm
}
<|endoftext|>


<commit_before>use llvm_sys::execution_engine::*;
use super::*;
use std::mem;

pub struct ExecutionEngine {
    pub ptr: LLVMExecutionEngineRef,
}

impl ExecutionEngine {
    pub fn create_for_module(module: Module) -> Result<ExecutionEngine, &'static str> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();

            let res = LLVMCreateExecutionEngineForModule(&mut ee, module.ptr, &mut out);

            if res == 0 { // no error message was set
                Ok(ExecutionEngine{
                    ptr: ee
                })
            } else {
                Err(c_str_to_str!(out as *const i8))
            }
        }
    }
}
<commit_msg>Impl Drop for ExecutionEngine<commit_after>use llvm_sys::execution_engine::*;
use super::*;
use std::mem;

pub struct ExecutionEngine {
    pub ptr: LLVMExecutionEngineRef,
}

impl ExecutionEngine {
    pub fn create_for_module(module: Module) -> Result<ExecutionEngine, &'static str> {
        unsafe {
            let mut ee = mem::uninitialized();
            let mut out = mem::zeroed();

            let res = LLVMCreateExecutionEngineForModule(&mut ee, module.ptr, &mut out);

            if res == 0 { // no error message was set
                Ok(ExecutionEngine{
                    ptr: ee
                })
            } else {
                Err(c_str_to_str!(out as *const i8))
            }
        }
    }
impl Drop for ExecutionEngine {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeExecutionEngine(self.ptr);
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    fs::File,
    io::{BufRead, BufReader},
    thread,
    time::Duration,
};

use anyhow::Context;
use cargo_registry_index::{Repository, RepositoryConfig};
use diesel::prelude::*;
use indicatif::{ProgressBar, ProgressIterator, ProgressStyle};

use crate::{
    admin::dialoguer,
    db,
    schema::{crates, dependencies, versions},
};

#[derive(clap::Parser, Debug, Copy, Clone)]
#[clap(
    name = "git-import",
    about = "Import missing fields from git into the database"
)]
pub struct Opts {
    /// Time in milliseconds to sleep between crate updates to reduce database load.
    #[clap(long)]
    delay: u64,
}

pub fn run(opts: Opts) -> anyhow::Result<()> {
    let conn = db::oneoff_connection().unwrap();
    println!("fetching git repo");
    let config = RepositoryConfig::from_environment();
    let repo = Repository::open(&config)?;
    repo.reset_head()?;
    println!("HEAD is at {}", repo.head_oid()?);
    let files = repo.get_files_modified_since(None)?;
    println!("found {} crates", files.len());
    if !dialoguer::confirm("continue?") {
        return Ok(());
    }

    let pb = ProgressBar::new(files.len() as u64);
    pb.set_style(ProgressStyle::with_template("{bar:60} ({pos}/{len}, ETA {eta})").unwrap());

    for file in files.iter().progress_with(pb.clone()) {
        thread::sleep(Duration::from_millis(opts.delay));
        let crate_name = file.file_name().unwrap().to_str().unwrap();
        let path = repo.index_file(crate_name);
        if !path.exists() {
            pb.suspend(|| println!("skipping {}", path.display()));
            continue;
        }
        let file = File::open(path)?;
        let reader = BufReader::new(file);
        let result = conn.transaction(|| -> anyhow::Result<()> {
            for line in reader.lines() {
                let krate: cargo_registry_index::Crate = serde_json::from_str(&line?)?;
                import_data(&conn, &krate).with_context(|| {
                    format!("Failed to update crate {}#{}", krate.name, krate.vers)
                })?
            }
            Ok(())
        });
        if let Err(err) = result {
            pb.suspend(|| println!("{}", err));
        }
    }
    println!("completed");

    Ok(())
}

fn import_data(conn: &PgConnection, krate: &cargo_registry_index::Crate) -> anyhow::Result<()> {
    let version_id: i32 = versions::table
        .inner_join(crates::table)
        .filter(crates::name.eq(&krate.name))
        .filter(versions::num.eq(&krate.vers))
        .select(versions::id)
        .first(conn)
        .with_context(|| {
            format!(
                "Failed to find {}#{} in the database",
                krate.name, krate.vers
            )
        })?;

    // Update the `checksum` and `links` fields.
    diesel::update(versions::table)
        .set((
            versions::checksum.eq(&krate.cksum),
            versions::links.eq(&krate.links),
        ))
        .filter(versions::id.eq(version_id))
        .filter(versions::checksum.is_null())
        .filter(versions::links.is_null())
        .execute(conn)
        .with_context(|| {
            format!(
                "Failed to update checksum/links of {}#{} (id: {version_id})",
                krate.name, krate.vers
            )
        })?;

    // Check if any of this crate's dependencies have a missing explicit_name.
    if krate.deps.iter().any(|d| d.package.is_some())
        && dependencies::table
            .filter(dependencies::version_id.eq(version_id))
            .filter(dependencies::explicit_name.is_not_null())
            .count()
            .get_result::<i64>(conn)?
            == 0
    {
        for dep in &krate.deps {
            if let Some(package) = &dep.package {
                // This is a little tricky because there can be two identical deps in the
                // database. The only difference in git is the field we're trying to
                // fill (explicit_name). Using `first` here & filtering out existing `explicit_name`
                // entries ensure that we assign one explicit_name to each dep.

                let id: i32 = dependencies::table
                    .inner_join(crates::table)
                    .filter(dependencies::explicit_name.is_null())
                    .filter(dependencies::version_id.eq(version_id))
                    .filter(dependencies::req.eq(&dep.req))
                    .filter(dependencies::features.eq(&dep.features))
                    .filter(dependencies::optional.eq(&dep.optional))
                    .filter(dependencies::default_features.eq(&dep.default_features))
                    .filter(dependencies::target.is_not_distinct_from(&dep.target))
                    .filter(dependencies::kind.eq(dep.kind.map(|k| k as i32).unwrap_or_default()))
                    .filter(crates::name.eq(package))
                    .select(dependencies::id)
                    .first(conn)
                    .with_context(|| {
                        format!(
                            "{}#{}: Failed to find matching dependency: {} {}",
                            krate.name, krate.vers, package, dep.req
                        )
                    })?;

                diesel::update(dependencies::table)
                    .set(dependencies::explicit_name.eq(&dep.name))
                    .filter(dependencies::id.eq(id))
                    .execute(conn)
                    .with_context(|| {
                        format!(
                            "Failed to update `explicit_name` of dependency {id} to {}",
                            dep.name
                        )
                    })?;
            }
        }
    }
    Ok(())
}
<commit_msg>admin::git_import: Print errors including stacktraces<commit_after>use std::{
    fs::File,
    io::{BufRead, BufReader},
    thread,
    time::Duration,
};

use anyhow::Context;
use cargo_registry_index::{Repository, RepositoryConfig};
use diesel::prelude::*;
use indicatif::{ProgressBar, ProgressIterator, ProgressStyle};

use crate::{
    admin::dialoguer,
    db,
    schema::{crates, dependencies, versions},
};

#[derive(clap::Parser, Debug, Copy, Clone)]
#[clap(
    name = "git-import",
    about = "Import missing fields from git into the database"
)]
pub struct Opts {
    /// Time in milliseconds to sleep between crate updates to reduce database load.
    #[clap(long)]
    delay: u64,
}

pub fn run(opts: Opts) -> anyhow::Result<()> {
    let conn = db::oneoff_connection().unwrap();
    println!("fetching git repo");
    let config = RepositoryConfig::from_environment();
    let repo = Repository::open(&config)?;
    repo.reset_head()?;
    println!("HEAD is at {}", repo.head_oid()?);
    let files = repo.get_files_modified_since(None)?;
    println!("found {} crates", files.len());
    if !dialoguer::confirm("continue?") {
        return Ok(());
    }

    let pb = ProgressBar::new(files.len() as u64);
    pb.set_style(ProgressStyle::with_template("{bar:60} ({pos}/{len}, ETA {eta})").unwrap());

    for file in files.iter().progress_with(pb.clone()) {
        thread::sleep(Duration::from_millis(opts.delay));
        let crate_name = file.file_name().unwrap().to_str().unwrap();
        let path = repo.index_file(crate_name);
        if !path.exists() {
            pb.suspend(|| println!("skipping {}", path.display()));
            continue;
        }
        let file = File::open(path)?;
        let reader = BufReader::new(file);
        let result = conn.transaction(|| -> anyhow::Result<()> {
            for line in reader.lines() {
                let krate: cargo_registry_index::Crate = serde_json::from_str(&line?)?;
                import_data(&conn, &krate).with_context(|| {
                    format!("Failed to update crate {}#{}", krate.name, krate.vers)
                })?
            }
            Ok(())
        });
        if let Err(err) = result {
            pb.suspend(|| println!("{err:?}"));
        }
    }
    println!("completed");

    Ok(())
}

fn import_data(conn: &PgConnection, krate: &cargo_registry_index::Crate) -> anyhow::Result<()> {
    let version_id: i32 = versions::table
        .inner_join(crates::table)
        .filter(crates::name.eq(&krate.name))
        .filter(versions::num.eq(&krate.vers))
        .select(versions::id)
        .first(conn)
        .with_context(|| {
            format!(
                "Failed to find {}#{} in the database",
                krate.name, krate.vers
            )
        })?;

    // Update the `checksum` and `links` fields.
    diesel::update(versions::table)
        .set((
            versions::checksum.eq(&krate.cksum),
            versions::links.eq(&krate.links),
        ))
        .filter(versions::id.eq(version_id))
        .filter(versions::checksum.is_null())
        .filter(versions::links.is_null())
        .execute(conn)
        .with_context(|| {
            format!(
                "Failed to update checksum/links of {}#{} (id: {version_id})",
                krate.name, krate.vers
            )
        })?;

    // Check if any of this crate's dependencies have a missing explicit_name.
    if krate.deps.iter().any(|d| d.package.is_some())
        && dependencies::table
            .filter(dependencies::version_id.eq(version_id))
            .filter(dependencies::explicit_name.is_not_null())
            .count()
            .get_result::<i64>(conn)?
            == 0
    {
        for dep in &krate.deps {
            if let Some(package) = &dep.package {
                // This is a little tricky because there can be two identical deps in the
                // database. The only difference in git is the field we're trying to
                // fill (explicit_name). Using `first` here & filtering out existing `explicit_name`
                // entries ensure that we assign one explicit_name to each dep.

                let id: i32 = dependencies::table
                    .inner_join(crates::table)
                    .filter(dependencies::explicit_name.is_null())
                    .filter(dependencies::version_id.eq(version_id))
                    .filter(dependencies::req.eq(&dep.req))
                    .filter(dependencies::features.eq(&dep.features))
                    .filter(dependencies::optional.eq(&dep.optional))
                    .filter(dependencies::default_features.eq(&dep.default_features))
                    .filter(dependencies::target.is_not_distinct_from(&dep.target))
                    .filter(dependencies::kind.eq(dep.kind.map(|k| k as i32).unwrap_or_default()))
                    .filter(crates::name.eq(package))
                    .select(dependencies::id)
                    .first(conn)
                    .with_context(|| {
                        format!(
                            "{}#{}: Failed to find matching dependency: {} {}",
                            krate.name, krate.vers, package, dep.req
                        )
                    })?;

                diesel::update(dependencies::table)
                    .set(dependencies::explicit_name.eq(&dep.name))
                    .filter(dependencies::id.eq(id))
                    .execute(conn)
                    .with_context(|| {
                        format!(
                            "Failed to update `explicit_name` of dependency {id} to {}",
                            dep.name
                        )
                    })?;
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! A window implemented by SDL2 back-end.

// External crates.
use sdl2;

// Local crate.
use game_window::{
    GameWindow,
};
use event;
use game_window_settings::GameWindowSettings;
use keyboard;
use mouse;
use gl;

/// A widow implemented by SDL2 back-end.
pub struct GameWindowSDL2 {
    window: sdl2::video::Window,
    // Allow dead code because this keeps track of the OpenGL context.
    // Will be released on drop.
    #[allow(dead_code)]
    context: sdl2::video::GLContext,
    settings: GameWindowSettings,
    should_close: bool,
    last_pressed_key: Option<sdl2::keycode::KeyCode>,
}

impl GameWindow for GameWindowSDL2 {
    fn new(settings: GameWindowSettings) -> GameWindowSDL2 {
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMajorVersion, 3);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMinorVersion, 3);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextProfileMask, sdl2::video::ll::SDL_GL_CONTEXT_PROFILE_CORE as int);

        let window = sdl2::video::Window::new(
            settings.title.as_slice(),
            sdl2::video::PosCentered,
            sdl2::video::PosCentered,
            settings.size[0] as int,
            settings.size[1] as int,
            sdl2::video::OpenGL
        ).unwrap();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers
        gl::load_with(|s| sdl2::video::gl_get_proc_address(s));

        GameWindowSDL2 {
            window: window,
            context: context,
            settings: settings,
            should_close: false,
            last_pressed_key: None,
        }
    }

    fn get_settings<'a>(&'a self) -> &'a GameWindowSettings {
        &self.settings
    }

    fn should_close(&self) -> bool {
        self.should_close
    }

    fn swap_buffers(&self) {
        self.window.gl_swap_window();
    }

    fn poll_event(&mut self) -> event::Event {
        match sdl2::event::poll_event() {
            sdl2::event::QuitEvent(_) => { self.should_close = true; },
            sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                match self.last_pressed_key {
                    Some(x) if x == key => return event::NoEvent,
                    _ => {},
                };
                self.last_pressed_key = Some(key);

                if self.settings.exit_on_esc
                && key == sdl2::keycode::EscapeKey {
                    self.should_close = true;
                } else {
                    return event::KeyPressed(sdl2_map_key(key));
                }
            },
            sdl2::event::KeyUpEvent(_, _, key, _, _) => {
                // Reset the last pressed key.
                self.last_pressed_key = match self.last_pressed_key {
                    Some(x) if x == key => None,
                    x => x,
                };

                return event::KeyReleased(sdl2_map_key(key));
            },
            sdl2::event::MouseButtonDownEvent(_, _, _, button, _, _) => {
                return event::MouseButtonPressed(sdl2_map_mouse(button));
            },
            sdl2::event::MouseButtonUpEvent(_, _, _, button, _, _) => {
                return event::MouseButtonReleased(sdl2_map_mouse(button));
            },
            sdl2::event::MouseMotionEvent(_, _, _, _, x, y, dx, dy) => {
                return event::MouseMoved(
                    x as f64,
                    y as f64,
                    Some((dx as f64, dy as f64))
                );
            },
            _ => {},
        }
        event::NoEvent
    }
}

fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use std::num::FromPrimitive;
    FromPrimitive::from_u64(keycode.code() as u64).unwrap()
}

fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> mouse::Button {
    match button {
        sdl2::mouse::LeftMouse => mouse::Left,
        sdl2::mouse::RightMouse => mouse::Right,
        sdl2::mouse::MiddleMouse => mouse::Middle,
        sdl2::mouse::X1Mouse => mouse::X1,
        sdl2::mouse::X2Mouse => mouse::X2,
        sdl2::mouse::UnknownMouse(_) => mouse::Unknown,
    }
}

<commit_msg>Upgraded to latest gl-rs<commit_after>//! A window implemented by SDL2 back-end.

// External crates.
use std;
use sdl2;

// Local crate.
use game_window::{
    GameWindow,
};
use event;
use game_window_settings::GameWindowSettings;
use keyboard;
use mouse;
use gl;

/// A widow implemented by SDL2 back-end.
pub struct GameWindowSDL2 {
    window: sdl2::video::Window,
    // Allow dead code because this keeps track of the OpenGL context.
    // Will be released on drop.
    #[allow(dead_code)]
    context: sdl2::video::GLContext,
    settings: GameWindowSettings,
    should_close: bool,
    last_pressed_key: Option<sdl2::keycode::KeyCode>,
}

impl GameWindow for GameWindowSDL2 {
    fn new(settings: GameWindowSettings) -> GameWindowSDL2 {
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMajorVersion, 3);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMinorVersion, 3);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextProfileMask, sdl2::video::ll::SDL_GL_CONTEXT_PROFILE_CORE as int);

        let window = sdl2::video::Window::new(
            settings.title.as_slice(),
            sdl2::video::PosCentered,
            sdl2::video::PosCentered,
            settings.size[0] as int,
            settings.size[1] as int,
            sdl2::video::OpenGL
        ).unwrap();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers
        gl::load_with(|s| unsafe {
            std::mem::transmute(sdl2::video::gl_get_proc_address(s))
        });

        GameWindowSDL2 {
            window: window,
            context: context,
            settings: settings,
            should_close: false,
            last_pressed_key: None,
        }
    }

    fn get_settings<'a>(&'a self) -> &'a GameWindowSettings {
        &self.settings
    }

    fn should_close(&self) -> bool {
        self.should_close
    }

    fn swap_buffers(&self) {
        self.window.gl_swap_window();
    }

    fn poll_event(&mut self) -> event::Event {
        match sdl2::event::poll_event() {
            sdl2::event::QuitEvent(_) => { self.should_close = true; },
            sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                match self.last_pressed_key {
                    Some(x) if x == key => return event::NoEvent,
                    _ => {},
                };
                self.last_pressed_key = Some(key);

                if self.settings.exit_on_esc
                && key == sdl2::keycode::EscapeKey {
                    self.should_close = true;
                } else {
                    return event::KeyPressed(sdl2_map_key(key));
                }
            },
            sdl2::event::KeyUpEvent(_, _, key, _, _) => {
                // Reset the last pressed key.
                self.last_pressed_key = match self.last_pressed_key {
                    Some(x) if x == key => None,
                    x => x,
                };

                return event::KeyReleased(sdl2_map_key(key));
            },
            sdl2::event::MouseButtonDownEvent(_, _, _, button, _, _) => {
                return event::MouseButtonPressed(sdl2_map_mouse(button));
            },
            sdl2::event::MouseButtonUpEvent(_, _, _, button, _, _) => {
                return event::MouseButtonReleased(sdl2_map_mouse(button));
            },
            sdl2::event::MouseMotionEvent(_, _, _, _, x, y, dx, dy) => {
                return event::MouseMoved(
                    x as f64,
                    y as f64,
                    Some((dx as f64, dy as f64))
                );
            },
            _ => {},
        }
        event::NoEvent
    }
}

fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use std::num::FromPrimitive;
    FromPrimitive::from_u64(keycode.code() as u64).unwrap()
}

fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> mouse::Button {
    match button {
        sdl2::mouse::LeftMouse => mouse::Left,
        sdl2::mouse::RightMouse => mouse::Right,
        sdl2::mouse::MiddleMouse => mouse::Middle,
        sdl2::mouse::X1Mouse => mouse::X1,
        sdl2::mouse::X2Mouse => mouse::X2,
        sdl2::mouse::UnknownMouse(_) => mouse::Unknown,
    }
}

<|endoftext|>


<commit_before>//! # MPEG-2 Program Streams (PS)
//!
//! This is the container format used at the top-level of a `*.sub` file.

use nom::IResult;
use std::fmt;

use errors::*;
use super::clock::{Clock, clock_and_ext};
use super::pes;

/// A parsed [MPEG-2 Program Stream header][MPEG-PS] (MPEG-PS).
///
/// [MPEG-PS]: https://en.wikipedia.org/wiki/MPEG_program_stream
#[derive(Debug, PartialEq, Eq)]
pub struct Header {
    /// The System Clock Reference (SCR) and SCR extension field.
    pub scr: Clock,
    /// The bit rate, in units of 50 bytes per second.
    pub bit_rate: u32,
}

impl fmt::Display for Header {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[PS packet @ {}, {} kbps]", self.scr, (self.bit_rate*50*8)/1024)
    }
}

/// Parse a Program Stream header.
named!(pub header<Header>,
    do_parse!(
        // Sync bytes.
        tag!(&[0x00, 0x00, 0x01, 0xba]) >>
        // 10-byte header.
        header: bits!(
            do_parse!(
                // MPEG-2 version tag.
                tag_bits!(u8, 2, 0b01) >>
                // System Clock Reference.
                scr: call!(clock_and_ext) >>
                // Bit rate.
                bit_rate: take_bits!(u32, 22) >>
                // Marker bits.
                tag_bits!(u8, 2, 0b11) >>
                // Reserved.
                take_bits!(u8, 5) >>
                // Number of bytes of stuffing.
                stuffing_length: take_bits!(usize, 3) >>
                // Stuffing bytes.
                take_bits!(u32, stuffing_length * 8) >>
                (Header {
                    scr: scr,
                    bit_rate: bit_rate,
                })
            )
        ) >>
        (header)
    )
);

/// A [Packetized Elementary Stream][pes] packet with a Program Stream
/// header.
///
/// [pes]: http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
#[derive(Debug, PartialEq, Eq)]
pub struct PesPacket<'a> {
    pub ps_header: Header,
    pub pes_packet: pes::Packet<'a>,
}

/// Parse a Program Stream packet and the following PES packet.
named!(pub pes_packet<PesPacket>,
    do_parse!(
        ps_header: call!(header) >>
        pes_packet: call!(pes::packet) >>
        (PesPacket {
            ps_header: ps_header,
            pes_packet: pes_packet,
        })
    )
);

/// An iterator over all the PES packets in an MPEG-2 Program Stream.
pub struct PesPackets<'a> {
    /// The remaining input to parse.
    remaining: &'a [u8],
}

impl<'a> Iterator for PesPackets<'a> {
    type Item = Result<PesPacket<'a>>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            // Search for the start of a ProgramStream packet.
            let needle = &[0x00, 0x00, 0x01, 0xba];
            let start = self.remaining.windows(needle.len())
                .position(|window| needle == window);

            if let Some(start) = start {
                // We found the start, so try to parse it.
                self.remaining = &self.remaining[start..];
                match pes_packet(self.remaining) {
                    // We found a packet!
                    IResult::Done(remaining, packet) => {
                        self.remaining = remaining;
                        trace!("Decoded packet {:?}", &packet);
                        return Some(Ok(packet));
                    }
                    // We have only a partial packet, and we hit the end of our
                    // data.
                    IResult::Incomplete(needed) => {
                        self.remaining = &[];
                        warn!("Incomplete packet, need: {:?}", needed);
                        return Some(Err("Incomplete PES packet".into()));
                    }
                    // We got something that looked like a packet but
                    // wasn't parseable.  Log it and keep trying.
                    IResult::Error(err) => {
                        self.remaining = &self.remaining[needle.len()..];
                        debug!("Skipping packet {:?}", &err);
                    }
                }
            } else {
                // We didn't find the start of a packet.
                self.remaining = &[];
                trace!("Reached end of data");
                return None;
            }
        }
    }
}

/// Iterate over all the PES packets in an MPEG-2 Program Stream (or at
/// least those which contain subtitles).
pub fn pes_packets(input: &[u8]) -> PesPackets {
    PesPackets { remaining: input }
}
<commit_msg>[crash] Avoid debug-only left-shift overflow on corrupt input<commit_after>//! # MPEG-2 Program Streams (PS)
//!
//! This is the container format used at the top-level of a `*.sub` file.

use nom::IResult;
use std::fmt;

use errors::*;
use super::clock::{Clock, clock_and_ext};
use super::pes;

/// A parsed [MPEG-2 Program Stream header][MPEG-PS] (MPEG-PS).
///
/// [MPEG-PS]: https://en.wikipedia.org/wiki/MPEG_program_stream
#[derive(Debug, PartialEq, Eq)]
pub struct Header {
    /// The System Clock Reference (SCR) and SCR extension field.
    pub scr: Clock,
    /// The bit rate, in units of 50 bytes per second.
    pub bit_rate: u32,
}

impl fmt::Display for Header {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[PS packet @ {}, {} kbps]", self.scr, (self.bit_rate*50*8)/1024)
    }
}

/// Parse a Program Stream header.
named!(pub header<Header>,
    do_parse!(
        // Sync bytes.
        tag!(&[0x00, 0x00, 0x01, 0xba]) >>
        // 10-byte header.
        header: bits!(
            do_parse!(
                // MPEG-2 version tag.
                tag_bits!(u8, 2, 0b01) >>
                // System Clock Reference.
                scr: call!(clock_and_ext) >>
                // Bit rate.
                bit_rate: take_bits!(u32, 22) >>
                // Marker bits.
                tag_bits!(u8, 2, 0b11) >>
                // Reserved.
                take_bits!(u8, 5) >>
                // Number of bytes of stuffing.
                stuffing_length: take_bits!(usize, 3) >>
                // Stuffing bytes.  We just want to ignore these, but use a
                // large enough type to prevent overflow panics when
                // fuzzing.
                take_bits!(u64, stuffing_length * 8) >>
                (Header {
                    scr: scr,
                    bit_rate: bit_rate,
                })
            )
        ) >>
        (header)
    )
);

/// A [Packetized Elementary Stream][pes] packet with a Program Stream
/// header.
///
/// [pes]: http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
#[derive(Debug, PartialEq, Eq)]
pub struct PesPacket<'a> {
    pub ps_header: Header,
    pub pes_packet: pes::Packet<'a>,
}

/// Parse a Program Stream packet and the following PES packet.
named!(pub pes_packet<PesPacket>,
    do_parse!(
        ps_header: call!(header) >>
        pes_packet: call!(pes::packet) >>
        (PesPacket {
            ps_header: ps_header,
            pes_packet: pes_packet,
        })
    )
);

/// An iterator over all the PES packets in an MPEG-2 Program Stream.
pub struct PesPackets<'a> {
    /// The remaining input to parse.
    remaining: &'a [u8],
}

impl<'a> Iterator for PesPackets<'a> {
    type Item = Result<PesPacket<'a>>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            // Search for the start of a ProgramStream packet.
            let needle = &[0x00, 0x00, 0x01, 0xba];
            let start = self.remaining.windows(needle.len())
                .position(|window| needle == window);

            if let Some(start) = start {
                // We found the start, so try to parse it.
                self.remaining = &self.remaining[start..];
                match pes_packet(self.remaining) {
                    // We found a packet!
                    IResult::Done(remaining, packet) => {
                        self.remaining = remaining;
                        trace!("Decoded packet {:?}", &packet);
                        return Some(Ok(packet));
                    }
                    // We have only a partial packet, and we hit the end of our
                    // data.
                    IResult::Incomplete(needed) => {
                        self.remaining = &[];
                        warn!("Incomplete packet, need: {:?}", needed);
                        return Some(Err("Incomplete PES packet".into()));
                    }
                    // We got something that looked like a packet but
                    // wasn't parseable.  Log it and keep trying.
                    IResult::Error(err) => {
                        self.remaining = &self.remaining[needle.len()..];
                        debug!("Skipping packet {:?}", &err);
                    }
                }
            } else {
                // We didn't find the start of a packet.
                self.remaining = &[];
                trace!("Reached end of data");
                return None;
            }
        }
    }
}

/// Iterate over all the PES packets in an MPEG-2 Program Stream (or at
/// least those which contain subtitles).
pub fn pes_packets(input: &[u8]) -> PesPackets {
    PesPackets { remaining: input }
}
<|endoftext|>


<commit_before>use conrod::{CharacterCache, Circle, CommonBuilder, Frameable, FramedRectangle, IndexSlot, Mouse,
             Point, Positionable, Scalar, UpdateArgs, Widget, WidgetKind};
use conrod::color::{self, Color, Colorable};
use vecmath;

use Side;

#[derive(Debug)]
pub struct OthelloDisk<F> {
    common: CommonBuilder,
    maybe_react: Option<F>,
    style: Style,
    disk: Option<Side>,
    flow_disk: Option<Side>,
}

pub const KIND: WidgetKind = "OthelloDisk";

widget_style!{
    KIND;
    style Style {
        - white_color: Color { color::WHITE },
        - black_color: Color { color::BLACK },
        - background_color: Color { theme.background_color },
        - frame: Scalar { theme.frame_width },
        - frame_color: Color { theme.frame_color },
        - radius_ratio: Scalar { 0.5 }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct State {
    interaction: Interaction,
    circle_idx: IndexSlot,
    rectangle_idx: IndexSlot,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Interaction {
    Normal,
    Highlighted,
    Clicked,
}

impl Interaction {
    fn color(&self, color: Color) -> Color {
        match *self {
            Interaction::Normal => color,
            Interaction::Highlighted => color.highlighted(),
            Interaction::Clicked => color.clicked(),
        }
    }
}

fn get_new_interaction(is_over: bool, prev: Interaction, mouse: Mouse) -> Interaction {
    use conrod::MouseButtonPosition::{Down, Up};
    use self::Interaction::{Clicked, Highlighted, Normal};
    match (is_over, prev, mouse.left.position) {
        // LMB is down over the button. But the button wasn't Highlighted last
        // update. This means the user clicked somewhere outside the button and
        // moved over the button holding LMB down. We do nothing in this case.
        (true, Normal, Down) => Normal,

        // LMB is down over the button. The button was either Highlighted or Clicked
        // last update. If it was highlighted before, that means the user clicked
        // just now, and we transition to the Clicked state. If it was clicked
        // before, that means the user is still holding LMB down from a previous
        // click, in which case the state remains Clicked.
        (true, _, Down) => Clicked,

        // LMB is up. The mouse is hovering over the button. Regardless of what the
        // state was last update, the state should definitely be Highlighted now.
        (true, _, Up) => Highlighted,

        // LMB is down, the mouse is not over the button, but the previous state was
        // Clicked. That means the user clicked the button and then moved the mouse
        // outside the button while holding LMB down. The button stays Clicked.
        (false, Clicked, Down) => Clicked,

        // If none of the above applies, then nothing interesting is happening with
        // this button.
        _ => Normal,
    }
}

fn is_over_circ(circ_center: Point, mouse_point: Point, radius: Scalar) -> bool {
    let offset = vecmath::vec2_sub(mouse_point, circ_center);
    vecmath::vec2_len(offset) <= radius
}

impl<F> OthelloDisk<F> {
    pub fn new() -> Self {
        OthelloDisk {
            common: CommonBuilder::new(),
            maybe_react: None,
            style: Style::new(),
            disk: None,
            flow_disk: None,
        }
    }

    builder_methods!{
        pub react { maybe_react = Some(F) }
        pub white_color { style.white_color = Some(Color) }
        pub black_color { style.black_color = Some(Color) }
        pub background_color { style.background_color = Some(Color) }
        pub radius_ratio { style.radius_ratio = Some(Scalar) }
        pub disk { disk = Some(Side) }
        pub flow_disk { flow_disk = Some(Side) }
    }
}

impl<F> Widget for OthelloDisk<F> where F: FnMut()
{
    type State = State;
    type Style = Style;

    fn common(&self) -> &CommonBuilder {
        &self.common
    }

    fn common_mut(&mut self) -> &mut CommonBuilder {
        &mut self.common
    }

    fn unique_kind(&self) -> &'static str {
        KIND
    }

    fn init_state(&self) -> State {
        State {
            interaction: Interaction::Normal,
            circle_idx: IndexSlot::new(),
            rectangle_idx: IndexSlot::new(),
        }
    }

    fn style(&self) -> Style {
        self.style.clone()
    }

    fn update<C: CharacterCache>(mut self, args: UpdateArgs<Self, C>) {
        let UpdateArgs { idx, state, rect, mut ui, style, .. } = args;
        let (xy, dim) = rect.xy_dim();
        let maybe_mouse = ui.input().maybe_mouse.map(|mouse| mouse.relative_to(xy));
        let radius_ratio = style.radius_ratio(ui.theme());
        let radius = rect.w() * radius_ratio;

        let new_interaction = match (self.disk.is_none(), maybe_mouse) {
            (false, _) | (true, None) => Interaction::Normal,
            (true, Some(mouse)) => {
                let is_over = is_over_circ([0.0, 0.0], mouse.xy, radius);

                get_new_interaction(is_over, state.view().interaction, mouse)
            }
        };

        if let (Interaction::Clicked, Interaction::Highlighted) = (state.view().interaction,
                                                                   new_interaction) {
            if let Some(ref mut react) = self.maybe_react {
                react();
            }
        }

        match (state.view().interaction, new_interaction) {
            (Interaction::Highlighted, Interaction::Clicked) => {
                ui.capture_mouse();
            }
            (Interaction::Clicked, Interaction::Highlighted) |
            (Interaction::Clicked, Interaction::Normal) => {
                ui.uncapture_mouse();
            }
            _ => {}
        }

        if state.view().interaction != new_interaction {
            state.update(|state| state.interaction = new_interaction);
        }

        let rectangle_idx = state.view().rectangle_idx.get(&mut ui);
        let background_color = style.background_color(ui.theme());
        let frame = style.frame(ui.theme());
        let frame_color = style.frame_color(ui.theme());
        FramedRectangle::new(dim)
            .middle_of(idx)
            .graphics_for(idx)
            .color(background_color)
            .frame(frame)
            .frame_color(frame_color)
            .set(rectangle_idx, &mut ui);

        if let Some(disk) = self.disk {
            let circle_color = match disk {
                Side::Black => new_interaction.color(style.black_color(ui.theme())),
                Side::White => new_interaction.color(style.white_color(ui.theme())),
            };
            let circle_idx = state.view().circle_idx.get(&mut ui);
            Circle::fill(radius)
                .middle_of(idx)
                .graphics_for(idx)
                .color(circle_color)
                .set(circle_idx, &mut ui);
        }

        if let Some(flow_disk) = self.flow_disk {
            let circle_color = match flow_disk {
                                   Side::Black => {
                                       new_interaction.color(style.black_color(ui.theme()))
                                   }
                                   Side::White => {
                                       new_interaction.color(style.white_color(ui.theme()))
                                   }
                               }
                               .alpha(0.5);
            let circle_idx = state.view().circle_idx.get(&mut ui);
            Circle::fill(radius)
                .middle_of(idx)
                .graphics_for(idx)
                .color(circle_color)
                .set(circle_idx, &mut ui);
        }
    }
}

impl<F> Frameable for OthelloDisk<F> {
    fn frame(mut self, width: f64) -> Self {
        self.style.frame = Some(width);
        self
    }

    fn frame_color(mut self, color: Color) -> Self {
        self.style.frame_color = Some(color);
        self
    }
}
<commit_msg>small refactoring<commit_after>use conrod::{CharacterCache, Circle, CommonBuilder, Frameable, FramedRectangle, IndexSlot, Mouse,
             Point, Positionable, Scalar, UpdateArgs, Widget, WidgetKind};
use conrod::color::{self, Color, Colorable};
use vecmath;

use Side;

#[derive(Debug)]
pub struct OthelloDisk<F> {
    common: CommonBuilder,
    maybe_react: Option<F>,
    style: Style,
    disk: Option<Side>,
    flow_disk: Option<Side>,
}

pub const KIND: WidgetKind = "OthelloDisk";

widget_style!{
    KIND;
    style Style {
        - white_color: Color { color::WHITE },
        - black_color: Color { color::BLACK },
        - background_color: Color { theme.background_color },
        - frame: Scalar { theme.frame_width },
        - frame_color: Color { theme.frame_color },
        - radius_ratio: Scalar { 0.5 }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct State {
    interaction: Interaction,
    circle_idx: IndexSlot,
    rectangle_idx: IndexSlot,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Interaction {
    Normal,
    Highlighted,
    Clicked,
}

impl Interaction {
    fn color(&self, color: Color) -> Color {
        match *self {
            Interaction::Normal => color,
            Interaction::Highlighted => color.highlighted(),
            Interaction::Clicked => color.clicked(),
        }
    }
}

fn get_new_interaction(is_over: bool, prev: Interaction, mouse: Mouse) -> Interaction {
    use conrod::MouseButtonPosition::{Down, Up};
    use self::Interaction::{Clicked, Highlighted, Normal};
    match (is_over, prev, mouse.left.position) {
        // LMB is down over the button. But the button wasn't Highlighted last
        // update. This means the user clicked somewhere outside the button and
        // moved over the button holding LMB down. We do nothing in this case.
        (true, Normal, Down) => Normal,

        // LMB is down over the button. The button was either Highlighted or Clicked
        // last update. If it was highlighted before, that means the user clicked
        // just now, and we transition to the Clicked state. If it was clicked
        // before, that means the user is still holding LMB down from a previous
        // click, in which case the state remains Clicked.
        (true, _, Down) => Clicked,

        // LMB is up. The mouse is hovering over the button. Regardless of what the
        // state was last update, the state should definitely be Highlighted now.
        (true, _, Up) => Highlighted,

        // LMB is down, the mouse is not over the button, but the previous state was
        // Clicked. That means the user clicked the button and then moved the mouse
        // outside the button while holding LMB down. The button stays Clicked.
        (false, Clicked, Down) => Clicked,

        // If none of the above applies, then nothing interesting is happening with
        // this button.
        _ => Normal,
    }
}

fn is_over_circ(circ_center: Point, mouse_point: Point, radius: Scalar) -> bool {
    let offset = vecmath::vec2_sub(mouse_point, circ_center);
    vecmath::vec2_len(offset) <= radius
}

impl<F> OthelloDisk<F> {
    pub fn new() -> Self {
        OthelloDisk {
            common: CommonBuilder::new(),
            maybe_react: None,
            style: Style::new(),
            disk: None,
            flow_disk: None,
        }
    }

    builder_methods!{
        pub react { maybe_react = Some(F) }
        pub white_color { style.white_color = Some(Color) }
        pub black_color { style.black_color = Some(Color) }
        pub background_color { style.background_color = Some(Color) }
        pub radius_ratio { style.radius_ratio = Some(Scalar) }
        pub disk { disk = Some(Side) }
        pub flow_disk { flow_disk = Some(Side) }
    }
}

impl<F> Widget for OthelloDisk<F> where F: FnMut()
{
    type State = State;
    type Style = Style;

    fn common(&self) -> &CommonBuilder {
        &self.common
    }

    fn common_mut(&mut self) -> &mut CommonBuilder {
        &mut self.common
    }

    fn unique_kind(&self) -> &'static str {
        KIND
    }

    fn init_state(&self) -> State {
        State {
            interaction: Interaction::Normal,
            circle_idx: IndexSlot::new(),
            rectangle_idx: IndexSlot::new(),
        }
    }

    fn style(&self) -> Style {
        self.style.clone()
    }

    fn update<C: CharacterCache>(mut self, args: UpdateArgs<Self, C>) {
        let UpdateArgs { idx, state, rect, mut ui, style, .. } = args;
        let (xy, dim) = rect.xy_dim();
        let maybe_mouse = ui.input().maybe_mouse.map(|mouse| mouse.relative_to(xy));
        let radius_ratio = style.radius_ratio(ui.theme());
        let radius = rect.w() * radius_ratio;

        let new_interaction = match (self.disk.is_none(), maybe_mouse) {
            (false, _) | (true, None) => Interaction::Normal,
            (true, Some(mouse)) => {
                let is_over = is_over_circ([0.0, 0.0], mouse.xy, radius);

                get_new_interaction(is_over, state.view().interaction, mouse)
            }
        };

        if let (Interaction::Clicked, Interaction::Highlighted) = (state.view().interaction,
                                                                   new_interaction) {
            if let Some(ref mut react) = self.maybe_react {
                react();
            }
        }

        match (state.view().interaction, new_interaction) {
            (Interaction::Highlighted, Interaction::Clicked) => {
                ui.capture_mouse();
            }
            (Interaction::Clicked, Interaction::Highlighted) |
            (Interaction::Clicked, Interaction::Normal) => {
                ui.uncapture_mouse();
            }
            _ => {}
        }

        if state.view().interaction != new_interaction {
            state.update(|state| state.interaction = new_interaction);
        }

        let rectangle_idx = state.view().rectangle_idx.get(&mut ui);
        let background_color = style.background_color(ui.theme());
        let frame = style.frame(ui.theme());
        let frame_color = style.frame_color(ui.theme());
        FramedRectangle::new(dim)
            .middle_of(idx)
            .graphics_for(idx)
            .color(background_color)
            .frame(frame)
            .frame_color(frame_color)
            .set(rectangle_idx, &mut ui);

        let circle_param = if let Some(side) = self.disk {
            Some((side, None))
        } else if let Some(side) = self.flow_disk {
            Some((side, Some(0.5)))
        } else {
            None
        };

        if let Some((side, alpha)) = circle_param {
            let mut circle_color = match side {
                Side::Black => new_interaction.color(style.black_color(ui.theme())),
                Side::White => new_interaction.color(style.white_color(ui.theme())),
            };
            if let Some(alpha) = alpha {
                circle_color = circle_color.alpha(alpha);
            }

            let circle_idx = state.view().circle_idx.get(&mut ui);
            Circle::fill(radius)
                .middle_of(idx)
                .graphics_for(idx)
                .color(circle_color)
                .set(circle_idx, &mut ui);
        }
    }
}

impl<F> Frameable for OthelloDisk<F> {
    fn frame(mut self, width: f64) -> Self {
        self.style.frame = Some(width);
        self
    }

    fn frame_color(mut self, color: Color) -> Self {
        self.style.frame_color = Some(color);
        self
    }
}
<|endoftext|>


<commit_before>use env_logger::{Builder, Env};
use log::debug;
use test_harness::BeaconChainHarness;
use types::ChainSpec;

#[test]
fn it_can_build_on_genesis_block() {
    Builder::from_env(Env::default().default_filter_or("info")).init();

    let spec = ChainSpec::few_validators();
    let validator_count = 8;

    let mut harness = BeaconChainHarness::new(spec, validator_count as usize);

    harness.advance_chain_with_block();
}

#[test]
#[ignore]
fn it_can_produce_past_first_epoch_boundary() {
    Builder::from_env(Env::default().default_filter_or("info")).init();

    let spec = ChainSpec::few_validators();
    let validator_count = 8;

    debug!("Starting harness build...");

    let mut harness = BeaconChainHarness::new(spec, validator_count);

    debug!("Harness built, tests starting..");

    let blocks = harness.spec.epoch_length * 2 + 1;

    for i in 0..blocks {
        harness.advance_chain_with_block();
        debug!("Produced block {}/{}.", i + 1, blocks);
    }

    harness.run_fork_choice();

    let dump = harness.chain_dump().expect("Chain dump failed.");

    assert_eq!(dump.len() as u64, blocks + 1); // + 1 for genesis block.

    harness.dump_to_file("/tmp/chaindump.json".to_string(), &dump);
}
<commit_msg>Fix failing test<commit_after>use env_logger::{Builder, Env};
use log::debug;
use test_harness::BeaconChainHarness;
use types::ChainSpec;

#[test]
fn it_can_build_on_genesis_block() {
    Builder::from_env(Env::default().default_filter_or("info")).init();

    let spec = ChainSpec::few_validators();
    let validator_count = 8;

    let mut harness = BeaconChainHarness::new(spec, validator_count as usize);

    harness.advance_chain_with_block();
}

#[test]
#[ignore]
fn it_can_produce_past_first_epoch_boundary() {
    Builder::from_env(Env::default().default_filter_or("info")).init();

    let spec = ChainSpec::few_validators();
    let validator_count = 8;

    debug!("Starting harness build...");

    let mut harness = BeaconChainHarness::new(spec, validator_count);

    debug!("Harness built, tests starting..");

    let blocks = harness.spec.epoch_length * 2 + 1;

    for i in 0..blocks {
        harness.advance_chain_with_block();
        debug!("Produced block {}/{}.", i + 1, blocks);
    }

    harness.run_fork_choice();

    let dump = harness.chain_dump().expect("Chain dump failed.");

    assert_eq!(dump.len() as u64, blocks + 1); // + 1 for genesis block.
}
<|endoftext|>