<commit_before>use turtle::{Angle, Color, Distance, Drawing, Point, Size, Turtle};

trait CubicBezier {
    const DEFAULT_SAMPLES: usize = 100;

    fn bezier_abs_pr(&mut self, samples: usize, points: [Point; 4]);
    fn bezier_rel_pr(&mut self, samples: usize, rel_points: [Point; 3]);

    fn bezier_abs(&mut self, points: [Point; 4]) {
        self.bezier_abs_pr(Self::DEFAULT_SAMPLES, points)
    }

    fn bezier_rel(&mut self, rel_points: [Point; 3]) {
        self.bezier_rel_pr(Self::DEFAULT_SAMPLES, rel_points)
    }

    fn curve_at(t: f64, points: [Point; 4]) -> Point {
        (1.0 - t).powi(3) * points[0]
            + 3.0 * (1.0 - t).powi(2) * t * points[1]
            + 3.0 * (1.0 - t) * t.powi(2) * points[2]
            + t.powi(3) * points[3]
    }
}

impl CubicBezier for Turtle {
    fn bezier_abs_pr(&mut self, samples: usize, points: [Point; 4]) {
        (0..=samples)
            .map(|i| i as f64 / samples as f64)
            .map(|t| Self::curve_at(t, points))
            .for_each(|point| {
                self.turn_towards(point);
                self.go_to(point);
            })
    }

    fn bezier_rel_pr(&mut self, samples: usize, rel_points: [Point; 3]) {
        let pos = self.position();
        self.bezier_abs_pr(
            samples,
            [
                pos,
                pos + rel_points[0],
                pos + rel_points[1],
                pos + rel_points[2],
            ],
        )
    }
}

const FRONT_SHELL_COLOR: &str = "#f74c00";
const BACK_SHELL_COLOR: &str = "#a52b00";
const PUPIL_COLOR: &str = "#ffffff";
const MOUTH_COLOR: &str = "#000000";
const ORIGINAL_SIZE: Size = Size {
    width: 1200,
    height: 800,
};

fn adapt_point(point: impl Into<Point>, size: Size) -> Point {
    let point = point.into();
    Point {
        x: size.width as f64 * point.x / ORIGINAL_SIZE.width as f64,
        y: -(size.height as f64) * point.y / ORIGINAL_SIZE.height as f64,
    }
}

fn rel_points(abs_points: [Point; 4]) -> [Point; 3] {
    [
        abs_points[1] - abs_points[0],
        abs_points[2] - abs_points[0],
        abs_points[3] - abs_points[0],
    ]
}

fn adapt_distance(distance: Distance, angle: Angle, size: Size) -> Distance {
    ((distance * angle.cos() * size.width as f64 / ORIGINAL_SIZE.width as f64).powi(2)
        + (distance * angle.sin() * size.height as f64 / ORIGINAL_SIZE.height as f64).powi(2))
    .sqrt()
}

fn main() {
    let mut drawing = Drawing::new();
    let size = drawing.size();
    drawing.set_center([size.width as f64 / 2.0, -(size.height as f64) / 2.0]);

    let mut turtle = drawing.add_turtle();
    turtle.use_radians();
    turtle.pen_up();

    let rp = rel_points;
    let ap = |point| adapt_point(point, size);
    let ad = |distance, angle| adapt_distance(distance, angle, size);

    let start_point = ap([240.0, 504.0]);
    turtle.set_fill_color(BACK_SHELL_COLOR);
    turtle.set_speed("instant");
    turtle.turn_towards(start_point);
    turtle.go_to(start_point);
    turtle.set_speed("faster");
    turtle.begin_fill();

    let start_heading = (180.0 + 32.01f64).to_radians();
    turtle.set_heading(start_heading);
    turtle.forward(ad(18.9, start_heading));
    turtle.bezier_rel(rp([
        ap([223.64, 514.18]),
        ap([222.18, 525.09]),
        ap([288.00, 597.09]),
        ap([323.94, 645.06]),
    ]));
    turtle.bezier_rel(rp([
        ap([323.91, 645.18]),
        ap([324.00, 623.09]),
        ap([283.27, 565.27]),
        ap([270.69, 529.94]),
    ]));
    turtle.bezier_rel(rp([
        ap([270.75, 529.94]),
        ap([444.75, 621.50]),
        ap([826.25, 622.50]),
        ap([973.09, 515.22]),
    ]));
    turtle.bezier_rel(rp([
        ap([973.12, 515.25]),
        ap([965.45, 552.18]),
        ap([923.09, 619.45]),
        ap([922.09, 646.52]),
    ]));
    turtle.bezier_rel(rp([
        ap([922.38, 647.00]),
        ap([931.09, 631.09]),
        ap([988.91, 554.55]),
        ap([1008.00, 517.12]),
    ]));
    let middle_curve_part1 = rp([
        ap([1008.12, 517.06]),
        ap([979.25, 500.88]),
        ap([960.12, 507.19]),
        ap([946.69, 510.31]),
    ]);
    turtle.bezier_rel(middle_curve_part1);
    let middle_curve_part2 = rp([
        ap([946.66, 510.41]),
        ap([750.73, 606.91]),
        ap([472.55, 603.45]),
        ap([239.57, 505.39]),
    ]);
    turtle.bezier_rel(middle_curve_part2);

    turtle.end_fill();
}
<commit_msg>Add front left leg and claw part to Ferris example<commit_after>use turtle::{Angle, Color, Distance, Drawing, Point, Size, Turtle};

trait CubicBezier {
    const DEFAULT_SAMPLES: usize = 100;

    fn bezier_abs_pr(&mut self, samples: usize, points: [Point; 4]);
    fn bezier_rel_pr(&mut self, samples: usize, rel_points: [Point; 3]);

    fn bezier_abs(&mut self, points: [Point; 4]) {
        self.bezier_abs_pr(Self::DEFAULT_SAMPLES, points)
    }

    fn bezier_rel(&mut self, rel_points: [Point; 3]) {
        self.bezier_rel_pr(Self::DEFAULT_SAMPLES, rel_points)
    }

    fn curve_at(t: f64, points: [Point; 4]) -> Point {
        (1.0 - t).powi(3) * points[0]
            + 3.0 * (1.0 - t).powi(2) * t * points[1]
            + 3.0 * (1.0 - t) * t.powi(2) * points[2]
            + t.powi(3) * points[3]
    }
}

impl CubicBezier for Turtle {
    fn bezier_abs_pr(&mut self, samples: usize, points: [Point; 4]) {
        (0..=samples)
            .map(|i| i as f64 / samples as f64)
            .map(|t| Self::curve_at(t, points))
            .for_each(|point| {
                self.turn_towards(point);
                self.go_to(point);
            })
    }

    fn bezier_rel_pr(&mut self, samples: usize, rel_points: [Point; 3]) {
        let pos = self.position();
        self.bezier_abs_pr(
            samples,
            [
                pos,
                pos + rel_points[0],
                pos + rel_points[1],
                pos + rel_points[2],
            ],
        )
    }
}

const FRONT_SHELL_COLOR: &str = "#f74c00";
const BACK_SHELL_COLOR: &str = "#a52b00";
const PUPIL_COLOR: &str = "#ffffff";
const MOUTH_COLOR: &str = "#000000";
const ORIGINAL_SIZE: Size = Size {
    width: 1200,
    height: 800,
};

fn adapt_point(point: impl Into<Point>, size: Size) -> Point {
    let point = point.into();
    Point {
        x: size.width as f64 * point.x / ORIGINAL_SIZE.width as f64,
        y: -(size.height as f64) * point.y / ORIGINAL_SIZE.height as f64,
    }
}

fn rel_points(abs_points: [Point; 4]) -> [Point; 3] {
    [
        abs_points[1] - abs_points[0],
        abs_points[2] - abs_points[0],
        abs_points[3] - abs_points[0],
    ]
}

fn adapt_distance(distance: Distance, angle: Angle, size: Size) -> Distance {
    ((distance * angle.cos() * size.width as f64 / ORIGINAL_SIZE.width as f64).powi(2)
        + (distance * angle.sin() * size.height as f64 / ORIGINAL_SIZE.height as f64).powi(2))
    .sqrt()
}

fn main() {
    let mut drawing = Drawing::new();
    let size = drawing.size();
    drawing.set_center([size.width as f64 / 2.0, -(size.height as f64) / 2.0]);

    let mut turtle = drawing.add_turtle();
    turtle.use_radians();
    turtle.pen_up();

    let rp = rel_points;
    let ap = |point| adapt_point(point, size);
    let ad = |distance, angle| adapt_distance(distance, angle, size);

    let start_point = ap([240.0, 504.0]);
    turtle.set_fill_color(BACK_SHELL_COLOR);
    turtle.set_speed("instant");
    turtle.turn_towards(start_point);
    turtle.go_to(start_point);
    turtle.set_speed("faster");
    turtle.begin_fill();

    let start_heading = (180.0 + 32.01f64).to_radians();
    turtle.set_heading(start_heading);
    turtle.forward(ad(18.9, start_heading));
    turtle.bezier_rel(rp([
        ap([223.64, 514.18]),
        ap([222.18, 525.09]),
        ap([288.00, 597.09]),
        ap([323.94, 645.06]),
    ]));
    turtle.bezier_rel(rp([
        ap([323.91, 645.18]),
        ap([324.00, 623.09]),
        ap([283.27, 565.27]),
        ap([270.69, 529.94]),
    ]));
    turtle.bezier_rel(rp([
        ap([270.75, 529.94]),
        ap([444.75, 621.50]),
        ap([826.25, 622.50]),
        ap([973.09, 515.22]),
    ]));
    turtle.bezier_rel(rp([
        ap([973.12, 515.25]),
        ap([965.45, 552.18]),
        ap([923.09, 619.45]),
        ap([922.09, 646.52]),
    ]));
    turtle.bezier_rel(rp([
        ap([922.38, 647.00]),
        ap([931.09, 631.09]),
        ap([988.91, 554.55]),
        ap([1008.00, 517.12]),
    ]));
    let middle_curve_part1 = rp([
        ap([1008.12, 517.06]),
        ap([979.25, 500.88]),
        ap([960.12, 507.19]),
        ap([946.69, 510.31]),
    ]);
    turtle.bezier_rel(middle_curve_part1);
    let middle_curve_part2 = rp([
        ap([946.66, 510.41]),
        ap([750.73, 606.91]),
        ap([472.55, 603.45]),
        ap([239.57, 505.39]),
    ]);
    turtle.bezier_rel(middle_curve_part2);

    turtle.end_fill();
    turtle.set_fill_color(FRONT_SHELL_COLOR);
    turtle.begin_fill();

    turtle.bezier_rel(rp([
        ap([239.45, 504.36]),
        ap([233.00, 508.18]),
        ap([213.45, 519.82]),
        ap([212.50, 524.44]),
    ]));
    turtle.bezier_rel(rp([
        ap([212.25, 524.44]),
        ap([215.00, 570.50]),
        ap([300.00, 657.50]),
        ap([304.52, 700.83]),
    ]));
    turtle.bezier_rel(rp([
        ap([303.56, 702.56]),
        ap([206.50, 599.75]),
        ap([133.25, 541.75]),
        ap([138.00, 522.82]),
    ]));
    turtle.bezier_rel(rp([
        ap([138.00, 523.18]),
        ap([137.82, 511.73]),
        ap([145.55, 510.64]),
        ap([176.00, 476.00]),
    ]));
    turtle.bezier_rel(rp([
        ap([175.64, 475.55]),
        ap([138.73, 455.36]),
        ap([111.09, 430.55]),
        ap([103.73, 408.91]),
    ]));
    turtle.bezier_rel(rp([
        ap([103.91, 409.55]),
        ap([-21.00, 349.50]),
        ap([5.00, 282.50]),
        ap([52.00, 244.12]),
    ]));
    turtle.bezier_rel(rp([
        ap([52.69, 244.19]),
        ap([59.00, 289.00]),
        ap([83.12, 323.00]),
        ap([109.56, 344.59]),
    ]));
    let left_claw_heading = (180.0 - 82.13f64).to_radians();
    turtle.set_heading(left_claw_heading);
    turtle.forward(ad(124.2, turtle.heading()));
    turtle.bezier_rel(rp([
        ap([93.13, 221.13]),
        ap([163.25, 250.75]),
        ap([216.25, 316.75]),
        ap([148.35, 405.39]),
    ]));
    turtle.bezier_rel(rp([
        ap([148.52, 405.43]),
        ap([160.27, 422.64]),
        ap([185.00, 435.45]),
        ap([207.04, 443.65]),
    ]));
    let left_claw_heading = 45f64.to_radians();
    turtle.set_heading(left_claw_heading);
    turtle.forward(ad(12.7, turtle.heading()));
}
<|endoftext|>


<commit_before>fn main() {
    unimplemented!()
}
<commit_msg>Implement sender example<commit_after>extern crate rosc;

use std::{net, env, process, thread, f32};
use rosc::types::{OscPacket, OscMessage, OscType};
use rosc::encoder;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 3 {
        println!("Usage ./sender HOST_IP:HOST_PORT CLIENT_IP:CLIENT_PORT");
        process::exit(1);
    }

    let (host_ip, host_port) = rosc::utils::parse_ip_and_port(&args[1]).unwrap();
    let (to_ip, to_port) = rosc::utils::parse_ip_and_port(&args[2]).unwrap();
    let sock = net::UdpSocket::bind((host_ip, host_port)).unwrap();

    // switch view
    let msg_buf = encoder::encode(&OscPacket::Message(OscMessage {
                      addr: "/3".to_string(),
                      args: None,
                  }))
                      .unwrap();

    sock.send_to(&msg_buf, net::SocketAddrV4::new(to_ip, to_port)).unwrap();

    // send random values to xy fields
    let steps = 128;
    let step_size: f32 = 2.0 * f32::consts::PI / steps as f32;
    for i in 0.. {
        let x = 0.5 + (step_size * (i % steps) as f32).sin() / 2.0;
        let y = 0.5 + (step_size * (i % steps) as f32).cos() / 2.0;
        let mut msg_buf = encoder::encode(&OscPacket::Message(OscMessage {
                              addr: "/3/xy1".to_string(),
                              args: Some(vec![OscType::Float(x), OscType::Float(y)]),
                          }))
                              .unwrap();

        sock.send_to(&msg_buf, net::SocketAddrV4::new(to_ip, to_port)).unwrap();
        msg_buf = encoder::encode(&OscPacket::Message(OscMessage {
                          addr: "/3/xy2".to_string(),
                          args: Some(vec![OscType::Float(y), OscType::Float(x)]),
                      }))
                          .unwrap();
        sock.send_to(&msg_buf, net::SocketAddrV4::new(to_ip, to_port)).unwrap();
        thread::sleep_ms(20);
    }

    drop(sock);
}
<|endoftext|>


<commit_before>#[macro_use(u32_bytes, bytes_u32)]
extern crate dhcp4r;

use std::net::UdpSocket;
use std::time::{Duration, Instant};
use std::collections::HashMap;
use std::ops::Add;
use std::cmp::PartialEq;

// Server configuration
const SERVER_IP: [u8; 4] = [192, 168, 1, 76];
const IP_START: [u8; 4] = [192, 168, 1, 100];
const SUBNET_MASK: [u8; 4] = [255, 255, 255, 0];
const DNS_IPS: [u8; 8] = [8, 8, 8, 8, 8, 8, 4, 4]; // google dns servers
const ROUTER_IP: [u8; 4] = [192, 168, 1, 254];
const LEASE_DURATION_SECS: u32 = 600;
const LEASE_NUM: u32 = 100;

// Derrived constants
const LEASE_DURATION_BYTES: [u8; 4] = u32_bytes!(LEASE_DURATION_SECS);
const IP_START_NUM: u32 = bytes_u32!(IP_START);

fn main() {
    let lease_duration: Duration = Duration::new(LEASE_DURATION_SECS as u64, 0);

    let mut lastpos: u32 = 0;
    let mut leases: HashMap<u32, ([u8; 6], Instant)> = HashMap::new();
    let socket = UdpSocket::bind("255.255.255.255:67").unwrap();
    // socket.set_broadcast(true).unwrap();
    let mut buf = [0; 1500];

    loop {
        let (n, _) = socket.recv_from(&mut buf).unwrap();
        println!("Packet received: {:?}", &buf[..n]);
        let packet = dhcp4r::decode(&buf[..n]).unwrap();

        if let Some(x) = packet.option(dhcp4r::OPTION_DHCP_MESSAGE_TYPE) {
            if x.len() != 1 {
                continue; // Invalid message - IGNORE
            }
            let resp_packet: dhcp4r::Packet;
            match x[0] {
                dhcp4r::DISCOVER => {
                    let instant = Instant::now();
                    for i in 1..LEASE_NUM {
                        if available(&mut leases, &packet.chaddr, &instant, lastpos) {
                            resp_packet = reply(dhcp4r::OFFER,
                                                &packet,
                                                u32_bytes!(IP_START_NUM + lastpos));
                            break;
                        }
                        lastpos = (lastpos + 1) % LEASE_NUM;
                    }
                    // TODO favour REQUESTED_IP_ADDRESS
                    // No available leases, ignore
                    continue;
                }

                dhcp4r::REQUEST => {
                    if notForThisServer(&packet) {
                        continue;
                    }

                    let req_ip = match packet.option(dhcp4r::OPTION_REQUESTED_IP_ADDRESS) {
                        None => packet.ciaddr,
                        Some(x) => {
                            if x.len() != 4 {
                                continue;
                            } else {
                                [x[0], x[1], x[2], x[3]]
                            }
                        }
                    };

                    let req_ip_num = bytes_u32!(req_ip);
                    if req_ip_num < IP_START_NUM || req_ip_num >= IP_START_NUM + LEASE_NUM ||
                       !available(&leases,
                                  &packet.chaddr,
                                  &Instant::now(),
                                  req_ip_num - IP_START_NUM) {
                        // TODO reply NAK
                        continue;
                    }

                    if let Some(l) = leases.get(&req_ip_num) {
                        // TODO check lease time
                        if l.0 != packet.chaddr {
                            // TODO reply NAK
                            continue;
                        }
                    }
                    leases.insert(req_ip_num - IP_START_NUM,
                                  (packet.chaddr, Instant::now().add(lease_duration)));
                    resp_packet = reply(dhcp4r::ACK, &packet, req_ip);
                }
                // Not technically necessary
                dhcp4r::RELEASE => {
                    if notForThisServer(&packet) {
                        continue;
                    }
                    let ip_num = bytes_u32!(packet.ciaddr);
                    if available(&leases, &packet.chaddr, &Instant::now(), ip_num) {
                        leases.remove(&ip_num);
                    }
                    continue;
                }
                // dhcp4r::INFORM => {}
                _ => {
                    continue;
                }
            }
            if let Err(x) = socket.send(&buf[..resp_packet.encode(&mut buf)]) {
                println!("Error: {}", x);
            }

        }

        // for option in packet.options {
        // print!("{}:{:?}\n", option.title(), option.data)
        // }
    }
}

fn notForThisServer(packet: &dhcp4r::Packet) -> bool {
    match packet.option(dhcp4r::OPTION_SERVER_IDENTIFIER) {
        None => true,
        Some(x) => x != SERVER_IP,
    }
}

fn available(leases: &HashMap<u32, ([u8; 6], Instant)>,
             chaddr: &[u8; 6],
             instant: &Instant,
             pos: u32)
             -> bool {
    if let Some(x) = leases.get(&pos) {
        return x.0 == *chaddr || instant.gt(&x.1);
    }
    true
}

// fn write(s: UdpSocket, p: dhcp4r::Packet) {
//
// }

fn nak<'a>(req_packet: dhcp4r::Packet, message: &'a [u8]) -> dhcp4r::Packet<'a> {
    dhcp4r::Packet {
        reply: true,
        hops: 0,
        xid: req_packet.xid,
        secs: 0,
        broadcast: req_packet.broadcast,
        ciaddr: [0, 0, 0, 0],
        yiaddr: [0, 0, 0, 0],
        siaddr: [0, 0, 0, 0],
        giaddr: req_packet.giaddr,
        chaddr: req_packet.chaddr,
        options: vec![dhcp4r::Option {
                          code: dhcp4r::OPTION_DHCP_MESSAGE_TYPE,
                          data: &[dhcp4r::NAK],
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_SERVER_IDENTIFIER,
                          data: &SERVER_IP,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_MESSAGE,
                          data: message,
                      }],
    }
}

fn reply<'a>(msg_type: u8, req_packet: &dhcp4r::Packet, offer_ip: [u8; 4]) -> dhcp4r::Packet<'a> {
    dhcp4r::Packet {
        reply: true,
        hops: 0,
        xid: req_packet.xid,
        secs: 0,
        broadcast: req_packet.broadcast,
        ciaddr: req_packet.ciaddr,
        yiaddr: req_packet.yiaddr,
        siaddr: SERVER_IP,
        giaddr: req_packet.giaddr,
        chaddr: req_packet.chaddr,
        options: vec![dhcp4r::Option {
                          code: dhcp4r::OPTION_DHCP_MESSAGE_TYPE,
                          data: &[msg_type],
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_SERVER_IDENTIFIER,
                          data: &SERVER_IP,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_IP_ADDRESS_LEASE_TIME,
                          data: &LEASE_DURATION_BYTES,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_ROUTER,
                          data: &ROUTER_IP,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_SUBNET_MASK,
                          data: &SUBNET_MASK,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_DOMAIN_NAME_SERVER,
                          data: &DNS_IPS,
                      }],
    }
}
<commit_msg>First working dhcp server<commit_after>#[macro_use(u32_bytes, bytes_u32)]
extern crate dhcp4r;

use std::net::{UdpSocket, SocketAddr, Ipv4Addr, IpAddr};
use std::time::{Duration, Instant};
use std::collections::HashMap;
use std::ops::Add;

// Server configuration
const SERVER_IP: [u8; 4] = [192, 168, 0, 76];
const IP_START: [u8; 4] = [192, 168, 0, 180];
const SUBNET_MASK: [u8; 4] = [255, 255, 255, 0];
const DNS_IPS: [u8; 4] = [192, 168, 0, 254]; //[8, 8, 8, 8,8, 8, 4, 4]; // google dns servers
const ROUTER_IP: [u8; 4] = [192, 168, 0, 254];
const LEASE_DURATION_SECS: u32 = 7200;
const LEASE_NUM: u32 = 100;

// Derrived constants
const LEASE_DURATION_BYTES: [u8; 4] = u32_bytes!(LEASE_DURATION_SECS);
const IP_START_NUM: u32 = bytes_u32!(IP_START);

fn main() {
    // let broadcast: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 67);

    let lease_duration: Duration = Duration::new(LEASE_DURATION_SECS as u64, 0);

    let mut lastpos: u32 = 0;
    let mut leases: HashMap<u32, ([u8; 6], Instant)> = HashMap::new();
    let socket = UdpSocket::bind("0.0.0.0:67").unwrap();
    socket.set_broadcast(true).unwrap();
    let mut in_buf = [0; 1500];
    let mut out_buf = [0; 1500];

    loop {
        let (n, src) = socket.recv_from(&mut in_buf).unwrap();
        println!("Packet received: {:?}", &in_buf[..n]);
        let packet = dhcp4r::decode(&in_buf[..n]).unwrap();

        if let Some(x) = packet.option(dhcp4r::OPTION_DHCP_MESSAGE_TYPE) {
            if x.len() != 1 {
                continue; // Invalid message - IGNORE
            }
            let send = Sender {
                soc: &socket,
                addr: src,
                buf: &mut out_buf, // broadcast: &broadcast,
            };
            match x[0] {
                dhcp4r::DISCOVER => {
                    // if let Some(x) = packet.option(dhcp4r::OPTION_REQUESTED_IP_ADDRESS) {}
                    for _ in 0..LEASE_NUM {
                        // TODO prefer REQUESTED_IP_ADDRESS
                        lastpos = (lastpos + 1) % LEASE_NUM;
                        if available(&mut leases,
                                     &packet.chaddr,
                                     &Instant::now(),
                                     IP_START_NUM + lastpos) {
                            reply(send,
                                  dhcp4r::OFFER,
                                  &packet,
                                  u32_bytes!(IP_START_NUM + lastpos));
                            break;
                        }

                    }
                }

                dhcp4r::REQUEST => {
                    if !for_this_server(&packet) {
                        continue;
                    }

                    let req_ip = match packet.option(dhcp4r::OPTION_REQUESTED_IP_ADDRESS) {
                        None => packet.ciaddr,
                        Some(x) => {
                            if x.len() != 4 {
                                continue;
                            } else {
                                [x[0], x[1], x[2], x[3]]
                            }
                        }
                    };

                    let req_ip_num = bytes_u32!(req_ip);
                    if !available(&leases, &packet.chaddr, &Instant::now(), req_ip_num) {
                        nak(send, &packet, b"Requested IP not available");
                        continue;
                    }
                    leases.insert(req_ip_num,
                                  (packet.chaddr, Instant::now().add(lease_duration)));
                    reply(send, dhcp4r::ACK, &packet, req_ip);
                }
                // Not technically necessary
                dhcp4r::RELEASE => {
                    if !for_this_server(&packet) {
                        continue;
                    }
                    let ip_num = bytes_u32!(packet.ciaddr);
                    if available(&leases, &packet.chaddr, &Instant::now(), ip_num) {
                        leases.remove(&ip_num);
                    }
                }
                // dhcp4r::INFORM => {}
                _ => {}
            }
        }

        // for option in packet.options {
        // print!("{}:{:?}\n", option.title(), option.data)
        // }
    }
}

struct Sender<'a> {
    buf: &'a mut [u8; 1500],
    soc: &'a UdpSocket,
    // broadcast: &'a SocketAddrV4,
    addr: SocketAddr,
}

impl<'a> Sender<'a> {
    fn send(self, p: dhcp4r::Packet) {
        let len = p.encode(self.buf);
        let mut addr = self.addr;
        if p.broadcast || addr.ip() == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) {
            addr.set_ip(IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255)));
        }

        if let Err(x) = self.soc.send_to(&self.buf[..len], addr) {
            println!("Error: {}", x);
        } else {
            println!("Packet sent: {:?}", &self.buf[..len]);
        }
    }
}

fn for_this_server(packet: &dhcp4r::Packet) -> bool {
    match packet.option(dhcp4r::OPTION_SERVER_IDENTIFIER) {
        None => false,
        Some(x) => x == SERVER_IP,
    }
}

fn available(leases: &HashMap<u32, ([u8; 6], Instant)>,
             chaddr: &[u8; 6],
             instant: &Instant,
             pos: u32)
             -> bool {
    return pos >= IP_START_NUM && pos < IP_START_NUM + LEASE_NUM &&
           match leases.get(&pos) {
        Some(x) => x.0 == *chaddr && instant.gt(&x.1),
        None => true,
    };
}

fn nak(s: Sender, req_packet: &dhcp4r::Packet, message: &[u8]) {
    s.send(dhcp4r::Packet {
        reply: true,
        hops: 0,
        xid: req_packet.xid,
        secs: 0,
        broadcast: req_packet.broadcast,
        ciaddr: [0, 0, 0, 0],
        yiaddr: [0, 0, 0, 0],
        siaddr: [0, 0, 0, 0],
        giaddr: req_packet.giaddr,
        chaddr: req_packet.chaddr,
        options: vec![dhcp4r::Option {
                          code: dhcp4r::OPTION_DHCP_MESSAGE_TYPE,
                          data: &[dhcp4r::NAK],
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_SERVER_IDENTIFIER,
                          data: &SERVER_IP,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_MESSAGE,
                          data: message,
                      }],
    });
}

fn reply(s: Sender, msg_type: u8, req_packet: &dhcp4r::Packet, offer_ip: [u8; 4]) {
    s.send(dhcp4r::Packet {
        reply: true,
        hops: 0,
        xid: req_packet.xid,
        secs: 0,
        broadcast: req_packet.broadcast,
        ciaddr: req_packet.ciaddr,
        yiaddr: offer_ip,
        siaddr: [0, 0, 0, 0], // SERVER_IP,
        giaddr: req_packet.giaddr,
        chaddr: req_packet.chaddr,
        options: vec![dhcp4r::Option {
                          code: dhcp4r::OPTION_DHCP_MESSAGE_TYPE,
                          data: &[msg_type],
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_SERVER_IDENTIFIER,
                          data: &SERVER_IP,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_IP_ADDRESS_LEASE_TIME,
                          data: &LEASE_DURATION_BYTES,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_SUBNET_MASK,
                          data: &SUBNET_MASK,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_ROUTER,
                          data: &ROUTER_IP,
                      },
                      dhcp4r::Option {
                          code: dhcp4r::OPTION_DOMAIN_NAME_SERVER,
                          data: &DNS_IPS,
                      }],
    });
}
<|endoftext|>


<commit_before>use crate::common::CompositeFile;
use crate::directory::FileSlice;
use crate::fastfield::MultiValuedFastFieldReader;
use crate::fastfield::{BytesFastFieldReader, FastValue};
use crate::fastfield::{FastFieldNotAvailableError, FastFieldReader};
use crate::schema::{Cardinality, Field, FieldType, Schema};
use crate::space_usage::PerFieldSpaceUsage;
use crate::TantivyError;

/// Provides access to all of the FastFieldReader.
///
/// Internally, `FastFieldReaders` have preloaded fast field readers,
/// and just wraps several `HashMap`.
#[derive(Clone)]
pub struct FastFieldReaders {
    schema: Schema,
    fast_fields_composite: CompositeFile,
}
#[derive(Eq, PartialEq, Debug)]
enum FastType {
    I64,
    U64,
    F64,
    Date,
}

fn type_and_cardinality(field_type: &FieldType) -> Option<(FastType, Cardinality)> {
    match field_type {
        FieldType::U64(options) => options
            .get_fastfield_cardinality()
            .map(|cardinality| (FastType::U64, cardinality)),
        FieldType::I64(options) => options
            .get_fastfield_cardinality()
            .map(|cardinality| (FastType::I64, cardinality)),
        FieldType::F64(options) => options
            .get_fastfield_cardinality()
            .map(|cardinality| (FastType::F64, cardinality)),
        FieldType::Date(options) => options
            .get_fastfield_cardinality()
            .map(|cardinality| (FastType::Date, cardinality)),
        FieldType::HierarchicalFacet => Some((FastType::U64, Cardinality::MultiValues)),
        _ => None,
    }
}

impl FastFieldReaders {
    pub(crate) fn new(
        schema: Schema,
        fast_fields_composite: CompositeFile,
    ) -> crate::Result<FastFieldReaders> {
        Ok(FastFieldReaders {
            fast_fields_composite,
            schema,
        })
    }

    pub(crate) fn space_usage(&self) -> PerFieldSpaceUsage {
        self.fast_fields_composite.space_usage()
    }

    fn fast_field_data(&self, field: Field, idx: usize) -> crate::Result<FileSlice> {
        self.fast_fields_composite
            .open_read_with_idx(field, idx)
            .ok_or_else(|| {
                let field_name = self.schema.get_field_entry(field).name();
                TantivyError::SchemaError(format!("Field({}) data was not found", field_name))
            })
    }

    fn check_type(
        &self,
        field: Field,
        expected_fast_type: FastType,
        expected_cardinality: Cardinality,
    ) -> crate::Result<()> {
        let field_entry = self.schema.get_field_entry(field);
        let (fast_type, cardinality) =
            type_and_cardinality(field_entry.field_type()).ok_or_else(|| {
                crate::TantivyError::SchemaError(format!(
                    "Field {:?} is not a fast field.",
                    field_entry.name()
                ))
            })?;
        if fast_type != expected_fast_type {
            return Err(crate::TantivyError::SchemaError(format!(
                "Field {:?} is of type {:?}, expected {:?}.",
                field_entry.name(),
                fast_type,
                expected_fast_type
            )));
        }
        if cardinality != expected_cardinality {
            return Err(crate::TantivyError::SchemaError(format!(
                "Field {:?} is of cardinality {:?}, expected {:?}.",
                field_entry.name(),
                cardinality,
                expected_cardinality
            )));
        }
        Ok(())
    }

    pub(crate) fn typed_fast_field_reader<TFastValue: FastValue>(
        &self,
        field: Field,
    ) -> crate::Result<FastFieldReader<TFastValue>> {
        let fast_field_slice = self.fast_field_data(field, 0)?;
        FastFieldReader::open(fast_field_slice)
    }

    pub(crate) fn typed_fast_field_multi_reader<TFastValue: FastValue>(
        &self,
        field: Field,
    ) -> crate::Result<MultiValuedFastFieldReader<TFastValue>> {
        let fast_field_slice_idx = self.fast_field_data(field, 0)?;
        let fast_field_slice_vals = self.fast_field_data(field, 1)?;
        let idx_reader = FastFieldReader::open(fast_field_slice_idx)?;
        let vals_reader: FastFieldReader<TFastValue> =
            FastFieldReader::open(fast_field_slice_vals)?;
        Ok(MultiValuedFastFieldReader::open(idx_reader, vals_reader))
    }

    /// Returns the `u64` fast field reader reader associated to `field`.
    ///
    /// If `field` is not a u64 fast field, this method returns `None`.
    pub fn u64(&self, field: Field) -> crate::Result<FastFieldReader<u64>> {
        self.check_type(field, FastType::U64, Cardinality::SingleValue)?;
        self.typed_fast_field_reader(field)
    }

    /// Returns the `i64` fast field reader reader associated to `field`.
    ///
    /// If `field` is not a i64 fast field, this method returns `None`.
    pub fn i64(&self, field: Field) -> crate::Result<FastFieldReader<i64>> {
        self.check_type(field, FastType::I64, Cardinality::SingleValue)?;
        self.typed_fast_field_reader(field)
    }

    /// Returns the `i64` fast field reader reader associated to `field`.
    ///
    /// If `field` is not a i64 fast field, this method returns `None`.
    pub fn date(&self, field: Field) -> crate::Result<FastFieldReader<crate::DateTime>> {
        self.check_type(field, FastType::Date, Cardinality::SingleValue)?;
        self.typed_fast_field_reader(field)
    }

    /// Returns the `f64` fast field reader reader associated to `field`.
    ///
    /// If `field` is not a f64 fast field, this method returns `None`.
    pub fn f64(&self, field: Field) -> crate::Result<FastFieldReader<f64>> {
        self.check_type(field, FastType::F64, Cardinality::SingleValue)?;
        self.typed_fast_field_reader(field)
    }

    /// Returns a `u64s` multi-valued fast field reader reader associated to `field`.
    ///
    /// If `field` is not a u64 multi-valued fast field, this method returns `None`.
    pub fn u64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<u64>> {
        self.check_type(field, FastType::U64, Cardinality::MultiValues)?;
        self.typed_fast_field_multi_reader(field)
    }

    /// Returns a `i64s` multi-valued fast field reader reader associated to `field`.
    ///
    /// If `field` is not a i64 multi-valued fast field, this method returns `None`.
    pub fn i64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<i64>> {
        self.check_type(field, FastType::I64, Cardinality::MultiValues)?;
        self.typed_fast_field_multi_reader(field)
    }

    /// Returns a `f64s` multi-valued fast field reader reader associated to `field`.
    ///
    /// If `field` is not a f64 multi-valued fast field, this method returns `None`.
    pub fn f64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<f64>> {
        self.check_type(field, FastType::F64, Cardinality::MultiValues)?;
        self.typed_fast_field_multi_reader(field)
    }

    /// Returns a `crate::DateTime` multi-valued fast field reader reader associated to `field`.
    ///
    /// If `field` is not a `crate::DateTime` multi-valued fast field, this method returns `None`.
    pub fn dates(
        &self,
        field: Field,
    ) -> crate::Result<MultiValuedFastFieldReader<crate::DateTime>> {
        self.check_type(field, FastType::Date, Cardinality::MultiValues)?;
        self.typed_fast_field_multi_reader(field)
    }

    /// Returns the `bytes` fast field reader associated to `field`.
    ///
    /// If `field` is not a bytes fast field, returns `None`.
    pub fn bytes(&self, field: Field) -> crate::Result<BytesFastFieldReader> {
        let field_entry = self.schema.get_field_entry(field);
        if let FieldType::Bytes(bytes_option) = field_entry.field_type() {
            if !bytes_option.is_fast() {
                return Err(crate::TantivyError::SchemaError(format!(
                    "Field {:?} is not a fast field.",
                    field_entry.name()
                )));
            }
            let fast_field_idx_file = self.fast_field_data(field, 0)?;
            let idx_reader = FastFieldReader::open(fast_field_idx_file)?;
            let data = self.fast_field_data(field, 1)?;
            BytesFastFieldReader::open(idx_reader, data)
        } else {
            Err(FastFieldNotAvailableError::new(field_entry).into())
        }
    }
}
<commit_msg>Re-added u64_lenient as a public API<commit_after>use crate::common::CompositeFile;
use crate::directory::FileSlice;
use crate::fastfield::MultiValuedFastFieldReader;
use crate::fastfield::{BytesFastFieldReader, FastValue};
use crate::fastfield::{FastFieldNotAvailableError, FastFieldReader};
use crate::schema::{Cardinality, Field, FieldType, Schema};
use crate::space_usage::PerFieldSpaceUsage;
use crate::TantivyError;

/// Provides access to all of the FastFieldReader.
///
/// Internally, `FastFieldReaders` have preloaded fast field readers,
/// and just wraps several `HashMap`.
#[derive(Clone)]
pub struct FastFieldReaders {
    schema: Schema,
    fast_fields_composite: CompositeFile,
}
#[derive(Eq, PartialEq, Debug)]
enum FastType {
    I64,
    U64,
    F64,
    Date,
}

fn type_and_cardinality(field_type: &FieldType) -> Option<(FastType, Cardinality)> {
    match field_type {
        FieldType::U64(options) => options
            .get_fastfield_cardinality()
            .map(|cardinality| (FastType::U64, cardinality)),
        FieldType::I64(options) => options
            .get_fastfield_cardinality()
            .map(|cardinality| (FastType::I64, cardinality)),
        FieldType::F64(options) => options
            .get_fastfield_cardinality()
            .map(|cardinality| (FastType::F64, cardinality)),
        FieldType::Date(options) => options
            .get_fastfield_cardinality()
            .map(|cardinality| (FastType::Date, cardinality)),
        FieldType::HierarchicalFacet => Some((FastType::U64, Cardinality::MultiValues)),
        _ => None,
    }
}

impl FastFieldReaders {
    pub(crate) fn new(
        schema: Schema,
        fast_fields_composite: CompositeFile,
    ) -> crate::Result<FastFieldReaders> {
        Ok(FastFieldReaders {
            fast_fields_composite,
            schema,
        })
    }

    pub(crate) fn space_usage(&self) -> PerFieldSpaceUsage {
        self.fast_fields_composite.space_usage()
    }

    fn fast_field_data(&self, field: Field, idx: usize) -> crate::Result<FileSlice> {
        self.fast_fields_composite
            .open_read_with_idx(field, idx)
            .ok_or_else(|| {
                let field_name = self.schema.get_field_entry(field).name();
                TantivyError::SchemaError(format!("Field({}) data was not found", field_name))
            })
    }

    fn check_type(
        &self,
        field: Field,
        expected_fast_type: FastType,
        expected_cardinality: Cardinality,
    ) -> crate::Result<()> {
        let field_entry = self.schema.get_field_entry(field);
        let (fast_type, cardinality) =
            type_and_cardinality(field_entry.field_type()).ok_or_else(|| {
                crate::TantivyError::SchemaError(format!(
                    "Field {:?} is not a fast field.",
                    field_entry.name()
                ))
            })?;
        if fast_type != expected_fast_type {
            return Err(crate::TantivyError::SchemaError(format!(
                "Field {:?} is of type {:?}, expected {:?}.",
                field_entry.name(),
                fast_type,
                expected_fast_type
            )));
        }
        if cardinality != expected_cardinality {
            return Err(crate::TantivyError::SchemaError(format!(
                "Field {:?} is of cardinality {:?}, expected {:?}.",
                field_entry.name(),
                cardinality,
                expected_cardinality
            )));
        }
        Ok(())
    }

    pub(crate) fn typed_fast_field_reader<TFastValue: FastValue>(
        &self,
        field: Field,
    ) -> crate::Result<FastFieldReader<TFastValue>> {
        let fast_field_slice = self.fast_field_data(field, 0)?;
        FastFieldReader::open(fast_field_slice)
    }

    pub(crate) fn typed_fast_field_multi_reader<TFastValue: FastValue>(
        &self,
        field: Field,
    ) -> crate::Result<MultiValuedFastFieldReader<TFastValue>> {
        let fast_field_slice_idx = self.fast_field_data(field, 0)?;
        let fast_field_slice_vals = self.fast_field_data(field, 1)?;
        let idx_reader = FastFieldReader::open(fast_field_slice_idx)?;
        let vals_reader: FastFieldReader<TFastValue> =
            FastFieldReader::open(fast_field_slice_vals)?;
        Ok(MultiValuedFastFieldReader::open(idx_reader, vals_reader))
    }

    /// Returns the `u64` fast field reader reader associated to `field`.
    ///
    /// If `field` is not a u64 fast field, this method returns `None`.
    pub fn u64(&self, field: Field) -> crate::Result<FastFieldReader<u64>> {
        self.check_type(field, FastType::U64, Cardinality::SingleValue)?;
        self.typed_fast_field_reader(field)
    }

    /// Returns the `u64` fast field reader reader associated to `field`, regardless of whether the given
    /// field is effectively of type `u64` or not.
    ///
    /// If not, the fastfield reader will returns the u64-value associated to the original FastValue.
    pub fn u64_lenient(&self, field: Field) -> crate::Result<FastFieldReader<u64>> {
        self.typed_fast_field_reader(field)
    }

    /// Returns the `i64` fast field reader reader associated to `field`.
    ///
    /// If `field` is not a i64 fast field, this method returns `None`.
    pub fn i64(&self, field: Field) -> crate::Result<FastFieldReader<i64>> {
        self.check_type(field, FastType::I64, Cardinality::SingleValue)?;
        self.typed_fast_field_reader(field)
    }

    /// Returns the `i64` fast field reader reader associated to `field`.
    ///
    /// If `field` is not a i64 fast field, this method returns `None`.
    pub fn date(&self, field: Field) -> crate::Result<FastFieldReader<crate::DateTime>> {
        self.check_type(field, FastType::Date, Cardinality::SingleValue)?;
        self.typed_fast_field_reader(field)
    }

    /// Returns the `f64` fast field reader reader associated to `field`.
    ///
    /// If `field` is not a f64 fast field, this method returns `None`.
    pub fn f64(&self, field: Field) -> crate::Result<FastFieldReader<f64>> {
        self.check_type(field, FastType::F64, Cardinality::SingleValue)?;
        self.typed_fast_field_reader(field)
    }

    /// Returns a `u64s` multi-valued fast field reader reader associated to `field`.
    ///
    /// If `field` is not a u64 multi-valued fast field, this method returns `None`.
    pub fn u64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<u64>> {
        self.check_type(field, FastType::U64, Cardinality::MultiValues)?;
        self.typed_fast_field_multi_reader(field)
    }

    /// Returns a `i64s` multi-valued fast field reader reader associated to `field`.
    ///
    /// If `field` is not a i64 multi-valued fast field, this method returns `None`.
    pub fn i64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<i64>> {
        self.check_type(field, FastType::I64, Cardinality::MultiValues)?;
        self.typed_fast_field_multi_reader(field)
    }

    /// Returns a `f64s` multi-valued fast field reader reader associated to `field`.
    ///
    /// If `field` is not a f64 multi-valued fast field, this method returns `None`.
    pub fn f64s(&self, field: Field) -> crate::Result<MultiValuedFastFieldReader<f64>> {
        self.check_type(field, FastType::F64, Cardinality::MultiValues)?;
        self.typed_fast_field_multi_reader(field)
    }

    /// Returns a `crate::DateTime` multi-valued fast field reader reader associated to `field`.
    ///
    /// If `field` is not a `crate::DateTime` multi-valued fast field, this method returns `None`.
    pub fn dates(
        &self,
        field: Field,
    ) -> crate::Result<MultiValuedFastFieldReader<crate::DateTime>> {
        self.check_type(field, FastType::Date, Cardinality::MultiValues)?;
        self.typed_fast_field_multi_reader(field)
    }

    /// Returns the `bytes` fast field reader associated to `field`.
    ///
    /// If `field` is not a bytes fast field, returns `None`.
    pub fn bytes(&self, field: Field) -> crate::Result<BytesFastFieldReader> {
        let field_entry = self.schema.get_field_entry(field);
        if let FieldType::Bytes(bytes_option) = field_entry.field_type() {
            if !bytes_option.is_fast() {
                return Err(crate::TantivyError::SchemaError(format!(
                    "Field {:?} is not a fast field.",
                    field_entry.name()
                )));
            }
            let fast_field_idx_file = self.fast_field_data(field, 0)?;
            let idx_reader = FastFieldReader::open(fast_field_idx_file)?;
            let data = self.fast_field_data(field, 1)?;
            BytesFastFieldReader::open(idx_reader, data)
        } else {
            Err(FastFieldNotAvailableError::new(field_entry).into())
        }
    }
}
<|endoftext|>


<commit_before>use glium::{Frame, VertexBuffer, Blend, Surface};
use glium::Display;
use glium::index::{IndexBuffer, PrimitiveType};
use glium::draw_parameters::DrawParameters;
use glium::draw_parameters::LinearBlendingFactor::*;
use glium::draw_parameters::BlendingFunction::*;
use glium::uniforms::{Uniforms, UniformsStorage, AsUniformValue};

use nalgebra::Norm;
use texturegen::GeneratorView;
use texturegen::process::{Process, Setting, BlendType};

use {SimContext, Selection, Node, Vect, input_pos, output_pos};
use super::{RenderContext, Vertex, vert};
use State::*;
use math::*;

pub fn render(display: &Display, rctx: &mut RenderContext, gen: GeneratorView<Node>, ctx: &SimContext) {
    let mut target = display.draw();
    target.clear_color(0.0157, 0.0173, 0.0204, 1.);
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let dims = display.get_framebuffer_dimensions();
    for (_, data) in gen.iter() {
        let pos = flip_y(data.pos);
        let corner_pos = pos - Vect::new(ctx.node_width, ctx.node_width) * 0.5;
        let matrix = rctx.cam * translation(corner_pos.x, corner_pos.y);
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        draw(&mut target, &rctx, "back", "plain", &uniforms, &draw_params);
        let matrix = rctx.cam * translation(corner_pos.x + 0.05, corner_pos.y + 0.05) * scale(0.9, 0.9);
        let program = data.shader.borrow();
        let program = program.as_ref().expect("Node didn't have shader.");
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        let model = rctx.models.get("node").unwrap();
        target.draw(&model.vertices, &model.indices, &program, &uniforms, &draw_params).expect("Drawing node failed.");

        let mut draw = |things: &[_]| {
            for p in things {
                let p = pos + flip_y(*p) - Vect::new(ctx.thingy_size, ctx.thingy_size) * 0.5;
                let matrix = rctx.cam * translation(p.x, p.y) * scale(ctx.thingy_size, ctx.thingy_size);
                let uniforms = uniform! {
                    matrix: *matrix.as_ref(),
                };
                draw(&mut target, &rctx, "node", "plain", &uniforms, &draw_params);
            }
        };
        draw(&data.outputs.borrow());
        draw(&data.inputs.borrow());
    }
    let mut lines = Vec::with_capacity(gen.connections());
    if let Some(AddingEdge) = ctx.state {
        if let Some(Selection::Output(trg)) = ctx.selected {
            let src = output_pos(&gen, trg, ctx.thingy_size);
            let trg = Vect::new(ctx.mouse_pos.x, -ctx.mouse_pos.y);
            add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
        }
    }
    for (src, trg) in gen.iter_connections() {
        let src = output_pos(&gen, src, ctx.thingy_size);
        let trg = input_pos(&gen, trg, ctx.thingy_size);
        let trg = Vect::new(trg[0], trg[1] + ctx.thingy_size);
        add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
    }
    let vertices = VertexBuffer::new(display, &lines).unwrap();
    let indices = (0..lines.len() as u32).collect::<Vec<_>>();
    let indices = IndexBuffer::new(display, PrimitiveType::LinesList, &indices).unwrap();
    let matrix = rctx.cam * translation(0., 0.);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
    };
    let program = rctx.programs.get("plain").unwrap();
    target.draw(&vertices, &indices, program, &uniforms, &draw_params).unwrap();

    if let Some(s) = ctx.selected {
        if let Some(node) = s.node() {
            let set = if let Selection::Setting(_, s) = s {
                Some(s)
            } else {
                None
            };
            let node = gen.get(node).expect("Selection should always point to real node.").0;
            let settings = node.settings();
            let size = 23.;
            for (i, setting) in settings.iter().enumerate() {
                if set == Some(i) {
                    continue;
                }
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = setting.to_string();
                string.push_str(": ");
                string.push_str(&node.setting(setting).to_string());
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
            if let Some(i) = set {
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = settings[i].to_string();
                string.push_str(": ");
                match node.setting(settings[i]) {
                    Setting::Blend(ref b) => {
                        let bb = rctx.fonts.bounding_box("anka", size, &string).unwrap();
                        string.push_str(&format!("{:?}", b));
                        let max = from_window_to_screen(dims, [bb.max.x, bb.max.y]);
                        let pos = pos + Vect::new(max.x * 1.5, -1. / 20.);
                        for (i, blend) in BlendType::iter_variants().enumerate() {
                            let blend = format!("{:?}", blend);
                            let pos = pos + Vect::new(0., -(i as f32 / 20.));
                            rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &blend);
                        }
                    },
                    _ => {
                        if let Some(Writing) = ctx.state {
                            let ch = if 0 % 120 < 60 { //TODO: Fix Me
                                '|'
                            } else {
                                ' '
                            };
                            if ctx.text.is_empty() {
                                string.push(ch);
                            } else {
                                let (a, b) = ctx.text.split_at(ctx.caret);
                                string.push_str(&format!("{}{}{}", a, ch, b));
                            }
                        }
                    }
                }
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
        }
    }
    target.finish().unwrap();
}

fn draw<A, B>(target: &mut Frame, rctx: &RenderContext, model: &str, program: &str, uniforms: &UniformsStorage<A, B>, draw_params: &DrawParameters)
    where A: AsUniformValue,
          B: Uniforms,
{
    let model = rctx.models.get(model).unwrap();
    let program = rctx.programs.get(program).unwrap();
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params).unwrap();
}

fn add_arrow(lines: &mut Vec<Vertex>, src: Vect, trg: Vect, len: f32, theta: f32) {
    lines.push(vert(src.x, src.y));
    lines.push(vert(trg.x, trg.y));
    let vec = (src - trg).normalize();
    let mut add_part = |theta: f32| {
        let (sin, cos) = theta.sin_cos();
        let arrow = Vect::new(
            vec.x * cos - vec.y * sin,
            vec.x * sin + vec.y * cos);
        lines.push(vert(trg.x, trg.y));
        let v = trg + (arrow * len);
        lines.push(vert(v.x, v.y));
    };
    add_part(theta);
    add_part(-theta);
}
<commit_msg>gen changed to world<commit_after>use glium::{Frame, VertexBuffer, Blend, Surface};
use glium::Display;
use glium::index::{IndexBuffer, PrimitiveType};
use glium::draw_parameters::DrawParameters;
use glium::draw_parameters::LinearBlendingFactor::*;
use glium::draw_parameters::BlendingFunction::*;
use glium::uniforms::{Uniforms, UniformsStorage, AsUniformValue};

use nalgebra::Norm;
use texturegen::GeneratorView;
use texturegen::process::{Process, Setting, BlendType};

use {SimContext, Selection, Node, Vect, input_pos, output_pos};
use super::{RenderContext, Vertex, vert};
use State::*;
use math::*;

pub fn render(display: &Display, rctx: &mut RenderContext, world: GeneratorView<Node>, ctx: &SimContext) {
    let mut target = display.draw();
    target.clear_color(0.0157, 0.0173, 0.0204, 1.);
    let draw_params = DrawParameters {
        blend: Blend {
            color: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            alpha: Addition {
                source: SourceAlpha,
                destination: OneMinusSourceAlpha,
            },
            constant_value: (0f32, 0f32, 0f32, 1f32),
        },
        smooth: None,
        ..Default::default()
    };
    let dims = display.get_framebuffer_dimensions();
    for (_, data) in world.iter() {
        let pos = flip_y(data.pos);
        let corner_pos = pos - Vect::new(ctx.node_width, ctx.node_width) * 0.5;
        let matrix = rctx.cam * translation(corner_pos.x, corner_pos.y);
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        draw(&mut target, &rctx, "back", "plain", &uniforms, &draw_params);
        let matrix = rctx.cam * translation(corner_pos.x + 0.05, corner_pos.y + 0.05) * scale(0.9, 0.9);
        let program = data.shader.borrow();
        let program = program.as_ref().expect("Node didn't have shader.");
        let uniforms = uniform! {
            matrix: *matrix.as_ref(),
        };
        let model = rctx.models.get("node").unwrap();
        target.draw(&model.vertices, &model.indices, &program, &uniforms, &draw_params).expect("Drawing node failed.");

        let mut draw = |things: &[_]| {
            for p in things {
                let p = pos + flip_y(*p) - Vect::new(ctx.thingy_size, ctx.thingy_size) * 0.5;
                let matrix = rctx.cam * translation(p.x, p.y) * scale(ctx.thingy_size, ctx.thingy_size);
                let uniforms = uniform! {
                    matrix: *matrix.as_ref(),
                };
                draw(&mut target, &rctx, "node", "plain", &uniforms, &draw_params);
            }
        };
        draw(&data.outputs.borrow());
        draw(&data.inputs.borrow());
    }
    let mut lines = Vec::with_capacity(gen.connections());
    if let Some(AddingEdge) = ctx.state {
        if let Some(Selection::Output(trg)) = ctx.selected {
            let src = output_pos(&gen, trg, ctx.thingy_size);
            let trg = Vect::new(ctx.mouse_pos.x, -ctx.mouse_pos.y);
            add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
        }
    }
    for (src, trg) in gen.iter_connections() {
        let src = output_pos(&gen, src, ctx.thingy_size);
        let trg = input_pos(&gen, trg, ctx.thingy_size);
        let trg = Vect::new(trg[0], trg[1] + ctx.thingy_size);
        add_arrow(&mut lines, src, trg, 0.1, 0.1 * TAU);
    }
    let vertices = VertexBuffer::new(display, &lines).unwrap();
    let indices = (0..lines.len() as u32).collect::<Vec<_>>();
    let indices = IndexBuffer::new(display, PrimitiveType::LinesList, &indices).unwrap();
    let matrix = rctx.cam * translation(0., 0.);
    let uniforms = uniform! {
        matrix: *matrix.as_ref(),
    };
    let program = rctx.programs.get("plain").unwrap();
    target.draw(&vertices, &indices, program, &uniforms, &draw_params).unwrap();

    if let Some(s) = ctx.selected {
        if let Some(node) = s.node() {
            let set = if let Selection::Setting(_, s) = s {
                Some(s)
            } else {
                None
            };
            let node = gen.get(node).expect("Selection should always point to real node.").0;
            let settings = node.settings();
            let size = 23.;
            for (i, setting) in settings.iter().enumerate() {
                if set == Some(i) {
                    continue;
                }
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = setting.to_string();
                string.push_str(": ");
                string.push_str(&node.setting(setting).to_string());
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
            if let Some(i) = set {
                let pos = Vect::new(0., -(i as f32) / 20.);
                let mut string = settings[i].to_string();
                string.push_str(": ");
                match node.setting(settings[i]) {
                    Setting::Blend(ref b) => {
                        let bb = rctx.fonts.bounding_box("anka", size, &string).unwrap();
                        string.push_str(&format!("{:?}", b));
                        let max = from_window_to_screen(dims, [bb.max.x, bb.max.y]);
                        let pos = pos + Vect::new(max.x * 1.5, -1. / 20.);
                        for (i, blend) in BlendType::iter_variants().enumerate() {
                            let blend = format!("{:?}", blend);
                            let pos = pos + Vect::new(0., -(i as f32 / 20.));
                            rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &blend);
                        }
                    },
                    _ => {
                        if let Some(Writing) = ctx.state {
                            let ch = if 0 % 120 < 60 { //TODO: Fix Me
                                '|'
                            } else {
                                ' '
                            };
                            if ctx.text.is_empty() {
                                string.push(ch);
                            } else {
                                let (a, b) = ctx.text.split_at(ctx.caret);
                                string.push_str(&format!("{}{}{}", a, ch, b));
                            }
                        }
                    }
                }
                rctx.fonts.draw_text(&display, &mut target, "anka", size, [0., 0., 0., 1.], pos, &string);
            }
        }
    }
    target.finish().unwrap();
}

fn draw<A, B>(target: &mut Frame, rctx: &RenderContext, model: &str, program: &str, uniforms: &UniformsStorage<A, B>, draw_params: &DrawParameters)
    where A: AsUniformValue,
          B: Uniforms,
{
    let model = rctx.models.get(model).unwrap();
    let program = rctx.programs.get(program).unwrap();
    target.draw(&model.vertices, &model.indices, program, uniforms, draw_params).unwrap();
}

fn add_arrow(lines: &mut Vec<Vertex>, src: Vect, trg: Vect, len: f32, theta: f32) {
    lines.push(vert(src.x, src.y));
    lines.push(vert(trg.x, trg.y));
    let vec = (src - trg).normalize();
    let mut add_part = |theta: f32| {
        let (sin, cos) = theta.sin_cos();
        let arrow = Vect::new(
            vec.x * cos - vec.y * sin,
            vec.x * sin + vec.y * cos);
        lines.push(vert(trg.x, trg.y));
        let v = trg + (arrow * len);
        lines.push(vert(v.x, v.y));
    };
    add_part(theta);
    add_part(-theta);
}
<|endoftext|>


<commit_before>use super::Request;
use crate::api_call::ApiCall;
use crate::version::*;
use http_types::Request as HTTPRequest;

impl From<Request> for HTTPRequest<String> {
    fn from(r: Request) -> Self {
        let (uri, body) = r.parameters.uri_and_body(r.path);
        let body = body.unwrap_or("").to_owned();
        let mut rb = HTTPRequest::builder();

        rb.header("User-Agent", USER_AGENT)
            .method(r.method)
            .uri(uri.as_ref())
            .body(body)
            .unwrap()
    }
}

impl From<&ApiCall<'_, '_, '_, '_, '_, '_>> for HTTPRequest<String> {
    fn from(i: &ApiCall) -> Self {
        Request::from(i).into()
    }
}

use super::FromRequest;

impl FromRequest<!> for HTTPRequest<String> {
    fn from_request(r: Request, _params: !) -> Self {
        Self::from(r)
    }
}
<commit_msg>http/request/http: use out Never type alias for FromRequest<commit_after>use super::Request;
use crate::api_call::ApiCall;
use crate::version::*;
use http_types::Request as HTTPRequest;

impl From<Request> for HTTPRequest<String> {
    fn from(r: Request) -> Self {
        let (uri, body) = r.parameters.uri_and_body(r.path);
        let body = body.unwrap_or("").to_owned();
        let mut rb = HTTPRequest::builder();

        rb.header("User-Agent", USER_AGENT)
            .method(r.method)
            .uri(uri.as_ref())
            .body(body)
            .unwrap()
    }
}

impl From<&ApiCall<'_, '_, '_, '_, '_, '_>> for HTTPRequest<String> {
    fn from(i: &ApiCall) -> Self {
        Request::from(i).into()
    }
}

use super::FromRequest;
use crate::Never;

impl FromRequest<Never> for HTTPRequest<String> {
    fn from_request(r: Request, _params: Never) -> Self {
        Self::from(r)
    }
}
<|endoftext|>


<commit_before>use Urgency;
use ffi;
use gdk_pixbuf;
use glib::translate::*;
use glib;
use glib_ffi;
use std;

glib_wrapper! {
    /// `Notification` represents a passive pop-up notification. It can contain
    /// summary text, body text, and an icon, as well as hints specifying how
    /// the notification should be presented. The notification is rendered by
    /// a notification daemon, and may present the notification in any number
    /// of ways. As such, there is a clear separation of content and
    /// presentation, and this API enforces that.
    pub struct Notification(Object<ffi::NotifyNotification>);

    match fn {
        get_type => || ffi::notify_notification_get_type(),
    }
}

impl Notification {
    /// Creates a new `Notification`. The summary text is required, but
    /// all other parameters are optional.
    /// ## `summary`
    /// The required summary text.
    /// ## `body`
    /// The optional body text.
    /// ## `icon`
    /// The optional icon theme icon name or filename.
    ///
    /// # Returns
    ///
    /// The new `Notification`.
    pub fn new<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(
        summary: &str,
        body: P,
        icon: Q,
    ) -> Notification {
        assert_initialized_libnotify!();
        let body = body.into();
        let body = body.to_glib_none();
        let icon = icon.into();
        let icon = icon.to_glib_none();
        unsafe {
            from_glib_full(ffi::notify_notification_new(
                summary.to_glib_none().0,
                body.0,
                icon.0,
            ))
        }
    }

    /// Synchronously tells the notification server to hide the notification on the screen.
    ///
    /// # Returns
    ///
    /// `Ok(())` on success, or `Err(err)` on error
    pub fn close(&self) -> Result<(), glib::error::Error> {
        assert_initialized_libnotify!();
        unsafe {
            let mut err: *mut glib_ffi::GError = std::ptr::null_mut();
            ffi::notify_notification_close(self.to_glib_none().0, &mut err);

            if !err.is_null() {
                return Err(glib::error::Error::wrap(err));
            } else {
                return Ok(());
            }
        }
    }

    /// Tells the notification server to display the notification on the screen.
    ///
    /// # Returns
    ///
    /// `Ok(())` on success, or `Err(err)` on error
    // TODO: test if Error leaks memory
    pub fn show(&self) -> Result<(), glib::error::Error> {
        assert_initialized_libnotify!();
        unsafe {
            let mut err: *mut glib_ffi::GError = std::ptr::null_mut();
            ffi::notify_notification_show(self.to_glib_none().0, &mut err);

            if !err.is_null() {
                return Err(glib::error::Error::wrap(err));
            } else {
                return Ok(());
            }
        }
    }

    /// Sets a hint for `key` with value `value`. If `value` is `None`,
    /// a previously set hint for `key` is unset.
    ///
    /// If `value` is floating, it is consumed.
    /// ## `key`
    /// the hint key
    /// ## `value`
    pub fn set_hint(&self, key: &str, value: Option<glib::variant::Variant>) {
        assert_initialized_libnotify!();

        let gvalue: *mut glib_ffi::GVariant = {
            match value {
                Some(ref value) => value.to_glib_none().0,
                None => std::ptr::null_mut(),
            }
        };

        unsafe {
            ffi::notify_notification_set_hint(
                self.to_glib_none().0,
                key.to_glib_none().0,
                gvalue,
            )
        }
    }

    /// Sets the image in the notification from a `gdk_pixbuf::Pixbuf`.
    /// ## `pixbuf`
    /// The image.
    pub fn set_image_from_pixbuf(&self, pixbuf: &gdk_pixbuf::Pixbuf) {
        assert_initialized_libnotify!();

        unsafe {
            ffi::notify_notification_set_image_from_pixbuf(
                self.to_glib_none().0,
                pixbuf.to_glib_none().0,
            );
        }
    }

    /// Clears all hints from the notification.
    pub fn clear_hints(&self) {
        unsafe {
            ffi::notify_notification_clear_hints(self.to_glib_none().0);
        }
    }

    /// Sets the application name for the notification. If this function is
    /// not called or if `app_name` is `None`, the application name will be
    /// set from the value used in `notify_init` or overridden with
    /// `notify_set_app_name`.
    /// ## `app_name`
    /// the localised application name
    pub fn set_app_name<'a, P: Into<Option<&'a str>>>(&self, app_name: P) {
        let app_name = app_name.into();
        let app_name = app_name.to_glib_none();
        unsafe {
            ffi::notify_notification_set_app_name(
                self.to_glib_none().0,
                app_name.0,
            );
        }
    }

    /// Sets the category of this notification. This can be used by the
    /// notification server to filter or display the data in a certain way.
    /// ## `category`
    /// The category.
    pub fn set_category(&self, category: &str) {
        unsafe {
            ffi::notify_notification_set_category(
                self.to_glib_none().0,
                category.to_glib_none().0,
            );
        }
    }

    /// Sets the timeout of the notification. To set the default time, pass
    /// `NOTIFY_EXPIRES_DEFAULT` as `timeout`. To set the notification to never
    /// expire, pass `NOTIFY_EXPIRES_NEVER`.
    ///
    /// Note that the timeout may be ignored by the server.
    /// ## `timeout`
    /// The timeout in milliseconds.
    pub fn set_timeout(&self, timeout: i32) {
        unsafe {
            ffi::notify_notification_set_timeout(
                self.to_glib_none().0,
                timeout,
            );
        }
    }

    /// Sets the urgency level of this notification.
    ///
    /// See: `Urgency`
    /// ## `urgency`
    /// The urgency level.
    pub fn set_urgency(&self, urgency: Urgency) {
        unsafe {
            ffi::notify_notification_set_urgency(
                self.to_glib_none().0,
                urgency.to_glib(),
            );
        }
    }

    /// Updates the notification text and icon. This won't send the update out
    /// and display it on the screen. For that, you will need to call
    /// `Notification::show`.
    /// ## `summary`
    /// The new required summary text.
    /// ## `body`
    /// The optional body text.
    /// ## `icon`
    /// The optional icon theme icon name or filename.
    ///
    /// # Returns
    ///
    /// `Ok(())` on success, or `Err(str)` if an invalid parameter was passed
    // TODO: switch back to BoolError when it hits stable glib
    pub fn update<
        'a,
        'b,
        P: Into<Option<&'a str>>,
        Q: Into<Option<&'b str>>,
    >(
        &self,
        summary: &str,
        body: P,
        icon: Q,
    ) -> Result<(), String> {
        let body = body.into();
        let body = body.to_glib_none();
        let icon = icon.into();
        let icon = icon.to_glib_none();
        unsafe {
            let b = ffi::notify_notification_update(
                self.to_glib_none().0,
                summary.to_glib_none().0,
                body.0,
                icon.0,
            );
            match b {
                glib_ffi::GFALSE => Err(
                    String::from("Invalid parameter passed"),
                ),
                _ => Ok(()),
            }
        }
    }
}
<commit_msg>Fix build against latest gtk-rs<commit_after>use Urgency;
use ffi;
use gdk_pixbuf;
use glib::translate::*;
use glib;
use glib_ffi;
use gobject_ffi;
use std;

glib_wrapper! {
    /// `Notification` represents a passive pop-up notification. It can contain
    /// summary text, body text, and an icon, as well as hints specifying how
    /// the notification should be presented. The notification is rendered by
    /// a notification daemon, and may present the notification in any number
    /// of ways. As such, there is a clear separation of content and
    /// presentation, and this API enforces that.
    pub struct Notification(Object<ffi::NotifyNotification>);

    match fn {
        get_type => || ffi::notify_notification_get_type(),
    }
}

impl Notification {
    /// Creates a new `Notification`. The summary text is required, but
    /// all other parameters are optional.
    /// ## `summary`
    /// The required summary text.
    /// ## `body`
    /// The optional body text.
    /// ## `icon`
    /// The optional icon theme icon name or filename.
    ///
    /// # Returns
    ///
    /// The new `Notification`.
    pub fn new<'a, 'b, P: Into<Option<&'a str>>, Q: Into<Option<&'b str>>>(
        summary: &str,
        body: P,
        icon: Q,
    ) -> Notification {
        assert_initialized_libnotify!();
        let body = body.into();
        let body = body.to_glib_none();
        let icon = icon.into();
        let icon = icon.to_glib_none();
        unsafe {
            from_glib_full(ffi::notify_notification_new(
                summary.to_glib_none().0,
                body.0,
                icon.0,
            ))
        }
    }

    /// Synchronously tells the notification server to hide the notification on the screen.
    ///
    /// # Returns
    ///
    /// `Ok(())` on success, or `Err(err)` on error
    pub fn close(&self) -> Result<(), glib::error::Error> {
        assert_initialized_libnotify!();
        unsafe {
            let mut err: *mut glib_ffi::GError = std::ptr::null_mut();
            ffi::notify_notification_close(self.to_glib_none().0, &mut err);

            if !err.is_null() {
                return Err(glib::error::Error::wrap(err));
            } else {
                return Ok(());
            }
        }
    }

    /// Tells the notification server to display the notification on the screen.
    ///
    /// # Returns
    ///
    /// `Ok(())` on success, or `Err(err)` on error
    // TODO: test if Error leaks memory
    pub fn show(&self) -> Result<(), glib::error::Error> {
        assert_initialized_libnotify!();
        unsafe {
            let mut err: *mut glib_ffi::GError = std::ptr::null_mut();
            ffi::notify_notification_show(self.to_glib_none().0, &mut err);

            if !err.is_null() {
                return Err(glib::error::Error::wrap(err));
            } else {
                return Ok(());
            }
        }
    }

    /// Sets a hint for `key` with value `value`. If `value` is `None`,
    /// a previously set hint for `key` is unset.
    ///
    /// If `value` is floating, it is consumed.
    /// ## `key`
    /// the hint key
    /// ## `value`
    pub fn set_hint(&self, key: &str, value: Option<glib::variant::Variant>) {
        assert_initialized_libnotify!();

        let gvalue: *mut glib_ffi::GVariant = {
            match value {
                Some(ref value) => value.to_glib_none().0,
                None => std::ptr::null_mut(),
            }
        };

        unsafe {
            ffi::notify_notification_set_hint(
                self.to_glib_none().0,
                key.to_glib_none().0,
                gvalue,
            )
        }
    }

    /// Sets the image in the notification from a `gdk_pixbuf::Pixbuf`.
    /// ## `pixbuf`
    /// The image.
    pub fn set_image_from_pixbuf(&self, pixbuf: &gdk_pixbuf::Pixbuf) {
        assert_initialized_libnotify!();

        unsafe {
            ffi::notify_notification_set_image_from_pixbuf(
                self.to_glib_none().0,
                pixbuf.to_glib_none().0,
            );
        }
    }

    /// Clears all hints from the notification.
    pub fn clear_hints(&self) {
        unsafe {
            ffi::notify_notification_clear_hints(self.to_glib_none().0);
        }
    }

    /// Sets the application name for the notification. If this function is
    /// not called or if `app_name` is `None`, the application name will be
    /// set from the value used in `notify_init` or overridden with
    /// `notify_set_app_name`.
    /// ## `app_name`
    /// the localised application name
    pub fn set_app_name<'a, P: Into<Option<&'a str>>>(&self, app_name: P) {
        let app_name = app_name.into();
        let app_name = app_name.to_glib_none();
        unsafe {
            ffi::notify_notification_set_app_name(
                self.to_glib_none().0,
                app_name.0,
            );
        }
    }

    /// Sets the category of this notification. This can be used by the
    /// notification server to filter or display the data in a certain way.
    /// ## `category`
    /// The category.
    pub fn set_category(&self, category: &str) {
        unsafe {
            ffi::notify_notification_set_category(
                self.to_glib_none().0,
                category.to_glib_none().0,
            );
        }
    }

    /// Sets the timeout of the notification. To set the default time, pass
    /// `NOTIFY_EXPIRES_DEFAULT` as `timeout`. To set the notification to never
    /// expire, pass `NOTIFY_EXPIRES_NEVER`.
    ///
    /// Note that the timeout may be ignored by the server.
    /// ## `timeout`
    /// The timeout in milliseconds.
    pub fn set_timeout(&self, timeout: i32) {
        unsafe {
            ffi::notify_notification_set_timeout(
                self.to_glib_none().0,
                timeout,
            );
        }
    }

    /// Sets the urgency level of this notification.
    ///
    /// See: `Urgency`
    /// ## `urgency`
    /// The urgency level.
    pub fn set_urgency(&self, urgency: Urgency) {
        unsafe {
            ffi::notify_notification_set_urgency(
                self.to_glib_none().0,
                urgency.to_glib(),
            );
        }
    }

    /// Updates the notification text and icon. This won't send the update out
    /// and display it on the screen. For that, you will need to call
    /// `Notification::show`.
    /// ## `summary`
    /// The new required summary text.
    /// ## `body`
    /// The optional body text.
    /// ## `icon`
    /// The optional icon theme icon name or filename.
    ///
    /// # Returns
    ///
    /// `Ok(())` on success, or `Err(str)` if an invalid parameter was passed
    // TODO: switch back to BoolError when it hits stable glib
    pub fn update<
        'a,
        'b,
        P: Into<Option<&'a str>>,
        Q: Into<Option<&'b str>>,
    >(
        &self,
        summary: &str,
        body: P,
        icon: Q,
    ) -> Result<(), String> {
        let body = body.into();
        let body = body.to_glib_none();
        let icon = icon.into();
        let icon = icon.to_glib_none();
        unsafe {
            let b = ffi::notify_notification_update(
                self.to_glib_none().0,
                summary.to_glib_none().0,
                body.0,
                icon.0,
            );
            match b {
                glib_ffi::GFALSE => Err(
                    String::from("Invalid parameter passed"),
                ),
                _ => Ok(()),
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use libnum;

use std::cmp;
use std::ops::{
    Add,
};

use linalg::LinalgScalar;

/// Compute the sum of the values in `xs`
pub fn unrolled_sum<A>(mut xs: &[A]) -> A
    where A: Clone + Add<Output=A> + libnum::Zero,
{
    // eightfold unrolled so that floating point can be vectorized
    // (even with strict floating point accuracy semantics)
    let mut sum = A::zero();
    let (mut p0, mut p1, mut p2, mut p3,
         mut p4, mut p5, mut p6, mut p7) =
        (A::zero(), A::zero(), A::zero(), A::zero(),
         A::zero(), A::zero(), A::zero(), A::zero());
    while xs.len() >= 8 {
        p0 = p0 + xs[0].clone();
        p1 = p1 + xs[1].clone();
        p2 = p2 + xs[2].clone();
        p3 = p3 + xs[3].clone();
        p4 = p4 + xs[4].clone();
        p5 = p5 + xs[5].clone();
        p6 = p6 + xs[6].clone();
        p7 = p7 + xs[7].clone();

        xs = &xs[8..];
    }
    sum = sum.clone() + (p0 + p4);
    sum = sum.clone() + (p1 + p5);
    sum = sum.clone() + (p2 + p6);
    sum = sum.clone() + (p3 + p7);
    for elt in xs {
        sum = sum.clone() + elt.clone();
    }
    sum
}

/// Compute the dot product.
///
/// `xs` and `ys` must be the same length
pub fn unrolled_dot<A>(xs: &[A], ys: &[A]) -> A
    where A: LinalgScalar,
{
    debug_assert_eq!(xs.len(), ys.len());
    // eightfold unrolled so that floating point can be vectorized
    // (even with strict floating point accuracy semantics)
    let len = cmp::min(xs.len(), ys.len());
    let mut xs = &xs[..len];
    let mut ys = &ys[..len];
    let mut sum = A::zero();
    let (mut p0, mut p1, mut p2, mut p3,
         mut p4, mut p5, mut p6, mut p7) =
        (A::zero(), A::zero(), A::zero(), A::zero(),
         A::zero(), A::zero(), A::zero(), A::zero());
    while xs.len() >= 8 {
        p0 = p0 + xs[0] * ys[0];
        p1 = p1 + xs[1] * ys[1];
        p2 = p2 + xs[2] * ys[2];
        p3 = p3 + xs[3] * ys[3];
        p4 = p4 + xs[4] * ys[4];
        p5 = p5 + xs[5] * ys[5];
        p6 = p6 + xs[6] * ys[6];
        p7 = p7 + xs[7] * ys[7];

        xs = &xs[8..];
        ys = &ys[8..];
    }
    sum = sum + (p0 + p4);
    sum = sum + (p1 + p5);
    sum = sum + (p2 + p6);
    sum = sum + (p3 + p7);
    for i in 0..xs.len() {
        sum = sum + xs[i] * ys[i];
    }
    sum
}

/// Compute pairwise equality
///
/// `xs` and `ys` must be the same length
pub fn unrolled_eq<A>(xs: &[A], ys: &[A]) -> bool
    where A: PartialEq
{
    debug_assert_eq!(xs.len(), ys.len());
    // eightfold unrolled for performance (this is not done by llvm automatically)
    let len = cmp::min(xs.len(), ys.len());
    let mut xs = &xs[..len];
    let mut ys = &ys[..len];

    while xs.len() >= 8 {
        if (xs[0] != ys[0])
        | (xs[1] != ys[1])
        | (xs[2] != ys[2])
        | (xs[3] != ys[3])
        | (xs[4] != ys[4])
        | (xs[5] != ys[5])
        | (xs[6] != ys[6])
        | (xs[7] != ys[7]) { return false; }
        xs = &xs[8..];
        ys = &ys[8..];
    }

    for i in 0..xs.len() {
        if xs[i] != ys[i] {
            return false;
        }
    }

    true
}
<commit_msg>numeric_util: Simplify epilogue in unrolled_sum<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use libnum;

use std::cmp;
use std::ops::{
    Add,
};

use linalg::LinalgScalar;

/// Compute the sum of the values in `xs`
pub fn unrolled_sum<A>(mut xs: &[A]) -> A
    where A: Clone + Add<Output=A> + libnum::Zero,
{
    // eightfold unrolled so that floating point can be vectorized
    // (even with strict floating point accuracy semantics)
    let mut sum = A::zero();
    let (mut p0, mut p1, mut p2, mut p3,
         mut p4, mut p5, mut p6, mut p7) =
        (A::zero(), A::zero(), A::zero(), A::zero(),
         A::zero(), A::zero(), A::zero(), A::zero());
    while xs.len() >= 8 {
        p0 = p0 + xs[0].clone();
        p1 = p1 + xs[1].clone();
        p2 = p2 + xs[2].clone();
        p3 = p3 + xs[3].clone();
        p4 = p4 + xs[4].clone();
        p5 = p5 + xs[5].clone();
        p6 = p6 + xs[6].clone();
        p7 = p7 + xs[7].clone();

        xs = &xs[8..];
    }
    sum = sum.clone() + (p0 + p4);
    sum = sum.clone() + (p1 + p5);
    sum = sum.clone() + (p2 + p6);
    sum = sum.clone() + (p3 + p7);

    // make it clear to the optimizer that this loop is short
    // and can not be autovectorized.
    for i in 0..8 {
        if i < xs.len() {
            sum = sum.clone() + xs[i].clone()
        } else {
            break;
        }
    }
    sum
}

/// Compute the dot product.
///
/// `xs` and `ys` must be the same length
pub fn unrolled_dot<A>(xs: &[A], ys: &[A]) -> A
    where A: LinalgScalar,
{
    debug_assert_eq!(xs.len(), ys.len());
    // eightfold unrolled so that floating point can be vectorized
    // (even with strict floating point accuracy semantics)
    let len = cmp::min(xs.len(), ys.len());
    let mut xs = &xs[..len];
    let mut ys = &ys[..len];
    let mut sum = A::zero();
    let (mut p0, mut p1, mut p2, mut p3,
         mut p4, mut p5, mut p6, mut p7) =
        (A::zero(), A::zero(), A::zero(), A::zero(),
         A::zero(), A::zero(), A::zero(), A::zero());
    while xs.len() >= 8 {
        p0 = p0 + xs[0] * ys[0];
        p1 = p1 + xs[1] * ys[1];
        p2 = p2 + xs[2] * ys[2];
        p3 = p3 + xs[3] * ys[3];
        p4 = p4 + xs[4] * ys[4];
        p5 = p5 + xs[5] * ys[5];
        p6 = p6 + xs[6] * ys[6];
        p7 = p7 + xs[7] * ys[7];

        xs = &xs[8..];
        ys = &ys[8..];
    }
    sum = sum + (p0 + p4);
    sum = sum + (p1 + p5);
    sum = sum + (p2 + p6);
    sum = sum + (p3 + p7);
    for i in 0..xs.len() {
        sum = sum + xs[i] * ys[i];
    }
    sum
}

/// Compute pairwise equality
///
/// `xs` and `ys` must be the same length
pub fn unrolled_eq<A>(xs: &[A], ys: &[A]) -> bool
    where A: PartialEq
{
    debug_assert_eq!(xs.len(), ys.len());
    // eightfold unrolled for performance (this is not done by llvm automatically)
    let len = cmp::min(xs.len(), ys.len());
    let mut xs = &xs[..len];
    let mut ys = &ys[..len];

    while xs.len() >= 8 {
        if (xs[0] != ys[0])
        | (xs[1] != ys[1])
        | (xs[2] != ys[2])
        | (xs[3] != ys[3])
        | (xs[4] != ys[4])
        | (xs[5] != ys[5])
        | (xs[6] != ys[6])
        | (xs[7] != ys[7]) { return false; }
        xs = &xs[8..];
        ys = &ys[8..];
    }

    for i in 0..xs.len() {
        if xs[i] != ys[i] {
            return false;
        }
    }

    true
}
<|endoftext|>