<commit_before>use std::collections::{HashMap, HashSet};
use plank_syntax::position::Spanned;
use ast::cfg::{Program, Function, Block, Reg, Instruction, Value, BlockId, BlockEnd};
use CompileCtx;

#[derive(PartialEq, Eq, Debug, Copy, Clone)]
enum VarState {
    Unassigned(u32),
    MaybeAssigned(u32),
    Assigned,
}

impl VarState {
    fn from_entries(entries: u32) -> VarState {
        if entries > 0 {
            VarState::Unassigned(entries)
        } else {
            VarState::Assigned
        }
    }

    fn reduce(&mut self) -> bool {
        match *self {
            VarState::Assigned => false,
            VarState::MaybeAssigned(1) |
            VarState::Unassigned(1) => {
                *self = VarState::Assigned;
                true
            }
            VarState::MaybeAssigned(ref mut x) => {
                debug_assert!(*x > 1);
                *x -= 1;
                false
            }
            VarState::Unassigned(x) => {
                debug_assert!(x > 1);
                *self = VarState::MaybeAssigned(x - 1);
                false
            }
        }
    }
}

struct Context<'a> {
    ctx: &'a mut CompileCtx,
    function: &'a Function,
    reported_regs: HashSet<Reg>,
    start_state: HashMap<(Reg, BlockId), VarState>,
}

impl<'a> Context<'a> {
    fn new(function: &'a Function, ctx: &'a mut CompileCtx) -> Self {
        Context {
            ctx,
            function,
            reported_regs: HashSet::new(),
            start_state: HashMap::new(),
        }
    }

    fn collect_assigned(&self, block: &Block) -> HashSet<Reg> {
        let mut assigned = HashSet::new();
        for op in &block.ops {
            match **op {
                Instruction::Init(reg) |
                Instruction::Assign(reg, _) |
                Instruction::BinaryOp(reg, _, _, _) |
                Instruction::Call(reg, _, _) |
                Instruction::UnaryOp(reg, _, _) |
                Instruction::TakeAddress(reg, _, _) |
                Instruction::CastAssign(reg, _) => {
                    assigned.insert(reg);
                }
                Instruction::Error |
                Instruction::Drop(_) |
                Instruction::DerefStore(_, _, _, _) |
                Instruction::FieldStore(_, _, _) |
                Instruction::StartStatement => {}
            }
        }
        assigned
    }

    fn check_block(&mut self, id: BlockId, block: &Block) {
        let mut assigned = HashSet::new();
        for op in &block.ops {
            match **op {
                Instruction::Assign(_, ref val) |
                Instruction::UnaryOp(_, _, ref val) |
                Instruction::FieldStore(_, _, ref val) |
                Instruction::CastAssign(_, ref val) => {
                    self.check_value(val, id, &assigned);
                }
                Instruction::DerefStore(ref a, _, _, ref b) |
                Instruction::BinaryOp(_, _, ref a, ref b) => {
                    self.check_value(a, id, &assigned);
                    self.check_value(b, id, &assigned);
                }
                Instruction::Call(_, ref value, ref params) => {
                    self.check_value(value, id, &assigned);
                    for param in params {
                        self.check_value(param, id, &assigned);
                    }
                }
                Instruction::Error |
                Instruction::StartStatement |
                Instruction::Drop(_) |
                Instruction::Init(_) => {}
                Instruction::TakeAddress(_, reg, _) => {
                    let val = Spanned::map(reg, Value::Reg);
                    self.check_value(&val, id, &assigned);
                }
            }
            match **op {
                Instruction::Init(reg) |
                Instruction::Assign(reg, _) |
                Instruction::BinaryOp(reg, _, _, _) |
                Instruction::Call(reg, _, _) |
                Instruction::UnaryOp(reg, _, _) |
                Instruction::TakeAddress(reg, _, _) |
                Instruction::CastAssign(reg, _) => {
                    assigned.insert(reg);
                }
                Instruction::Error |
                Instruction::Drop(_) |
                Instruction::DerefStore(_, _, _, _) |
                Instruction::FieldStore(_, _, _) |
                Instruction::StartStatement => {}
            }
        }
    }

    fn check_value(&mut self, value: &Spanned<Value>, block: BlockId, block_assigned: &HashSet<Reg>) {
        match **value {
            Value::Int(_, _) |
            Value::Symbol(_, _) |
            Value::Bytes(_) |
            Value::Unit |
            Value::Error => {}
            Value::Reg(reg) if self.reported_regs.contains(&reg) => {}
            Value::Reg(reg) if block_assigned.contains(&reg) => {}
            Value::Reg(reg) => {
                let var_symbol = self.function.register_symbols[&reg];
                let name = self.ctx.symbols.get_name(var_symbol);
                println!("state of {:?}, block {:?}", reg, block);
                let msg = match self.start_state[&(reg, block)] {
                    VarState::Assigned => return,
                    VarState::Unassigned(_) => format!(
                        "var `{}` is not initialized before usage",
                        name,
                    ),
                    VarState::MaybeAssigned(_) => format!(
                        "var `{}` might be uninitialized here",
                        name,
                    ),
                };
                let span = Spanned::span(value);
                self.ctx
                    .reporter
                    .warning(msg, span)
                    .span(span)
                    .build();
                self.reported_regs.insert(reg);
            }
        }
    }

    fn visit_start(&mut self, block: BlockId, reg: Reg) {
        if self.start_state.get_mut(&(reg, block)).unwrap().reduce() {
            match self.function.blocks[&block].end {
                BlockEnd::Jump(to) => {
                    self.visit_start(to, reg);
                }
                BlockEnd::Branch(_, a, b) => {
                    self.visit_start(a, reg);
                    self.visit_start(b, reg);
                }
                BlockEnd::Return(_) | BlockEnd::Error => {}
            }
        }
    }

    fn count_entries(&self) -> HashMap<BlockId, u32> {
        let mut entries = HashMap::new();
        for (&id, block) in &self.function.blocks {
            entries.entry(id).or_insert(0);
            match block.end {
                BlockEnd::Jump(to) => {
                    *entries.entry(to).or_insert(0) += 1;
                }
                BlockEnd::Branch(_, a, b) => {
                    *entries.entry(a).or_insert(0) += 1;
                    *entries.entry(b).or_insert(0) += 1;
                }
                BlockEnd::Return(_) | BlockEnd::Error => {}
            }
        }
        entries
    }

    fn check_function(&mut self) {
        for (block, entries) in self.count_entries() {
            for &reg in self.function.registers.keys() {
                self.start_state.insert((reg, block), VarState::from_entries(entries));
            }
        }
        if let Some(block) = self.function.start_block {
            for &reg in &self.function.parameters {
                self.start_state.insert((reg, block), VarState::Unassigned(1));
                self.visit_start(block, reg);
            }
        }
        for block in self.function.blocks.values() {
            for reg in self.collect_assigned(block) {
                match block.end {
                    BlockEnd::Jump(to) => {
                        self.visit_start(to, reg);
                    }
                    BlockEnd::Branch(_, a, b) => {
                        self.visit_start(a, reg);
                        self.visit_start(b, reg);
                    }
                    BlockEnd::Return(_) | BlockEnd::Error => {}
                }
            }
        }
        for (&id, block) in &self.function.blocks {
            self.check_block(id, block);
        }
    }
}

pub(crate) fn check_program(program: &Program, ctx: &mut CompileCtx) {
    for f in program.functions.values() {
        let mut ctx = Context::new(f, ctx);
        ctx.check_function();
    }
}
<commit_msg>fix the assign check, this time for real<commit_after>use std::collections::{HashMap, HashSet};
use plank_syntax::position::Spanned;
use ast::cfg::{Program, Function, Block, Reg, Instruction, Value, BlockId, BlockEnd};
use CompileCtx;

#[derive(PartialEq, Eq, Debug, Copy, Clone)]
enum VarState {
    Unassigned(u32),
    MaybeAssigned(u32),
    Assigned,
}

impl VarState {
    fn from_entries(entries: u32) -> VarState {
        if entries > 0 {
            VarState::Unassigned(entries)
        } else {
            VarState::Assigned
        }
    }

    fn reduce(&mut self) -> bool {
        match *self {
            VarState::Assigned => false,
            VarState::MaybeAssigned(1) |
            VarState::Unassigned(1) => {
                *self = VarState::Assigned;
                true
            }
            VarState::MaybeAssigned(ref mut x) => {
                debug_assert!(*x > 1);
                *x -= 1;
                false
            }
            VarState::Unassigned(x) => {
                debug_assert!(x > 1);
                *self = VarState::MaybeAssigned(x - 1);
                false
            }
        }
    }
}

struct Context<'a> {
    ctx: &'a mut CompileCtx,
    function: &'a Function,
    reported_regs: HashSet<Reg>,
    assign_position: HashMap<(Reg, BlockId), usize>,
    reachable_labels: HashSet<(Reg, BlockId)>,
}

impl<'a> Context<'a> {
    fn new(function: &'a Function, ctx: &'a mut CompileCtx) -> Self {
        Context {
            ctx,
            function,
            reported_regs: HashSet::new(),
            assign_position: HashMap::new(),
            reachable_labels: HashSet::new(),
        }
    }

    fn store_assigns(&mut self, id: BlockId, block: &Block) {
        for (index, op) in block.ops.iter().enumerate() {
            match **op {
                Instruction::Init(reg) |
                Instruction::Assign(reg, _) |
                Instruction::BinaryOp(reg, _, _, _) |
                Instruction::Call(reg, _, _) |
                Instruction::UnaryOp(reg, _, _) |
                Instruction::TakeAddress(reg, _, _) |
                Instruction::CastAssign(reg, _) => {
                    self.assign_position.entry((reg, id)).or_insert(index);
                }
                Instruction::Error |
                Instruction::Drop(_) |
                Instruction::DerefStore(_, _, _, _) |
                Instruction::FieldStore(_, _, _) |
                Instruction::StartStatement => {}
            }
        }
    }

    fn check_block(&mut self, id: BlockId, block: &Block) {
        for (index, op) in block.ops.iter().enumerate() {
            match **op {
                Instruction::Assign(_, ref val) |
                Instruction::UnaryOp(_, _, ref val) |
                Instruction::FieldStore(_, _, ref val) |
                Instruction::CastAssign(_, ref val) => {
                    self.check_value(val, id, index);
                }
                Instruction::DerefStore(ref a, _, _, ref b) |
                Instruction::BinaryOp(_, _, ref a, ref b) => {
                    self.check_value(a, id, index);
                    self.check_value(b, id, index);
                }
                Instruction::Call(_, ref value, ref params) => {
                    self.check_value(value, id, index);
                    for param in params {
                        self.check_value(param, id, index);
                    }
                }
                Instruction::TakeAddress(_, reg, _) => {
                    let val = Spanned::map(reg, Value::Reg);
                    self.check_value(&val, id, index);
                }
                Instruction::Error |
                Instruction::StartStatement |
                Instruction::Drop(_) |
                Instruction::Init(_) => {}
            }
        }
    }

    fn check_value(&mut self, value: &Spanned<Value>, block: BlockId, pos: usize) {
        match **value {
            Value::Int(_, _) |
            Value::Symbol(_, _) |
            Value::Bytes(_) |
            Value::Unit |
            Value::Error => {}
            Value::Reg(reg) if self.reported_regs.contains(&reg) => {}
            Value::Reg(reg) => {
                let assign_pos = self.assign_position.get(&(reg, block)).cloned();
                if assign_pos.map(|p| p < pos) == Some(true) {
                    return;
                }
                if !self.reachable_labels.contains(&(reg, block)) {
                    return;
                }
                let var_symbol = self.function.register_symbols[&reg];
                let name = self.ctx.symbols.get_name(var_symbol);
                let msg = format!("var `{}` might be uninitialized here", name);
                let span = Spanned::span(value);
                self.ctx
                    .reporter
                    .warning(msg, span)
                    .span(span)
                    .build();
                self.reported_regs.insert(reg);
            }
        }
    }

    fn visit_label(&mut self, reg: Reg, block: BlockId) {
        if !self.reachable_labels.contains(&(reg, block)) {
            self.reachable_labels.insert((reg, block));
            if self.assign_position.contains_key(&(reg, block)) {
                return;
            }
            match self.function.blocks[&block].end {
                BlockEnd::Jump(to) => {
                    self.visit_label(reg, to);
                }
                BlockEnd::Branch(_, a, b) => {
                    self.visit_label(reg, a);
                    self.visit_label(reg, b);
                }
                BlockEnd::Return(_) | BlockEnd::Error => {}
            }
        }
    }

    fn check_function(&mut self) {
        for (&id, block) in &self.function.blocks {
            self.store_assigns(id, block);
        }
        let parameters = self.function.parameters.iter().cloned().collect::<HashSet<_>>();
        if let Some(block) = self.function.start_block {
            for &reg in self.function.registers.keys() {
                if !parameters.contains(&reg) {
                    self.visit_label(reg, block);
                }
            }
        }
        for (&id, block) in &self.function.blocks {
            self.check_block(id, block);
        }
    }
}

pub(crate) fn check_program(program: &Program, ctx: &mut CompileCtx) {
    for f in program.functions.values() {
        let mut ctx = Context::new(f, ctx);
        ctx.check_function();
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;

extern crate tokio_core;
extern crate futures;
extern crate tokio_solicit;

use std::str;
use std::io::{self};

use futures::{Future, Stream};
use futures::future::{self};
use tokio_core::reactor::{Core};

use tokio_solicit::client::H2Client;

// Shows the usage of `H2Client` when establishing an HTTP/2 connection over cleartext TCP.
// Also demonstrates how to stream the body of the response (i.e. get response body chunks as soon
// as they are received on a `futures::Stream`.
fn cleartext_example() {
    let mut core = Core::new().expect("event loop required");
    let handle = core.handle();

    let addr = "127.0.0.1:8080".parse().expect("valid IP address");

    let future_client = H2Client::cleartext_connect("localhost", &addr, &handle);

    let future_response = future_client.and_then(|mut client| {
        println!("Connection established.");

        // For the first request, we simply want the full body, without streaming individual body
        // chunks...
        let get = client.get(b"/get").into_full_body_response();
        let post = client.post(b"/post", b"Hello, world!".to_vec());

        // ...for the other, we accumulate the body "manually" in order to do some more
        // processing for each chunk (for demo purposes). Also, discards the headers.
        let post = post.and_then(|(_headers, body)| {
            body.fold(Vec::<u8>::new(), |mut vec, chunk| {
                println!("receiving a new chunk of size {}", chunk.body.len());

                vec.extend(chunk.body.into_iter());
                future::ok::<_, io::Error>(vec)
            })
        });

        // Finally, yield a future that resolves once both requests are complete (and both bodies
        // are available).
        Future::join(get, post)
    }).map(|(get_response, post_response_body)| {
        // Convert the bodies to a UTF-8 string
        let get_res: String = str::from_utf8(&get_response.body).unwrap().into();
        let post_res: String = str::from_utf8(&post_response_body).unwrap().into();

        // ...and yield a pair of bodies converted to a string.
        (get_res, post_res)
    });

    let res = core.run(future_response).expect("responses!");

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

fn main() {
    env_logger::init().expect("logger init is required");

    // Establish an http/2 connection (over cleartext TCP), issue a couple of requests, and
    // stream the body of the response of one of them. Wait until both are ready and then
    // print the bodies.
    cleartext_example();

    // An additional demo showing how to perform a streaming _request_ (i.e. the body of the
    // request is streamed out to the server).
    do_streaming_request();
}

fn do_streaming_request() {
    use std::iter;
    use tokio_solicit::client::HttpRequestBody;
    use futures::Sink;

    let mut core = Core::new().expect("event loop required");
    let handle = core.handle();
    let addr = "127.0.0.1:8080".parse().expect("valid IP address");
    let future_client = H2Client::cleartext_connect("localhost", &addr, &handle);

    let future_response = future_client.and_then(|mut client| {
        let (post, tx) = client.streaming_request(b"POST", b"/post", iter::empty());
        tx
            .send(Ok(HttpRequestBody::new(b"HELLO ".to_vec())))
            .and_then(|tx| tx.send(Ok(HttpRequestBody::new(b" WORLD".to_vec()))))
            .and_then(|tx| tx.send(Ok(HttpRequestBody::new(b"!".to_vec()))))
            .map_err(|_err| io::Error::from(io::ErrorKind::BrokenPipe))
            .and_then(|_tx| post.into_full_body_response())
    });

    let res = core.run(future_response).expect("response");
    println!("{:?}", res);
}
<commit_msg>Example: Add a TLS/ALPN example<commit_after>extern crate env_logger;

extern crate tokio_core;
extern crate futures;
extern crate tokio_solicit;

use std::str;
use std::io::{self};

use futures::{Future, Stream};
use futures::future::{self};
use tokio_core::reactor::{Core};

use tokio_solicit::client::H2Client;

// Shows the usage of `H2Client` when establishing an HTTP/2 connection over cleartext TCP.
// Also demonstrates how to stream the body of the response (i.e. get response body chunks as soon
// as they are received on a `futures::Stream`.
fn cleartext_example() {
    let mut core = Core::new().expect("event loop required");
    let handle = core.handle();

    let addr = "127.0.0.1:8080".parse().expect("valid IP address");

    let future_client = H2Client::cleartext_connect("localhost", &addr, &handle);

    let future_response = future_client.and_then(|mut client| {
        println!("Connection established.");

        // For the first request, we simply want the full body, without streaming individual body
        // chunks...
        let get = client.get(b"/get").into_full_body_response();
        let post = client.post(b"/post", b"Hello, world!".to_vec());

        // ...for the other, we accumulate the body "manually" in order to do some more
        // processing for each chunk (for demo purposes). Also, discards the headers.
        let post = post.and_then(|(_headers, body)| {
            body.fold(Vec::<u8>::new(), |mut vec, chunk| {
                println!("receiving a new chunk of size {}", chunk.body.len());

                vec.extend(chunk.body.into_iter());
                future::ok::<_, io::Error>(vec)
            })
        });

        // Finally, yield a future that resolves once both requests are complete (and both bodies
        // are available).
        Future::join(get, post)
    }).map(|(get_response, post_response_body)| {
        // Convert the bodies to a UTF-8 string
        let get_res: String = str::from_utf8(&get_response.body).unwrap().into();
        let post_res: String = str::from_utf8(&post_response_body).unwrap().into();

        // ...and yield a pair of bodies converted to a string.
        (get_res, post_res)
    });

    let res = core.run(future_response).expect("responses!");

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

/// Fetches the response of google.com over HTTP/2.
///
/// The connection is negotiated during the TLS handshake using ALPN.
fn alpn_example() {
    println!();
    println!("---- ALPN example ----");
    use std::net::{ToSocketAddrs};

    let mut core = Core::new().expect("event loop required");
    let handle = core.handle();
    let addr =
        "google.com:443"
            .to_socket_addrs()
            .expect("unable to resolve the domain name")
            .next()
            .expect("no matching ip addresses");

    let future_response = H2Client::connect("google.com", &addr, &handle).and_then(|mut client| {
        // Ask for the homepage...
        client.get(b"/").into_full_body_response()
    });

    let response = core.run(future_response).expect("unexpected failure");
    // Print both the headers and the response body...
    println!("{:?}", response.headers);
    // (Recklessly assume it's utf-8!)
    let body = str::from_utf8(&response.body).unwrap();
    println!("{}", body);

    println!("---- ALPN example end ----");
}

fn main() {
    env_logger::init().expect("logger init is required");

    // Establish an http/2 connection (over cleartext TCP), issue a couple of requests, and
    // stream the body of the response of one of them. Wait until both are ready and then
    // print the bodies.
    cleartext_example();

    // Show how to estalbish a connection over TLS, while negotiating the use of http/2 over ALPN.
    alpn_example();

    // An additional demo showing how to perform a streaming _request_ (i.e. the body of the
    // request is streamed out to the server).
    do_streaming_request();
}

fn do_streaming_request() {
    println!();
    println!("---- streaming request example ----");
    use std::iter;
    use tokio_solicit::client::HttpRequestBody;
    use futures::Sink;

    let mut core = Core::new().expect("event loop required");
    let handle = core.handle();
    let addr = "127.0.0.1:8080".parse().expect("valid IP address");
    let future_client = H2Client::cleartext_connect("localhost", &addr, &handle);

    let future_response = future_client.and_then(|mut client| {
        let (post, tx) = client.streaming_request(b"POST", b"/post", iter::empty());
        tx
            .send(Ok(HttpRequestBody::new(b"HELLO ".to_vec())))
            .and_then(|tx| tx.send(Ok(HttpRequestBody::new(b" WORLD".to_vec()))))
            .and_then(|tx| tx.send(Ok(HttpRequestBody::new(b"!".to_vec()))))
            .map_err(|_err| io::Error::from(io::ErrorKind::BrokenPipe))
            .and_then(|_tx| post.into_full_body_response())
    });

    let res = core.run(future_response).expect("response");
    println!("{:?}", res);
    println!("---- streaming request example end ----");
}
<|endoftext|>


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

trait Rotate {
    fn rot(&self, angle: Angle) -> Self;
}

impl Rotate for Point {
    fn rot(&self, angle: Angle) -> Self {
        let (sin_angle, cos_angle) = angle.sin_cos();
        [
            self.x * cos_angle - self.y * sin_angle,
            self.x * sin_angle + self.y * cos_angle,
        ]
        .into()
    }
}

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_rel_head_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 bezier_rel_head(&mut self, rel_points: [Point; 3]) {
        self.bezier_rel_head_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],
            ],
        )
    }

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

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()));

    let spike_start_turn = 52.57f64.to_radians();
    let spike_start_length = 49.2;
    let spike_top_curve = rp([
        ap([509.52, 106.52]),
        ap([512.17, 99.17]),
        ap([524.30, 96.83]),
        ap([529.52, 102.48]),
    ]);
    let spike_end_turn = 58.28f64.to_radians();
    let spike_end_length = 47.49;
    let spike_between_length = 12.0;
    turtle.left(81.32f64.to_radians() - spike_start_turn);

    for _ in 0..13 {
        turtle.left(spike_start_turn);
        turtle.forward(ad(spike_start_length, turtle.heading()));
        turtle.bezier_rel_head(spike_top_curve);
        turtle.forward(ad(spike_end_length, turtle.heading()));
        turtle.left(spike_end_turn);
        turtle.forward(ad(spike_between_length, turtle.heading()));
    }
}
<commit_msg>Add right leg, claw and torso parts to Ferris example<commit_after>use turtle::{Angle, Distance, Drawing, Point, Size, Turtle};

trait Rotate {
    fn rot(&self, angle: Angle) -> Self;
}

impl Rotate for Point {
    fn rot(&self, angle: Angle) -> Self {
        let (sin_angle, cos_angle) = angle.sin_cos();
        [
            self.x * cos_angle - self.y * sin_angle,
            self.x * sin_angle + self.y * cos_angle,
        ]
        .into()
    }
}

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_rel_head_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 bezier_rel_head(&mut self, rel_points: [Point; 3]) {
        self.bezier_rel_head_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],
            ],
        )
    }

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

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()));

    let spike_start_turn = 52.57f64.to_radians();
    let spike_start_length = 49.2;
    let spike_top_curve = rp([
        ap([509.52, 106.52]),
        ap([512.17, 99.17]),
        ap([524.30, 96.83]),
        ap([529.52, 102.48]),
    ]);
    let spike_end_turn = 58.28f64.to_radians();
    let spike_end_length = 47.49;
    let spike_between_length = 12.0;
    turtle.left(81.32f64.to_radians() - spike_start_turn);

    for _ in 0..13 {
        turtle.left(spike_start_turn);
        turtle.forward(ad(spike_start_length, turtle.heading()));
        turtle.bezier_rel_head(spike_top_curve);
        turtle.forward(ad(spike_end_length, turtle.heading()));
        turtle.left(spike_end_turn);
        turtle.forward(ad(spike_between_length, turtle.heading()));
    }

    turtle.bezier_rel(rp([
        ap([1000.36, 439.64]),
        ap([1008.36, 434.45]),
        ap([1035.27, 410.91]),
        ap([1041.87, 402.91]),
    ]));
    let right_claw_heading = 66.8f64.to_radians();
    turtle.set_heading(right_claw_heading);
    turtle.forward(ad(22.8, right_claw_heading));
    turtle.bezier_rel(rp([
        ap([1050.65, 381.52]),
        ap([980.00, 298.25]),
        ap([1027.75, 236.75]),
        ap([1109.50, 200.62]),
    ]));
    turtle.bezier_rel(rp([
        ap([1109.57, 200.26]),
        ap([1096.75, 232.50]),
        ap([1100.12, 304.25]),
        ap([1100.13, 316.87]),
    ]));
    turtle.bezier_rel(rp([
        ap([1101.50, 316.91]),
        ap([1139.00, 298.00]),
        ap([1156.62, 260.62]),
        ap([1166.34, 219.34]),
    ]));
    turtle.bezier_rel(rp([
        ap([1166.53, 218.62]),
        ap([1216.75, 298.00]),
        ap([1148.50, 372.00]),
        ap([1085.75, 405.78]),
    ]));
    turtle.bezier_rel(rp([
        ap([1085.78, 405.72]),
        ap([1077.36, 420.27]),
        ap([1048.64, 453.45]),
        ap([1033.47, 465.31]),
    ]));
    let right_leg_heading = -36.3f64.to_radians();
    turtle.set_heading(right_leg_heading);
    turtle.forward(ad(60.8, right_leg_heading));
    turtle.bezier_rel(rp([
        ap([1081.88, 502.06]),
        ap([1084.65, 506.52]),
        ap([1088.26, 511.17]),
        ap([1074.84, 534.82]),
    ]));
    let right_leg_heading = (180.0 + 55.56f64).to_radians();
    turtle.set_heading(right_leg_heading);
    turtle.forward(ad(127.3, right_leg_heading));
    turtle.bezier_rel(rp([
        ap([1002.84, 639.87]),
        ap([975.18, 675.00]),
        ap([965.82, 698.00]),
        ap([959.53, 702.47]),
    ]));
    turtle.bezier_rel(rp([
        ap([959.13, 701.74]),
        ap([958.25, 656.00]),
        ap([1012.12, 586.75]),
        ap([1016.50, 523.19]),
    ]));
    let right_leg_heading = (180.0 - 41.87f64).to_radians();
    turtle.set_heading(right_leg_heading);
    turtle.forward(ad(11.4, right_leg_heading));
    turtle.bezier_rel(middle_curve_part1);
    turtle.bezier_rel(middle_curve_part2);
    turtle.end_fill();

    turtle.set_speed(23);
}
<|endoftext|>


<commit_before>
// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
// https://serde.rs/codegen-hybrid.html

#[derive(Debug, Serialize, Deserialize)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
    pub id: i64,
    pub name: String,
    pub path: String,
    pub description: String,
    pub visibility_level: i64,
    pub lfs_enabled: bool,
    pub avatar_url: Option<String>,
    pub web_url: String,
    pub request_access_enabled: bool,
}

pub type Groups = Vec<Group>;

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectOwner {
    pub name: String,
    pub username: String,
    pub id: i64,
    pub state: String,
    pub avatar_url: String,
    pub web_url: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectNamespaceAvatar {
    url: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectNamespace {
    id: i64,
    name: String,
    path: String,
    owner_id: Option<i64>,  // FIXME: Why would a project not have this?
    created_at: String,  // FIXME: Date instead?
    updated_at: String,  // FIXME: Date instead?
    description: String,
    avatar: Option<ProjectNamespaceAvatar>,
    membership_lock: Option<bool>,
    share_with_group_lock: bool,
    visibility_level: i64,
    request_access_enabled: bool,
    ldap_sync_status: Option<String>,
    ldap_sync_error: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_update_at: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_successful_update_at: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_sync_at: Option<String>,  // FIXME: Is String the proper type?
    deleted_at: Option<String>,  // FIXME: Is String the proper type?
    lfs_enabled: Option<String>,  // FIXME: Is String the proper type?
    repository_size_limit: Option<String>  // FIXME: Is String the proper type?
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectForkedFrom {
    id: i64,
    http_url_to_repo: String,
    web_url: String,
    name: String,
    name_with_namespace: String,
    path: String,
    path_with_namespace: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectAccess {
    access_level: i64,
    notification_level: i64,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectPermissions {
    project_access: Option<ProjectAccess>,
    group_access: Option<ProjectAccess>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectSharedWithGroup {
    group_id: i64,
    group_name: String,
    group_access_level: i64,
}

// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
#[derive(Debug, Serialize, Deserialize)]
pub struct Project {
    id: i64,
    description: String,
    default_branch: Option<String>,
    tag_list: Vec<String>,
    public: bool,
    archived: bool,
    visibility_level: i64,
    ssh_url_to_repo: String,
    http_url_to_repo: String,
    web_url: String,
    // owner: Option<ProjectOwner>,  // FIXME: Why would a project not have an owner?
    name: String,
    name_with_namespace: String,
    path: String,
    path_with_namespace: String,
    container_registry_enabled: Option<bool>,
    issues_enabled: bool,
    merge_requests_enabled: bool,
    wiki_enabled: bool,
    builds_enabled: bool,
    snippets_enabled: bool,
    created_at: String,  // FIXME: Date instead?
    last_activity_at: String,  // FIXME: Date instead?
    shared_runners_enabled: bool,
    lfs_enabled: bool,
    creator_id: i64,
    namespace: ProjectNamespace,
    forked_from_project: Option<ProjectForkedFrom>,
    avatar_url: Option<String>,
    star_count: i64,
    forks_count: i64,
    open_issues_count: i64,
    runners_token: Option<String>,
    public_builds: bool,
    shared_with_groups: Vec<ProjectSharedWithGroup>,
    only_allow_merge_if_build_succeeds: bool,
    request_access_enabled: bool,
    only_allow_merge_if_all_discussions_are_resolved: Option<bool>,  // FIXME: Is bool the proper type?
    approvals_before_merge: Option<i64>,
    permissions: ProjectPermissions,
}

pub type Projects = Vec<Project>;
<commit_msg>Add new struct and enums for Issues<commit_after>
// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
// https://serde.rs/codegen-hybrid.html

#[derive(Debug, Serialize, Deserialize)]
pub struct Version {
    pub version: String,
    pub revision: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Group {
    pub id: i64,
    pub name: String,
    pub path: String,
    pub description: String,
    pub visibility_level: i64,
    pub lfs_enabled: bool,
    pub avatar_url: Option<String>,
    pub web_url: String,
    pub request_access_enabled: bool,
}

pub type Groups = Vec<Group>;

#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectOwner {
    pub name: String,
    pub username: String,
    pub id: i64,
    pub state: String,
    pub avatar_url: String,
    pub web_url: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectNamespaceAvatar {
    url: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectNamespace {
    id: i64,
    name: String,
    path: String,
    owner_id: Option<i64>,  // FIXME: Why would a project not have this?
    created_at: String,  // FIXME: Date instead?
    updated_at: String,  // FIXME: Date instead?
    description: String,
    avatar: Option<ProjectNamespaceAvatar>,
    membership_lock: Option<bool>,
    share_with_group_lock: bool,
    visibility_level: i64,
    request_access_enabled: bool,
    ldap_sync_status: Option<String>,
    ldap_sync_error: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_update_at: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_successful_update_at: Option<String>,  // FIXME: Is String the proper type?
    ldap_sync_last_sync_at: Option<String>,  // FIXME: Is String the proper type?
    deleted_at: Option<String>,  // FIXME: Is String the proper type?
    lfs_enabled: Option<String>,  // FIXME: Is String the proper type?
    repository_size_limit: Option<String>  // FIXME: Is String the proper type?
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectForkedFrom {
    id: i64,
    http_url_to_repo: String,
    web_url: String,
    name: String,
    name_with_namespace: String,
    path: String,
    path_with_namespace: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectAccess {
    access_level: i64,
    notification_level: i64,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectPermissions {
    project_access: Option<ProjectAccess>,
    group_access: Option<ProjectAccess>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ProjectSharedWithGroup {
    group_id: i64,
    group_name: String,
    group_access_level: i64,
}

// https://users.rust-lang.org/t/what-am-i-doing-wrong-go-program-is-12x-faster-than-rust/5692/13
// https://doc.rust-lang.org/rustc-serialize/rustc_serialize/json/index.html
#[derive(Debug, Serialize, Deserialize)]
pub struct Project {
    id: i64,
    description: String,
    default_branch: Option<String>,
    tag_list: Vec<String>,
    public: bool,
    archived: bool,
    visibility_level: i64,
    ssh_url_to_repo: String,
    http_url_to_repo: String,
    web_url: String,
    // owner: Option<ProjectOwner>,  // FIXME: Why would a project not have an owner?
    name: String,
    name_with_namespace: String,
    path: String,
    path_with_namespace: String,
    container_registry_enabled: Option<bool>,
    issues_enabled: bool,
    merge_requests_enabled: bool,
    wiki_enabled: bool,
    builds_enabled: bool,
    snippets_enabled: bool,
    created_at: String,  // FIXME: Date instead?
    last_activity_at: String,  // FIXME: Date instead?
    shared_runners_enabled: bool,
    lfs_enabled: bool,
    creator_id: i64,
    namespace: ProjectNamespace,
    forked_from_project: Option<ProjectForkedFrom>,
    avatar_url: Option<String>,
    star_count: i64,
    forks_count: i64,
    open_issues_count: i64,
    runners_token: Option<String>,
    public_builds: bool,
    shared_with_groups: Vec<ProjectSharedWithGroup>,
    only_allow_merge_if_build_succeeds: bool,
    request_access_enabled: bool,
    only_allow_merge_if_all_discussions_are_resolved: Option<bool>,  // FIXME: Is bool the proper type?
    approvals_before_merge: Option<i64>,
    permissions: ProjectPermissions,
}

pub type Projects = Vec<Project>;

#[derive(Debug, Serialize, Deserialize)]
enum IssueState {
    #[serde(rename = "opened")]
    Opened,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
enum IssueAuthorState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "blocked")]
    Blocked,
}

#[derive(Debug, Serialize, Deserialize)]
enum MilestoneState {
    #[serde(rename = "active")]
    Active,

    #[serde(rename = "closed")]
    Closed,
}

#[derive(Debug, Serialize, Deserialize)]
struct Milestone {
    id: i64,
    iid: i64,
    project_id: i64,
    title: String,
    description: String,
    state: MilestoneState,
    created_at: String,  // FIXME: Use date type?
    updated_at: String,  // FIXME: Use date type?
    due_date: Option<String>  // FIXME: Use date type?
}

#[derive(Debug, Serialize, Deserialize)]
struct User {
    name: String,
    username: String,
    id: i64,
    state: IssueAuthorState,
    avatar_url: Option<String>,
    web_url: Option<String>
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Issue {
    id: i64,
    iid: i64,
    project_id: i64,
    title: String,
    description: String,
    state: IssueState,
    created_at: String,  // FIXME: Use date type?
    updated_at: String,  // FIXME: Use date type?
    labels: Vec<String>,
    milestone: Option<Milestone>,
    assignee: Option<String>,
    author: User,
    subscribed: bool,
    user_notes_count: i64,
    upvotes: i64,
    downvotes: i64,
    due_date: Option<String>,  // FIXME: Use date type?
    confidential: bool,
    web_url: Option<String>
}

pub type Issues = Vec<Issue>;
<|endoftext|>


<commit_before>extern crate tray_rust;
extern crate rand;
extern crate image;

use rand::StdRng;

use tray_rust::linalg::{AnimatedTransform, Transform, Point, Vector};
use tray_rust::film;
use tray_rust::film::{Colorf, RenderTarget, Camera, ImageSample};
use tray_rust::film::filter::MitchellNetravali;
use tray_rust::geometry::{Geometry, Sphere, Instance};
use tray_rust::material::Matte;
use tray_rust::sampler::{BlockQueue, LowDiscrepancy, Sampler};

fn main() {
    let width = 800usize;
    let height = 600usize;
    let filter =
        Box::new(MitchellNetravali::new(2.0, 2.0, 0.333333333333333333, 0.333333333333333333));
    let mut rt = RenderTarget::new((width, height), (20, 20), filter);
    let transform =
        AnimatedTransform::unanimated(&Transform::look_at(&Point::new(0.0, 0.0, -10.0),
                                                          &Point::new(0.0, 0.0, 0.0),
                                                          &Vector::new(0.0, 1.0, 0.0)));
    let camera = Camera::new(transform, 40.0, rt.dimensions(), 0.5, 0);
    let sphere = Sphere::new(1.5);
    let geometry_lock = std::sync::Arc::new(sphere);
    let white_wall = Matte::new(&Colorf::new(0.740063, 0.742313, 0.733934), 1.0);
    let material_lock = std::sync::Arc::new(white_wall);
    let position_transform =
        AnimatedTransform::unanimated(&Transform::translate(&Vector::new(0.0, 2.0, 0.0)));
    let instance = Instance::receiver(geometry_lock,
                                      material_lock,
                                      position_transform,
                                      "single_sphere".to_string());

    let dim = rt.dimensions();
    // A block queue is how work is distributed among threads, it's a list of tiles
    // of the image that have yet to be rendered. Each thread will pull a block from
    // this queue and render it.
    let block_queue = BlockQueue::new((dim.0 as u32, dim.1 as u32), (8, 8), (0, 0));
    let block_dim = block_queue.block_dim();
    // A sample is responsible for choosing randomly placed locations within a pixel to
    // get a good sampling of the image. Using a poor quality sampler will resuly in a
    // noiser and more aliased image that converges slower. The LowDiscrepency sampler
    // is a good choice for quality.
    let mut sampler = LowDiscrepancy::new(block_dim, 2);
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    let mut block_samples = Vec::with_capacity(sampler.max_spp() * (block_dim.0 * block_dim.1) as usize);
    let mut rng = match StdRng::new() {
        Ok(r) => r,
        Err(e) => { println!("Failed to get StdRng, {}", e); return }
    };
    // Grab a block from the queue and start working on it, submitting samples
    // to the render target thread after each pixel
    for b in block_queue.iter() {
        sampler.select_block(b);
        let mut pixel_samples = 0;
        // While the sampler has samples left to take for this pixel, take some samples
        while sampler.has_samples() {
            // Get samples for a pixel and render them
            sampler.get_samples(&mut sample_pos, &mut rng);
            for s in &sample_pos[..] {
                let mut ray = camera.generate_ray(s, 0.0);
                if let Some(hit) = instance.intersect(&mut ray) {
                    block_samples.push(ImageSample::new(s.0, s.1, Colorf::broadcast(1.0)));
                } else {
                    // For correct filtering we also MUST set a background color of some kind
                    // if we miss, otherwise the pixel weights will be wrong and we'll see object
                    // fringes and artifacts at object boundaries w/ nothing. Try removing this
                    // line and rendering again.
                    block_samples.push(ImageSample::new(s.0, s.1, Colorf::black()));
                }
            }
        }
        // We write all samples at once so we don't need to lock the render target tiles as often
        rt.write(&block_samples, sampler.get_region());
        block_samples.clear();
    }

    // Get the sRGB8 render buffer from the floating point framebuffer and save it
    let img = rt.get_render();
    match image::save_buffer("sphere.png", &img[..], dim.0 as u32, dim.1 as u32, image::RGB(8)) {
        Ok(_) => {},
            Err(e) => println!("Error saving image, {}", e),
    };
}

<commit_msg>Fixed some clippy errors: unused imports, unused variables, unneeded mut, etc etc.<commit_after>extern crate tray_rust;
extern crate rand;
extern crate image;

use rand::StdRng;

use tray_rust::linalg::{AnimatedTransform, Transform, Point, Vector};
use tray_rust::film::{Colorf, RenderTarget, Camera, ImageSample};
use tray_rust::film::filter::MitchellNetravali;
use tray_rust::geometry::{Sphere, Instance};
use tray_rust::material::Matte;
use tray_rust::sampler::{BlockQueue, LowDiscrepancy, Sampler};

fn main() {
    let width = 800usize;
    let height = 600usize;
    let filter =
        Box::new(MitchellNetravali::new(2.0, 2.0, 0.333333333333333333, 0.333333333333333333));
    let rt = RenderTarget::new((width, height), (20, 20), filter);
    let transform =
        AnimatedTransform::unanimated(&Transform::look_at(&Point::new(0.0, 0.0, -10.0),
                                                          &Point::new(0.0, 0.0, 0.0),
                                                          &Vector::new(0.0, 1.0, 0.0)));
    let camera = Camera::new(transform, 40.0, rt.dimensions(), 0.5, 0);
    let sphere = Sphere::new(1.5);
    let geometry_lock = std::sync::Arc::new(sphere);
    let white_wall = Matte::new(&Colorf::new(0.740063, 0.742313, 0.733934), 1.0);
    let material_lock = std::sync::Arc::new(white_wall);
    let position_transform =
        AnimatedTransform::unanimated(&Transform::translate(&Vector::new(0.0, 2.0, 0.0)));
    let instance = Instance::receiver(geometry_lock,
                                      material_lock,
                                      position_transform,
                                      "single_sphere".to_string());

    let dim = rt.dimensions();
    // A block queue is how work is distributed among threads, it's a list of tiles
    // of the image that have yet to be rendered. Each thread will pull a block from
    // this queue and render it.
    let block_queue = BlockQueue::new((dim.0 as u32, dim.1 as u32), (8, 8), (0, 0));
    let block_dim = block_queue.block_dim();
    // A sample is responsible for choosing randomly placed locations within a pixel to
    // get a good sampling of the image. Using a poor quality sampler will resuly in a
    // noiser and more aliased image that converges slower. The LowDiscrepency sampler
    // is a good choice for quality.
    let mut sampler = LowDiscrepancy::new(block_dim, 2);
    let mut sample_pos = Vec::with_capacity(sampler.max_spp());
    let mut block_samples = Vec::with_capacity(sampler.max_spp() *
                                               (block_dim.0 * block_dim.1) as usize);
    let mut rng = match StdRng::new() {
        Ok(r) => r,
        Err(e) => {
            println!("Failed to get StdRng, {}", e);
            return;
        }
    };
    // Grab a block from the queue and start working on it, submitting samples
    // to the render target thread after each pixel
    for b in block_queue.iter() {
        sampler.select_block(b);
        // While the sampler has samples left to take for this pixel, take some samples
        while sampler.has_samples() {
            // Get samples for a pixel and render them
            sampler.get_samples(&mut sample_pos, &mut rng);
            for s in &sample_pos[..] {
                let mut ray = camera.generate_ray(s, 0.0);
                if let Some(_) = instance.intersect(&mut ray) {
                    block_samples.push(ImageSample::new(s.0, s.1, Colorf::broadcast(1.0)));
                } else {
                    // For correct filtering we also MUST set a background color of some kind
                    // if we miss, otherwise the pixel weights will be wrong and we'll see object
                    // fringes and artifacts at object boundaries w/ nothing. Try removing this
                    // line and rendering again.
                    block_samples.push(ImageSample::new(s.0, s.1, Colorf::black()));
                }
            }
        }
        // We write all samples at once so we don't need to lock the render target tiles as often
        rt.write(&block_samples, sampler.get_region());
        block_samples.clear();
    }

    // Get the sRGB8 render buffer from the floating point framebuffer and save it
    let img = rt.get_render();
    match image::save_buffer("sphere.png",
                             &img[..],
                             dim.0 as u32,
                             dim.1 as u32,
                             image::RGB(8)) {
        Ok(_) => {}
        Err(e) => println!("Error saving image, {}", e),
    };
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::account_config::constants::CORE_CODE_ADDRESS;
use move_core_types::{
    identifier::{IdentStr, Identifier},
    language_storage::{ModuleId, StructTag},
};
use once_cell::sync::Lazy;

pub const ACCOUNT_MODULE_NAME: &str = "LibraAccount";

// Account
static ACCOUNT_MODULE_IDENTIFIER: Lazy<Identifier> =
    Lazy::new(|| Identifier::new("LibraAccount").unwrap());
static ACCOUNT_STRUCT_NAME: Lazy<Identifier> = Lazy::new(|| Identifier::new("T").unwrap());
static ACCOUNT_BALANCE_STRUCT_NAME: Lazy<Identifier> =
    Lazy::new(|| Identifier::new("Balance").unwrap());

/// The ModuleId for the Account module.
pub static ACCOUNT_MODULE: Lazy<ModuleId> =
    Lazy::new(|| ModuleId::new(CORE_CODE_ADDRESS, ACCOUNT_MODULE_IDENTIFIER.clone()));

// Payment Events
static SENT_EVENT_NAME: Lazy<Identifier> =
    Lazy::new(|| Identifier::new("SentPaymentEvent").unwrap());
static RECEIVED_EVENT_NAME: Lazy<Identifier> =
    Lazy::new(|| Identifier::new("ReceivedPaymentEvent").unwrap());

pub fn account_balance_struct_name() -> &'static IdentStr {
    &*ACCOUNT_BALANCE_STRUCT_NAME
}

pub fn sent_event_name() -> &'static IdentStr {
    &*SENT_EVENT_NAME
}

pub fn received_event_name() -> &'static IdentStr {
    &*RECEIVED_EVENT_NAME
}

pub fn account_struct_tag() -> StructTag {
    StructTag {
        address: CORE_CODE_ADDRESS,
        module: ACCOUNT_MODULE_IDENTIFIER.clone(),
        name: ACCOUNT_STRUCT_NAME.to_owned(),
        type_params: vec![],
    }
}

pub fn sent_payment_tag() -> StructTag {
    StructTag {
        address: CORE_CODE_ADDRESS,
        module: ACCOUNT_MODULE_IDENTIFIER.clone(),
        name: sent_event_name().to_owned(),
        type_params: vec![],
    }
}

pub fn received_payment_tag() -> StructTag {
    StructTag {
        address: CORE_CODE_ADDRESS,
        module: ACCOUNT_MODULE_IDENTIFIER.clone(),
        name: received_event_name().to_owned(),
        type_params: vec![],
    }
}
<commit_msg>Removing account_balance_struct_name from types/src/account_config/constants/account.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::account_config::constants::CORE_CODE_ADDRESS;
use move_core_types::{
    identifier::{IdentStr, Identifier},
    language_storage::{ModuleId, StructTag},
};
use once_cell::sync::Lazy;

pub const ACCOUNT_MODULE_NAME: &str = "LibraAccount";

// Account
static ACCOUNT_MODULE_IDENTIFIER: Lazy<Identifier> =
    Lazy::new(|| Identifier::new("LibraAccount").unwrap());
static ACCOUNT_STRUCT_NAME: Lazy<Identifier> = Lazy::new(|| Identifier::new("T").unwrap());

/// The ModuleId for the Account module.
pub static ACCOUNT_MODULE: Lazy<ModuleId> =
    Lazy::new(|| ModuleId::new(CORE_CODE_ADDRESS, ACCOUNT_MODULE_IDENTIFIER.clone()));

// Payment Events
static SENT_EVENT_NAME: Lazy<Identifier> =
    Lazy::new(|| Identifier::new("SentPaymentEvent").unwrap());
static RECEIVED_EVENT_NAME: Lazy<Identifier> =
    Lazy::new(|| Identifier::new("ReceivedPaymentEvent").unwrap());

pub fn sent_event_name() -> &'static IdentStr {
    &*SENT_EVENT_NAME
}

pub fn received_event_name() -> &'static IdentStr {
    &*RECEIVED_EVENT_NAME
}

pub fn account_struct_tag() -> StructTag {
    StructTag {
        address: CORE_CODE_ADDRESS,
        module: ACCOUNT_MODULE_IDENTIFIER.clone(),
        name: ACCOUNT_STRUCT_NAME.to_owned(),
        type_params: vec![],
    }
}

pub fn sent_payment_tag() -> StructTag {
    StructTag {
        address: CORE_CODE_ADDRESS,
        module: ACCOUNT_MODULE_IDENTIFIER.clone(),
        name: sent_event_name().to_owned(),
        type_params: vec![],
    }
}

pub fn received_payment_tag() -> StructTag {
    StructTag {
        address: CORE_CODE_ADDRESS,
        module: ACCOUNT_MODULE_IDENTIFIER.clone(),
        name: received_event_name().to_owned(),
        type_params: vec![],
    }
}
<|endoftext|>


<commit_before>extern crate glutin;
extern crate libc;
use glutin::*;
use std::ptr;

mod gl {
    include!(concat!(env!("OUT_DIR"), "/test_gl_bindings.rs"));
}
use gl::types::*;

#[cfg(not(target_os = "linux"))]
#[test]
fn test_headless() {
    let width: i32 = 2;
    let height: i32 = 1;
    let window = glutin::HeadlessRendererBuilder::new(width as u32, height as u32).build().unwrap();

    unsafe { window.make_current() };

    let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    unsafe {
        let mut framebuffer = 0;
        let mut texture = 0;
        gl.GenFramebuffers(1, &mut framebuffer);
        gl.BindFramebuffer(gl::FRAMEBUFFER, framebuffer);
        gl.GenTextures(1, &mut texture);
        gl.BindTexture(gl::TEXTURE_2D, texture);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
        gl.TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, width, height,
                     0, gl::RGBA, gl::UNSIGNED_BYTE, ptr::null());
        gl.FramebufferTexture(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, texture, 0);
        let status = gl.CheckFramebufferStatus(gl::FRAMEBUFFER);
        if status != gl::FRAMEBUFFER_COMPLETE {
          panic!("Error while creating the framebuffer");
        }

        gl.ClearColor(0.0, 1.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);
        gl.Enable(gl::SCISSOR_TEST);
        gl.Scissor(1, 0, 1, 1);
        gl.ClearColor(1.0, 0.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);

        let mut values: Vec<u8> = vec![0;(width*height*4) as usize];
        gl.ReadPixels(0, 0, width, height, gl::RGBA, gl::UNSIGNED_BYTE, values.as_mut_ptr() as *mut GLvoid);

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

        assert_eq!(values[0], 0);
        assert_eq!(values[1], 255);
        assert_eq!(values[2], 0);
        assert_eq!(values[3], 255);

        assert_eq!(values[4], 255);
        assert_eq!(values[5], 0);
        assert_eq!(values[6], 0);
        assert_eq!(values[7], 255);
    }
}
<commit_msg>Bigger headless window size in test<commit_after>extern crate glutin;
extern crate libc;
use glutin::*;
use std::ptr;

mod gl {
    include!(concat!(env!("OUT_DIR"), "/test_gl_bindings.rs"));
}
use gl::types::*;

#[cfg(not(target_os = "linux"))]
#[test]
fn test_headless() {
    let width: i32 = 256;
    let height: i32 = 256;
    let window = glutin::HeadlessRendererBuilder::new(width as u32, height as u32).build().unwrap();

    unsafe { window.make_current() };

    let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    unsafe {
        let mut framebuffer = 0;
        let mut texture = 0;
        gl.GenFramebuffers(1, &mut framebuffer);
        gl.BindFramebuffer(gl::FRAMEBUFFER, framebuffer);
        gl.GenTextures(1, &mut texture);
        gl.BindTexture(gl::TEXTURE_2D, texture);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
        gl.TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, width, height,
                     0, gl::RGBA, gl::UNSIGNED_BYTE, ptr::null());
        gl.FramebufferTexture(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, texture, 0);
        let status = gl.CheckFramebufferStatus(gl::FRAMEBUFFER);
        if status != gl::FRAMEBUFFER_COMPLETE {
          panic!("Error while creating the framebuffer");
        }

        gl.ClearColor(0.0, 1.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);
        gl.Enable(gl::SCISSOR_TEST);
        gl.Scissor(1, 0, 1, 1);
        gl.ClearColor(1.0, 0.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);

        let mut values: Vec<u8> = vec![0;(width*height*4) as usize];
        gl.ReadPixels(0, 0, width, height, gl::RGBA, gl::UNSIGNED_BYTE, values.as_mut_ptr() as *mut GLvoid);

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

        assert_eq!(values[0], 0);
        assert_eq!(values[1], 255);
        assert_eq!(values[2], 0);
        assert_eq!(values[3], 255);

        assert_eq!(values[4], 255);
        assert_eq!(values[5], 0);
        assert_eq!(values[6], 0);
        assert_eq!(values[7], 255);
    }
}
<|endoftext|>


<commit_before>#![feature(try_trait)]

use serde::Deserialize;

#[derive(Deserialize)]
struct Versions {
    stable: Option<String>,
    bottle: bool,
}

#[derive(Deserialize)]
struct Bottle {
    stable: Option<BottleStable>,
}

#[derive(Deserialize)]
struct BottleStable {
    rebuild: u64,
    files: serde_json::Value,
}

#[derive(Deserialize)]
struct Formula {
    name: String,
    versions: Versions,
    bottle: Bottle,
}

#[derive(Deserialize)]
struct Formulae(Vec<Formula>);

#[derive(Deserialize)]
struct BottleInfo {
    url: String,
    sha256: String,
}

fn d(f: &Formula) -> Option<()> {
    if f.versions.bottle {
        let name = &f.name;
        let ver = f.versions.stable.as_ref()?;
        let bs = f.bottle.stable.as_ref()?;
        let rebuild = bs.rebuild;
        for (platform, v) in bs.files.as_object()?.iter() {
            if let Ok(bi) = serde_json::from_value::<BottleInfo>(v.clone()) {
                if rebuild == 0 {
                    println!("{} {} bottles/{}-{}.{}.bottle.tar.gz", bi.sha256, bi.url, name, ver, platform);
                } else {
                    println!("{} {} bottles/{}-{}.{}.bottle.{}.tar.gz", bi.sha256, bi.url, name, ver, platform, rebuild);
                }
            }
        }
    }
    Some(())
}

fn main() {
    let f: Formulae = serde_json::from_reader(std::io::stdin()).unwrap();
    for f in f.0 {
        d(&f);
    }
}
<commit_msg>homebrew-bottles: adopt upstream incompatible URL changes<commit_after>#![feature(try_trait)]

use serde::Deserialize;

#[derive(Deserialize)]
struct Versions {
    stable: Option<String>,
    bottle: bool,
}

#[derive(Deserialize)]
struct Bottle {
    stable: Option<BottleStable>,
}

#[derive(Deserialize)]
struct BottleStable {
    rebuild: u64,
    files: serde_json::Value,
}

#[derive(Deserialize)]
struct Formula {
    name: String,
    versions: Versions,
    bottle: Bottle,
}

#[derive(Deserialize)]
struct Formulae(Vec<Formula>);

#[derive(Deserialize)]
struct BottleInfo {
    url: String,
    sha256: String,
}

fn d(f: &Formula) -> Option<()> {
    if f.versions.bottle {
        let name = &f.name;
        let ver = f.versions.stable.as_ref()?;
        let bs = f.bottle.stable.as_ref()?;
        let rebuild = bs.rebuild;
        for (platform, v) in bs.files.as_object()?.iter() {
            if let Ok(bi) = serde_json::from_value::<BottleInfo>(v.clone()) {
                if rebuild == 0 {
                    println!("{} {} {}-{}.{}.bottle.tar.gz", bi.sha256, bi.url, name, ver, platform);
                } else {
                    println!("{} {} {}-{}.{}.bottle.{}.tar.gz", bi.sha256, bi.url, name, ver, platform, rebuild);
                }
            }
        }
    }
    Some(())
}

fn main() {
    let f: Formulae = serde_json::from_reader(std::io::stdin()).unwrap();
    for f in f.0 {
        d(&f);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

use bytes::Bytes;
use futures_core::Stream;
use http_body::Body as HttpBody;
use pin_project_lite::pin_project;
use tokio::time::Sleep;

/// An asynchronous request body.
pub struct Body {
    inner: Inner,
}

// The `Stream` trait isn't stable, so the impl isn't public.
pub(crate) struct ImplStream(Body);

enum Inner {
    Reusable(Bytes),
    Streaming {
        body: Pin<
            Box<
                dyn HttpBody<Data = Bytes, Error = Box<dyn std::error::Error + Send + Sync>>
                    + Send
                    + Sync,
            >,
        >,
        timeout: Option<Pin<Box<Sleep>>>,
    },
}

pin_project! {
    struct WrapStream<S> {
        #[pin]
        inner: S,
    }
}

struct WrapHyper(hyper::Body);

impl Body {
    /// Returns a reference to the internal data of the `Body`.
    ///
    /// `None` is returned, if the underlying data is a stream.
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match &self.inner {
            Inner::Reusable(bytes) => Some(bytes.as_ref()),
            Inner::Streaming { .. } => None,
        }
    }

    /// Wrap a futures `Stream` in a box inside `Body`.
    ///
    /// # Example
    ///
    /// ```
    /// # use reqwest::Body;
    /// # use futures_util;
    /// # fn main() {
    /// let chunks: Vec<Result<_, ::std::io::Error>> = vec![
    ///     Ok("hello"),
    ///     Ok(" "),
    ///     Ok("world"),
    /// ];
    ///
    /// let stream = futures_util::stream::iter(chunks);
    ///
    /// let body = Body::wrap_stream(stream);
    /// # }
    /// ```
    ///
    /// # Optional
    ///
    /// This requires the `stream` feature to be enabled.
    #[cfg(feature = "stream")]
    pub fn wrap_stream<S>(stream: S) -> Body
    where
        S: futures_core::stream::TryStream + Send + Sync + 'static,
        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
        Bytes: From<S::Ok>,
    {
        Body::stream(stream)
    }

    pub(crate) fn stream<S>(stream: S) -> Body
    where
        S: futures_core::stream::TryStream + Send + Sync + 'static,
        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
        Bytes: From<S::Ok>,
    {
        use futures_util::TryStreamExt;

        let body = Box::pin(WrapStream {
            inner: stream.map_ok(Bytes::from).map_err(Into::into),
        });
        Body {
            inner: Inner::Streaming {
                body,
                timeout: None,
            },
        }
    }

    pub(crate) fn response(body: hyper::Body, timeout: Option<Pin<Box<Sleep>>>) -> Body {
        Body {
            inner: Inner::Streaming {
                body: Box::pin(WrapHyper(body)),
                timeout,
            },
        }
    }

    #[cfg(feature = "blocking")]
    pub(crate) fn wrap(body: hyper::Body) -> Body {
        Body {
            inner: Inner::Streaming {
                body: Box::pin(WrapHyper(body)),
                timeout: None,
            },
        }
    }

    pub(crate) fn empty() -> Body {
        Body::reusable(Bytes::new())
    }

    pub(crate) fn reusable(chunk: Bytes) -> Body {
        Body {
            inner: Inner::Reusable(chunk),
        }
    }

    pub(crate) fn try_reuse(self) -> (Option<Bytes>, Self) {
        let reuse = match self.inner {
            Inner::Reusable(ref chunk) => Some(chunk.clone()),
            Inner::Streaming { .. } => None,
        };

        (reuse, self)
    }

    pub(crate) fn try_clone(&self) -> Option<Body> {
        match self.inner {
            Inner::Reusable(ref chunk) => Some(Body::reusable(chunk.clone())),
            Inner::Streaming { .. } => None,
        }
    }

    pub(crate) fn into_stream(self) -> ImplStream {
        ImplStream(self)
    }

    #[cfg(feature = "multipart")]
    pub(crate) fn content_length(&self) -> Option<u64> {
        match self.inner {
            Inner::Reusable(ref bytes) => Some(bytes.len() as u64),
            Inner::Streaming { ref body, .. } => body.size_hint().exact(),
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        Body::reusable(bytes)
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        Body::reusable(vec.into())
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from(s: &'static [u8]) -> Body {
        Body::reusable(Bytes::from_static(s))
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        Body::reusable(s.into())
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(s: &'static str) -> Body {
        s.as_bytes().into()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body").finish()
    }
}

// ===== impl ImplStream =====

impl HttpBody for ImplStream {
    type Data = Bytes;
    type Error = crate::Error;

    fn poll_data(
        mut self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
        let opt_try_chunk = match self.0.inner {
            Inner::Streaming {
                ref mut body,
                ref mut timeout,
            } => {
                if let Some(ref mut timeout) = timeout {
                    if let Poll::Ready(()) = timeout.as_mut().poll(cx) {
                        return Poll::Ready(Some(Err(crate::error::body(crate::error::TimedOut))));
                    }
                }
                futures_core::ready!(Pin::new(body).poll_data(cx))
                    .map(|opt_chunk| opt_chunk.map(Into::into).map_err(crate::error::body))
            }
            Inner::Reusable(ref mut bytes) => {
                if bytes.is_empty() {
                    None
                } else {
                    Some(Ok(std::mem::replace(bytes, Bytes::new())))
                }
            }
        };

        Poll::Ready(opt_try_chunk)
    }

    fn poll_trailers(
        self: Pin<&mut Self>,
        _cx: &mut Context,
    ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
        Poll::Ready(Ok(None))
    }

    fn is_end_stream(&self) -> bool {
        match self.0.inner {
            Inner::Streaming { ref body, .. } => body.is_end_stream(),
            Inner::Reusable(ref bytes) => bytes.is_empty(),
        }
    }

    fn size_hint(&self) -> http_body::SizeHint {
        match self.0.inner {
            Inner::Streaming { ref body, .. } => body.size_hint(),
            Inner::Reusable(ref bytes) => {
                let mut hint = http_body::SizeHint::default();
                hint.set_exact(bytes.len() as u64);
                hint
            }
        }
    }
}

impl Stream for ImplStream {
    type Item = Result<Bytes, crate::Error>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
        self.poll_data(cx)
    }
}

// ===== impl WrapStream =====

impl<S, D, E> HttpBody for WrapStream<S>
where
    S: Stream<Item = Result<D, E>>,
    D: Into<Bytes>,
    E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
    type Data = Bytes;
    type Error = E;

    fn poll_data(
        self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
        let item = futures_core::ready!(self.project().inner.poll_next(cx)?);

        Poll::Ready(item.map(|val| Ok(val.into())))
    }

    fn poll_trailers(
        self: Pin<&mut Self>,
        _cx: &mut Context,
    ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
        Poll::Ready(Ok(None))
    }
}

// ===== impl WrapHyper =====

impl HttpBody for WrapHyper {
    type Data = Bytes;
    type Error = Box<dyn std::error::Error + Send + Sync>;

    fn poll_data(
        mut self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
        // safe pin projection
        Pin::new(&mut self.0)
            .poll_data(cx)
            .map(|opt| opt.map(|res| res.map_err(Into::into)))
    }

    fn poll_trailers(
        self: Pin<&mut Self>,
        _cx: &mut Context,
    ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
        Poll::Ready(Ok(None))
    }

    fn is_end_stream(&self) -> bool {
        self.0.is_end_stream()
    }

    fn size_hint(&self) -> http_body::SizeHint {
        HttpBody::size_hint(&self.0)
    }
}

#[cfg(test)]
mod tests {
    use super::Body;

    #[test]
    fn test_as_bytes() {
        let test_data = b"Test body";
        let body = Body::from(&test_data[..]);
        assert_eq!(body.as_bytes(), Some(&test_data[..]));
    }
}
<commit_msg>impl From<hyper::Body> for Body (#1236)<commit_after>use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

use bytes::Bytes;
use futures_core::Stream;
use http_body::Body as HttpBody;
use pin_project_lite::pin_project;
use tokio::time::Sleep;

/// An asynchronous request body.
pub struct Body {
    inner: Inner,
}

// The `Stream` trait isn't stable, so the impl isn't public.
pub(crate) struct ImplStream(Body);

enum Inner {
    Reusable(Bytes),
    Streaming {
        body: Pin<
            Box<
                dyn HttpBody<Data = Bytes, Error = Box<dyn std::error::Error + Send + Sync>>
                    + Send
                    + Sync,
            >,
        >,
        timeout: Option<Pin<Box<Sleep>>>,
    },
}

pin_project! {
    struct WrapStream<S> {
        #[pin]
        inner: S,
    }
}

struct WrapHyper(hyper::Body);

impl Body {
    /// Returns a reference to the internal data of the `Body`.
    ///
    /// `None` is returned, if the underlying data is a stream.
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match &self.inner {
            Inner::Reusable(bytes) => Some(bytes.as_ref()),
            Inner::Streaming { .. } => None,
        }
    }

    /// Wrap a futures `Stream` in a box inside `Body`.
    ///
    /// # Example
    ///
    /// ```
    /// # use reqwest::Body;
    /// # use futures_util;
    /// # fn main() {
    /// let chunks: Vec<Result<_, ::std::io::Error>> = vec![
    ///     Ok("hello"),
    ///     Ok(" "),
    ///     Ok("world"),
    /// ];
    ///
    /// let stream = futures_util::stream::iter(chunks);
    ///
    /// let body = Body::wrap_stream(stream);
    /// # }
    /// ```
    ///
    /// # Optional
    ///
    /// This requires the `stream` feature to be enabled.
    #[cfg(feature = "stream")]
    pub fn wrap_stream<S>(stream: S) -> Body
    where
        S: futures_core::stream::TryStream + Send + Sync + 'static,
        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
        Bytes: From<S::Ok>,
    {
        Body::stream(stream)
    }

    pub(crate) fn stream<S>(stream: S) -> Body
    where
        S: futures_core::stream::TryStream + Send + Sync + 'static,
        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
        Bytes: From<S::Ok>,
    {
        use futures_util::TryStreamExt;

        let body = Box::pin(WrapStream {
            inner: stream.map_ok(Bytes::from).map_err(Into::into),
        });
        Body {
            inner: Inner::Streaming {
                body,
                timeout: None,
            },
        }
    }

    pub(crate) fn response(body: hyper::Body, timeout: Option<Pin<Box<Sleep>>>) -> Body {
        Body {
            inner: Inner::Streaming {
                body: Box::pin(WrapHyper(body)),
                timeout,
            },
        }
    }

    #[cfg(feature = "blocking")]
    pub(crate) fn wrap(body: hyper::Body) -> Body {
        Body {
            inner: Inner::Streaming {
                body: Box::pin(WrapHyper(body)),
                timeout: None,
            },
        }
    }

    pub(crate) fn empty() -> Body {
        Body::reusable(Bytes::new())
    }

    pub(crate) fn reusable(chunk: Bytes) -> Body {
        Body {
            inner: Inner::Reusable(chunk),
        }
    }

    pub(crate) fn try_reuse(self) -> (Option<Bytes>, Self) {
        let reuse = match self.inner {
            Inner::Reusable(ref chunk) => Some(chunk.clone()),
            Inner::Streaming { .. } => None,
        };

        (reuse, self)
    }

    pub(crate) fn try_clone(&self) -> Option<Body> {
        match self.inner {
            Inner::Reusable(ref chunk) => Some(Body::reusable(chunk.clone())),
            Inner::Streaming { .. } => None,
        }
    }

    pub(crate) fn into_stream(self) -> ImplStream {
        ImplStream(self)
    }

    #[cfg(feature = "multipart")]
    pub(crate) fn content_length(&self) -> Option<u64> {
        match self.inner {
            Inner::Reusable(ref bytes) => Some(bytes.len() as u64),
            Inner::Streaming { ref body, .. } => body.size_hint().exact(),
        }
    }
}

impl From<hyper::Body> for Body {
    #[inline]
    fn from(body: hyper::Body) -> Body {
        Self {
            inner: Inner::Streaming {
                body: Box::pin(WrapHyper(body)),
                timeout: None,
            },
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        Body::reusable(bytes)
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        Body::reusable(vec.into())
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from(s: &'static [u8]) -> Body {
        Body::reusable(Bytes::from_static(s))
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        Body::reusable(s.into())
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(s: &'static str) -> Body {
        s.as_bytes().into()
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Body").finish()
    }
}

// ===== impl ImplStream =====

impl HttpBody for ImplStream {
    type Data = Bytes;
    type Error = crate::Error;

    fn poll_data(
        mut self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
        let opt_try_chunk = match self.0.inner {
            Inner::Streaming {
                ref mut body,
                ref mut timeout,
            } => {
                if let Some(ref mut timeout) = timeout {
                    if let Poll::Ready(()) = timeout.as_mut().poll(cx) {
                        return Poll::Ready(Some(Err(crate::error::body(crate::error::TimedOut))));
                    }
                }
                futures_core::ready!(Pin::new(body).poll_data(cx))
                    .map(|opt_chunk| opt_chunk.map(Into::into).map_err(crate::error::body))
            }
            Inner::Reusable(ref mut bytes) => {
                if bytes.is_empty() {
                    None
                } else {
                    Some(Ok(std::mem::replace(bytes, Bytes::new())))
                }
            }
        };

        Poll::Ready(opt_try_chunk)
    }

    fn poll_trailers(
        self: Pin<&mut Self>,
        _cx: &mut Context,
    ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
        Poll::Ready(Ok(None))
    }

    fn is_end_stream(&self) -> bool {
        match self.0.inner {
            Inner::Streaming { ref body, .. } => body.is_end_stream(),
            Inner::Reusable(ref bytes) => bytes.is_empty(),
        }
    }

    fn size_hint(&self) -> http_body::SizeHint {
        match self.0.inner {
            Inner::Streaming { ref body, .. } => body.size_hint(),
            Inner::Reusable(ref bytes) => {
                let mut hint = http_body::SizeHint::default();
                hint.set_exact(bytes.len() as u64);
                hint
            }
        }
    }
}

impl Stream for ImplStream {
    type Item = Result<Bytes, crate::Error>;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
        self.poll_data(cx)
    }
}

// ===== impl WrapStream =====

impl<S, D, E> HttpBody for WrapStream<S>
where
    S: Stream<Item = Result<D, E>>,
    D: Into<Bytes>,
    E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
    type Data = Bytes;
    type Error = E;

    fn poll_data(
        self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
        let item = futures_core::ready!(self.project().inner.poll_next(cx)?);

        Poll::Ready(item.map(|val| Ok(val.into())))
    }

    fn poll_trailers(
        self: Pin<&mut Self>,
        _cx: &mut Context,
    ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
        Poll::Ready(Ok(None))
    }
}

// ===== impl WrapHyper =====

impl HttpBody for WrapHyper {
    type Data = Bytes;
    type Error = Box<dyn std::error::Error + Send + Sync>;

    fn poll_data(
        mut self: Pin<&mut Self>,
        cx: &mut Context,
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
        // safe pin projection
        Pin::new(&mut self.0)
            .poll_data(cx)
            .map(|opt| opt.map(|res| res.map_err(Into::into)))
    }

    fn poll_trailers(
        self: Pin<&mut Self>,
        _cx: &mut Context,
    ) -> Poll<Result<Option<http::HeaderMap>, Self::Error>> {
        Poll::Ready(Ok(None))
    }

    fn is_end_stream(&self) -> bool {
        self.0.is_end_stream()
    }

    fn size_hint(&self) -> http_body::SizeHint {
        HttpBody::size_hint(&self.0)
    }
}

#[cfg(test)]
mod tests {
    use super::Body;

    #[test]
    fn test_as_bytes() {
        let test_data = b"Test body";
        let body = Body::from(&test_data[..]);
        assert_eq!(body.as_bytes(), Some(&test_data[..]));
    }
}
<|endoftext|>