<commit_before>use std::rc::Rc;

use widget::{Property, PropertyResult, Template, Widget};
use layout_object::{LayoutObject, ScrollLayoutObject};

/// `Offset` is used to move an widget along the x- and y-axis.
#[derive(Default, Clone, Copy)]
pub struct Offset(pub i32, pub i32);

pub struct ScrollViewer {
    pub child: Option<Rc<Widget>>,
    pub offset: Property<Offset>,
}

impl Default for ScrollViewer {
    fn default() -> ScrollViewer {
        ScrollViewer {
            child: None,
            offset: Property::new(Offset::default()),
        }
    }
}

impl Widget for ScrollViewer {
    fn template(&self) -> Template {
        print!("ScrollViewer -> ");
        if let Some(child) = &self.child {
            Template::Single(child.clone())
        } else {
            Template::Empty
        }
    }

    fn properties(&self) -> Vec<PropertyResult> {
        vec![self.offset.build()]
    }

    fn layout_object(&self) -> Box<LayoutObject> {
        Box::new(ScrollLayoutObject)
    }
}
<commit_msg>Update.<commit_after>use std::rc::Rc;

use widget::{Property, PropertyResult, Template, Widget};
use layout_object::{LayoutObject, ScrollLayoutObject};

/// `Offset` is used to move an widget along the x- and y-axis.
#[derive(Default, Clone, Copy)]
pub struct Offset(pub i32, pub i32);

/// This layout widget orders its children vertical.
pub struct ScrollViewer {
    pub child: Option<Rc<Widget>>,
    pub offset: Property<Offset>,
}

impl Default for ScrollViewer {
    fn default() -> ScrollViewer {
        ScrollViewer {
            child: None,
            offset: Property::new(Offset::default()),
        }
    }
}

impl Widget for ScrollViewer {
    fn template(&self) -> Template {
        print!("ScrollViewer -> ");
        if let Some(child) = &self.child {
            Template::Single(child.clone())
        } else {
            Template::Empty
        }
    }

    fn properties(&self) -> Vec<PropertyResult> {
        vec![self.offset.build()]
    }

    fn layout_object(&self) -> Box<LayoutObject> {
        Box::new(ScrollLayoutObject)
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Macros to make our custom address types require a lot less repetitive code.
#[macro_export]
macro_rules! Addr {
    (($size:ty) $(pub)* enum $name:ident $($tail:tt)*) => {
        Addr! { @impl $name, $size }
    };
    (($size:ty) $(pub)* struct $name:ident $($tail:tt)*) => {
        Addr! { @impl $name, $size }
    };
    (@impl $ty:ident, $size:ty) => {

        impl ::core::fmt::Debug for $ty {
            fn fmt(&self, f: &mut ::core::fmt::Formatter)
                  -> ::core::fmt::Result {
                write!(f, "{}({:#x})", stringify!($ty), self.0)
            }
        }

        impl ::core::fmt::Pointer for $ty {
            fn fmt(&self, f: &mut ::core::fmt::Formatter)
                  -> ::core::fmt::Result {
                write!(f, "{:#x}", self.0)
            }
        }

        impl ::core::convert::Into<$size> for $ty {
            #[inline] fn into(self) -> $size { self.0 }
        }

        impl ::core::convert::From<$size> for $ty {
            #[inline] fn from(n: $size) -> Self { $ty(n) }
        }

        impl<T> ::core::convert::From<*mut T> for $ty {
            #[inline] fn from(ptr: *mut T) -> Self { $ty(ptr as $size) }
        }

        impl<T> ::core::convert::From<*const T> for $ty {
            #[inline] fn from(ptr: *const T) -> Self { $ty(ptr as $size) }
        }

        impl ::core::ops::Deref for $ty {
            type Target = $size;
            #[inline] fn deref(&self) -> &Self::Target { &self.0 }
        }

        impl $ty {
            #[inline(always)]
            pub const fn as_mut_ptr<T>(&self) -> *mut T { self.0 as *mut _ }

            #[inline(always)]
            pub const fn as_ptr<T>(&self) -> *const T { self.0 as *const _ }

        }

        impl_ops! {
            Add, add, + for $ty, $size
            Sub, sub, - for $ty, $size
            Div, div, / for $ty, $size
            Mul, mul, * for $ty, $size
            Shl, shl, >> for $ty, $size
            Shr, shr, << for $ty, $size
            Rem, rem, % for $ty, $size
            BitAnd, bitand, & for $ty, $size
            BitOr, bitor, | for $ty, $size
            BitXor, bitxor, ^ for $ty, $size

        }

        impl_assign_ops! {
            AddAssign, add_assign, += for $ty, $size
            SubAssign, sub_assign, -= for $ty, $size
            DivAssign, div_assign, /= for $ty, $size
            MulAssign, mul_assign, *= for $ty, $size
            ShlAssign, shl_assign, >>= for $ty, $size
            ShrAssign, shr_assign, <<= for $ty, $size
            RemAssign, rem_assign, %= for $ty, $size
            BitAndAssign, bitand_assign, &= for $ty, $size
            BitOrAssign, bitor_assign, |= for $ty, $size
            BitXorAssign, bitxor_assign, ^= for $ty, $size
        }

        impl_fmt! {
            Binary for $ty
            Display for $ty
            Octal for $ty
            LowerHex for $ty
            UpperHex for $ty
        }

        impl Addr for $ty {
            type Repr = $size;

            #[inline] fn align_down(&self, align: Self::Repr) -> Self {
                use util::Align;
                $ty ( self.0.align_down(align) )
            }

            #[inline] fn align_up(&self, align: Self::Repr) -> Self {
                use util::Align;
                // assert!(align.is_page_aligned());
                $ty ( self.0.align_up(align) )
            }

            #[inline] fn is_page_aligned(&self) -> bool {
                **self % PAGE_SIZE as <Self as Addr>::Repr == 0 as <Self as Addr>::Repr
            }
        }

    }
}

macro_rules! impl_page_ops {
    ($($name:ident, $fun:ident, $op:tt for $ty:ident, $size:ty)*) => {$(
        impl ::core::ops::$name<$ty> for $ty {
            type Output = Self;

            #[inline] fn $fun(self, rhs: $ty) -> Self {
                expr!( $ty { number: expr!(self.number $op rhs.number) })
            }
        }
        impl ::core::ops::$name<$size> for $ty {
            type Output = $ty;

            #[inline] fn $fun(self, rhs: $size) -> Self {
                expr!($ty{ number: expr!(self.number $op rhs) })
            }
        }

        forward_ref_binop! {
            $name, $fun for $ty, $ty
        }
        forward_ref_binop! {
            $name, $fun for $ty, $size
        }
    )*}
}

macro_rules! impl_page_assign_ops {
    ($($name:ident, $fun:ident, $op:tt for $ty:ident, $size:ty)*) => {$(
        impl ::core::ops::$name<$ty> for $ty {

            #[inline] fn $fun(&mut self, rhs: $ty) {
                expr!(self.number $op rhs.number);
            }
        }
        impl ::core::ops::$name<$size> for $ty {

            #[inline] fn $fun(&mut self, rhs: $size) {
                expr!(self.number $op rhs);
            }
        }
    )*}
}

macro_rules! Page {
    (($addr:ty) $(pub)* struct $name:ident $($tail:tt)*) => {
        Page! { @impl $name, $addr }
    };
    (@impl $ty:ident, $addr:ty) => {

        impl Page for $ty {
            type Address = $addr;

            /// Create a new `Page` containing the given address.
            //  TODO: rewrite this as `up`/`down` using the page shift, instead.
            fn containing(addr: $addr) -> Self {
                use ::PAGE_SHIFT;
                assert!( *addr < 0x0000_8000_0000_0000 ||
                         *addr >= 0xffff_8000_0000_0000
                       , "invalid address: 0x{:x}", addr );
                $ty { number: *addr >> PAGE_SHIFT as <Self::Address as Addr>::Repr }
            }

            /// Return the start virtual address of this page
            #[inline]
            fn base(&self) -> $addr {
                Self::Address::from(
                    self.number << PAGE_SHIFT as <Self::Address as Addr>::Repr )
            }

            #[inline] fn number(&self) -> usize {
                self.number as usize
            }
        }

        // impl ::core::num::One for $ty {
        //     #[inline] fn one() -> Self {
        //         $ty { number:
        //             <<$addr as Addr>::Repr as ::core::num::One>::one()
        //         }
        //     }
        // }

        impl ::core::iter::Step for $ty {
            #[inline]
            fn step(&self, by: &Self) -> Option<Self> {
                self.number
                    .step(&by.number)
                    .map(|s| $ty { number: s})
            }

            #[inline]
            #[allow(trivial_numeric_casts)]
            fn steps_between(start: &$ty, end: &$ty, by: &$ty)
                            -> Option<usize> {
                use ::core::iter::Step;
                <<$addr as Addr>::Repr as Step>::steps_between( &start.number
                                                              , &end.number
                                                              , &by.number
                                                              )
            }

            #[inline]
            fn steps_between_by_one(start: &$ty, end: &$ty) -> Option<usize> {
                use ::core::iter::Step;
                <<$addr as Addr>::Repr as Step>::steps_between( &start.number
                                                              , &end.number
                                                              , &1
                                                              )
            }

            #[inline] fn sub_one(&self) -> Self { self - 1 }

            #[inline] fn add_one(&self) -> Self { self + 1 }

            #[inline] fn replace_one(&mut self) -> Self { unimplemented!() }

            #[inline] fn replace_zero(&mut self) -> Self { unimplemented!() }

            #[inline] fn is_negative(&self) -> bool { unimplemented!(); }

        }

        impl<A> ::core::convert::From<A> for $ty
        where <Self as Page>::Address: ::core::convert::From<A> {
            #[inline] fn from(addr: A) -> Self {
                $ty::containing(<Self as Page>::Address::from(addr))
            }
        }

        impl_page_ops! {
            Add, add, + for $ty, <<$ty as Page>::Address as Addr>::Repr
            Sub, sub, - for $ty, <<$ty as Page>::Address as Addr>::Repr
            Div, div, / for $ty, <<$ty as Page>::Address as Addr>::Repr
            Mul, mul, * for $ty, <<$ty as Page>::Address as Addr>::Repr
            Shl, shl, >> for $ty,<<$ty as Page>::Address as Addr>::Repr
            Shr, shr, << for $ty, <<$ty as Page>::Address as Addr>::Repr
            Rem, rem, % for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitAnd, bitand, & for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitOr, bitor, | for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitXor, bitxor, ^ for $ty, <<$ty as Page>::Address as Addr>::Repr

        }

        impl_page_assign_ops! {
            AddAssign, add_assign, += for $ty, <<$ty as Page>::Address as Addr>::Repr
            SubAssign, sub_assign, -= for $ty, <<$ty as Page>::Address as Addr>::Repr
            DivAssign, div_assign, /= for $ty, <<$ty as Page>::Address as Addr>::Repr
            MulAssign, mul_assign, *= for $ty, <<$ty as Page>::Address as Addr>::Repr
            ShlAssign, shl_assign, >>= for $ty, <<$ty as Page>::Address as Addr>::Repr
            ShrAssign, shr_assign, <<= for $ty, <<$ty as Page>::Address as Addr>::Repr
            RemAssign, rem_assign, %= for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitAndAssign, bitand_assign, &= for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitOrAssign, bitor_assign, |= for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitXorAssign, bitxor_assign, ^= for $ty, <<$ty as Page>::Address as Addr>::Repr
        }
    }
}
<commit_msg>feat(memory): add const constructor to {V, P}Addr<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Macros to make our custom address types require a lot less repetitive code.
#[macro_export]
macro_rules! Addr {
    (($size:ty) $(pub)* enum $name:ident $($tail:tt)*) => {
        Addr! { @impl $name, $size }
    };
    (($size:ty) $(pub)* struct $name:ident $($tail:tt)*) => {
        Addr! { @impl $name, $size }
    };
    (@impl $ty:ident, $size:ty) => {

        impl ::core::fmt::Debug for $ty {
            fn fmt(&self, f: &mut ::core::fmt::Formatter)
                  -> ::core::fmt::Result {
                write!(f, "{}({:#x})", stringify!($ty), self.0)
            }
        }

        impl ::core::fmt::Pointer for $ty {
            fn fmt(&self, f: &mut ::core::fmt::Formatter)
                  -> ::core::fmt::Result {
                write!(f, "{:#x}", self.0)
            }
        }

        impl ::core::convert::Into<$size> for $ty {
            #[inline] fn into(self) -> $size { self.0 }
        }

        impl ::core::convert::From<$size> for $ty {
            #[inline] fn from(n: $size) -> Self { $ty(n) }
        }

        impl<T> ::core::convert::From<*mut T> for $ty {
            #[inline] fn from(ptr: *mut T) -> Self { $ty(ptr as $size) }
        }

        impl<T> ::core::convert::From<*const T> for $ty {
            #[inline] fn from(ptr: *const T) -> Self { $ty(ptr as $size) }
        }

        impl ::core::ops::Deref for $ty {
            type Target = $size;
            #[inline] fn deref(&self) -> &Self::Target { &self.0 }
        }

        impl $ty {
            #[inline(always)]
            pub const fn as_mut_ptr<T>(&self) -> *mut T { self.0 as *mut _ }

            #[inline(always)]
            pub const fn as_ptr<T>(&self) -> *const T { self.0 as *const _ }

            #[inline(always)]
            pub const fn new(value: $size) -> Self { $ty(value) }

        }

        impl_ops! {
            Add, add, + for $ty, $size
            Sub, sub, - for $ty, $size
            Div, div, / for $ty, $size
            Mul, mul, * for $ty, $size
            Shl, shl, >> for $ty, $size
            Shr, shr, << for $ty, $size
            Rem, rem, % for $ty, $size
            BitAnd, bitand, & for $ty, $size
            BitOr, bitor, | for $ty, $size
            BitXor, bitxor, ^ for $ty, $size

        }

        impl_assign_ops! {
            AddAssign, add_assign, += for $ty, $size
            SubAssign, sub_assign, -= for $ty, $size
            DivAssign, div_assign, /= for $ty, $size
            MulAssign, mul_assign, *= for $ty, $size
            ShlAssign, shl_assign, >>= for $ty, $size
            ShrAssign, shr_assign, <<= for $ty, $size
            RemAssign, rem_assign, %= for $ty, $size
            BitAndAssign, bitand_assign, &= for $ty, $size
            BitOrAssign, bitor_assign, |= for $ty, $size
            BitXorAssign, bitxor_assign, ^= for $ty, $size
        }

        impl_fmt! {
            Binary for $ty
            Display for $ty
            Octal for $ty
            LowerHex for $ty
            UpperHex for $ty
        }

        impl Addr for $ty {
            type Repr = $size;

            #[inline] fn align_down(&self, align: Self::Repr) -> Self {
                use util::Align;
                $ty ( self.0.align_down(align) )
            }

            #[inline] fn align_up(&self, align: Self::Repr) -> Self {
                use util::Align;
                // assert!(align.is_page_aligned());
                $ty ( self.0.align_up(align) )
            }

            #[inline] fn is_page_aligned(&self) -> bool {
                **self % PAGE_SIZE as <Self as Addr>::Repr == 0 as <Self as Addr>::Repr
            }
        }

    }
}

macro_rules! impl_page_ops {
    ($($name:ident, $fun:ident, $op:tt for $ty:ident, $size:ty)*) => {$(
        impl ::core::ops::$name<$ty> for $ty {
            type Output = Self;

            #[inline] fn $fun(self, rhs: $ty) -> Self {
                expr!( $ty { number: expr!(self.number $op rhs.number) })
            }
        }
        impl ::core::ops::$name<$size> for $ty {
            type Output = $ty;

            #[inline] fn $fun(self, rhs: $size) -> Self {
                expr!($ty{ number: expr!(self.number $op rhs) })
            }
        }

        forward_ref_binop! {
            $name, $fun for $ty, $ty
        }
        forward_ref_binop! {
            $name, $fun for $ty, $size
        }
    )*}
}

macro_rules! impl_page_assign_ops {
    ($($name:ident, $fun:ident, $op:tt for $ty:ident, $size:ty)*) => {$(
        impl ::core::ops::$name<$ty> for $ty {

            #[inline] fn $fun(&mut self, rhs: $ty) {
                expr!(self.number $op rhs.number);
            }
        }
        impl ::core::ops::$name<$size> for $ty {

            #[inline] fn $fun(&mut self, rhs: $size) {
                expr!(self.number $op rhs);
            }
        }
    )*}
}

macro_rules! Page {
    (($addr:ty) $(pub)* struct $name:ident $($tail:tt)*) => {
        Page! { @impl $name, $addr }
    };
    (@impl $ty:ident, $addr:ty) => {

        impl Page for $ty {
            type Address = $addr;

            /// Create a new `Page` containing the given address.
            //  TODO: rewrite this as `up`/`down` using the page shift, instead.
            fn containing(addr: $addr) -> Self {
                use ::PAGE_SHIFT;
                assert!( *addr < 0x0000_8000_0000_0000 ||
                         *addr >= 0xffff_8000_0000_0000
                       , "invalid address: 0x{:x}", addr );
                $ty { number: *addr >> PAGE_SHIFT as <Self::Address as Addr>::Repr }
            }

            /// Return the start virtual address of this page
            #[inline]
            fn base(&self) -> $addr {
                Self::Address::from(
                    self.number << PAGE_SHIFT as <Self::Address as Addr>::Repr )
            }

            #[inline] fn number(&self) -> usize {
                self.number as usize
            }
        }

        // impl ::core::num::One for $ty {
        //     #[inline] fn one() -> Self {
        //         $ty { number:
        //             <<$addr as Addr>::Repr as ::core::num::One>::one()
        //         }
        //     }
        // }

        impl ::core::iter::Step for $ty {
            #[inline]
            fn step(&self, by: &Self) -> Option<Self> {
                self.number
                    .step(&by.number)
                    .map(|s| $ty { number: s})
            }

            #[inline]
            #[allow(trivial_numeric_casts)]
            fn steps_between(start: &$ty, end: &$ty, by: &$ty)
                            -> Option<usize> {
                use ::core::iter::Step;
                <<$addr as Addr>::Repr as Step>::steps_between( &start.number
                                                              , &end.number
                                                              , &by.number
                                                              )
            }

            #[inline]
            fn steps_between_by_one(start: &$ty, end: &$ty) -> Option<usize> {
                use ::core::iter::Step;
                <<$addr as Addr>::Repr as Step>::steps_between( &start.number
                                                              , &end.number
                                                              , &1
                                                              )
            }

            #[inline] fn sub_one(&self) -> Self { self - 1 }

            #[inline] fn add_one(&self) -> Self { self + 1 }

            #[inline] fn replace_one(&mut self) -> Self { unimplemented!() }

            #[inline] fn replace_zero(&mut self) -> Self { unimplemented!() }

            #[inline] fn is_negative(&self) -> bool { unimplemented!(); }

        }

        impl<A> ::core::convert::From<A> for $ty
        where <Self as Page>::Address: ::core::convert::From<A> {
            #[inline] fn from(addr: A) -> Self {
                $ty::containing(<Self as Page>::Address::from(addr))
            }
        }

        impl_page_ops! {
            Add, add, + for $ty, <<$ty as Page>::Address as Addr>::Repr
            Sub, sub, - for $ty, <<$ty as Page>::Address as Addr>::Repr
            Div, div, / for $ty, <<$ty as Page>::Address as Addr>::Repr
            Mul, mul, * for $ty, <<$ty as Page>::Address as Addr>::Repr
            Shl, shl, >> for $ty,<<$ty as Page>::Address as Addr>::Repr
            Shr, shr, << for $ty, <<$ty as Page>::Address as Addr>::Repr
            Rem, rem, % for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitAnd, bitand, & for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitOr, bitor, | for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitXor, bitxor, ^ for $ty, <<$ty as Page>::Address as Addr>::Repr

        }

        impl_page_assign_ops! {
            AddAssign, add_assign, += for $ty, <<$ty as Page>::Address as Addr>::Repr
            SubAssign, sub_assign, -= for $ty, <<$ty as Page>::Address as Addr>::Repr
            DivAssign, div_assign, /= for $ty, <<$ty as Page>::Address as Addr>::Repr
            MulAssign, mul_assign, *= for $ty, <<$ty as Page>::Address as Addr>::Repr
            ShlAssign, shl_assign, >>= for $ty, <<$ty as Page>::Address as Addr>::Repr
            ShrAssign, shr_assign, <<= for $ty, <<$ty as Page>::Address as Addr>::Repr
            RemAssign, rem_assign, %= for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitAndAssign, bitand_assign, &= for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitOrAssign, bitor_assign, |= for $ty, <<$ty as Page>::Address as Addr>::Repr
            BitXorAssign, bitxor_assign, ^= for $ty, <<$ty as Page>::Address as Addr>::Repr
        }
    }
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::{ensure, Result};
use erased_serde::Serialize;
use serialport::SerialPortType;
use std::any::Any;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::rc::Rc;
use std::time::Duration;

use crate::io::gpio::GpioPin;
use crate::io::spi::Target;
use crate::io::uart::{Uart, UartError};
use crate::transport::common::uart::SerialPortUart;
use crate::transport::{
    Capabilities, Capability, Transport, TransportError, TransportInterfaceType,
};
use crate::util::parse_int::ParseInt;
use crate::util::rom_detect::{RomDetect, RomKind};

pub mod gpio;
pub mod spi;
pub mod usb;

#[derive(Default)]
struct Inner {
    spi: Option<Rc<dyn Target>>,
    gpio: HashMap<String, Rc<dyn GpioPin>>,
    uart: HashMap<u32, Rc<dyn Uart>>,
}

pub struct CW310 {
    device: Rc<RefCell<usb::Backend>>,
    uart_override: Vec<String>,
    inner: RefCell<Inner>,
}

impl CW310 {
    // Pins needed for SPI on the CW310 board.
    const PIN_CLK: &'static str = "USB_SPI_SCK";
    const PIN_SDI: &'static str = "USB_SPI_COPI";
    const PIN_SDO: &'static str = "USB_SPI_CIPO";
    const PIN_CS: &'static str = "USB_SPI_CS";
    // Pins needed for reset & bootstrap on the CW310 board.
    const PIN_TRST: &'static str = "USB_A13";
    const PIN_SRST: &'static str = "USB_A14";
    const PIN_SW_STRAP0: &'static str = "USB_A15";
    const PIN_SW_STRAP1: &'static str = "USB_A16";
    const PIN_SW_STRAP2: &'static str = "USB_A17";
    const PIN_TAP_STRAP0: &'static str = "USB_A18";
    const PIN_TAP_STRAP1: &'static str = "USB_A19";

    pub fn new(
        usb_vid: Option<u16>,
        usb_pid: Option<u16>,
        usb_serial: Option<&str>,
        uart_override: &[&str],
    ) -> anyhow::Result<Self> {
        let board = CW310 {
            device: Rc::new(RefCell::new(usb::Backend::new(
                usb_vid, usb_pid, usb_serial,
            )?)),
            uart_override: uart_override.iter().map(|s| s.to_string()).collect(),
            inner: RefCell::default(),
        };
        board.init_pin_directions()?;
        board.init_pin_values()?;
        Ok(board)
    }

    // Initialize the IO direction of some basic pins on the board.
    fn init_pin_directions(&self) -> anyhow::Result<()> {
        let device = self.device.borrow();
        device.pin_set_output(Self::PIN_TRST, true)?;
        device.pin_set_output(Self::PIN_SRST, true)?;
        device.pin_set_output(Self::PIN_TAP_STRAP0, true)?;
        device.pin_set_output(Self::PIN_TAP_STRAP1, true)?;
        device.pin_set_output(Self::PIN_SW_STRAP0, true)?;
        device.pin_set_output(Self::PIN_SW_STRAP1, true)?;
        device.pin_set_output(Self::PIN_SW_STRAP2, true)?;
        Ok(())
    }

    // Initialize the values of the output pins on the board.
    fn init_pin_values(&self) -> anyhow::Result<()> {
        let device = self.device.borrow();
        device.pin_set_state(Self::PIN_TRST, true)?;
        device.pin_set_state(Self::PIN_SRST, true)?;
        device.pin_set_state(Self::PIN_TAP_STRAP0, false)?;
        device.pin_set_state(Self::PIN_TAP_STRAP1, true)?;
        device.pin_set_state(Self::PIN_SW_STRAP0, false)?;
        device.pin_set_state(Self::PIN_SW_STRAP1, false)?;
        device.pin_set_state(Self::PIN_SW_STRAP2, false)?;
        Ok(())
    }

    fn open_uart(&self, instance: u32) -> Result<SerialPortUart> {
        if self.uart_override.is_empty() {
            let usb = self.device.borrow();
            let serial_number = usb.get_serial_number();

            let mut ports = serialport::available_ports()
                .map_err(|e| UartError::EnumerationError(e.to_string()))?;
            ports.retain(|port| {
                if let SerialPortType::UsbPort(info) = &port.port_type {
                    if info.serial_number.as_deref() == Some(serial_number) {
                        return true;
                    }
                }
                false
            });
            // The CW board seems to have the last port connected as OpenTitan UART 0.
            // Reverse the sort order so the last port will be instance 0.
            ports.sort_by(|a, b| b.port_name.cmp(&a.port_name));

            let port = ports.get(instance as usize).ok_or_else(|| {
                TransportError::InvalidInstance(TransportInterfaceType::Uart, instance.to_string())
            })?;
            SerialPortUart::open(&port.port_name)
        } else {
            let instance = instance as usize;
            ensure!(
                instance < self.uart_override.len(),
                TransportError::InvalidInstance(TransportInterfaceType::Uart, instance.to_string())
            );
            SerialPortUart::open(&self.uart_override[instance])
        }
    }
}

impl Transport for CW310 {
    fn capabilities(&self) -> Result<Capabilities> {
        Ok(Capabilities::new(
            Capability::SPI | Capability::GPIO | Capability::UART,
        ))
    }

    fn uart(&self, instance: &str) -> Result<Rc<dyn Uart>> {
        let mut inner = self.inner.borrow_mut();
        let instance = u32::from_str(instance).ok().ok_or_else(|| {
            TransportError::InvalidInstance(TransportInterfaceType::Uart, instance.to_string())
        })?;
        let uart = match inner.uart.entry(instance) {
            Entry::Vacant(v) => {
                let u = v.insert(Rc::new(self.open_uart(instance)?));
                Rc::clone(u)
            }
            Entry::Occupied(o) => Rc::clone(o.get()),
        };
        Ok(uart)
    }

    fn gpio_pin(&self, pinname: &str) -> Result<Rc<dyn GpioPin>> {
        let mut inner = self.inner.borrow_mut();
        Ok(match inner.gpio.entry(pinname.to_string()) {
            Entry::Vacant(v) => {
                let u = v.insert(Rc::new(gpio::CW310GpioPin::open(
                    Rc::clone(&self.device),
                    pinname.to_string(),
                )?));
                Rc::clone(u)
            }
            Entry::Occupied(o) => Rc::clone(o.get()),
        })
    }

    fn spi(&self, instance: &str) -> Result<Rc<dyn Target>> {
        ensure!(
            instance == "0",
            TransportError::InvalidInstance(TransportInterfaceType::Spi, instance.to_string())
        );
        let mut inner = self.inner.borrow_mut();
        if inner.spi.is_none() {
            inner.spi = Some(Rc::new(spi::CW310Spi::open(Rc::clone(&self.device))?));
        }
        Ok(Rc::clone(inner.spi.as_ref().unwrap()))
    }

    fn dispatch(&self, action: &dyn Any) -> Result<Option<Box<dyn Serialize>>> {
        if let Some(fpga_program) = action.downcast_ref::<FpgaProgram>() {
            if fpga_program.bitstream.starts_with(b"__skip__") {
                log::info!("Skip loading the __skip__ bitstream.");
                return Ok(None);
            }
            if let Some(rom_kind) = &fpga_program.rom_kind {
                let mut rd = RomDetect::new(
                    *rom_kind,
                    &fpga_program.bitstream,
                    Some(fpga_program.rom_timeout),
                )?;
                // Open the console UART.
                let uart = self.uart("0")?;

                // Send a reset pulse so the ROM will print the FPGA version.
                let reset_pin = self.gpio_pin(Self::PIN_SRST)?;
                // Reset is active low, sleep, then drive high.
                reset_pin.write(false)?;
                std::thread::sleep(fpga_program.rom_reset_pulse);
                reset_pin.write(true)?;

                // Now read the uart until the ROM prints it's version.
                if rd.detect(&*uart)? {
                    log::info!("Already running the correct bitstream.  Skip loading bitstream.");
                    // If we're already running the right ROM+bitstream,
                    // then we can skip bootstrap.
                    return Ok(None);
                }
            }

            // Program the FPGA bitstream.
            let usb = self.device.borrow();
            usb.spi1_enable(false)?;
            usb.fpga_program(&fpga_program.bitstream)?;
            Ok(None)
        } else if let Some(_set_pll) = action.downcast_ref::<SetPll>() {
            const TARGET_FREQ: u32 = 100_000_000;
            let usb = self.device.borrow();
            usb.pll_enable(true)?;
            usb.pll_out_freq_set(1, TARGET_FREQ)?;
            usb.pll_out_freq_set(2, TARGET_FREQ)?;
            usb.pll_out_enable(0, false)?;
            usb.pll_out_enable(1, true)?;
            usb.pll_out_enable(2, false)?;
            usb.pll_write_defaults()?;
            Ok(None)
        } else {
            Err(TransportError::UnsupportedOperation.into())
        }
    }
}

/// Command for Transport::dispatch().
pub struct FpgaProgram {
    /// The bitstream content to load into the FPGA.
    pub bitstream: Vec<u8>,
    /// What type of ROM to expect.
    pub rom_kind: Option<RomKind>,
    /// How long of a reset pulse to send to the device.
    pub rom_reset_pulse: Duration,
    /// How long to wait for the ROM to print its type and version.
    pub rom_timeout: Duration,
}

/// Command for Transport::dispatch().
pub struct SetPll {}
<commit_msg>[ottool] Open the uart first<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::{ensure, Result};
use erased_serde::Serialize;
use serialport::SerialPortType;
use std::any::Any;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::rc::Rc;
use std::time::Duration;

use crate::io::gpio::GpioPin;
use crate::io::spi::Target;
use crate::io::uart::{Uart, UartError};
use crate::transport::common::uart::SerialPortUart;
use crate::transport::{
    Capabilities, Capability, Transport, TransportError, TransportInterfaceType,
};
use crate::util::parse_int::ParseInt;
use crate::util::rom_detect::{RomDetect, RomKind};

pub mod gpio;
pub mod spi;
pub mod usb;

#[derive(Default)]
struct Inner {
    spi: Option<Rc<dyn Target>>,
    gpio: HashMap<String, Rc<dyn GpioPin>>,
    uart: HashMap<u32, Rc<dyn Uart>>,
}

pub struct CW310 {
    device: Rc<RefCell<usb::Backend>>,
    uart_override: Vec<String>,
    inner: RefCell<Inner>,
}

impl CW310 {
    // Pins needed for SPI on the CW310 board.
    const PIN_CLK: &'static str = "USB_SPI_SCK";
    const PIN_SDI: &'static str = "USB_SPI_COPI";
    const PIN_SDO: &'static str = "USB_SPI_CIPO";
    const PIN_CS: &'static str = "USB_SPI_CS";
    // Pins needed for reset & bootstrap on the CW310 board.
    const PIN_TRST: &'static str = "USB_A13";
    const PIN_SRST: &'static str = "USB_A14";
    const PIN_SW_STRAP0: &'static str = "USB_A15";
    const PIN_SW_STRAP1: &'static str = "USB_A16";
    const PIN_SW_STRAP2: &'static str = "USB_A17";
    const PIN_TAP_STRAP0: &'static str = "USB_A18";
    const PIN_TAP_STRAP1: &'static str = "USB_A19";

    pub fn new(
        usb_vid: Option<u16>,
        usb_pid: Option<u16>,
        usb_serial: Option<&str>,
        uart_override: &[&str],
    ) -> anyhow::Result<Self> {
        let board = CW310 {
            device: Rc::new(RefCell::new(usb::Backend::new(
                usb_vid, usb_pid, usb_serial,
            )?)),
            uart_override: uart_override.iter().map(|s| s.to_string()).collect(),
            inner: RefCell::default(),
        };
        board.init_pin_directions()?;
        board.init_pin_values()?;
        Ok(board)
    }

    // Initialize the IO direction of some basic pins on the board.
    fn init_pin_directions(&self) -> anyhow::Result<()> {
        let device = self.device.borrow();
        device.pin_set_output(Self::PIN_TRST, true)?;
        device.pin_set_output(Self::PIN_SRST, true)?;
        device.pin_set_output(Self::PIN_TAP_STRAP0, true)?;
        device.pin_set_output(Self::PIN_TAP_STRAP1, true)?;
        device.pin_set_output(Self::PIN_SW_STRAP0, true)?;
        device.pin_set_output(Self::PIN_SW_STRAP1, true)?;
        device.pin_set_output(Self::PIN_SW_STRAP2, true)?;
        Ok(())
    }

    // Initialize the values of the output pins on the board.
    fn init_pin_values(&self) -> anyhow::Result<()> {
        let device = self.device.borrow();
        device.pin_set_state(Self::PIN_TRST, true)?;
        device.pin_set_state(Self::PIN_SRST, true)?;
        device.pin_set_state(Self::PIN_TAP_STRAP0, false)?;
        device.pin_set_state(Self::PIN_TAP_STRAP1, true)?;
        device.pin_set_state(Self::PIN_SW_STRAP0, false)?;
        device.pin_set_state(Self::PIN_SW_STRAP1, false)?;
        device.pin_set_state(Self::PIN_SW_STRAP2, false)?;
        Ok(())
    }

    fn open_uart(&self, instance: u32) -> Result<SerialPortUart> {
        if self.uart_override.is_empty() {
            let usb = self.device.borrow();
            let serial_number = usb.get_serial_number();

            let mut ports = serialport::available_ports()
                .map_err(|e| UartError::EnumerationError(e.to_string()))?;
            ports.retain(|port| {
                if let SerialPortType::UsbPort(info) = &port.port_type {
                    if info.serial_number.as_deref() == Some(serial_number) {
                        return true;
                    }
                }
                false
            });
            // The CW board seems to have the last port connected as OpenTitan UART 0.
            // Reverse the sort order so the last port will be instance 0.
            ports.sort_by(|a, b| b.port_name.cmp(&a.port_name));

            let port = ports.get(instance as usize).ok_or_else(|| {
                TransportError::InvalidInstance(TransportInterfaceType::Uart, instance.to_string())
            })?;
            SerialPortUart::open(&port.port_name)
        } else {
            let instance = instance as usize;
            ensure!(
                instance < self.uart_override.len(),
                TransportError::InvalidInstance(TransportInterfaceType::Uart, instance.to_string())
            );
            SerialPortUart::open(&self.uart_override[instance])
        }
    }
}

impl Transport for CW310 {
    fn capabilities(&self) -> Result<Capabilities> {
        Ok(Capabilities::new(
            Capability::SPI | Capability::GPIO | Capability::UART,
        ))
    }

    fn uart(&self, instance: &str) -> Result<Rc<dyn Uart>> {
        let mut inner = self.inner.borrow_mut();
        let instance = u32::from_str(instance).ok().ok_or_else(|| {
            TransportError::InvalidInstance(TransportInterfaceType::Uart, instance.to_string())
        })?;
        let uart = match inner.uart.entry(instance) {
            Entry::Vacant(v) => {
                let u = v.insert(Rc::new(self.open_uart(instance)?));
                Rc::clone(u)
            }
            Entry::Occupied(o) => Rc::clone(o.get()),
        };
        Ok(uart)
    }

    fn gpio_pin(&self, pinname: &str) -> Result<Rc<dyn GpioPin>> {
        let mut inner = self.inner.borrow_mut();
        Ok(match inner.gpio.entry(pinname.to_string()) {
            Entry::Vacant(v) => {
                let u = v.insert(Rc::new(gpio::CW310GpioPin::open(
                    Rc::clone(&self.device),
                    pinname.to_string(),
                )?));
                Rc::clone(u)
            }
            Entry::Occupied(o) => Rc::clone(o.get()),
        })
    }

    fn spi(&self, instance: &str) -> Result<Rc<dyn Target>> {
        ensure!(
            instance == "0",
            TransportError::InvalidInstance(TransportInterfaceType::Spi, instance.to_string())
        );
        let mut inner = self.inner.borrow_mut();
        if inner.spi.is_none() {
            inner.spi = Some(Rc::new(spi::CW310Spi::open(Rc::clone(&self.device))?));
        }
        Ok(Rc::clone(inner.spi.as_ref().unwrap()))
    }

    fn dispatch(&self, action: &dyn Any) -> Result<Option<Box<dyn Serialize>>> {
        if let Some(fpga_program) = action.downcast_ref::<FpgaProgram>() {
            // Open the console UART.  We do this first so we get the receiver
            // started and the uart buffering data for us.
            let uart = self.uart("0")?;
            if fpga_program.bitstream.starts_with(b"__skip__") {
                log::info!("Skip loading the __skip__ bitstream.");
                return Ok(None);
            }
            if let Some(rom_kind) = &fpga_program.rom_kind {
                let mut rd = RomDetect::new(
                    *rom_kind,
                    &fpga_program.bitstream,
                    Some(fpga_program.rom_timeout),
                )?;

                // Send a reset pulse so the ROM will print the FPGA version.
                let reset_pin = self.gpio_pin(Self::PIN_SRST)?;
                // Reset is active low, sleep, then drive high.
                reset_pin.write(false)?;
                std::thread::sleep(fpga_program.rom_reset_pulse);
                reset_pin.write(true)?;

                // Now read the uart until the ROM prints it's version.
                if rd.detect(&*uart)? {
                    log::info!("Already running the correct bitstream.  Skip loading bitstream.");
                    // If we're already running the right ROM+bitstream,
                    // then we can skip bootstrap.
                    return Ok(None);
                }
            }

            // Program the FPGA bitstream.
            let usb = self.device.borrow();
            usb.spi1_enable(false)?;
            usb.fpga_program(&fpga_program.bitstream)?;
            Ok(None)
        } else if let Some(_set_pll) = action.downcast_ref::<SetPll>() {
            const TARGET_FREQ: u32 = 100_000_000;
            let usb = self.device.borrow();
            usb.pll_enable(true)?;
            usb.pll_out_freq_set(1, TARGET_FREQ)?;
            usb.pll_out_freq_set(2, TARGET_FREQ)?;
            usb.pll_out_enable(0, false)?;
            usb.pll_out_enable(1, true)?;
            usb.pll_out_enable(2, false)?;
            usb.pll_write_defaults()?;
            Ok(None)
        } else {
            Err(TransportError::UnsupportedOperation.into())
        }
    }
}

/// Command for Transport::dispatch().
pub struct FpgaProgram {
    /// The bitstream content to load into the FPGA.
    pub bitstream: Vec<u8>,
    /// What type of ROM to expect.
    pub rom_kind: Option<RomKind>,
    /// How long of a reset pulse to send to the device.
    pub rom_reset_pulse: Duration,
    /// How long to wait for the ROM to print its type and version.
    pub rom_timeout: Duration,
}

/// Command for Transport::dispatch().
pub struct SetPll {}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use frame_builder::FrameBuilder;
use prim_store::{BorderPrimitiveCpu, BorderPrimitiveGpu, PrimitiveContainer};
use tiling::PrimitiveFlags;
use util::pack_as_float;
use webrender_traits::{BorderSide, BorderStyle, BorderWidths, ColorF, NormalBorder};
use webrender_traits::{ClipId, ClipRegion, LayerPoint, LayerRect, LayerSize};

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BorderCornerKind {
    None,
    Solid,
    Clip,
    Unhandled,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BorderEdgeKind {
    None,
    Solid,
    Unhandled,
}

pub trait NormalBorderHelpers {
    fn get_corner(&self,
                  edge0: &BorderSide,
                  width0: f32,
                  edge1: &BorderSide,
                  width1: f32,
                  radius: &LayerSize) -> BorderCornerKind;

    fn get_edge(&self,
                edge: &BorderSide,
                width: f32) -> (BorderEdgeKind, f32);
}

impl NormalBorderHelpers for NormalBorder {
    fn get_corner(&self,
                  edge0: &BorderSide,
                  width0: f32,
                  edge1: &BorderSide,
                  width1: f32,
                  radius: &LayerSize) -> BorderCornerKind {
        // If either width is zero, a corner isn't formed.
        if width0 == 0.0 || width1 == 0.0 {
            return BorderCornerKind::None;
        }

        // If both edges are transparent, no corner is formed.
        if edge0.color.a == 0.0 && edge1.color.a == 0.0 {
            return BorderCornerKind::None;
        }

        match (edge0.style, edge1.style) {
            // If either edge is none or hidden, no corner is needed.
            (BorderStyle::None, _) | (_, BorderStyle::None) => BorderCornerKind::None,
            (BorderStyle::Hidden, _) | (_, BorderStyle::Hidden) => BorderCornerKind::None,

            // If both borders are solid, we can draw them with a simple rectangle if
            // both the colors match and there is no radius.
            (BorderStyle::Solid, BorderStyle::Solid) => {
                if edge0.color == edge1.color && radius.width == 0.0 && radius.height == 0.0 {
                    BorderCornerKind::Solid
                } else {
                    BorderCornerKind::Clip
                }
            }

            // Assume complex for these cases.
            // TODO(gw): There are some cases in here that can be handled with a fast path.
            // For example, with inset/outset borders, two of the four corners are solid.
            (BorderStyle::Dotted, _) | (_, BorderStyle::Dotted) => BorderCornerKind::Unhandled,
            (BorderStyle::Dashed, _) | (_, BorderStyle::Dashed) => BorderCornerKind::Unhandled,
            (BorderStyle::Double, _) | (_, BorderStyle::Double) => BorderCornerKind::Unhandled,
            (BorderStyle::Groove, _) | (_, BorderStyle::Groove) => BorderCornerKind::Unhandled,
            (BorderStyle::Ridge, _) | (_, BorderStyle::Ridge) => BorderCornerKind::Unhandled,
            (BorderStyle::Outset, _) | (_, BorderStyle::Outset) => BorderCornerKind::Unhandled,
            (BorderStyle::Inset, _) | (_, BorderStyle::Inset) => BorderCornerKind::Unhandled,
        }
    }

    fn get_edge(&self,
                edge: &BorderSide,
                width: f32) -> (BorderEdgeKind, f32) {
        if width == 0.0 {
            return (BorderEdgeKind::None, 0.0);
        }

        match edge.style {
            BorderStyle::None |
            BorderStyle::Hidden => (BorderEdgeKind::None, 0.0),

            BorderStyle::Solid |
            BorderStyle::Inset |
            BorderStyle::Outset => (BorderEdgeKind::Solid, width),

            BorderStyle::Double |
            BorderStyle::Dotted |
            BorderStyle::Dashed |
            BorderStyle::Groove |
            BorderStyle::Ridge => (BorderEdgeKind::Unhandled, width),
        }
    }
}

impl FrameBuilder {
    fn add_normal_border_primitive(&mut self,
                                   rect: &LayerRect,
                                   border: &NormalBorder,
                                   widths: &BorderWidths,
                                   clip_id: ClipId,
                                   clip_region: &ClipRegion,
                                   use_new_border_path: bool) {
        let radius = &border.radius;
        let left = &border.left;
        let right = &border.right;
        let top = &border.top;
        let bottom = &border.bottom;

        // These colors are used during inset/outset scaling.
        let left_color      = left.border_color(1.0, 2.0/3.0, 0.3, 0.7);
        let top_color       = top.border_color(1.0, 2.0/3.0, 0.3, 0.7);
        let right_color     = right.border_color(2.0/3.0, 1.0, 0.7, 0.3);
        let bottom_color    = bottom.border_color(2.0/3.0, 1.0, 0.7, 0.3);

        let prim_cpu = BorderPrimitiveCpu {
            use_new_border_path: use_new_border_path,
        };

        let prim_gpu = BorderPrimitiveGpu {
            colors: [ left_color, top_color, right_color, bottom_color ],
            widths: [ widths.left,
                      widths.top,
                      widths.right,
                      widths.bottom ],
            style: [
                pack_as_float(left.style as u32),
                pack_as_float(top.style as u32),
                pack_as_float(right.style as u32),
                pack_as_float(bottom.style as u32),
            ],
            radii: [
                radius.top_left,
                radius.top_right,
                radius.bottom_right,
                radius.bottom_left,
            ],
        };

        self.add_primitive(clip_id,
                           &rect,
                           clip_region,
                           &[],
                           PrimitiveContainer::Border(prim_cpu, prim_gpu));
    }

    // TODO(gw): This allows us to move border types over to the
    // simplified shader model one at a time. Once all borders
    // are converted, this can be removed, along with the complex
    // border code path.
    pub fn add_normal_border(&mut self,
                             rect: &LayerRect,
                             border: &NormalBorder,
                             widths: &BorderWidths,
                             clip_id: ClipId,
                             clip_region: &ClipRegion) {
        // The border shader is quite expensive. For simple borders, we can just draw
        // the border with a few rectangles. This generally gives better batching, and
        // a GPU win in fragment shader time.
        // More importantly, the software (OSMesa) implementation we run tests on is
        // particularly slow at running our complex border shader, compared to the
        // rectangle shader. This has the effect of making some of our tests time
        // out more often on CI (the actual cause is simply too many Servo processes and
        // threads being run on CI at once).

        let radius = &border.radius;
        let left = &border.left;
        let right = &border.right;
        let top = &border.top;
        let bottom = &border.bottom;

        let corners = [
            border.get_corner(left, widths.left, top, widths.top, &radius.top_left),
            border.get_corner(top, widths.top, right, widths.right, &radius.top_right),
            border.get_corner(right, widths.right, bottom, widths.bottom, &radius.bottom_right),
            border.get_corner(bottom, widths.bottom, left, widths.left, &radius.bottom_left),
        ];

        // If any of the corners are unhandled, fall back to slow path for now.
        if corners.iter().any(|c| *c == BorderCornerKind::Unhandled) {
            self.add_normal_border_primitive(rect,
                                             border,
                                             widths,
                                             clip_id,
                                             clip_region,
                                             false);
            return;
        }

        let (left_edge, left_len) = border.get_edge(left, widths.left);
        let (top_edge, top_len) = border.get_edge(top, widths.top);
        let (right_edge, right_len) = border.get_edge(right, widths.right);
        let (bottom_edge, bottom_len) = border.get_edge(bottom, widths.bottom);

        let edges = [
            left_edge,
            top_edge,
            right_edge,
            bottom_edge,
        ];

        // If any of the edges are unhandled, fall back to slow path for now.
        if edges.iter().any(|e| *e == BorderEdgeKind::Unhandled) {
            self.add_normal_border_primitive(rect,
                                             border,
                                             widths,
                                             clip_id,
                                             clip_region,
                                             false);
            return;
        }

        // Use a simple rectangle case when all edges and corners are either
        // solid or none.
        let all_corners_simple = corners.iter().all(|c| {
            *c == BorderCornerKind::Solid || *c == BorderCornerKind::None
        });
        let all_edges_simple = edges.iter().all(|e| {
            *e == BorderEdgeKind::Solid || *e == BorderEdgeKind::None
        });

        if all_corners_simple && all_edges_simple {
            let p0 = rect.origin;
            let p1 = rect.bottom_right();
            let rect_width = rect.size.width;
            let rect_height = rect.size.height;

            // Add a solid rectangle for each visible edge/corner combination.
            if top_edge == BorderEdgeKind::Solid {
                self.add_solid_rectangle(clip_id,
                                         &LayerRect::new(p0,
                                                         LayerSize::new(rect_width, top_len)),
                                         clip_region,
                                         &border.top.color,
                                         PrimitiveFlags::None);
            }
            if left_edge == BorderEdgeKind::Solid {
                self.add_solid_rectangle(clip_id,
                                         &LayerRect::new(LayerPoint::new(p0.x, p0.y + top_len),
                                                         LayerSize::new(left_len,
                                                                        rect_height - top_len - bottom_len)),
                                         clip_region,
                                         &border.left.color,
                                         PrimitiveFlags::None);
            }
            if right_edge == BorderEdgeKind::Solid {
                self.add_solid_rectangle(clip_id,
                                         &LayerRect::new(LayerPoint::new(p1.x - right_len,
                                                                         p0.y + top_len),
                                                         LayerSize::new(right_len,
                                                                        rect_height - top_len - bottom_len)),
                                         clip_region,
                                         &border.right.color,
                                         PrimitiveFlags::None);
            }
            if bottom_edge == BorderEdgeKind::Solid {
                self.add_solid_rectangle(clip_id,
                                         &LayerRect::new(LayerPoint::new(p0.x, p1.y - bottom_len),
                                                         LayerSize::new(rect_width, bottom_len)),
                                         clip_region,
                                         &border.bottom.color,
                                         PrimitiveFlags::None);
            }
        } else {
            self.add_normal_border_primitive(rect,
                                             border,
                                             widths,
                                             clip_id,
                                             clip_region,
                                             true);
        }
    }
}

pub trait BorderSideHelpers {
    fn border_color(&self,
                    scale_factor_0: f32,
                    scale_factor_1: f32,
                    black_color_0: f32,
                    black_color_1: f32) -> ColorF;
}

impl BorderSideHelpers for BorderSide {
    fn border_color(&self,
                    scale_factor_0: f32,
                    scale_factor_1: f32,
                    black_color_0: f32,
                    black_color_1: f32) -> ColorF {
        match self.style {
            BorderStyle::Inset => {
                if self.color.r != 0.0 || self.color.g != 0.0 || self.color.b != 0.0 {
                    self.color.scale_rgb(scale_factor_1)
                } else {
                    ColorF::new(black_color_0, black_color_0, black_color_0, self.color.a)
                }
            }
            BorderStyle::Outset => {
                if self.color.r != 0.0 || self.color.g != 0.0 || self.color.b != 0.0 {
                    self.color.scale_rgb(scale_factor_0)
                } else {
                    ColorF::new(black_color_1, black_color_1, black_color_1, self.color.a)
                }
            }
            _ => self.color,
        }
    }
}
<commit_msg>Auto merge of #1112 - glennw:outset-inset, r=kvark<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use frame_builder::FrameBuilder;
use prim_store::{BorderPrimitiveCpu, BorderPrimitiveGpu, PrimitiveContainer};
use tiling::PrimitiveFlags;
use util::pack_as_float;
use webrender_traits::{BorderSide, BorderStyle, BorderWidths, ColorF, NormalBorder};
use webrender_traits::{ClipId, ClipRegion, LayerPoint, LayerRect, LayerSize};

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BorderCornerKind {
    None,
    Solid,
    Clip,
    Unhandled,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BorderEdgeKind {
    None,
    Solid,
    Unhandled,
}

pub trait NormalBorderHelpers {
    fn get_corner(&self,
                  edge0: &BorderSide,
                  width0: f32,
                  edge1: &BorderSide,
                  width1: f32,
                  radius: &LayerSize) -> BorderCornerKind;

    fn get_edge(&self,
                edge: &BorderSide,
                width: f32) -> (BorderEdgeKind, f32);
}

impl NormalBorderHelpers for NormalBorder {
    fn get_corner(&self,
                  edge0: &BorderSide,
                  width0: f32,
                  edge1: &BorderSide,
                  width1: f32,
                  radius: &LayerSize) -> BorderCornerKind {
        // If either width is zero, a corner isn't formed.
        if width0 == 0.0 || width1 == 0.0 {
            return BorderCornerKind::None;
        }

        // If both edges are transparent, no corner is formed.
        if edge0.color.a == 0.0 && edge1.color.a == 0.0 {
            return BorderCornerKind::None;
        }

        match (edge0.style, edge1.style) {
            // If either edge is none or hidden, no corner is needed.
            (BorderStyle::None, _) | (_, BorderStyle::None) => BorderCornerKind::None,
            (BorderStyle::Hidden, _) | (_, BorderStyle::Hidden) => BorderCornerKind::None,

            // If both borders are solid, we can draw them with a simple rectangle if
            // both the colors match and there is no radius.
            (BorderStyle::Solid, BorderStyle::Solid) => {
                if edge0.color == edge1.color && radius.width == 0.0 && radius.height == 0.0 {
                    BorderCornerKind::Solid
                } else {
                    BorderCornerKind::Clip
                }
            }

            // Inset / outset borders just modtify the color of edges, so can be
            // drawn with the normal border corner shader.
            (BorderStyle::Outset, BorderStyle::Outset) |
            (BorderStyle::Inset, BorderStyle::Inset) => BorderCornerKind::Clip,

            // Assume complex for these cases.
            // TODO(gw): There are some cases in here that can be handled with a fast path.
            // For example, with inset/outset borders, two of the four corners are solid.
            (BorderStyle::Dotted, _) | (_, BorderStyle::Dotted) => BorderCornerKind::Unhandled,
            (BorderStyle::Dashed, _) | (_, BorderStyle::Dashed) => BorderCornerKind::Unhandled,
            (BorderStyle::Double, _) | (_, BorderStyle::Double) => BorderCornerKind::Unhandled,
            (BorderStyle::Groove, _) | (_, BorderStyle::Groove) => BorderCornerKind::Unhandled,
            (BorderStyle::Ridge, _) | (_, BorderStyle::Ridge) => BorderCornerKind::Unhandled,
            (BorderStyle::Outset, _) | (_, BorderStyle::Outset) => BorderCornerKind::Unhandled,
            (BorderStyle::Inset, _) | (_, BorderStyle::Inset) => BorderCornerKind::Unhandled,
        }
    }

    fn get_edge(&self,
                edge: &BorderSide,
                width: f32) -> (BorderEdgeKind, f32) {
        if width == 0.0 {
            return (BorderEdgeKind::None, 0.0);
        }

        match edge.style {
            BorderStyle::None |
            BorderStyle::Hidden => (BorderEdgeKind::None, 0.0),

            BorderStyle::Solid |
            BorderStyle::Inset |
            BorderStyle::Outset => (BorderEdgeKind::Solid, width),

            BorderStyle::Double |
            BorderStyle::Dotted |
            BorderStyle::Dashed |
            BorderStyle::Groove |
            BorderStyle::Ridge => (BorderEdgeKind::Unhandled, width),
        }
    }
}

impl FrameBuilder {
    fn add_normal_border_primitive(&mut self,
                                   rect: &LayerRect,
                                   border: &NormalBorder,
                                   widths: &BorderWidths,
                                   clip_id: ClipId,
                                   clip_region: &ClipRegion,
                                   use_new_border_path: bool) {
        let radius = &border.radius;
        let left = &border.left;
        let right = &border.right;
        let top = &border.top;
        let bottom = &border.bottom;

        // These colors are used during inset/outset scaling.
        let left_color      = left.border_color(1.0, 2.0/3.0, 0.3, 0.7);
        let top_color       = top.border_color(1.0, 2.0/3.0, 0.3, 0.7);
        let right_color     = right.border_color(2.0/3.0, 1.0, 0.7, 0.3);
        let bottom_color    = bottom.border_color(2.0/3.0, 1.0, 0.7, 0.3);

        let prim_cpu = BorderPrimitiveCpu {
            use_new_border_path: use_new_border_path,
        };

        let prim_gpu = BorderPrimitiveGpu {
            colors: [ left_color, top_color, right_color, bottom_color ],
            widths: [ widths.left,
                      widths.top,
                      widths.right,
                      widths.bottom ],
            style: [
                pack_as_float(left.style as u32),
                pack_as_float(top.style as u32),
                pack_as_float(right.style as u32),
                pack_as_float(bottom.style as u32),
            ],
            radii: [
                radius.top_left,
                radius.top_right,
                radius.bottom_right,
                radius.bottom_left,
            ],
        };

        self.add_primitive(clip_id,
                           &rect,
                           clip_region,
                           &[],
                           PrimitiveContainer::Border(prim_cpu, prim_gpu));
    }

    // TODO(gw): This allows us to move border types over to the
    // simplified shader model one at a time. Once all borders
    // are converted, this can be removed, along with the complex
    // border code path.
    pub fn add_normal_border(&mut self,
                             rect: &LayerRect,
                             border: &NormalBorder,
                             widths: &BorderWidths,
                             clip_id: ClipId,
                             clip_region: &ClipRegion) {
        // The border shader is quite expensive. For simple borders, we can just draw
        // the border with a few rectangles. This generally gives better batching, and
        // a GPU win in fragment shader time.
        // More importantly, the software (OSMesa) implementation we run tests on is
        // particularly slow at running our complex border shader, compared to the
        // rectangle shader. This has the effect of making some of our tests time
        // out more often on CI (the actual cause is simply too many Servo processes and
        // threads being run on CI at once).

        let radius = &border.radius;
        let left = &border.left;
        let right = &border.right;
        let top = &border.top;
        let bottom = &border.bottom;

        let corners = [
            border.get_corner(left, widths.left, top, widths.top, &radius.top_left),
            border.get_corner(top, widths.top, right, widths.right, &radius.top_right),
            border.get_corner(right, widths.right, bottom, widths.bottom, &radius.bottom_right),
            border.get_corner(bottom, widths.bottom, left, widths.left, &radius.bottom_left),
        ];

        // If any of the corners are unhandled, fall back to slow path for now.
        if corners.iter().any(|c| *c == BorderCornerKind::Unhandled) {
            self.add_normal_border_primitive(rect,
                                             border,
                                             widths,
                                             clip_id,
                                             clip_region,
                                             false);
            return;
        }

        let (left_edge, left_len) = border.get_edge(left, widths.left);
        let (top_edge, top_len) = border.get_edge(top, widths.top);
        let (right_edge, right_len) = border.get_edge(right, widths.right);
        let (bottom_edge, bottom_len) = border.get_edge(bottom, widths.bottom);

        let edges = [
            left_edge,
            top_edge,
            right_edge,
            bottom_edge,
        ];

        // If any of the edges are unhandled, fall back to slow path for now.
        if edges.iter().any(|e| *e == BorderEdgeKind::Unhandled) {
            self.add_normal_border_primitive(rect,
                                             border,
                                             widths,
                                             clip_id,
                                             clip_region,
                                             false);
            return;
        }

        // Use a simple rectangle case when all edges and corners are either
        // solid or none.
        let all_corners_simple = corners.iter().all(|c| {
            *c == BorderCornerKind::Solid || *c == BorderCornerKind::None
        });
        let all_edges_simple = edges.iter().all(|e| {
            *e == BorderEdgeKind::Solid || *e == BorderEdgeKind::None
        });

        if all_corners_simple && all_edges_simple {
            let p0 = rect.origin;
            let p1 = rect.bottom_right();
            let rect_width = rect.size.width;
            let rect_height = rect.size.height;

            // Add a solid rectangle for each visible edge/corner combination.
            if top_edge == BorderEdgeKind::Solid {
                self.add_solid_rectangle(clip_id,
                                         &LayerRect::new(p0,
                                                         LayerSize::new(rect_width, top_len)),
                                         clip_region,
                                         &border.top.color,
                                         PrimitiveFlags::None);
            }
            if left_edge == BorderEdgeKind::Solid {
                self.add_solid_rectangle(clip_id,
                                         &LayerRect::new(LayerPoint::new(p0.x, p0.y + top_len),
                                                         LayerSize::new(left_len,
                                                                        rect_height - top_len - bottom_len)),
                                         clip_region,
                                         &border.left.color,
                                         PrimitiveFlags::None);
            }
            if right_edge == BorderEdgeKind::Solid {
                self.add_solid_rectangle(clip_id,
                                         &LayerRect::new(LayerPoint::new(p1.x - right_len,
                                                                         p0.y + top_len),
                                                         LayerSize::new(right_len,
                                                                        rect_height - top_len - bottom_len)),
                                         clip_region,
                                         &border.right.color,
                                         PrimitiveFlags::None);
            }
            if bottom_edge == BorderEdgeKind::Solid {
                self.add_solid_rectangle(clip_id,
                                         &LayerRect::new(LayerPoint::new(p0.x, p1.y - bottom_len),
                                                         LayerSize::new(rect_width, bottom_len)),
                                         clip_region,
                                         &border.bottom.color,
                                         PrimitiveFlags::None);
            }
        } else {
            self.add_normal_border_primitive(rect,
                                             border,
                                             widths,
                                             clip_id,
                                             clip_region,
                                             true);
        }
    }
}

pub trait BorderSideHelpers {
    fn border_color(&self,
                    scale_factor_0: f32,
                    scale_factor_1: f32,
                    black_color_0: f32,
                    black_color_1: f32) -> ColorF;
}

impl BorderSideHelpers for BorderSide {
    fn border_color(&self,
                    scale_factor_0: f32,
                    scale_factor_1: f32,
                    black_color_0: f32,
                    black_color_1: f32) -> ColorF {
        match self.style {
            BorderStyle::Inset => {
                if self.color.r != 0.0 || self.color.g != 0.0 || self.color.b != 0.0 {
                    self.color.scale_rgb(scale_factor_1)
                } else {
                    ColorF::new(black_color_0, black_color_0, black_color_0, self.color.a)
                }
            }
            BorderStyle::Outset => {
                if self.color.r != 0.0 || self.color.g != 0.0 || self.color.b != 0.0 {
                    self.color.scale_rgb(scale_factor_0)
                } else {
                    ColorF::new(black_color_1, black_color_1, black_color_1, self.color.a)
                }
            }
            _ => self.color,
        }
    }
}
<|endoftext|>


<commit_before>extern crate neat;
extern crate rand;
extern crate graph_neighbor_matching;
extern crate graph_io_gml;
extern crate closed01;
extern crate petgraph;
extern crate cppn;
extern crate asexp;
#[macro_use]
extern crate log;
extern crate env_logger;

mod common;
mod config;

use neat::population::{Population, Unrated, Runner};
use neat::traits::FitnessEval;
use neat::genomes::acyclic_network::{Genome, GlobalCache, GlobalInnovationCache, Mater,
                                     ElementStrategy};
use neat::fitness::Fitness;
use graph_neighbor_matching::graph::{GraphBuilder, OwnedGraph};
use rand::Rng;
use std::marker::PhantomData;
use common::{load_graph, Neuron, convert_neuron_from_str, GraphSimilarity, NodeCount};
use cppn::cppn::{Cppn, CppnNode};
use cppn::bipolar::BipolarActivationFunction;
use cppn::substrate::Substrate;
use cppn::position::Position2d;
use neat::weight::{Weight, WeightRange};
use neat::distribute::DistributeInterval;
use closed01::Closed01;

type Node = CppnNode<BipolarActivationFunction>;

fn generate_substrate(node_count: &NodeCount) -> Substrate<Position2d, Neuron> {
    let mut substrate = Substrate::new();

    let mut y_iter = DistributeInterval::new(3, -1.0, 1.0); // 3 layers (Input, Hidden, Output)

    // Inputs
    {
        let y = y_iter.next().unwrap();
        for x in DistributeInterval::new(node_count.inputs, -1.0, 1.0) {
            substrate.add_node(Position2d::new(x, y), Neuron::Input);
        }
    }

    // Hidden
    {
        let y = y_iter.next().unwrap();
        for x in DistributeInterval::new(node_count.hidden, -1.0, 1.0) {
            substrate.add_node(Position2d::new(x, y), Neuron::Hidden);
        }
    }

    // Outputs
    {
        let y = y_iter.next().unwrap();
        for x in DistributeInterval::new(node_count.outputs, -1.0, 1.0) {
            substrate.add_node(Position2d::new(x, y), Neuron::Output);
        }
    }

    return substrate;
}

fn genome_to_graph(genome: &Genome<Node>, node_count: &NodeCount) -> OwnedGraph<Neuron> {
    let substrate = generate_substrate(node_count);
    let mut cppn = Cppn::new(genome.network());

    // now develop the cppn. the result is a graph
    let mut builder = GraphBuilder::new();
    for (i, node) in substrate.nodes().iter().enumerate() {
        let _ = builder.add_node(i, node.node_type.clone());
    }
    for link in substrate.iter_links(&mut cppn, None) {
        if link.weight >= 0.0 && link.weight <= 1.0 {
            builder.add_edge(link.source_idx,
                             link.target_idx,
                             Closed01::new(link.weight as f32));
        }
    }
    return builder.graph();
}

#[derive(Debug)]
struct FitnessEvaluator {
    sim: GraphSimilarity,
    node_count: NodeCount,
}

impl FitnessEval<Genome<Node>> for FitnessEvaluator {
    // A larger fitness means "better"
    fn fitness(&self, genome: &Genome<Node>) -> Fitness {
        Fitness::new(self.sim.fitness(&genome_to_graph(genome, &self.node_count)) as f64)
    }
}

struct ES;

impl ElementStrategy<Node> for ES {
    fn link_weight_range(&self) -> WeightRange {
        WeightRange::bipolar(1.0)
    }

    fn full_link_weight(&self) -> Weight {
        WeightRange::bipolar(1.0).high()
    }

    fn random_node_type<R: Rng>(&self, rng: &mut R) -> Node {
        let af = &[BipolarActivationFunction::Identity,
                   BipolarActivationFunction::Linear,
                   BipolarActivationFunction::Gaussian,
                   BipolarActivationFunction::Sigmoid,
                   BipolarActivationFunction::Sine];

        CppnNode::Hidden(*rng.choose(af).unwrap())
    }
}

fn main() {
    env_logger::init().unwrap();

    let mut rng = rand::thread_rng();

    let cfg = config::Configuration::from_file();

    println!("{:?}", cfg);

    let target_graph = load_graph(&cfg.target_graph_file(), convert_neuron_from_str);
    let node_count = NodeCount::from_graph(&target_graph);

    let fitness_evaluator = FitnessEvaluator {
        sim: GraphSimilarity {
            target_graph: target_graph,
            edge_score: cfg.edge_score(),
            iters: cfg.neighbormatching_iters(),
            eps: cfg.neighbormatching_eps(),
        },
        node_count: node_count,
    };

    let mut cache = GlobalInnovationCache::new();

    // start with minimal random topology.

    let template_genome = {
        let mut genome = Genome::new();

        // 4 inputs (x1,y1,x2,y2)
        for _ in 0..4 {
            genome.add_node(cache.create_node_innovation(), CppnNode::Input);
        }

        // 1 output (y)
        genome.add_node(cache.create_node_innovation(), CppnNode::Output);

        // 1 bias node
        genome.add_node(cache.create_node_innovation(), CppnNode::Bias);

        genome
    };

    let mut initial_pop = Population::<_, Unrated>::new();

    for _ in 0..cfg.population_size() {
        initial_pop.add_genome(Box::new(template_genome.clone()));
    }
    assert!(initial_pop.len() == cfg.population_size());

    let mut mater = Mater {
        p_crossover: cfg.p_crossover(),
        p_crossover_detail: cfg.probabilistic_crossover(),
        p_mutate_element: cfg.p_mutate_element(),
        weight_perturbance: cfg.weight_perturbance(),
        mutate_weights: cfg.mutate_weights(),
        global_cache: &mut cache,
        element_strategy: &ES,
        _n: PhantomData,
    };

    let mut runner = Runner {
        pop_size: cfg.population_size(),
        elite_percentage: cfg.elite_percentage(),
        selection_percentage: cfg.selection_percentage(),
        compatibility_threshold: cfg.compatibility_threshold(),
        compatibility: cfg.genome_compatibility(),
        mate: &mut mater,
        fitness: &fitness_evaluator,
        _marker: PhantomData,
    };

    let max_iters = cfg.stop_after_iters();
    let good_fitness = cfg.stop_if_fitness_better_than();
    let (iter, new_pop) = runner.run(initial_pop,
                                     &|iter, pop, _| {
                                         iter >= max_iters ||
                                         pop.best_individual().unwrap().fitness().get() >
                                         good_fitness
                                     },
                                     &mut rng);

    let final_pop = new_pop.sort();

    println!("iter: {}", iter);
    println!("{:#?}", final_pop.best_individual());
}
<commit_msg>Refactor. Print out the generated graphs.<commit_after>extern crate neat;
extern crate rand;
extern crate graph_neighbor_matching;
extern crate graph_io_gml;
extern crate closed01;
extern crate petgraph;
extern crate cppn;
extern crate asexp;
#[macro_use]
extern crate log;
extern crate env_logger;

mod common;
mod config;

use neat::population::{Population, Unrated, NicheRunner};
use neat::traits::FitnessEval;
use neat::genomes::acyclic_network::{Genome, GlobalCache, GlobalInnovationCache, Mater,
                                     ElementStrategy};
use neat::fitness::Fitness;
use graph_neighbor_matching::graph::{GraphBuilder, OwnedGraph};
use rand::Rng;
use std::marker::PhantomData;
use common::{load_graph, Neuron, convert_neuron_from_str, GraphSimilarity, NodeCount, write_gml};
use cppn::cppn::{Cppn, CppnNode};
use cppn::bipolar::BipolarActivationFunction;
use cppn::substrate::Substrate;
use cppn::position::Position2d;
use neat::weight::{Weight, WeightRange};
use neat::distribute::DistributeInterval;
use closed01::Closed01;

type Node = CppnNode<BipolarActivationFunction>;

fn generate_substrate(node_count: &NodeCount) -> Substrate<Position2d, Neuron> {
    let mut substrate = Substrate::new();

    let mut y_iter = DistributeInterval::new(3, -1.0, 1.0); // 3 layers (Input, Hidden, Output)

    // Inputs
    {
        let y = y_iter.next().unwrap();
        for x in DistributeInterval::new(node_count.inputs, -1.0, 1.0) {
            substrate.add_node(Position2d::new(x, y), Neuron::Input);
        }
    }

    // Hidden
    {
        let y = y_iter.next().unwrap();
        for x in DistributeInterval::new(node_count.hidden, -1.0, 1.0) {
            substrate.add_node(Position2d::new(x, y), Neuron::Hidden);
        }
    }

    // Outputs
    {
        let y = y_iter.next().unwrap();
        for x in DistributeInterval::new(node_count.outputs, -1.0, 1.0) {
            substrate.add_node(Position2d::new(x, y), Neuron::Output);
        }
    }

    return substrate;
}

#[derive(Debug)]
struct FitnessEvaluator {
    sim: GraphSimilarity,
    node_count: NodeCount,
}

impl FitnessEvaluator {
    fn genome_to_graph(&self, genome: &Genome<Node>) -> OwnedGraph<Neuron> {
        let substrate = generate_substrate(&self.node_count);
        let mut cppn = Cppn::new(genome.network());

        // now develop the cppn. the result is a graph
        let mut builder = GraphBuilder::new();
        for (i, node) in substrate.nodes().iter().enumerate() {
            let _ = builder.add_node(i, node.node_type.clone());
        }
        for link in substrate.iter_links(&mut cppn, None) {
            if link.weight >= 0.0 && link.weight <= 1.0 {
                builder.add_edge(link.source_idx,
                                 link.target_idx,
                                 Closed01::new(link.weight as f32));
            }
        }
        return builder.graph();
    }
}

impl FitnessEval<Genome<Node>> for FitnessEvaluator {
    // A larger fitness means "better"
    fn fitness(&self, genome: &Genome<Node>) -> Fitness {
        Fitness::new(self.sim.fitness(&self.genome_to_graph(genome)) as f64)
    }
}

struct ES;

impl ElementStrategy<Node> for ES {
    fn link_weight_range(&self) -> WeightRange {
        WeightRange::bipolar(1.0)
    }

    fn full_link_weight(&self) -> Weight {
        self.link_weight_range().high()
    }

    fn random_node_type<R: Rng>(&self, rng: &mut R) -> Node {
        let af = &[BipolarActivationFunction::Identity,
                   BipolarActivationFunction::Linear,
                   BipolarActivationFunction::Gaussian,
                   BipolarActivationFunction::Sigmoid,
                   BipolarActivationFunction::Sine];

        CppnNode::Hidden(*rng.choose(af).unwrap())
    }
}

fn main() {
    env_logger::init().unwrap();

    let mut rng = rand::thread_rng();

    let cfg = config::Configuration::from_file();

    println!("{:?}", cfg);

    let target_graph = load_graph(&cfg.target_graph_file(), convert_neuron_from_str);
    let node_count = NodeCount::from_graph(&target_graph);

    let fitness_evaluator = FitnessEvaluator {
        sim: GraphSimilarity {
            target_graph: target_graph,
            edge_score: cfg.edge_score(),
            iters: cfg.neighbormatching_iters(),
            eps: cfg.neighbormatching_eps(),
        },
        node_count: node_count,
    };

    let mut cache = GlobalInnovationCache::new();

    // start with minimal random topology.

    let template_genome = {
        let mut genome = Genome::new();

        // 4 inputs (x1,y1,x2,y2)
        for _ in 0..4 {
            genome.add_node(cache.create_node_innovation(), CppnNode::Input);
        }

        // 1 output (y)
        genome.add_node(cache.create_node_innovation(), CppnNode::Output);

        // 1 bias node
        genome.add_node(cache.create_node_innovation(), CppnNode::Bias);

        genome
    };

    let mut initial_pop = Population::<_, Unrated>::new();

    for _ in 0..cfg.population_size() {
        initial_pop.add_genome(Box::new(template_genome.clone()));
    }
    assert!(initial_pop.len() == cfg.population_size());

    let mut mater = Mater {
        p_crossover: cfg.p_crossover(),
        p_crossover_detail: cfg.probabilistic_crossover(),
        p_mutate_element: cfg.p_mutate_element(),
        weight_perturbance: cfg.weight_perturbance(),
        mutate_weights: cfg.mutate_weights(),
        global_cache: &mut cache,
        element_strategy: &ES,
        _n: PhantomData,
    };

    let mut niche_runner = NicheRunner::new(&fitness_evaluator);

    niche_runner.add_unrated_population_as_niche(initial_pop);

    while niche_runner.has_next_iteration(cfg.stop_after_iters()) {
        println!("iteration: {}", niche_runner.current_iteration());

        let best_fitness = niche_runner.best_individual().fitness().get();;
        println!("best fitness: {:2}", best_fitness);
        println!("num individuals: {}", niche_runner.num_individuals());

        if best_fitness > cfg.stop_if_fitness_better_than() {
            println!("Premature abort.");
            break;
        }

        // partition into n niches.
        niche_runner.partition_n_sorted(5, cfg.genome_compatibility(), &mut rng);
        println!("partitioned into num niches: {}", niche_runner.num_niches());

        niche_runner.reproduce_global(cfg.population_size(),
                                      cfg.elite_percentage(),
                                      cfg.selection_percentage(),
                                      &mut mater,
                                      &mut rng);
    }

    let final_pop = niche_runner.into_population().sort();

    {
        let best = final_pop.best_individual().unwrap();
        write_gml("best.gml", &fitness_evaluator.genome_to_graph(best.genome()));
    }

    for (i, ind) in final_pop.into_iter().enumerate() {
        println!("individual #{}: {:.3}", i, ind.fitness().get());
        write_gml(&format!("ind_{:03}_{}.gml", i, (ind.fitness().get() * 100.0) as usize), &fitness_evaluator.genome_to_graph(ind.genome()));
    }

    write_gml("target.gml", &fitness_evaluator.sim.target_graph);
}
<|endoftext|>


<commit_before>use std::mem;

struct Fibonacci {
    curr: u32,
    next: u32,
}

// Implement 'Iterator' for 'Fibonacci'
impl Iterator for Fibonacci {
    type Item = u32;
    // The 'Iterator' trait only requires the 'next' method to be defined. The
    // return type is 'Option<T>', 'None' is returned when the 'Iterator' is
    // over, otherwise the next value is returned wrapped in 'Some'
    fn next(&mut self) -> Option<u32> {
        let new_next = self.curr + self.next;
        let new_curr = mem::replace(&mut self.next, new_next);

        // 'Some' is always returned, this is an infinite value generator
        Some(mem::replace(&mut self.curr, new_curr))
    }
}

// Returns a fibonacci sequence generator
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 1, next: 1 }
}

fn main() {
    // Iterator that generates: 0, 1 and 2
    let mut sequence = range(0u32, 3);

    println!("Four consecutive `next` calls on range(0, 3)");
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // The for construct will iterate an 'Iterator' until it returns 'None'.
    // Every 'Some' value is unwrapped and bound to a variable.
    println!("Iterate over range(0, 3) using for");
    for i in range(0u32, 3) {
        println!("> {}", i);
    }

    // The 'take(n)' method will reduce an iterator to its first 'n' terms,
    // which is pretty useful for infinite value generators
    println!("The first four terms of the Fibonacci sequence are: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // The 'skip(n)' method will shorten an iterator by dropping its first 'n'
    // terms
    println!("The next four terms of the Fibonacci sequence are: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u32, 3, 3, 7];

    // The 'iter' method produces an 'Iterator' over an array/slice
    println!("Iterate the following array {:?}", array.as_slice());
    for i in array.iter() {
        println!("> {}", i);
    }
}
<commit_msg>Use ... notation to avoid range unstable warning<commit_after>use std::mem;

struct Fibonacci {
    curr: u32,
    next: u32,
}

// Implement 'Iterator' for 'Fibonacci'
impl Iterator for Fibonacci {
    type Item = u32;
    // The 'Iterator' trait only requires the 'next' method to be defined. The
    // return type is 'Option<T>', 'None' is returned when the 'Iterator' is
    // over, otherwise the next value is returned wrapped in 'Some'
    fn next(&mut self) -> Option<u32> {
        let new_next = self.curr + self.next;
        let new_curr = mem::replace(&mut self.next, new_next);

        // 'Some' is always returned, this is an infinite value generator
        Some(mem::replace(&mut self.curr, new_curr))
    }
}

// Returns a fibonacci sequence generator
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 1, next: 1 }
}

fn main() {
    // Iterator that generates: 0, 1 and 2
    let mut sequence = 0..3;

    println!("Four consecutive `next` calls on range(0, 3)");
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // The for construct will iterate an 'Iterator' until it returns 'None'.
    // Every 'Some' value is unwrapped and bound to a variable.
    println!("Iterate over range(0, 3) using for");
    for i in 0..3 {
        println!("> {}", i);
    }

    // The 'take(n)' method will reduce an iterator to its first 'n' terms,
    // which is pretty useful for infinite value generators
    println!("The first four terms of the Fibonacci sequence are: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // The 'skip(n)' method will shorten an iterator by dropping its first 'n'
    // terms
    println!("The next four terms of the Fibonacci sequence are: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u32, 3, 3, 7];

    // The 'iter' method produces an 'Iterator' over an array/slice
    println!("Iterate the following array {:?}", array.as_slice());
    for i in array.iter() {
        println!("> {}", i);
    }
}
<|endoftext|>


<commit_before>use std::io;
use hyper::method::Method;
use serde_json;
use ::{Result, Error};
use ::connection::Connection;
use ::odata::Parameters;
use super::Path;

/// Item content reader/writer
pub struct Content {
	stream: Box<io::Read>,
}

impl Content {
	pub fn open_for_read(conn: Connection, id: String) -> Result<Self> {
		let params = Parameters::new().custom_add(("redirect", "false"));
		let uri = Path::Id(id).entity_and_parameters(Some("/Download"), Some(params));

		// Try to obtain download specifications
		let specs: serde_json::Value = match conn.query_string(Method::Get, uri, None, None) {
			Ok(json) => serde_json::from_str(&json).unwrap(),
			Err(err) =>  return err.result()
		};

		// Get download URL from the specs and open the stream
		let download_url = match specs.find("DownloadUrl") {
			Some(v) => v.as_string().unwrap(),
			None => return Error::new("DownloadSpecification.DownloadUrl property is missing.").result()
		};

		let reader = match conn.custom_request(Method::Get, download_url.to_owned(), None, None) {
			Ok(response) => Box::new(response),
			Err(err) => return Error::new("Cannot start download").because(err).result()
		};

		Ok(Content {
			stream: reader,
		})
	}
}

impl io::Read for Content {
	fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
		self.stream.read(buf)
	}
}
<commit_msg>Update docs<commit_after>use std::io;
use hyper::method::Method;
use serde_json;
use ::{Result, Error};
use ::connection::Connection;
use ::odata::Parameters;
use super::Path;

/// Item content reader/writer.
///
/// The struct implementds `std::io::Read` and `std::io::Write` traits so it can be used
/// neat abilities of the standard Rust library to read and write data.
///
/// ## Panics
/// The instance of `Content` can only read or only write data during the lifetime.
/// Writing data will panic if `Content` was created fo reading data and reading data
/// will panic of it was created for writing.
pub struct Content {
	stream: Box<io::Read>,
}

impl Content {
	/// Create the new instance of `Content` for reading data. Most time there is no need
	/// to create this struct directly. The better practice is to use method `download()`
	/// of the `Items` instance.
	pub fn open_for_read(conn: Connection, id: String) -> Result<Self> {
		let params = Parameters::new().custom_add(("redirect", "false"));
		let uri = Path::Id(id).entity_and_parameters(Some("/Download"), Some(params));

		// Try to obtain download specifications
		let specs: serde_json::Value = match conn.query_string(Method::Get, uri, None, None) {
			Ok(json) => serde_json::from_str(&json).unwrap(),
			Err(err) =>  return err.result()
		};

		// Get download URL from the specs and open the stream
		let download_url = match specs.find("DownloadUrl") {
			Some(v) => v.as_string().unwrap(),
			None => return Error::new("DownloadSpecification.DownloadUrl property is missing.").result()
		};

		let reader = match conn.custom_request(Method::Get, download_url.to_owned(), None, None) {
			Ok(response) => Box::new(response),
			Err(err) => return Error::new("Cannot start download").because(err).result()
		};

		Ok(Content {
			stream: reader,
		})
	}
}

impl io::Read for Content {
	fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
		self.stream.read(buf)
	}
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::fmt::Debug;

use crate::base::AssertionApi;
use crate::{AssertionResult, AssertionStrategy, Subject};

pub trait OptionAssertion<'a, T, R>
where
    AssertionResult: AssertionStrategy<R>,
{
    fn is_none(&self) -> R
    where
        T: PartialEq + Debug;
    fn is_some(&self) -> R
    where
        T: PartialEq + Debug;
    fn has_value<B>(&self, expected: B) -> R
    where
        B: Borrow<T>,
        T: PartialEq + Debug;
}

impl<'a, T, R> OptionAssertion<'a, T, R> for Subject<'a, Option<T>, (), R>
where
    AssertionResult: AssertionStrategy<R>,
{
    fn is_none(&self) -> R
    where
        T: PartialEq + Debug,
    {
        match self.actual() {
            None => self.new_result().do_ok(),
            Some(actual) => self
                .new_result()
                .add_fact("expected", "None")
                .add_fact("actual", format!("Some({:?})", actual))
                .do_fail(),
        }
    }

    fn is_some(&self) -> R
    where
        T: PartialEq + Debug,
    {
        match self.actual() {
            None => self
                .new_result()
                .add_fact("expected", "Some(_)")
                .add_fact("actual", "None")
                .do_fail(),
            Some(_) => self.new_result().do_ok(),
        }
    }

    fn has_value<B>(&self, expected: B) -> R
    where
        B: Borrow<T>,
        T: PartialEq + Debug,
    {
        match self.actual() {
            Some(actual) if expected.borrow().eq(actual) => self.new_result().do_ok(),
            Some(actual) => self
                .new_result()
                .add_fact("expected", format!("Some({:?})", expected.borrow()))
                .add_fact("actual", format!("Some({:?})", actual))
                .do_fail(),
            None => self
                .new_result()
                .add_fact("expected", format!("Some({:?})", expected.borrow()))
                .add_fact("actual", "None")
                .do_fail(),
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::testing::*;

    use super::*;

    #[test]
    fn is_none() {
        let none: Option<isize> = Option::None;
        let one: Option<isize> = Option::from(1);
        assert_that!(none).is_none();
        assert_that!(check_that!(one).is_none()).facts_are(vec![
            Fact::new("expected", "None"),
            Fact::new("actual", "Some(1)"),
        ]);
        assert_that!(check_that!(Option::Some("some")).is_none()).facts_are(vec![
            Fact::new("expected", "None"),
            Fact::new("actual", r#"Some("some")"#),
        ]);
    }

    #[test]
    fn is_some() {
        let none: Option<isize> = Option::None;
        let one: Option<isize> = Option::from(1);
        assert_that!(one).is_some();
        assert_that!(check_that!(none).is_some()).facts_are(vec![
            Fact::new("expected", "Some(_)"),
            Fact::new("actual", "None"),
        ]);
    }

    #[test]
    fn has_value() {
        let none: Option<isize> = Option::None;
        let one: Option<isize> = Option::from(1);
        assert_that!(one).has_value(1);
        assert_that!(Option::from("")).has_value("");

        assert_that!(check_that!(none).has_value(1)).facts_are(vec![
            Fact::new("expected", "Some(1)"),
            Fact::new("actual", "None"),
        ]);
        assert_that!(check_that!(one).has_value(2)).facts_are(vec![
            Fact::new("expected", "Some(2)"),
            Fact::new("actual", "Some(1)"),
        ]);
        assert_that!(check_that!(Option::from("1")).has_value("2")).facts_are(vec![
            Fact::new("expected", r#"Some("2")"#),
            Fact::new("actual", r#"Some("1")"#),
        ]);
    }
}
<commit_msg>Write rustdoc for `OptionAssertion`<commit_after>use std::borrow::Borrow;
use std::fmt::Debug;

use crate::base::AssertionApi;
use crate::{AssertionResult, AssertionStrategy, Subject};

/// Trait for option assertion.
///
/// # Example
/// ```
/// use assertor::*;
///
/// assert_that!(Option::Some(1)).has_value(1);
/// assert_that!(Option::Some(1)).is_some();
/// assert_that!(Option::<usize>::None).is_none();
/// ```
pub trait OptionAssertion<'a, T, R>
where
    AssertionResult: AssertionStrategy<R>,
{
    /// Checks the subject is [`Option::None`].
    fn is_none(&self) -> R
    where
        T: PartialEq + Debug;

    /// Checks the subject is [`Option::Some(_)`](`Option::Some`).
    fn is_some(&self) -> R
    where
        T: PartialEq + Debug;

    /// Checks the subject is [`Option::Some(expected)`](`Option::Some`).
    fn has_value<B>(&self, expected: B) -> R
    where
        B: Borrow<T>,
        T: PartialEq + Debug;
}

impl<'a, T, R> OptionAssertion<'a, T, R> for Subject<'a, Option<T>, (), R>
where
    AssertionResult: AssertionStrategy<R>,
{
    fn is_none(&self) -> R
    where
        T: PartialEq + Debug,
    {
        match self.actual() {
            None => self.new_result().do_ok(),
            Some(actual) => self
                .new_result()
                .add_fact("expected", "None")
                .add_fact("actual", format!("Some({:?})", actual))
                .do_fail(),
        }
    }

    fn is_some(&self) -> R
    where
        T: PartialEq + Debug,
    {
        match self.actual() {
            None => self
                .new_result()
                .add_fact("expected", "Some(_)")
                .add_fact("actual", "None")
                .do_fail(),
            Some(_) => self.new_result().do_ok(),
        }
    }

    fn has_value<B>(&self, expected: B) -> R
    where
        B: Borrow<T>,
        T: PartialEq + Debug,
    {
        match self.actual() {
            Some(actual) if expected.borrow().eq(actual) => self.new_result().do_ok(),
            Some(actual) => self
                .new_result()
                .add_fact("expected", format!("Some({:?})", expected.borrow()))
                .add_fact("actual", format!("Some({:?})", actual))
                .do_fail(),
            None => self
                .new_result()
                .add_fact("expected", format!("Some({:?})", expected.borrow()))
                .add_fact("actual", "None")
                .do_fail(),
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::testing::*;

    use super::*;

    #[test]
    fn is_none() {
        let none: Option<isize> = Option::None;
        let one: Option<isize> = Option::from(1);
        assert_that!(none).is_none();
        assert_that!(check_that!(one).is_none()).facts_are(vec![
            Fact::new("expected", "None"),
            Fact::new("actual", "Some(1)"),
        ]);
        assert_that!(check_that!(Option::Some("some")).is_none()).facts_are(vec![
            Fact::new("expected", "None"),
            Fact::new("actual", r#"Some("some")"#),
        ]);
    }

    #[test]
    fn is_some() {
        let none: Option<isize> = Option::None;
        let one: Option<isize> = Option::from(1);
        assert_that!(one).is_some();
        assert_that!(check_that!(none).is_some()).facts_are(vec![
            Fact::new("expected", "Some(_)"),
            Fact::new("actual", "None"),
        ]);
    }

    #[test]
    fn has_value() {
        let none: Option<isize> = Option::None;
        let one: Option<isize> = Option::from(1);
        assert_that!(one).has_value(1);
        assert_that!(Option::from("")).has_value("");

        assert_that!(check_that!(none).has_value(1)).facts_are(vec![
            Fact::new("expected", "Some(1)"),
            Fact::new("actual", "None"),
        ]);
        assert_that!(check_that!(one).has_value(2)).facts_are(vec![
            Fact::new("expected", "Some(2)"),
            Fact::new("actual", "Some(1)"),
        ]);
        assert_that!(check_that!(Option::from("1")).has_value("2")).facts_are(vec![
            Fact::new("expected", r#"Some("2")"#),
            Fact::new("actual", r#"Some("1")"#),
        ]);
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Basic is_cell_alive implementation.<commit_after>use std::collections::HashSet;

fn is_cell_alive(world: HashSet<(i8,i8)>, cell_coordinates: (i8,i8)) -> bool {
    return world.contains(&cell_coordinates);
}

#[test]
fn is_cell_alive_should_return_true_for_alive_cell(){
    let coords = (0,0);
    let mut world: HashSet<(i8,i8)> = HashSet::new();
    world.insert(coords);
    let is_alive = is_cell_alive(world,coords);
    assert_eq!(true, is_alive);
}

#[test]
fn is_cell_alive_should_return_false_for_dead_cell(){
    let coords = (0,0);
    let world: HashSet<(i8,i8)> = HashSet::new();
    let is_alive = is_cell_alive(world,coords);
    assert_eq!(false, is_alive);
}
<|endoftext|>