<commit_before>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;
extern crate mio;
extern crate rand;
extern crate docopt;
extern crate quiche;
extern crate env_logger;

use std::fs;
use std::io;
use std::net;
use std::path;

use std::collections::hash_map;
use std::collections::HashMap;

use docopt::Docopt;

use rand::Rng;

const LOCAL_CONN_ID_LEN: usize = 16;

const TRANSPORT_PARAMS: quiche::TransportParams = quiche::TransportParams {
    idle_timeout: 30,
    initial_max_data: 10_000_000,
    initial_max_bidi_streams: 100,
    initial_max_uni_streams: 100,
    max_packet_size: 1500,
    ack_delay_exponent: 3,
    disable_migration: true,
    max_ack_delay: 25,
    initial_max_stream_data_bidi_local: 1_000_000,
    initial_max_stream_data_bidi_remote: 1_000_000,
    initial_max_stream_data_uni: 1_000_000,
    stateless_reset_token_present: true,
    stateless_reset_token: [0xba; 16],
};

const USAGE: &str = "Usage: server [options]

Options:
  -h --help         Show this screen.
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
";

fn main() {
    let mut buf = [0; TRANSPORT_PARAMS.max_packet_size as usize];
    let mut out = [0; TRANSPORT_PARAMS.max_packet_size as usize];

    env_logger::init();

    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen")).unwrap();

    let poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket).unwrap();
    poll.register(&socket, mio::Token(0),
                  mio::Ready::readable(),
                  mio::PollOpt::edge()).unwrap();

    let mut connections: HashMap<net::SocketAddr, Box<quiche::Connection>> =
        HashMap::new();

    loop {
        poll.poll(&mut events, None).unwrap();

        'read: loop {
            let (len, src) = match socket.recv_from(&mut buf) {
                Ok(v) => v,

                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            let buf = &mut buf[..len];

            let hdr = match quiche::Header::from_slice(buf, LOCAL_CONN_ID_LEN) {
                Ok(v) => v,

                Err(e) => {
                    error!("Parsing packet header failed: {:?}", e);
                    continue
                }
            };

            if hdr.ty == quiche::Type::VersionNegotiation {
                error!("Version negotiation invalid on the server");
                continue;
            }

            let conn = match connections.entry(src) {
                hash_map::Entry::Vacant(v) => {
                    if hdr.version != quiche::VERSION_DRAFT15 {
                        warn!("Doing version negotiation");

                        let len = quiche::Connection::negotiate_version(&hdr, &mut out)
                                               .unwrap();
                        let out = &out[..len];

                        socket.send_to(out, &src).unwrap();
                        continue;
                    }

                    if hdr.ty != quiche::Type::Initial {
                        error!("Packet is not Initial");
                        continue;
                    }

                    let mut scid: [u8; LOCAL_CONN_ID_LEN] = [0; LOCAL_CONN_ID_LEN];
                    rand::thread_rng().fill(&mut scid[..]);

                    let config = quiche::Config {
                        version: quiche::VERSION_DRAFT15,

                        local_conn_id: &scid,

                        local_transport_params: &TRANSPORT_PARAMS,

                        tls_server_name: args.get_str("--name"),
                        tls_certificate: args.get_str("--cert"),
                        tls_certificate_key: args.get_str("--key"),
                    };

                    debug!("New connection: dcid={} scid={} lcid={}",
                           hex_dump(&hdr.dcid),
                           hex_dump(&hdr.scid),
                           hex_dump(&scid));

                    let conn = quiche::Connection::new(config, true).unwrap();

                    v.insert(conn)
                },

                hash_map::Entry::Occupied(v) => v.into_mut(),
            };

            let mut left = len;

            // Process potentially coalesced packets.
            while left > 0 {
                let read = match conn.recv(&mut buf[len - left..len]) {
                    Ok(v)  => v,

                    Err(e) => {
                        error!("{} recv failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break 'read;
                    },
                };

                left -= read;

                debug!("{} read {} bytes", conn.trace_id(), read);
            }

            let streams: Vec<u64> = conn.stream_iter().collect();
            for s in streams {
                info!("{} stream {} is readable", conn.trace_id(), s);
                handle_stream(conn, s, &args);
            }
        }

        for (src, conn) in &mut connections {
            loop {
                let write = match conn.send(&mut out) {
                    Ok(v) => v,

                    Err(quiche::Error::NothingToDo) => {
                        debug!("{} done writing", conn.trace_id());
                        break;
                    },

                    Err(e) => {
                        error!("{} send failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break;
                    },
                };

                // TODO: coalesce packets.
                socket.send_to(&out[..write], &src).unwrap();

                debug!("{} written {} bytes", conn.trace_id(), write);
            }
        }

        // Garbage collect closed connections.
        connections.retain(|_, ref mut c| {
            debug!("Collecting garbage");

            if c.is_closed() {
                debug!("{} connection collected", c.trace_id());
            }

            !c.is_closed()
        });
    }
}

fn handle_stream(conn: &mut quiche::Connection, stream: u64, args: &docopt::ArgvMap) {
    let stream_data = match conn.stream_recv(stream) {
        Ok(v) => v,

        Err(quiche::Error::NothingToDo) => return,

        Err(e) => panic!("{} stream recv failed {:?}",
                         conn.trace_id(), e),
    };

    info!("{} stream {} has {} bytes (fin? {})", conn.trace_id(),
          stream, stream_data.len(), stream_data.fin());

    if stream_data.len() > 4 && &stream_data[..4] == b"GET " {
        let uri = &stream_data[4..stream_data.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = path::Path::new(&uri);
        let mut path = path::PathBuf::from(args.get_str("--root"));

        for c in uri.components() {
            if let path::Component::Normal(v) = c {
                path.push(v)
            }
        }

        info!("{} got GET request for {:?} on stream {}",
              conn.trace_id(), path, stream);

        let data = fs::read(path.as_path())
                      .unwrap_or_else(|_| Vec::from(String::from("Not Found!\r\n")));

        info!("{} sending response of size {} on stream {}",
              conn.trace_id(), data.len(), stream);

        if let Err(e) = conn.stream_send(stream, &data, true) {
            error!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter()
                              .map(|b| format!("{:02x}", b))
                              .collect();

    vec.join("")
}
<commit_msg>server: only Initial should trigger version negotiation<commit_after>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;
extern crate mio;
extern crate rand;
extern crate docopt;
extern crate quiche;
extern crate env_logger;

use std::fs;
use std::io;
use std::net;
use std::path;

use std::collections::hash_map;
use std::collections::HashMap;

use docopt::Docopt;

use rand::Rng;

const LOCAL_CONN_ID_LEN: usize = 16;

const TRANSPORT_PARAMS: quiche::TransportParams = quiche::TransportParams {
    idle_timeout: 30,
    initial_max_data: 10_000_000,
    initial_max_bidi_streams: 100,
    initial_max_uni_streams: 100,
    max_packet_size: 1500,
    ack_delay_exponent: 3,
    disable_migration: true,
    max_ack_delay: 25,
    initial_max_stream_data_bidi_local: 1_000_000,
    initial_max_stream_data_bidi_remote: 1_000_000,
    initial_max_stream_data_uni: 1_000_000,
    stateless_reset_token_present: true,
    stateless_reset_token: [0xba; 16],
};

const USAGE: &str = "Usage: server [options]

Options:
  -h --help         Show this screen.
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
";

fn main() {
    let mut buf = [0; TRANSPORT_PARAMS.max_packet_size as usize];
    let mut out = [0; TRANSPORT_PARAMS.max_packet_size as usize];

    env_logger::init();

    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen")).unwrap();

    let poll = mio::Poll::new().unwrap();
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket).unwrap();
    poll.register(&socket, mio::Token(0),
                  mio::Ready::readable(),
                  mio::PollOpt::edge()).unwrap();

    let mut connections: HashMap<net::SocketAddr, Box<quiche::Connection>> =
        HashMap::new();

    loop {
        poll.poll(&mut events, None).unwrap();

        'read: loop {
            let (len, src) = match socket.recv_from(&mut buf) {
                Ok(v) => v,

                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            let buf = &mut buf[..len];

            let hdr = match quiche::Header::from_slice(buf, LOCAL_CONN_ID_LEN) {
                Ok(v) => v,

                Err(e) => {
                    error!("Parsing packet header failed: {:?}", e);
                    continue
                }
            };

            if hdr.ty == quiche::Type::VersionNegotiation {
                error!("Version negotiation invalid on the server");
                continue;
            }

            let conn = match connections.entry(src) {
                hash_map::Entry::Vacant(v) => {
                    if hdr.ty != quiche::Type::Initial {
                        error!("Packet is not Initial");
                        continue;
                    }

                    if hdr.version != quiche::VERSION_DRAFT15 {
                        warn!("Doing version negotiation");

                        let len = quiche::Connection::negotiate_version(&hdr, &mut out)
                                               .unwrap();
                        let out = &out[..len];

                        socket.send_to(out, &src).unwrap();
                        continue;
                    }

                    let mut scid: [u8; LOCAL_CONN_ID_LEN] = [0; LOCAL_CONN_ID_LEN];
                    rand::thread_rng().fill(&mut scid[..]);

                    let config = quiche::Config {
                        version: quiche::VERSION_DRAFT15,

                        local_conn_id: &scid,

                        local_transport_params: &TRANSPORT_PARAMS,

                        tls_server_name: args.get_str("--name"),
                        tls_certificate: args.get_str("--cert"),
                        tls_certificate_key: args.get_str("--key"),
                    };

                    debug!("New connection: dcid={} scid={} lcid={}",
                           hex_dump(&hdr.dcid),
                           hex_dump(&hdr.scid),
                           hex_dump(&scid));

                    let conn = quiche::Connection::new(config, true).unwrap();

                    v.insert(conn)
                },

                hash_map::Entry::Occupied(v) => v.into_mut(),
            };

            let mut left = len;

            // Process potentially coalesced packets.
            while left > 0 {
                let read = match conn.recv(&mut buf[len - left..len]) {
                    Ok(v)  => v,

                    Err(e) => {
                        error!("{} recv failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break 'read;
                    },
                };

                left -= read;

                debug!("{} read {} bytes", conn.trace_id(), read);
            }

            let streams: Vec<u64> = conn.stream_iter().collect();
            for s in streams {
                info!("{} stream {} is readable", conn.trace_id(), s);
                handle_stream(conn, s, &args);
            }
        }

        for (src, conn) in &mut connections {
            loop {
                let write = match conn.send(&mut out) {
                    Ok(v) => v,

                    Err(quiche::Error::NothingToDo) => {
                        debug!("{} done writing", conn.trace_id());
                        break;
                    },

                    Err(e) => {
                        error!("{} send failed: {:?}", conn.trace_id(), e);
                        conn.close(false, e.to_wire(), b"fail").unwrap();
                        break;
                    },
                };

                // TODO: coalesce packets.
                socket.send_to(&out[..write], &src).unwrap();

                debug!("{} written {} bytes", conn.trace_id(), write);
            }
        }

        // Garbage collect closed connections.
        connections.retain(|_, ref mut c| {
            debug!("Collecting garbage");

            if c.is_closed() {
                debug!("{} connection collected", c.trace_id());
            }

            !c.is_closed()
        });
    }
}

fn handle_stream(conn: &mut quiche::Connection, stream: u64, args: &docopt::ArgvMap) {
    let stream_data = match conn.stream_recv(stream) {
        Ok(v) => v,

        Err(quiche::Error::NothingToDo) => return,

        Err(e) => panic!("{} stream recv failed {:?}",
                         conn.trace_id(), e),
    };

    info!("{} stream {} has {} bytes (fin? {})", conn.trace_id(),
          stream, stream_data.len(), stream_data.fin());

    if stream_data.len() > 4 && &stream_data[..4] == b"GET " {
        let uri = &stream_data[4..stream_data.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = path::Path::new(&uri);
        let mut path = path::PathBuf::from(args.get_str("--root"));

        for c in uri.components() {
            if let path::Component::Normal(v) = c {
                path.push(v)
            }
        }

        info!("{} got GET request for {:?} on stream {}",
              conn.trace_id(), path, stream);

        let data = fs::read(path.as_path())
                      .unwrap_or_else(|_| Vec::from(String::from("Not Found!\r\n")));

        info!("{} sending response of size {} on stream {}",
              conn.trace_id(), data.len(), stream);

        if let Err(e) = conn.stream_send(stream, &data, true) {
            error!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter()
                              .map(|b| format!("{:02x}", b))
                              .collect();

    vec.join("")
}
<|endoftext|>


<commit_before>extern crate fbx_direct;
extern crate env_logger;

use std::fs::File;
use std::io::BufReader;

use fbx_direct::reader::{EventReader, FbxEvent};

fn indent(size: usize) -> String {
    const INDENT: &'static str = "    ";
    (0..size).map(|_| INDENT)
        .fold(String::with_capacity(size * INDENT.len()), |r, s| r + s)
}

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

    let file = BufReader::new(File::open("sample.fbx").unwrap());

    let parser = EventReader::new(file);
    let mut depth = 0;
    for e in parser {
        match e {
            Err(e) => {
                println!("Error: {:?}", e);
                break;
            },
            Ok(ref e@FbxEvent::StartNode { .. }) => {
                println!("{}{:?}", indent(depth), e);
                depth += 1;
            },
            Ok(ref e@FbxEvent::EndNode) => {
                depth -= 1;
                println!("{}{:?}", indent(depth), e);
            },
            _ => {
                println!("{}{:?}", indent(depth), e);
            }
        }
    }
}
<commit_msg>Improve example `simple.rs`<commit_after>extern crate fbx_direct;
extern crate env_logger;

use std::fs::File;
use std::io::BufReader;

use fbx_direct::reader::{EventReader, FbxEvent};

fn indent(size: usize) -> String {
    const INDENT: &'static str = "    ";
    (0..size).map(|_| INDENT)
        .fold(String::with_capacity(size * INDENT.len()), |r, s| r + s)
}

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

    let file = BufReader::new(File::open("sample.fbx").unwrap());

    let parser = EventReader::new(file);
    let mut depth = 0;
    for e in parser {
        match e {
            Ok(ref e@FbxEvent::StartNode { .. }) => {
                println!("{}{:?}", indent(depth), e);
                depth += 1;
            },
            Ok(ref e@FbxEvent::EndNode) => {
                depth -= 1;
                println!("{}{:?}", indent(depth), e);
            },
            Ok(e) => {
                println!("{}{:?}", indent(depth), e);
            },
            Err(e) => {
                println!("Error: {:?}", e);
                break;
            },
        }
    }
}
<|endoftext|>


<commit_before>use super::{function, trait_impls};
use crate::{
    analysis::enums::Info,
    analysis::special_functions::Type,
    codegen::general::{
        self, cfg_deprecated, derives, doc_alias, version_condition, version_condition_no_doc,
        version_condition_string,
    },
    config::gobjects::GObject,
    env::Env,
    file_saver,
    library::*,
    nameutil::{enum_member_name, use_glib_if_needed, use_glib_type},
    traits::*,
    version::Version,
};
use std::{
    collections::HashSet,
    io::{prelude::*, Result},
    path::Path,
};

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    if env.analysis.enumerations.is_empty() {
        return;
    }

    let path = root_path.join("enums.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        general::start_comments(w, &env.config)?;
        general::uses(w, env, &env.analysis.enum_imports)?;
        writeln!(w)?;

        mod_rs.push("\nmod enums;".into());
        for enum_analysis in &env.analysis.enumerations {
            let config = &env.config.objects[&enum_analysis.full_name];
            let enum_ = enum_analysis.type_(&env.library);

            if let Some(cfg) = version_condition_string(env, enum_.version, false, 0) {
                mod_rs.push(cfg);
            }
            mod_rs.push(format!("pub use self::enums::{};", enum_.name));
            generate_enum(env, w, enum_, config, enum_analysis)?;
        }

        Ok(())
    });
}

#[allow(clippy::write_literal)]
fn generate_enum(
    env: &Env,
    w: &mut dyn Write,
    enum_: &Enumeration,
    config: &GObject,
    analysis: &Info,
) -> Result<()> {
    struct Member {
        name: String,
        c_name: String,
        value: String,
        version: Option<Version>,
        deprecated_version: Option<Version>,
    }

    let mut members: Vec<Member> = Vec::new();
    let mut vals: HashSet<String> = HashSet::new();
    let sys_crate_name = env.main_sys_crate_name();

    for member in &enum_.members {
        let member_config = config.members.matched(&member.name);
        let is_alias = member_config.iter().any(|m| m.alias);
        let generate = member_config.iter().all(|m| m.status.need_generate());
        if is_alias || !generate || vals.contains(&member.value) {
            continue;
        }
        vals.insert(member.value.clone());
        let deprecated_version = member_config
            .iter()
            .filter_map(|m| m.deprecated_version)
            .next();
        let version = member_config.iter().filter_map(|m| m.version).next();
        members.push(Member {
            name: enum_member_name(&member.name),
            c_name: member.c_identifier.clone(),
            value: member.value.clone(),
            version,
            deprecated_version,
        });
    }

    cfg_deprecated(w, env, enum_.deprecated_version, false, 0)?;
    version_condition(w, env, enum_.version, false, 0)?;
    if config.must_use {
        writeln!(w, "#[must_use]")?;
    }

    if let Some(ref d) = config.derives {
        derives(w, &d, 1)?;
    } else {
        writeln!(w, "#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]")?;
    }
    writeln!(w, "#[derive(Clone, Copy)]")?;
    writeln!(w, "#[non_exhaustive]")?;
    doc_alias(w, &enum_.c_type, "", 0)?;

    writeln!(w, "pub enum {} {{", enum_.name)?;
    for member in &members {
        cfg_deprecated(w, env, member.deprecated_version, false, 1)?;
        version_condition(w, env, member.version, false, 1)?;
        doc_alias(w, &member.c_name, "", 1)?;
        writeln!(w, "\t{},", member.name)?;
    }
    writeln!(
        w,
        "\
    #[doc(hidden)]
    __Unknown(i32),
}}"
    )?;

    let functions = analysis
        .functions
        .iter()
        .filter(|f| f.status.need_generate())
        .collect::<Vec<_>>();

    if !functions.is_empty() {
        writeln!(w)?;
        version_condition(w, env, enum_.version, false, 0)?;
        write!(w, "impl {} {{", analysis.name)?;
        for func_analysis in functions {
            function::generate(
                w,
                env,
                func_analysis,
                Some(&analysis.specials),
                false,
                false,
                1,
            )?;
        }
        writeln!(w, "}}")?;
    }

    trait_impls::generate(
        w,
        env,
        &analysis.name,
        &analysis.functions,
        &analysis.specials,
        None,
    )?;

    writeln!(w)?;

    if config.generate_display_trait && !analysis.specials.has_trait(Type::Display) {
        // Generate Display trait implementation.
        version_condition(w, env, enum_.version, false, 0)?;
        writeln!(
            w,
            "impl fmt::Display for {0} {{\n\
             \tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{\n\
             \t\twrite!(f, \"{0}::{{}}\", match *self {{",
            enum_.name
        )?;
        for member in &members {
            version_condition_no_doc(w, env, member.version, false, 3)?;
            writeln!(w, "\t\t\t{0}::{1} => \"{1}\",", enum_.name, member.name)?;
        }
        writeln!(
            w,
            "\t\t\t_ => \"Unknown\",\n\
             \t\t}})\n\
             \t}}\n\
             }}\n"
        )?;
    }

    // Generate ToGlib trait implementation.
    version_condition(w, env, enum_.version, false, 0)?;
    writeln!(
        w,
        "#[doc(hidden)]
impl ToGlib for {name} {{
    type GlibType = {sys_crate_name}::{ffi_name};

    fn to_glib(&self) -> {sys_crate_name}::{ffi_name} {{
        match *self {{",
        sys_crate_name = sys_crate_name,
        name = enum_.name,
        ffi_name = enum_.c_type
    )?;
    for member in &members {
        version_condition_no_doc(w, env, member.version, false, 3)?;
        writeln!(
            w,
            "\t\t\t{}::{} => {}::{},",
            enum_.name, member.name, sys_crate_name, member.c_name
        )?;
    }
    writeln!(w, "\t\t\t{}::__Unknown(value) => value,", enum_.name)?;
    writeln!(
        w,
        "\
        }}
    }}
}}
"
    )?;

    let assert = if env.config.generate_safety_asserts {
        "skip_assert_initialized!();\n\t\t"
    } else {
        ""
    };

    // Generate FromGlib trait implementation.
    version_condition(w, env, enum_.version, false, 0)?;
    writeln!(
        w,
        "#[doc(hidden)]
impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{
    unsafe fn from_glib(value: {sys_crate_name}::{ffi_name}) -> Self {{
        {assert}match value {{",
        sys_crate_name = sys_crate_name,
        name = enum_.name,
        ffi_name = enum_.c_type,
        assert = assert
    )?;
    for member in &members {
        version_condition_no_doc(w, env, member.version, false, 3)?;
        writeln!(
            w,
            "\t\t\t{} => {}::{},",
            member.value, enum_.name, member.name
        )?;
    }
    writeln!(w, "\t\t\tvalue => {}::__Unknown(value),", enum_.name)?;
    writeln!(
        w,
        "\
        }}
    }}
}}
"
    )?;

    // Generate ErrorDomain trait implementation.
    if let Some(ref domain) = enum_.error_domain {
        let has_failed_member = members.iter().any(|m| m.name == "Failed");

        version_condition(w, env, enum_.version, false, 0)?;
        writeln!(
            w,
            "impl ErrorDomain for {name} {{
    fn domain() -> Quark {{
        {assert}",
            name = enum_.name,
            assert = assert
        )?;

        match domain {
            ErrorDomain::Quark(ref quark) => {
                writeln!(
                    w,
                    "        static QUARK: once_cell::sync::Lazy<{0}ffi::GQuark> = once_cell::sync::Lazy::new(|| unsafe {{
            {0}ffi::g_quark_from_static_string(b\"{1}\\0\".as_ptr() as *const _)
        }});
        unsafe {{ from_glib(*QUARK) }}",
                    use_glib_if_needed(env, ""),
                    quark,
                )?;
            }
            ErrorDomain::Function(ref f) => {
                writeln!(
                    w,
                    "        unsafe {{ from_glib({sys_crate_name}::{get_quark}()) }}",
                    sys_crate_name = sys_crate_name,
                    get_quark = f
                )?;
            }
        }

        writeln!(
            w,
            "    }}

    fn code(self) -> i32 {{
        self.to_glib()
    }}

    fn from(code: i32) -> Option<Self> {{
        {assert}match code {{",
            assert = assert
        )?;

        for member in &members {
            version_condition_no_doc(w, env, member.version, false, 3)?;
            writeln!(
                w,
                "\t\t\t{} => Some({}::{}),",
                member.value, enum_.name, member.name
            )?;
        }
        if has_failed_member {
            writeln!(w, "\t\t\t_ => Some({}::Failed),", enum_.name)?;
        } else {
            writeln!(w, "\t\t\tvalue => Some({}::__Unknown(value)),", enum_.name)?;
        }

        writeln!(
            w,
            "\
        }}
    }}
}}
"
        )?;
    }

    // Generate StaticType trait implementation.
    if let Some(ref get_type) = enum_.glib_get_type {
        let configured_functions = config.functions.matched("get_type");
        let version = std::iter::once(enum_.version)
            .chain(configured_functions.iter().map(|f| f.version))
            .max()
            .flatten();

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl StaticType for {name} {{
    fn static_type() -> Type {{
        unsafe {{ from_glib({sys_crate_name}::{get_type}()) }}
    }}
}}",
            sys_crate_name = sys_crate_name,
            name = enum_.name,
            get_type = get_type
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl<'a> FromValueOptional<'a> for {name} {{
    unsafe fn from_value_optional(value: &{gvalue}) -> Option<Self> {{
        Some(FromValue::from_value(value))
    }}
}}",
            name = enum_.name,
            gvalue = use_glib_type(env, "Value"),
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl<'a> FromValue<'a> for {name} {{
    unsafe fn from_value(value: &{gvalue}) -> Self {{
        from_glib({glib}(value.to_glib_none().0))
    }}
}}",
            name = enum_.name,
            glib = use_glib_type(env, "gobject_ffi::g_value_get_enum"),
            gvalue = use_glib_type(env, "Value"),
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl SetValue for {name} {{
    unsafe fn set_value(value: &mut {gvalue}, this: &Self) {{
        {glib}(value.to_glib_none_mut().0, this.to_glib())
    }}
}}",
            name = enum_.name,
            glib = use_glib_type(env, "gobject_ffi::g_value_set_enum"),
            gvalue = use_glib_type(env, "Value"),
        )?;
        writeln!(w)?;
    }

    Ok(())
}
<commit_msg>doc_alias: don't generate if the enum c_name = rust_name<commit_after>use super::{function, trait_impls};
use crate::{
    analysis::enums::Info,
    analysis::special_functions::Type,
    codegen::general::{
        self, cfg_deprecated, derives, doc_alias, version_condition, version_condition_no_doc,
        version_condition_string,
    },
    config::gobjects::GObject,
    env::Env,
    file_saver,
    library::*,
    nameutil::{enum_member_name, use_glib_if_needed, use_glib_type},
    traits::*,
    version::Version,
};
use std::{
    collections::HashSet,
    io::{prelude::*, Result},
    path::Path,
};

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    if env.analysis.enumerations.is_empty() {
        return;
    }

    let path = root_path.join("enums.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        general::start_comments(w, &env.config)?;
        general::uses(w, env, &env.analysis.enum_imports)?;
        writeln!(w)?;

        mod_rs.push("\nmod enums;".into());
        for enum_analysis in &env.analysis.enumerations {
            let config = &env.config.objects[&enum_analysis.full_name];
            let enum_ = enum_analysis.type_(&env.library);

            if let Some(cfg) = version_condition_string(env, enum_.version, false, 0) {
                mod_rs.push(cfg);
            }
            mod_rs.push(format!("pub use self::enums::{};", enum_.name));
            generate_enum(env, w, enum_, config, enum_analysis)?;
        }

        Ok(())
    });
}

#[allow(clippy::write_literal)]
fn generate_enum(
    env: &Env,
    w: &mut dyn Write,
    enum_: &Enumeration,
    config: &GObject,
    analysis: &Info,
) -> Result<()> {
    struct Member {
        name: String,
        c_name: String,
        value: String,
        version: Option<Version>,
        deprecated_version: Option<Version>,
    }

    let mut members: Vec<Member> = Vec::new();
    let mut vals: HashSet<String> = HashSet::new();
    let sys_crate_name = env.main_sys_crate_name();

    for member in &enum_.members {
        let member_config = config.members.matched(&member.name);
        let is_alias = member_config.iter().any(|m| m.alias);
        let generate = member_config.iter().all(|m| m.status.need_generate());
        if is_alias || !generate || vals.contains(&member.value) {
            continue;
        }
        vals.insert(member.value.clone());
        let deprecated_version = member_config
            .iter()
            .filter_map(|m| m.deprecated_version)
            .next();
        let version = member_config.iter().filter_map(|m| m.version).next();
        members.push(Member {
            name: enum_member_name(&member.name),
            c_name: member.c_identifier.clone(),
            value: member.value.clone(),
            version,
            deprecated_version,
        });
    }

    cfg_deprecated(w, env, enum_.deprecated_version, false, 0)?;
    version_condition(w, env, enum_.version, false, 0)?;
    if config.must_use {
        writeln!(w, "#[must_use]")?;
    }

    if let Some(ref d) = config.derives {
        derives(w, &d, 1)?;
    } else {
        writeln!(w, "#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]")?;
    }
    writeln!(w, "#[derive(Clone, Copy)]")?;
    writeln!(w, "#[non_exhaustive]")?;
    doc_alias(w, &enum_.c_type, "", 0)?;

    writeln!(w, "pub enum {} {{", enum_.name)?;
    for member in &members {
        cfg_deprecated(w, env, member.deprecated_version, false, 1)?;
        version_condition(w, env, member.version, false, 1)?;
        // Don't generate a doc_alias if the C name is the same as the Rust one
        if member.c_name != member.name {
            doc_alias(w, &member.c_name, "", 1)?;
        }
        writeln!(w, "\t{},", member.name)?;
    }
    writeln!(
        w,
        "\
    #[doc(hidden)]
    __Unknown(i32),
}}"
    )?;

    let functions = analysis
        .functions
        .iter()
        .filter(|f| f.status.need_generate())
        .collect::<Vec<_>>();

    if !functions.is_empty() {
        writeln!(w)?;
        version_condition(w, env, enum_.version, false, 0)?;
        write!(w, "impl {} {{", analysis.name)?;
        for func_analysis in functions {
            function::generate(
                w,
                env,
                func_analysis,
                Some(&analysis.specials),
                false,
                false,
                1,
            )?;
        }
        writeln!(w, "}}")?;
    }

    trait_impls::generate(
        w,
        env,
        &analysis.name,
        &analysis.functions,
        &analysis.specials,
        None,
    )?;

    writeln!(w)?;

    if config.generate_display_trait && !analysis.specials.has_trait(Type::Display) {
        // Generate Display trait implementation.
        version_condition(w, env, enum_.version, false, 0)?;
        writeln!(
            w,
            "impl fmt::Display for {0} {{\n\
             \tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{\n\
             \t\twrite!(f, \"{0}::{{}}\", match *self {{",
            enum_.name
        )?;
        for member in &members {
            version_condition_no_doc(w, env, member.version, false, 3)?;
            writeln!(w, "\t\t\t{0}::{1} => \"{1}\",", enum_.name, member.name)?;
        }
        writeln!(
            w,
            "\t\t\t_ => \"Unknown\",\n\
             \t\t}})\n\
             \t}}\n\
             }}\n"
        )?;
    }

    // Generate ToGlib trait implementation.
    version_condition(w, env, enum_.version, false, 0)?;
    writeln!(
        w,
        "#[doc(hidden)]
impl ToGlib for {name} {{
    type GlibType = {sys_crate_name}::{ffi_name};

    fn to_glib(&self) -> {sys_crate_name}::{ffi_name} {{
        match *self {{",
        sys_crate_name = sys_crate_name,
        name = enum_.name,
        ffi_name = enum_.c_type
    )?;
    for member in &members {
        version_condition_no_doc(w, env, member.version, false, 3)?;
        writeln!(
            w,
            "\t\t\t{}::{} => {}::{},",
            enum_.name, member.name, sys_crate_name, member.c_name
        )?;
    }
    writeln!(w, "\t\t\t{}::__Unknown(value) => value,", enum_.name)?;
    writeln!(
        w,
        "\
        }}
    }}
}}
"
    )?;

    let assert = if env.config.generate_safety_asserts {
        "skip_assert_initialized!();\n\t\t"
    } else {
        ""
    };

    // Generate FromGlib trait implementation.
    version_condition(w, env, enum_.version, false, 0)?;
    writeln!(
        w,
        "#[doc(hidden)]
impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{
    unsafe fn from_glib(value: {sys_crate_name}::{ffi_name}) -> Self {{
        {assert}match value {{",
        sys_crate_name = sys_crate_name,
        name = enum_.name,
        ffi_name = enum_.c_type,
        assert = assert
    )?;
    for member in &members {
        version_condition_no_doc(w, env, member.version, false, 3)?;
        writeln!(
            w,
            "\t\t\t{} => {}::{},",
            member.value, enum_.name, member.name
        )?;
    }
    writeln!(w, "\t\t\tvalue => {}::__Unknown(value),", enum_.name)?;
    writeln!(
        w,
        "\
        }}
    }}
}}
"
    )?;

    // Generate ErrorDomain trait implementation.
    if let Some(ref domain) = enum_.error_domain {
        let has_failed_member = members.iter().any(|m| m.name == "Failed");

        version_condition(w, env, enum_.version, false, 0)?;
        writeln!(
            w,
            "impl ErrorDomain for {name} {{
    fn domain() -> Quark {{
        {assert}",
            name = enum_.name,
            assert = assert
        )?;

        match domain {
            ErrorDomain::Quark(ref quark) => {
                writeln!(
                    w,
                    "        static QUARK: once_cell::sync::Lazy<{0}ffi::GQuark> = once_cell::sync::Lazy::new(|| unsafe {{
            {0}ffi::g_quark_from_static_string(b\"{1}\\0\".as_ptr() as *const _)
        }});
        unsafe {{ from_glib(*QUARK) }}",
                    use_glib_if_needed(env, ""),
                    quark,
                )?;
            }
            ErrorDomain::Function(ref f) => {
                writeln!(
                    w,
                    "        unsafe {{ from_glib({sys_crate_name}::{get_quark}()) }}",
                    sys_crate_name = sys_crate_name,
                    get_quark = f
                )?;
            }
        }

        writeln!(
            w,
            "    }}

    fn code(self) -> i32 {{
        self.to_glib()
    }}

    fn from(code: i32) -> Option<Self> {{
        {assert}match code {{",
            assert = assert
        )?;

        for member in &members {
            version_condition_no_doc(w, env, member.version, false, 3)?;
            writeln!(
                w,
                "\t\t\t{} => Some({}::{}),",
                member.value, enum_.name, member.name
            )?;
        }
        if has_failed_member {
            writeln!(w, "\t\t\t_ => Some({}::Failed),", enum_.name)?;
        } else {
            writeln!(w, "\t\t\tvalue => Some({}::__Unknown(value)),", enum_.name)?;
        }

        writeln!(
            w,
            "\
        }}
    }}
}}
"
        )?;
    }

    // Generate StaticType trait implementation.
    if let Some(ref get_type) = enum_.glib_get_type {
        let configured_functions = config.functions.matched("get_type");
        let version = std::iter::once(enum_.version)
            .chain(configured_functions.iter().map(|f| f.version))
            .max()
            .flatten();

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl StaticType for {name} {{
    fn static_type() -> Type {{
        unsafe {{ from_glib({sys_crate_name}::{get_type}()) }}
    }}
}}",
            sys_crate_name = sys_crate_name,
            name = enum_.name,
            get_type = get_type
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl<'a> FromValueOptional<'a> for {name} {{
    unsafe fn from_value_optional(value: &{gvalue}) -> Option<Self> {{
        Some(FromValue::from_value(value))
    }}
}}",
            name = enum_.name,
            gvalue = use_glib_type(env, "Value"),
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl<'a> FromValue<'a> for {name} {{
    unsafe fn from_value(value: &{gvalue}) -> Self {{
        from_glib({glib}(value.to_glib_none().0))
    }}
}}",
            name = enum_.name,
            glib = use_glib_type(env, "gobject_ffi::g_value_get_enum"),
            gvalue = use_glib_type(env, "Value"),
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl SetValue for {name} {{
    unsafe fn set_value(value: &mut {gvalue}, this: &Self) {{
        {glib}(value.to_glib_none_mut().0, this.to_glib())
    }}
}}",
            name = enum_.name,
            glib = use_glib_type(env, "gobject_ffi::g_value_set_enum"),
            gvalue = use_glib_type(env, "Value"),
        )?;
        writeln!(w)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::mem;

use super::{BoundingVolume, Ray, Triangle};
use math::Vector3;

const NUM_PLANE_SET_NORMALS: usize = 7;
const PLAN_SET_NORMALS: &'static [Vector3; NUM_PLANE_SET_NORMALS] = &[
    Vector3::new(1.0, 0.0, 0.0),
    Vector3::new(0.0, 1.0, 0.0),
    Vector3::new(0.0, 0.0, 1.0),
    // 0.577350269 = 3.0_f32.sqrt() / 3.0 but alas `sqrt` isn't a const fn
    // so it cannot be used in this context.
    Vector3::new(0.577350269, 0.577350269, 0.577350269),
    Vector3::new(-0.577350269, 0.577350269, 0.577350269),
    Vector3::new(-0.577350269, -0.577350269, 0.577350269),
    Vector3::new(0.577350269, -0.577350269, 0.577350269),
];

pub struct ExtentVolume {
    distances: [[f32; 2]; NUM_PLANE_SET_NORMALS],
}

impl BoundingVolume for ExtentVolume {
    fn new(triangles: &[Triangle]) -> Self {
        let mut distances = [[std::f32::INFINITY, std::f32::NEG_INFINITY]; NUM_PLANE_SET_NORMALS];

        assert!(
            !triangles.is_empty(),
            "Creating ExtentVolume with 0 vertices"
        );
        if triangles.is_empty() {
            return Self { distances };
        }

        for triangle in triangles {
            for point in &triangle.vertices {
                let vertex = point.as_vector();

                for (normal_idx, plane_normal) in PLAN_SET_NORMALS.iter().enumerate() {
                    let distance = plane_normal.dot(&vertex);

                    distances[normal_idx][0] = f32::min(distances[normal_idx][0], distance);
                    distances[normal_idx][1] = f32::max(distances[normal_idx][1], distance);
                }
            }
        }

        Self { distances }
    }

    fn intersect(&self, ray: Ray) -> bool {
        let origin_vector = ray.origin.as_vector();

        let (precomputed_numerator, precomputed_denominator) = {
            let mut precomputed_numerator: [f32; NUM_PLANE_SET_NORMALS] =
                [std::f32::NAN; NUM_PLANE_SET_NORMALS];
            let mut precomputed_denominator: [f32; NUM_PLANE_SET_NORMALS] =
                [std::f32::NAN; NUM_PLANE_SET_NORMALS];

            for i in 0..NUM_PLANE_SET_NORMALS {
                precomputed_numerator[i] = PLAN_SET_NORMALS[i].dot(&origin_vector);
                precomputed_denominator[i] = PLAN_SET_NORMALS[i].dot(&ray.direction);
            }

            (precomputed_numerator, precomputed_denominator)
        };

        let mut t_near = std::f32::NEG_INFINITY;
        let mut t_far = std::f32::INFINITY;

        for i in 0..NUM_PLANE_SET_NORMALS {
            let mut tn =
                (self.distances[i][0] - precomputed_numerator[i]) / precomputed_denominator[i];
            let mut tf =
                (self.distances[i][1] - precomputed_numerator[i]) / precomputed_denominator[i];

            if precomputed_denominator[i] < 0.0 {
                mem::swap(&mut tn, &mut tf);
            }

            t_near = f32::max(tn, t_near);
            t_far = f32::min(tf, t_far);

            if t_near > t_far {
                return false;
            }
        }

        true
    }
}
<commit_msg>Move precomputed values to function for extents<commit_after>use std::mem;

use super::{BoundingVolume, Ray, Triangle};
use math::Vector3;

const NUM_PLANE_SET_NORMALS: usize = 7;
const PLAN_SET_NORMALS: &'static [Vector3; NUM_PLANE_SET_NORMALS] = &[
    Vector3::new(1.0, 0.0, 0.0),
    Vector3::new(0.0, 1.0, 0.0),
    Vector3::new(0.0, 0.0, 1.0),
    // 0.577350269 = 3.0_f32.sqrt() / 3.0 but alas `sqrt` isn't a const fn
    // so it cannot be used in this context.
    Vector3::new(0.577350269, 0.577350269, 0.577350269),
    Vector3::new(-0.577350269, 0.577350269, 0.577350269),
    Vector3::new(-0.577350269, -0.577350269, 0.577350269),
    Vector3::new(0.577350269, -0.577350269, 0.577350269),
];

pub struct ExtentVolume {
    distances: [[f32; 2]; NUM_PLANE_SET_NORMALS],
}

impl BoundingVolume for ExtentVolume {
    fn new(triangles: &[Triangle]) -> Self {
        let mut distances = [[std::f32::INFINITY, std::f32::NEG_INFINITY]; NUM_PLANE_SET_NORMALS];

        assert!(
            !triangles.is_empty(),
            "Creating ExtentVolume with 0 vertices"
        );
        if triangles.is_empty() {
            return Self { distances };
        }

        for triangle in triangles {
            for point in &triangle.vertices {
                let vertex = point.as_vector();

                for (normal_idx, plane_normal) in PLAN_SET_NORMALS.iter().enumerate() {
                    let distance = plane_normal.dot(&vertex);

                    distances[normal_idx][0] = f32::min(distances[normal_idx][0], distance);
                    distances[normal_idx][1] = f32::max(distances[normal_idx][1], distance);
                }
            }
        }

        Self { distances }
    }

    fn intersect(&self, ray: Ray) -> bool {
        let (precomputed_numerator, precomputed_denominator) = Self::precompute(&ray);

        let mut t_near = std::f32::NEG_INFINITY;
        let mut t_far = std::f32::INFINITY;

        for i in 0..NUM_PLANE_SET_NORMALS {
            let mut tn =
                (self.distances[i][0] - precomputed_numerator[i]) / precomputed_denominator[i];
            let mut tf =
                (self.distances[i][1] - precomputed_numerator[i]) / precomputed_denominator[i];

            if precomputed_denominator[i] < 0.0 {
                mem::swap(&mut tn, &mut tf);
            }

            t_near = f32::max(tn, t_near);
            t_far = f32::min(tf, t_far);

            if t_near > t_far {
                return false;
            }
        }

        true
    }
}

impl ExtentVolume {
    fn precompute(ray: &Ray) -> ([f32; NUM_PLANE_SET_NORMALS], [f32; NUM_PLANE_SET_NORMALS]) {
        let origin_vector = ray.origin.as_vector();

        let mut precomputed_numerator: [f32; NUM_PLANE_SET_NORMALS] =
            [std::f32::NAN; NUM_PLANE_SET_NORMALS];
        let mut precomputed_denominator: [f32; NUM_PLANE_SET_NORMALS] =
            [std::f32::NAN; NUM_PLANE_SET_NORMALS];

        for i in 0..NUM_PLANE_SET_NORMALS {
            precomputed_numerator[i] = PLAN_SET_NORMALS[i].dot(&origin_vector);
            precomputed_denominator[i] = PLAN_SET_NORMALS[i].dot(&ray.direction);
        }

        (precomputed_numerator, precomputed_denominator)
    }
}
<|endoftext|>


<commit_before>pub use self::param::*;
pub use self::reg::*;

use baseline::fct::ExHandler;
use ctxt::{Context, FctId};
use execstate::ExecState;
use object::{Handle, Obj};
use stacktrace::StackFrameInfo;

pub mod asm;
pub mod param;
pub mod reg;
pub mod trap;

pub fn sfi_from_execution_state(es: &ExecState) -> StackFrameInfo {
    let ra = es.regs[REG_LR.asm() as usize];

    StackFrameInfo {
        last: ptr::null(),
        fp: es.regs[REG_FP.asm() as usize],
        sp: es.sp,
        ra: ra,
        xpc: ra - 1,
    }
}

pub fn resume_with_handler(es: &mut ExecState,
                           handler: &ExHandler,
                           fp: usize,
                           exception: Handle<Obj>,
                           stacksize: usize) {
    unimplemented!();
}

pub fn fp_from_execstate(es: &ExecState) -> usize {
    es.regs[REG_FP.asm() as usize]
}

pub fn get_exception_object(es: &ExecState) -> Handle<Obj> {
    let obj: Handle<Obj> = es.regs[REG_RESULT.int() as usize].into();

    obj
}

pub fn patch_fct_call(es: &mut ExecState, fct_ptr: *const u8) {
    unimplemented!();
}

pub fn patch_vtable_call(ctxt: &Context, es: &mut ExecState, fid: FctId, fct_ptr: *const u8) {
    unimplemented!();
}
<commit_msg>arm64: fixed compile errors<commit_after>use std::ptr;

use baseline::fct::ExHandler;
use ctxt::{Context, FctId};
use execstate::ExecState;
use object::{Handle, Obj};
use stacktrace::StackFrameInfo;

pub use self::param::*;
pub use self::reg::*;

pub mod asm;
pub mod param;
pub mod reg;
pub mod trap;

pub fn sfi_from_execution_state(es: &ExecState) -> StackFrameInfo {
    let ra = es.regs[REG_LR.asm() as usize];

    StackFrameInfo {
        last: ptr::null(),
        fp: es.regs[REG_FP.asm() as usize],
        sp: es.sp,
        ra: ra,
        xpc: ra - 1,
    }
}

pub fn resume_with_handler(es: &mut ExecState,
                           handler: &ExHandler,
                           fp: usize,
                           exception: Handle<Obj>,
                           stacksize: usize) {
    unimplemented!();
}

pub fn fp_from_execstate(es: &ExecState) -> usize {
    es.regs[REG_FP.asm() as usize]
}

pub fn get_exception_object(es: &ExecState) -> Handle<Obj> {
    let obj: Handle<Obj> = es.regs[REG_RESULT.asm() as usize].into();

    obj
}

pub fn patch_fct_call(es: &mut ExecState, fct_ptr: *const u8) {
    unimplemented!();
}

pub fn patch_vtable_call(ctxt: &Context, es: &mut ExecState, fid: FctId, fct_ptr: *const u8) {
    unimplemented!();
}
<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Build a block to mine: gathers transactions from the pool, assembles
//! them into a block and returns it.

use crate::util::RwLock;
use chrono::prelude::{DateTime, NaiveDateTime, Utc};
use rand::{thread_rng, Rng};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use crate::chain;
use crate::common::types::Error;
use crate::core::core::verifier_cache::VerifierCache;
use crate::core::{consensus, core, global, ser};
use crate::keychain::{ExtKeychain, Identifier, Keychain};
use crate::pool;
use crate::util;
use crate::wallet::{self, BlockFees};

// Ensure a block suitable for mining is built and returned
// If a wallet listener URL is not provided the reward will be "burnt"
// Warning: This call does not return until/unless a new block can be built
pub fn get_block(
	chain: &Arc<chain::Chain>,
	tx_pool: &Arc<RwLock<pool::TransactionPool>>,
	verifier_cache: Arc<RwLock<dyn VerifierCache>>,
	key_id: Option<Identifier>,
	wallet_listener_url: Option<String>,
) -> (core::Block, BlockFees) {
	let wallet_retry_interval = 5;
	// get the latest chain state and build a block on top of it
	let mut result = build_block(
		chain,
		tx_pool,
		verifier_cache.clone(),
		key_id.clone(),
		wallet_listener_url.clone(),
	);
	while let Err(e) = result {
		match e {
			self::Error::Chain(c) => match c.kind() {
				chain::ErrorKind::DuplicateCommitment(_) => {
					debug!(
						"Duplicate commit for potential coinbase detected. Trying next derivation."
					);
				}
				_ => {
					error!("Chain Error: {}", c);
				}
			},
			self::Error::Wallet(_) => {
				error!(
					"Error building new block: Can't connect to wallet listener at {:?}; will retry",
					wallet_listener_url.as_ref().unwrap()
				);
				thread::sleep(Duration::from_secs(wallet_retry_interval));
			}
			ae => {
				warn!("Error building new block: {:?}. Retrying.", ae);
			}
		}
		thread::sleep(Duration::from_millis(100));
		result = build_block(
			chain,
			tx_pool,
			verifier_cache.clone(),
			key_id.clone(),
			wallet_listener_url.clone(),
		);
	}
	return result.unwrap();
}

/// Builds a new block with the chain head as previous and eligible
/// transactions from the pool.
fn build_block(
	chain: &Arc<chain::Chain>,
	tx_pool: &Arc<RwLock<pool::TransactionPool>>,
	verifier_cache: Arc<RwLock<dyn VerifierCache>>,
	key_id: Option<Identifier>,
	wallet_listener_url: Option<String>,
) -> Result<(core::Block, BlockFees), Error> {
	let head = chain.head_header()?;

	// prepare the block header timestamp
	let mut now_sec = Utc::now().timestamp();
	let head_sec = head.timestamp.timestamp();
	if now_sec <= head_sec {
		now_sec = head_sec + 1;
	}

	// Determine the difficulty our block should be at.
	// Note: do not keep the difficulty_iter in scope (it has an active batch).
	let difficulty = consensus::next_difficulty(head.height + 1, chain.difficulty_iter());

	// extract current transaction from the pool
	let txs = tx_pool.read().prepare_mineable_transactions()?;

	// build the coinbase and the block itself
	let fees = txs.iter().map(|tx| tx.fee()).sum();
	let height = head.height + 1;
	let block_fees = BlockFees {
		fees,
		key_id,
		height,
	};

	let (output, kernel, block_fees) = get_coinbase(wallet_listener_url, block_fees)?;
	let mut b = core::Block::from_reward(&head, txs, output, kernel, difficulty.difficulty)?;

	// making sure we're not spending time mining a useless block
	b.validate(&head.total_kernel_offset, verifier_cache)?;

	b.header.pow.nonce = thread_rng().gen();
	b.header.pow.secondary_scaling = difficulty.secondary_scaling;
	b.header.timestamp = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(now_sec, 0), Utc);

	debug!(
		"Built new block with {} inputs and {} outputs, block difficulty: {}, cumulative difficulty {}",
		b.inputs().len(),
		b.outputs().len(),
		difficulty.difficulty,
		b.header.total_difficulty().to_num(),
	);

	// Now set txhashset roots and sizes on the header of the block being built.
	let roots_result = chain.set_txhashset_roots(&mut b);

	match roots_result {
		Ok(_) => Ok((b, block_fees)),

		// If it's a duplicate commitment, it's likely trying to use
		// a key that's already been derived but not in the wallet
		// for some reason, allow caller to retry
		Err(e) => {
			match e.kind() {
				chain::ErrorKind::DuplicateCommitment(e) => Err(Error::Chain(
					chain::ErrorKind::DuplicateCommitment(e).into(),
				)),

				//Some other issue, possibly duplicate kernel
				_ => {
					error!("Error setting txhashset root to build a block: {:?}", e);
					Err(Error::Chain(
						chain::ErrorKind::Other(format!("{:?}", e)).into(),
					))
				}
			}
		}
	}
}

///
/// Probably only want to do this when testing.
///
fn burn_reward(block_fees: BlockFees) -> Result<(core::Output, core::TxKernel, BlockFees), Error> {
	warn!("Burning block fees: {:?}", block_fees);
	let keychain = ExtKeychain::from_random_seed(global::is_floonet()).unwrap();
	let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0);
	let (out, kernel) =
		crate::core::libtx::reward::output(&keychain, &key_id, block_fees.fees).unwrap();
	Ok((out, kernel, block_fees))
}

// Connect to the wallet listener and get coinbase.
// Warning: If a wallet listener URL is not provided the reward will be "burnt"
fn get_coinbase(
	wallet_listener_url: Option<String>,
	block_fees: BlockFees,
) -> Result<(core::Output, core::TxKernel, BlockFees), Error> {
	match wallet_listener_url {
		None => {
			// Burn it
			return burn_reward(block_fees);
		}
		Some(wallet_listener_url) => {
			let res = wallet::create_coinbase(&wallet_listener_url, &block_fees)?;
			let out_bin = util::from_hex(res.output).unwrap();
			let kern_bin = util::from_hex(res.kernel).unwrap();
			let key_id_bin = util::from_hex(res.key_id).unwrap();
			let output = ser::deserialize(&mut &out_bin[..]).unwrap();
			let kernel = ser::deserialize(&mut &kern_bin[..]).unwrap();
			let key_id = ser::deserialize(&mut &key_id_bin[..]).unwrap();
			let block_fees = BlockFees {
				key_id: Some(key_id),
				..block_fees
			};

			debug!("get_coinbase: {:?}", block_fees);
			return Ok((output, kernel, block_fees));
		}
	}
}
<commit_msg>Fallback to building empty block to mine (if txpool is somehow in invalid state) (#2451)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Build a block to mine: gathers transactions from the pool, assembles
//! them into a block and returns it.

use crate::util::RwLock;
use chrono::prelude::{DateTime, NaiveDateTime, Utc};
use rand::{thread_rng, Rng};
use std::sync::Arc;
use std::thread;
use std::time::Duration;

use crate::chain;
use crate::common::types::Error;
use crate::core::core::verifier_cache::VerifierCache;
use crate::core::{consensus, core, global, ser};
use crate::keychain::{ExtKeychain, Identifier, Keychain};
use crate::pool;
use crate::util;
use crate::wallet::{self, BlockFees};

// Ensure a block suitable for mining is built and returned
// If a wallet listener URL is not provided the reward will be "burnt"
// Warning: This call does not return until/unless a new block can be built
pub fn get_block(
	chain: &Arc<chain::Chain>,
	tx_pool: &Arc<RwLock<pool::TransactionPool>>,
	verifier_cache: Arc<RwLock<dyn VerifierCache>>,
	key_id: Option<Identifier>,
	wallet_listener_url: Option<String>,
) -> (core::Block, BlockFees) {
	let wallet_retry_interval = 5;
	// get the latest chain state and build a block on top of it
	let mut result = build_block(
		chain,
		tx_pool,
		verifier_cache.clone(),
		key_id.clone(),
		wallet_listener_url.clone(),
	);
	while let Err(e) = result {
		match e {
			self::Error::Chain(c) => match c.kind() {
				chain::ErrorKind::DuplicateCommitment(_) => {
					debug!(
						"Duplicate commit for potential coinbase detected. Trying next derivation."
					);
				}
				_ => {
					error!("Chain Error: {}", c);
				}
			},
			self::Error::Wallet(_) => {
				error!(
					"Error building new block: Can't connect to wallet listener at {:?}; will retry",
					wallet_listener_url.as_ref().unwrap()
				);
				thread::sleep(Duration::from_secs(wallet_retry_interval));
			}
			ae => {
				warn!("Error building new block: {:?}. Retrying.", ae);
			}
		}
		thread::sleep(Duration::from_millis(100));
		result = build_block(
			chain,
			tx_pool,
			verifier_cache.clone(),
			key_id.clone(),
			wallet_listener_url.clone(),
		);
	}
	return result.unwrap();
}

/// Builds a new block with the chain head as previous and eligible
/// transactions from the pool.
fn build_block(
	chain: &Arc<chain::Chain>,
	tx_pool: &Arc<RwLock<pool::TransactionPool>>,
	verifier_cache: Arc<RwLock<dyn VerifierCache>>,
	key_id: Option<Identifier>,
	wallet_listener_url: Option<String>,
) -> Result<(core::Block, BlockFees), Error> {
	let head = chain.head_header()?;

	// prepare the block header timestamp
	let mut now_sec = Utc::now().timestamp();
	let head_sec = head.timestamp.timestamp();
	if now_sec <= head_sec {
		now_sec = head_sec + 1;
	}

	// Determine the difficulty our block should be at.
	// Note: do not keep the difficulty_iter in scope (it has an active batch).
	let difficulty = consensus::next_difficulty(head.height + 1, chain.difficulty_iter());

	// Extract current "mineable" transactions from the pool.
	// If this fails for *any* reason then fallback to an empty vec of txs.
	// This will allow us to mine an "empty" block if the txpool is in an
	// invalid (and unexpected) state.
	let txs = match tx_pool.read().prepare_mineable_transactions() {
		Ok(txs) => txs,
		Err(e) => {
			error!(
				"build_block: Failed to prepare mineable txs from txpool: {:?}",
				e
			);
			warn!("build_block: Falling back to mining empty block.");
			vec![]
		}
	};

	// build the coinbase and the block itself
	let fees = txs.iter().map(|tx| tx.fee()).sum();
	let height = head.height + 1;
	let block_fees = BlockFees {
		fees,
		key_id,
		height,
	};

	let (output, kernel, block_fees) = get_coinbase(wallet_listener_url, block_fees)?;
	let mut b = core::Block::from_reward(&head, txs, output, kernel, difficulty.difficulty)?;

	// making sure we're not spending time mining a useless block
	b.validate(&head.total_kernel_offset, verifier_cache)?;

	b.header.pow.nonce = thread_rng().gen();
	b.header.pow.secondary_scaling = difficulty.secondary_scaling;
	b.header.timestamp = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(now_sec, 0), Utc);

	debug!(
		"Built new block with {} inputs and {} outputs, block difficulty: {}, cumulative difficulty {}",
		b.inputs().len(),
		b.outputs().len(),
		difficulty.difficulty,
		b.header.total_difficulty().to_num(),
	);

	// Now set txhashset roots and sizes on the header of the block being built.
	match chain.set_txhashset_roots(&mut b) {
		Ok(_) => Ok((b, block_fees)),
		Err(e) => {
			match e.kind() {
				// If this is a duplicate commitment then likely trying to use
				// a key that hass already been derived but not in the wallet
				// for some reason, allow caller to retry.
				chain::ErrorKind::DuplicateCommitment(e) => Err(Error::Chain(
					chain::ErrorKind::DuplicateCommitment(e).into(),
				)),

				// Some other issue, possibly duplicate kernel
				_ => {
					error!("Error setting txhashset root to build a block: {:?}", e);
					Err(Error::Chain(
						chain::ErrorKind::Other(format!("{:?}", e)).into(),
					))
				}
			}
		}
	}
}

///
/// Probably only want to do this when testing.
///
fn burn_reward(block_fees: BlockFees) -> Result<(core::Output, core::TxKernel, BlockFees), Error> {
	warn!("Burning block fees: {:?}", block_fees);
	let keychain = ExtKeychain::from_random_seed(global::is_floonet()).unwrap();
	let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0);
	let (out, kernel) =
		crate::core::libtx::reward::output(&keychain, &key_id, block_fees.fees).unwrap();
	Ok((out, kernel, block_fees))
}

// Connect to the wallet listener and get coinbase.
// Warning: If a wallet listener URL is not provided the reward will be "burnt"
fn get_coinbase(
	wallet_listener_url: Option<String>,
	block_fees: BlockFees,
) -> Result<(core::Output, core::TxKernel, BlockFees), Error> {
	match wallet_listener_url {
		None => {
			// Burn it
			return burn_reward(block_fees);
		}
		Some(wallet_listener_url) => {
			let res = wallet::create_coinbase(&wallet_listener_url, &block_fees)?;
			let out_bin = util::from_hex(res.output).unwrap();
			let kern_bin = util::from_hex(res.kernel).unwrap();
			let key_id_bin = util::from_hex(res.key_id).unwrap();
			let output = ser::deserialize(&mut &out_bin[..]).unwrap();
			let kernel = ser::deserialize(&mut &kern_bin[..]).unwrap();
			let key_id = ser::deserialize(&mut &key_id_bin[..]).unwrap();
			let block_fees = BlockFees {
				key_id: Some(key_id),
				..block_fees
			};

			debug!("get_coinbase: {:?}", block_fees);
			return Ok((output, kernel, block_fees));
		}
	}
}
<|endoftext|>


<commit_before>use std::io::fs;
use std::io::File;
use std::collections::HashMap;
use std::os;

fn examine_files(directory_path: &Path, map: &mut HashMap<(u64,u64), Box<String>>) {

    let entries = fs::readdir(directory_path);

    if !entries.is_ok() {
        return;
    }

    for entry in entries.unwrap().iter() {
        if entry.is_dir() {
            examine_files(entry, map);
        } else {
            let path = entry.as_str().unwrap();
            let stat = entry.stat();
            if stat.is_ok() {
                let unwrapped_stat = stat.unwrap();
                map.insert((unwrapped_stat.size, unwrapped_stat.modified), box path.to_string());
            }
        }
    }
}

fn compare_files(src_path: Path, new_path: Path) -> bool {
    let mut src_file = File::open(&src_path);
    let mut new_file = File::open(&new_path);
    let src_data = src_file.read_to_end();
    let new_data = new_file.read_to_end();

    src_data == new_data
}

fn main() {

    let args = os::args();

    if args.len() != 3 {
        println!("Usage: {} <original-directory> <new-directory>", args[0]);
        return;
    }

    let src_directory = Path::new(args[1].clone());
    let dst_directory = Path::new(args[2].clone());

    let mut src_map = HashMap::<(u64, u64), Box<String>>::new();
    examine_files(&Path::new(src_directory.clone()), &mut src_map);
    let mut new_map = HashMap::<(u64, u64), Box<String>>::new();
    examine_files(&Path::new(dst_directory.clone()), &mut new_map);
    for (key, value) in new_map.iter() {
        if src_map.contains_key(key) {
            let src_path = Path::new(*src_map.get(key).clone());
            let new_path = Path::new(*value.clone());
            if compare_files(src_path.clone(), new_path.clone()) {
                println!("{} was renamed to {}",
                         src_path.path_relative_from(&src_directory).unwrap().as_str().unwrap(),
                         new_path.path_relative_from(&dst_directory).unwrap().as_str().unwrap());
            }
        }
    }
}
<commit_msg>Avoid unnecessary copying<commit_after>use std::io::fs;
use std::io::File;
use std::collections::HashMap;
use std::os;

fn examine_files(directory_path: &Path, map: &mut HashMap<(u64,u64), Box<String>>) {

    let entries = fs::readdir(directory_path);

    if !entries.is_ok() {
        return;
    }

    for entry in entries.unwrap().iter() {
        if entry.is_dir() {
            examine_files(entry, map);
        } else {
            let path = entry.as_str().unwrap();
            let stat = entry.stat();
            if stat.is_ok() {
                let unwrapped_stat = stat.unwrap();
                map.insert((unwrapped_stat.size, unwrapped_stat.modified), box path.to_string());
            }
        }
    }
}

fn compare_files(src_path: &Path, new_path: &Path) -> bool {
    let mut src_file = File::open(src_path);
    let mut new_file = File::open(new_path);
    let src_data = src_file.read_to_end();
    let new_data = new_file.read_to_end();

    src_data == new_data
}

fn main() {

    let args = os::args();

    if args.len() != 3 {
        println!("Usage: {} <original-directory> <new-directory>", args[0]);
        return;
    }

    let src_directory = Path::new(args[1].clone());
    let dst_directory = Path::new(args[2].clone());

    let mut src_map = HashMap::<(u64, u64), Box<String>>::new();
    examine_files(&src_directory, &mut src_map);
    let mut new_map = HashMap::<(u64, u64), Box<String>>::new();
    examine_files(&dst_directory, &mut new_map);
    for (key, value) in new_map.iter() {
        if src_map.contains_key(key) {
            let src_path = Path::new(*src_map.get(key).clone());
            let new_path = Path::new(*value.clone());
            if compare_files(&src_path, &new_path) {
                println!("{} was renamed to {}",
                         src_path.path_relative_from(&src_directory).unwrap().as_str().unwrap(),
                         new_path.path_relative_from(&dst_directory).unwrap().as_str().unwrap());
            }
        }
    }
}
<|endoftext|>


<commit_before>use azure::core::errors::AzureError;
use azure::core::lease::LeaseId;
use azure::core::range::Range;
use azure::core::{
    BlobNameRequired, BlobNameSupport, ClientRequestIdOption, ClientRequestIdSupport, ClientRequired, ContainerNameRequired,
    ContainerNameSupport, LeaseIdOption, LeaseIdSupport, No, RangeRequired, RangeSupport, SnapshotOption, SnapshotSupport, TimeoutOption,
    TimeoutSupport, ToAssign, Yes,
};
use azure::storage::blob::requests::GetBlobBuilder;
use azure::storage::client::Client;
use chrono::{DateTime, Utc};
use futures::prelude::*;
use futures::stream;
use std::marker::PhantomData;

#[derive(Debug, Clone)]
pub struct BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    client: &'a Client,
    p_container_name: PhantomData<ContainerNameSet>,
    p_blob_name: PhantomData<BlobNameSet>,
    p_range: PhantomData<RangeSet>,
    container_name: Option<&'a str>,
    blob_name: Option<&'a str>,
    snapshot: Option<DateTime<Utc>>,
    timeout: Option<u64>,
    range: Option<&'a Range>,
    lease_id: Option<&'a LeaseId>,
    client_request_id: Option<&'a str>,
    increment: u64,
}

impl<'a> BlobStreamBuilder<'a, No, No, No> {
    #[inline]
    pub(crate) fn new(client: &'a Client) -> BlobStreamBuilder<'a, No, No, No> {
        BlobStreamBuilder {
            client,
            p_container_name: PhantomData {},
            container_name: None,
            p_blob_name: PhantomData {},
            blob_name: None,
            p_range: PhantomData {},
            range: None,
            snapshot: None,
            timeout: None,
            lease_id: None,
            client_request_id: None,
            increment: 1024 * 1024,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> ClientRequired<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn client(&self) -> &'a Client {
        self.client
    }
}

impl<'a, BlobNameSet, RangeSet> ContainerNameRequired<'a> for BlobStreamBuilder<'a, Yes, BlobNameSet, RangeSet>
where
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn container_name(&self) -> &'a str {
        self.container_name.unwrap()
    }
}

impl<'a, ContainerNameSet, RangeSet> BlobNameRequired<'a> for BlobStreamBuilder<'a, ContainerNameSet, Yes, RangeSet>
where
    ContainerNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn blob_name(&self) -> &'a str {
        self.blob_name.unwrap()
    }
}

impl<'a, ContainerNameSet, BlobNameSet> RangeRequired<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, Yes>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
{
    #[inline]
    fn range(&self) -> &'a Range {
        self.range.unwrap()
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> SnapshotOption for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn snapshot(&self) -> Option<DateTime<Utc>> {
        self.snapshot
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> TimeoutOption for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn timeout(&self) -> Option<u64> {
        self.timeout
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> LeaseIdOption<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn lease_id(&self) -> Option<&'a LeaseId> {
        self.lease_id
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> ClientRequestIdOption<'a>
    for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn client_request_id(&self) -> Option<&'a str> {
        self.client_request_id
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> ContainerNameSupport<'a>
    for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, Yes, BlobNameSet, RangeSet>;

    #[inline]
    fn with_container_name(self, container_name: &'a str) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: Some(container_name),
            blob_name: self.blob_name,
            range: self.range,
            snapshot: self.snapshot,
            timeout: self.timeout,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> BlobNameSupport<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, Yes, RangeSet>;

    #[inline]
    fn with_blob_name(self, blob_name: &'a str) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: Some(blob_name),
            range: self.range,
            snapshot: self.snapshot,
            timeout: self.timeout,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> RangeSupport<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, Yes>;

    #[inline]
    fn with_range(self, range: &'a Range) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            range: Some(range),
            snapshot: self.snapshot,
            timeout: self.timeout,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> SnapshotSupport for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>;

    #[inline]
    fn with_snapshot(self, snapshot: DateTime<Utc>) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            snapshot: Some(snapshot),
            timeout: self.timeout,
            range: self.range,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> TimeoutSupport for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>;

    #[inline]
    fn with_timeout(self, timeout: u64) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            snapshot: self.snapshot,
            timeout: Some(timeout),
            range: self.range,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> LeaseIdSupport<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>;

    #[inline]
    fn with_lease_id(self, lease_id: &'a LeaseId) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            snapshot: self.snapshot,
            timeout: self.timeout,
            range: self.range,
            lease_id: Some(lease_id),
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> ClientRequestIdSupport<'a>
    for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>;

    #[inline]
    fn with_client_request_id(self, client_request_id: &'a str) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            snapshot: self.snapshot,
            timeout: self.timeout,
            range: self.range,
            lease_id: self.lease_id,
            client_request_id: Some(client_request_id),
            increment: self.increment,
        }
    }
}

// methods callable regardless
impl<'a, ContainerNameSet, BlobNameSet, RangeSet> BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{}

impl<'a> BlobStreamBuilder<'a, Yes, Yes, Yes> {
    #[inline]
    pub fn finalize(self) -> impl Stream<Item = Vec<u8>, Error = AzureError> {
        let container_name = self.container_name().to_owned();
        let blob_name = self.blob_name().to_owned();
        let range = self.range().to_owned();

        let snapshot = self.snapshot.to_owned();
        let timeout = self.timeout.to_owned();
        let lease_id = self.lease_id.cloned();
        let client_request_id = self.client_request_id.map(|v| v.to_owned());
        let increment = self.increment;

        let client = self.client().clone();

        stream::unfold(Some(range), move |remaining| {
            let remaining = match remaining {
                Some(range) => range,
                None => return None,
            };

            let range = if remaining.start + increment > remaining.end {
                Range::new(remaining.start, remaining.end)
            } else {
                Range::new(remaining.start, remaining.start + increment)
            };
            println!("getting blob {:?} out of {:?}", range, remaining);

            let mut req = GetBlobBuilder::new(&client)
                .with_container_name(&container_name)
                .with_blob_name(&blob_name)
                .with_range(&range);

            if let Some(snapshot) = snapshot {
                req = req.with_snapshot(snapshot);
            }
            if let Some(timeout) = timeout {
                req = req.with_timeout(timeout);
            }
            if let Some(ref lease_id) = &lease_id {
                req = req.with_lease_id(lease_id);
            }
            if let Some(ref client_request_id) = &client_request_id {
                req = req.with_client_request_id(client_request_id);
            }

            let req = req.finalize();
            Some(req.map(move |response| {
                (
                    response.data,
                    if remaining.end > range.end {
                        Some(Range::new(range.end, remaining.end))
                    } else {
                        None
                    },
                )
            }))
        })
    }
}
<commit_msg>Remove println when streaming blob<commit_after>use azure::core::errors::AzureError;
use azure::core::lease::LeaseId;
use azure::core::range::Range;
use azure::core::{
    BlobNameRequired, BlobNameSupport, ClientRequestIdOption, ClientRequestIdSupport, ClientRequired, ContainerNameRequired,
    ContainerNameSupport, LeaseIdOption, LeaseIdSupport, No, RangeRequired, RangeSupport, SnapshotOption, SnapshotSupport, TimeoutOption,
    TimeoutSupport, ToAssign, Yes,
};
use azure::storage::blob::requests::GetBlobBuilder;
use azure::storage::client::Client;
use chrono::{DateTime, Utc};
use futures::prelude::*;
use futures::stream;
use std::marker::PhantomData;

#[derive(Debug, Clone)]
pub struct BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    client: &'a Client,
    p_container_name: PhantomData<ContainerNameSet>,
    p_blob_name: PhantomData<BlobNameSet>,
    p_range: PhantomData<RangeSet>,
    container_name: Option<&'a str>,
    blob_name: Option<&'a str>,
    snapshot: Option<DateTime<Utc>>,
    timeout: Option<u64>,
    range: Option<&'a Range>,
    lease_id: Option<&'a LeaseId>,
    client_request_id: Option<&'a str>,
    increment: u64,
}

impl<'a> BlobStreamBuilder<'a, No, No, No> {
    #[inline]
    pub(crate) fn new(client: &'a Client) -> BlobStreamBuilder<'a, No, No, No> {
        BlobStreamBuilder {
            client,
            p_container_name: PhantomData {},
            container_name: None,
            p_blob_name: PhantomData {},
            blob_name: None,
            p_range: PhantomData {},
            range: None,
            snapshot: None,
            timeout: None,
            lease_id: None,
            client_request_id: None,
            increment: 1024 * 1024,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> ClientRequired<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn client(&self) -> &'a Client {
        self.client
    }
}

impl<'a, BlobNameSet, RangeSet> ContainerNameRequired<'a> for BlobStreamBuilder<'a, Yes, BlobNameSet, RangeSet>
where
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn container_name(&self) -> &'a str {
        self.container_name.unwrap()
    }
}

impl<'a, ContainerNameSet, RangeSet> BlobNameRequired<'a> for BlobStreamBuilder<'a, ContainerNameSet, Yes, RangeSet>
where
    ContainerNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn blob_name(&self) -> &'a str {
        self.blob_name.unwrap()
    }
}

impl<'a, ContainerNameSet, BlobNameSet> RangeRequired<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, Yes>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
{
    #[inline]
    fn range(&self) -> &'a Range {
        self.range.unwrap()
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> SnapshotOption for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn snapshot(&self) -> Option<DateTime<Utc>> {
        self.snapshot
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> TimeoutOption for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn timeout(&self) -> Option<u64> {
        self.timeout
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> LeaseIdOption<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn lease_id(&self) -> Option<&'a LeaseId> {
        self.lease_id
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> ClientRequestIdOption<'a>
    for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    #[inline]
    fn client_request_id(&self) -> Option<&'a str> {
        self.client_request_id
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> ContainerNameSupport<'a>
    for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, Yes, BlobNameSet, RangeSet>;

    #[inline]
    fn with_container_name(self, container_name: &'a str) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: Some(container_name),
            blob_name: self.blob_name,
            range: self.range,
            snapshot: self.snapshot,
            timeout: self.timeout,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> BlobNameSupport<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, Yes, RangeSet>;

    #[inline]
    fn with_blob_name(self, blob_name: &'a str) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: Some(blob_name),
            range: self.range,
            snapshot: self.snapshot,
            timeout: self.timeout,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> RangeSupport<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, Yes>;

    #[inline]
    fn with_range(self, range: &'a Range) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            range: Some(range),
            snapshot: self.snapshot,
            timeout: self.timeout,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> SnapshotSupport for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>;

    #[inline]
    fn with_snapshot(self, snapshot: DateTime<Utc>) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            snapshot: Some(snapshot),
            timeout: self.timeout,
            range: self.range,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> TimeoutSupport for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>;

    #[inline]
    fn with_timeout(self, timeout: u64) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            snapshot: self.snapshot,
            timeout: Some(timeout),
            range: self.range,
            lease_id: self.lease_id,
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> LeaseIdSupport<'a> for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>;

    #[inline]
    fn with_lease_id(self, lease_id: &'a LeaseId) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            snapshot: self.snapshot,
            timeout: self.timeout,
            range: self.range,
            lease_id: Some(lease_id),
            client_request_id: self.client_request_id,
            increment: self.increment,
        }
    }
}

impl<'a, ContainerNameSet, BlobNameSet, RangeSet> ClientRequestIdSupport<'a>
    for BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{
    type O = BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>;

    #[inline]
    fn with_client_request_id(self, client_request_id: &'a str) -> Self::O {
        BlobStreamBuilder {
            client: self.client,
            p_container_name: PhantomData {},
            p_blob_name: PhantomData {},
            p_range: PhantomData {},
            container_name: self.container_name,
            blob_name: self.blob_name,
            snapshot: self.snapshot,
            timeout: self.timeout,
            range: self.range,
            lease_id: self.lease_id,
            client_request_id: Some(client_request_id),
            increment: self.increment,
        }
    }
}

// methods callable regardless
impl<'a, ContainerNameSet, BlobNameSet, RangeSet> BlobStreamBuilder<'a, ContainerNameSet, BlobNameSet, RangeSet>
where
    ContainerNameSet: ToAssign,
    BlobNameSet: ToAssign,
    RangeSet: ToAssign,
{}

impl<'a> BlobStreamBuilder<'a, Yes, Yes, Yes> {
    #[inline]
    pub fn finalize(self) -> impl Stream<Item = Vec<u8>, Error = AzureError> {
        let container_name = self.container_name().to_owned();
        let blob_name = self.blob_name().to_owned();
        let range = self.range().to_owned();

        let snapshot = self.snapshot.to_owned();
        let timeout = self.timeout.to_owned();
        let lease_id = self.lease_id.cloned();
        let client_request_id = self.client_request_id.map(|v| v.to_owned());
        let increment = self.increment;

        let client = self.client().clone();

        stream::unfold(Some(range), move |remaining| {
            let remaining = match remaining {
                Some(range) => range,
                None => return None,
            };

            let range = if remaining.start + increment > remaining.end {
                Range::new(remaining.start, remaining.end)
            } else {
                Range::new(remaining.start, remaining.start + increment)
            };

            let mut req = GetBlobBuilder::new(&client)
                .with_container_name(&container_name)
                .with_blob_name(&blob_name)
                .with_range(&range);

            if let Some(snapshot) = snapshot {
                req = req.with_snapshot(snapshot);
            }
            if let Some(timeout) = timeout {
                req = req.with_timeout(timeout);
            }
            if let Some(ref lease_id) = &lease_id {
                req = req.with_lease_id(lease_id);
            }
            if let Some(ref client_request_id) = &client_request_id {
                req = req.with_client_request_id(client_request_id);
            }

            let req = req.finalize();
            Some(req.map(move |response| {
                (
                    response.data,
                    if remaining.end > range.end {
                        Some(Range::new(range.end, remaining.end))
                    } else {
                        None
                    },
                )
            }))
        })
    }
}
<|endoftext|>