<commit_before>extern crate "pkg-config" as pkg_config;
use std::os;
use std::old_io::{self, fs, Command};
use std::old_io::process::InheritFd;

fn main() {
    match pkg_config::find_library("sass") {
        Ok(_) => return,
        Err(_) => {}
    }
    let src = Path::new(os::getenv("CARGO_MANIFEST_DIR").unwrap());
    let mut cmd = Command::new("make");
    let dst = Path::new(os::getenv("OUT_DIR").unwrap());
    cmd.cwd(&src.join("libsass"));
    run(& mut cmd);

    // copy to the output folder
    let _ = fs::copy(&src.join("libsass/lib/libsass.a"),&dst);

    println!("cargo:rustc-flags=-l sass -l dylib=stdc++");

}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(cmd.stdout(InheritFd(1))
               .stderr(InheritFd(2))
               .status()
               .unwrap()
               .success());

}
<commit_msg>Use explicit path for library<commit_after>extern crate "pkg-config" as pkg_config;
use std::os;
use std::old_io::{self, fs, Command};
use std::old_io::process::InheritFd;

fn main() {
    match pkg_config::find_library("sass") {
        Ok(_) => return,
        Err(_) => {}
    }
    let src = Path::new(os::getenv("CARGO_MANIFEST_DIR").unwrap());
    let mut cmd = Command::new("make");
    cmd.cwd(&src.join("libsass"));
    run(& mut cmd);

    // copy to the output folder
    let dst = Path::new(os::getenv("OUT_DIR").unwrap()).join("libsass");
    let _ = fs::copy(&src.join("libsass/lib/libsass.a"),&dst);

    println!("cargo:rustc-flags=-l sass -L {} -l dylib=stdc++",dst.display());

}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(cmd.stdout(InheritFd(1))
               .stderr(InheritFd(2))
               .status()
               .unwrap()
               .success());

}
<|endoftext|>


<commit_before>mod audio;
mod debuggerui;
mod gbaui;
mod glutil;
mod pyrite_window;

use std::path::{Path, PathBuf};

use anyhow::Context as _;
use debuggerui::DebuggerWindow;
use gbaui::GbaWindow;
use glutin::{
    dpi::LogicalSize,
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
    window::{WindowBuilder, WindowId},
    PossiblyCurrent, WindowedContext,
};
use pyrite::{config::Config, GbaHandle};
use pyrite_window::PyriteWindow;

struct Windows {
    gba_handle: GbaHandle,
    gba: Box<GbaWindow>,
    debugger: Option<Box<DebuggerWindow>>,
    config: std::sync::Arc<Config>,
}

impl Windows {
    fn new(
        config: std::sync::Arc<Config>,
        window: WindowedContext<PossiblyCurrent>,
        gba: GbaHandle,
    ) -> anyhow::Result<Windows> {
        Ok(Windows {
            config: config.clone(),
            gba_handle: gba.clone(),
            gba: Box::new(
                GbaWindow::new(config, window, gba).context("error while creating GBA window")?,
            ),
            debugger: None,
        })
    }

    fn main_events_cleared(&mut self) {
        if self.gba.update() {
            self.gba.request_redraw();
        }

        if let Some(ref mut debugger) = self.debugger {
            if debugger.update() {
                debugger.request_redraw();
            }
        }
    }

    fn is_gba(&self, id: WindowId) -> bool {
        self.gba.window_id() == id
    }

    fn is_debugger(&self, id: WindowId) -> bool {
        self.debugger
            .as_ref()
            .filter(|d| d.window_id() == id)
            .is_some()
    }

    fn with_window<F>(&mut self, id: WindowId, f: F)
    where
        F: FnOnce(&mut dyn PyriteWindow),
    {
        if self.is_gba(id) {
            f(&mut *self.gba);
        } else if self.is_debugger(id) {
            if let Some(ref mut debugger) = self.debugger {
                f(&mut **debugger)
            }
        }
    }

    fn create_debugger_window(&mut self, el: &EventLoopWindowTarget<()>) -> anyhow::Result<()> {
        if self.debugger.is_some() {
            return Ok(());
        }

        let window = WindowBuilder::new()
            .with_title("Pyrite Debugger")
            .with_inner_size(LogicalSize::new(640.0f32, 320.0));
        let window = unsafe {
            glutin::ContextBuilder::new()
                .with_vsync(self.config.graphics.vsync.unwrap_or(true))
                .build_windowed(window, el)
                .context("failed to create windowed context")?
                .make_current()
                .map_err(|err| anyhow::anyhow!("{:?}", err))
                .context("failed to make window current")?
        };
        self.debugger = Some(Box::new(
            DebuggerWindow::new(self.gba_handle.clone(), window)
                .context("error while creating debugger window")?,
        ));

        Ok(())
    }

    fn close_debugger(&mut self) {
        self.debugger = None;
    }
}

fn on_window_event(
    event: WindowEvent,
    el: &EventLoopWindowTarget<()>,
    id: WindowId,
    windows: &mut Windows,
    flow: &mut ControlFlow,
) -> anyhow::Result<()> {
    match event {
        WindowEvent::CloseRequested if windows.is_gba(id) => {
            windows.with_window(id, |window| window.process_window_event(event));
            *flow = ControlFlow::Exit;
        }

        WindowEvent::CloseRequested if windows.is_debugger(id) => {
            windows.with_window(id, |window| window.process_window_event(event));
            windows.close_debugger();
        }

        event => {
            windows.with_window(id, |window| window.process_window_event(event));

            if windows.is_gba(id) {
                if windows.gba.wants_exit() {
                    *flow = ControlFlow::Exit;
                }

                if windows.gba.wants_debugger() {
                    if let Err(err) = windows.create_debugger_window(el) {
                        log::error!("error while creating debugger window: {err:?}");
                    }
                }
            } else if windows.is_debugger(id)
                && windows.debugger.as_ref().map(|d| d.wants_close()) == Some(true)
            {
                windows.close_debugger();
            }
        }
    }
    Ok(())
}

fn on_event(
    windows: &mut Windows,
    event: Event<()>,
    el: &EventLoopWindowTarget<()>,
    flow: &mut ControlFlow,
) -> anyhow::Result<()> {
    *flow = ControlFlow::Wait;

    match event {
        Event::WindowEvent { event, window_id } => {
            on_window_event(event, el, window_id, windows, flow)?
        }
        Event::RedrawRequested(window_id) => {
            windows.with_window(window_id, |window| window.gl_render(flow));
        }
        Event::MainEventsCleared => windows.main_events_cleared(),
        _ => *flow = ControlFlow::Poll,
    }
    Ok(())
}

fn run(event_loop: EventLoop<()>) -> anyhow::Result<()> {
    let config = std::sync::Arc::new(
        pyrite::config::from_toml_path("pyrite.toml")
            .map_err(|err| {
                let err = anyhow::Error::from(err);
                log::error!("{:#}", err);
            })
            .unwrap_or_default(),
    );

    let args = parse_args().context("error occurred while parsing arguments")?;

    let gba = pyrite::GbaHandle::new();

    let mut skip_frames = args.skip_to_frame.unwrap_or(0);
    let skipping_frames = skip_frames > 0;
    if skip_frames > 0 {
        gba.after_frame_wait(|_gba, state| {
            state.target_fps = 10000.0;
        });

        gba.on_frame(move |gba, state| {
            skip_frames -= 1;

            let render_frame = skip_frames <= 1 || (state.frame_count() % 2 == 0);
            gba.video_mut().set_skip_render(!render_frame);

            if skip_frames == 0 {
                state.target_fps = 60.0;
                state.paused = args.pause_on_startup;
                state.remove_callback();
            }
        });
    }

    let rom = std::fs::read(&args.rom)
        .with_context(|| format!("failed to read ROM path `{}`", args.rom.display()))?;

    let bios = config.gba.bios_path.as_ref().and_then(|path| {
        match std::fs::read(&path)
            .with_context(|| format!("failed to read path {}", path.display()))
        {
            Ok(data) => Some(data),
            Err(err) => {
                log::error!("error occurred while loading BIOS: {:?}", err);
                None
            }
        }
    });
    let boot_from_bios = config.gba.boot_from_bios.unwrap_or(true);
    gba.after_frame_wait(move |gba, _| {
        gba.set_gamepak(rom);
        gba.set_bios(bios);
        gba.reset(boot_from_bios);
    });
    let _stream = audio::run(gba.clone()).context("error while starting audio")?;

    let window = WindowBuilder::new()
        .with_title("Pyrite")
        .with_inner_size(LogicalSize::new(480.0f32, 320.0));
    let window = unsafe {
        glutin::ContextBuilder::new()
            .with_vsync(config.graphics.vsync.unwrap_or(true))
            .build_windowed(window, &event_loop)
            .context("failed to create windowed context")?
            .make_current()
            .map_err(|err| anyhow::anyhow!("{:?}", err))
            .context("failed to make window current")?
    };
    let mut windows = Windows::new(config, window, gba).context("error initializing windows")?;

    if skipping_frames || !args.pause_on_startup {
        windows.gba_handle.set_paused(false);
    }

    event_loop.run(move |event, el, control_flow| {
        if let Err(err) = on_event(&mut windows, event, el, control_flow) {
            log::error!("error occurred in event loop: {:?}", err);
            *control_flow = ControlFlow::Exit;
        }
    });
}

fn main() -> anyhow::Result<()> {
    pretty_env_logger::init();
    let event_loop = EventLoop::new();

    run(event_loop).context("error occurred while running main loop")?;
    unreachable!("run should never return unless there is an error");
}

fn parse_args() -> anyhow::Result<Args> {
    use clap::{Arg, Command};
    use std::str::FromStr;

    let rom_arg = Arg::new("ROM").takes_value(true).required(true).index(1);
    let skip_to_frame_arg = Arg::new("skip-to-frame")
        .short('F')
        .takes_value(true)
        .long("skip-to-frame")
        .help("Skip to the given frame on startup.");
    let pause_on_startup = Arg::new("pause-on-startup")
        .short('P')
        .takes_value(false)
        .long("pause-on-startup")
        .help("Pause the emulator on startup. If `skip to frame` is set, this will pause after skipping.");

    let matches = Command::new("pyrite")
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(rom_arg)
        .arg(skip_to_frame_arg)
        .arg(pause_on_startup)
        .get_matches();

    let rom: PathBuf = if let Some(rom_path) = matches.value_of("ROM") {
        Path::new(rom_path).into()
    } else {
        unreachable!("no ROM path provided");
    };

    let skip_to_frame = matches
        .value_of("skip-to-frame")
        .map(u32::from_str)
        .transpose()
        .context("skip-to-frame must be a valid integer")?;
    let pause_on_startup = matches.is_present("pause-on-startup");

    Ok(Args {
        rom,
        skip_to_frame,
        pause_on_startup,
    })
}

struct Args {
    rom: PathBuf,
    skip_to_frame: Option<u32>,
    pause_on_startup: bool,
}
<commit_msg>Add profiling argument.<commit_after>mod audio;
mod debuggerui;
mod gbaui;
mod glutil;
mod pyrite_window;

use std::path::{Path, PathBuf};

use anyhow::Context as _;
use debuggerui::DebuggerWindow;
use gbaui::GbaWindow;
use glutin::{
    dpi::LogicalSize,
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
    window::{WindowBuilder, WindowId},
    PossiblyCurrent, WindowedContext,
};
use pyrite::{config::Config, GbaHandle};
use pyrite_window::PyriteWindow;

struct Windows {
    gba_handle: GbaHandle,
    gba: Box<GbaWindow>,
    debugger: Option<Box<DebuggerWindow>>,
    config: std::sync::Arc<Config>,
}

impl Windows {
    fn new(
        config: std::sync::Arc<Config>,
        window: WindowedContext<PossiblyCurrent>,
        gba: GbaHandle,
    ) -> anyhow::Result<Windows> {
        Ok(Windows {
            config: config.clone(),
            gba_handle: gba.clone(),
            gba: Box::new(
                GbaWindow::new(config, window, gba).context("error while creating GBA window")?,
            ),
            debugger: None,
        })
    }

    fn main_events_cleared(&mut self) {
        if self.gba.update() {
            self.gba.request_redraw();
        }

        if let Some(ref mut debugger) = self.debugger {
            if debugger.update() {
                debugger.request_redraw();
            }
        }
    }

    fn is_gba(&self, id: WindowId) -> bool {
        self.gba.window_id() == id
    }

    fn is_debugger(&self, id: WindowId) -> bool {
        self.debugger
            .as_ref()
            .filter(|d| d.window_id() == id)
            .is_some()
    }

    fn with_window<F>(&mut self, id: WindowId, f: F)
    where
        F: FnOnce(&mut dyn PyriteWindow),
    {
        if self.is_gba(id) {
            f(&mut *self.gba);
        } else if self.is_debugger(id) {
            if let Some(ref mut debugger) = self.debugger {
                f(&mut **debugger)
            }
        }
    }

    fn create_debugger_window(&mut self, el: &EventLoopWindowTarget<()>) -> anyhow::Result<()> {
        if self.debugger.is_some() {
            return Ok(());
        }

        let window = WindowBuilder::new()
            .with_title("Pyrite Debugger")
            .with_inner_size(LogicalSize::new(640.0f32, 320.0));
        let window = unsafe {
            glutin::ContextBuilder::new()
                .with_vsync(self.config.graphics.vsync.unwrap_or(true))
                .build_windowed(window, el)
                .context("failed to create windowed context")?
                .make_current()
                .map_err(|err| anyhow::anyhow!("{:?}", err))
                .context("failed to make window current")?
        };
        self.debugger = Some(Box::new(
            DebuggerWindow::new(self.gba_handle.clone(), window)
                .context("error while creating debugger window")?,
        ));

        Ok(())
    }

    fn close_debugger(&mut self) {
        self.debugger = None;
    }
}

fn on_window_event(
    event: WindowEvent,
    el: &EventLoopWindowTarget<()>,
    id: WindowId,
    windows: &mut Windows,
    flow: &mut ControlFlow,
) -> anyhow::Result<()> {
    match event {
        WindowEvent::CloseRequested if windows.is_gba(id) => {
            windows.with_window(id, |window| window.process_window_event(event));
            *flow = ControlFlow::Exit;
        }

        WindowEvent::CloseRequested if windows.is_debugger(id) => {
            windows.with_window(id, |window| window.process_window_event(event));
            windows.close_debugger();
        }

        event => {
            windows.with_window(id, |window| window.process_window_event(event));

            if windows.is_gba(id) {
                if windows.gba.wants_exit() {
                    *flow = ControlFlow::Exit;
                }

                if windows.gba.wants_debugger() {
                    if let Err(err) = windows.create_debugger_window(el) {
                        log::error!("error while creating debugger window: {err:?}");
                    }
                }
            } else if windows.is_debugger(id)
                && windows.debugger.as_ref().map(|d| d.wants_close()) == Some(true)
            {
                windows.close_debugger();
            }
        }
    }
    Ok(())
}

fn on_event(
    windows: &mut Windows,
    event: Event<()>,
    el: &EventLoopWindowTarget<()>,
    flow: &mut ControlFlow,
) -> anyhow::Result<()> {
    *flow = ControlFlow::Wait;

    match event {
        Event::WindowEvent { event, window_id } => {
            on_window_event(event, el, window_id, windows, flow)?
        }
        Event::RedrawRequested(window_id) => {
            windows.with_window(window_id, |window| window.gl_render(flow));
        }
        Event::MainEventsCleared => windows.main_events_cleared(),
        _ => *flow = ControlFlow::Poll,
    }
    Ok(())
}

fn run(event_loop: EventLoop<()>) -> anyhow::Result<()> {
    let config = std::sync::Arc::new(
        pyrite::config::from_toml_path("pyrite.toml")
            .map_err(|err| {
                let err = anyhow::Error::from(err);
                log::error!("{:#}", err);
            })
            .unwrap_or_default(),
    );

    let args = parse_args().context("error occurred while parsing arguments")?;

    let gba = pyrite::GbaHandle::new();

    let mut skip_frames = args.skip_to_frame.unwrap_or(0);
    let skipping_frames = skip_frames > 0;
    if skip_frames > 0 {
        gba.after_frame_wait(|_gba, state| {
            state.target_fps = 10000.0;
        });

        gba.on_frame(move |gba, state| {
            skip_frames -= 1;

            let render_frame =
                args.profiling || (skip_frames <= 1 || (state.frame_count() % 2 == 0));
            gba.video_mut().set_skip_render(!render_frame);

            if skip_frames == 0 {
                state.target_fps = 60.0;
                state.paused = args.pause_on_startup;
                state.remove_callback();

                if args.exit_after_skip {
                    std::process::exit(0);
                }
            }
        });
    }

    let rom = std::fs::read(&args.rom)
        .with_context(|| format!("failed to read ROM path `{}`", args.rom.display()))?;

    let bios = config.gba.bios_path.as_ref().and_then(|path| {
        match std::fs::read(&path)
            .with_context(|| format!("failed to read path {}", path.display()))
        {
            Ok(data) => Some(data),
            Err(err) => {
                log::error!("error occurred while loading BIOS: {:?}", err);
                None
            }
        }
    });
    let boot_from_bios = config.gba.boot_from_bios.unwrap_or(true);
    gba.after_frame_wait(move |gba, _| {
        gba.set_gamepak(rom);
        gba.set_bios(bios);
        gba.reset(boot_from_bios);
    });
    let _stream = audio::run(gba.clone()).context("error while starting audio")?;

    let window = WindowBuilder::new()
        .with_title("Pyrite")
        .with_inner_size(LogicalSize::new(480.0f32, 320.0));
    let window = unsafe {
        glutin::ContextBuilder::new()
            .with_vsync(config.graphics.vsync.unwrap_or(true))
            .build_windowed(window, &event_loop)
            .context("failed to create windowed context")?
            .make_current()
            .map_err(|err| anyhow::anyhow!("{:?}", err))
            .context("failed to make window current")?
    };
    let mut windows = Windows::new(config, window, gba).context("error initializing windows")?;

    if skipping_frames || !args.pause_on_startup {
        windows.gba_handle.set_paused(false);
    }

    event_loop.run(move |event, el, control_flow| {
        if let Err(err) = on_event(&mut windows, event, el, control_flow) {
            log::error!("error occurred in event loop: {:?}", err);
            *control_flow = ControlFlow::Exit;
        }
    });
}

fn main() -> anyhow::Result<()> {
    pretty_env_logger::init();
    let event_loop = EventLoop::new();

    run(event_loop).context("error occurred while running main loop")?;
    unreachable!("run should never return unless there is an error");
}

fn parse_args() -> anyhow::Result<Args> {
    use clap::{Arg, Command};
    use std::str::FromStr;

    let rom_arg = Arg::new("ROM").takes_value(true).required(true).index(1);
    let skip_to_frame_arg = Arg::new("skip-to-frame")
        .short('F')
        .takes_value(true)
        .long("skip-to-frame")
        .help("Skip to the given frame on startup.");
    let pause_on_startup_arg = Arg::new("pause-on-startup")
        .short('P')
        .long("pause-on-startup")
        .help("Pause the emulator on startup. If `skip to frame` is set, this will pause after skipping.");
    let exit_after_skip_arg = Arg::new("exit-after-skip")
        .long("exit-after-skip")
        .help("Causes the emulator to exit afer skipping frames if `skip-to-frame` was specified.");
    let profiling_arg = Arg::new("profiling")
        .long("profiling")
        .help("Enable this if profiling. This will stop the emulator from skipping frames.");

    let matches = Command::new("pyrite")
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(rom_arg)
        .arg(skip_to_frame_arg)
        .arg(pause_on_startup_arg)
        .arg(exit_after_skip_arg)
        .arg(profiling_arg)
        .get_matches();

    let rom: PathBuf = if let Some(rom_path) = matches.value_of("ROM") {
        Path::new(rom_path).into()
    } else {
        unreachable!("no ROM path provided");
    };

    let skip_to_frame = matches
        .value_of("skip-to-frame")
        .map(u32::from_str)
        .transpose()
        .context("skip-to-frame must be a valid integer")?;
    let pause_on_startup = matches.is_present("pause-on-startup");
    let exit_after_skip = matches.is_present("exit-after-skip");
    let profiling = matches.is_present("profiling");

    Ok(Args {
        rom,
        skip_to_frame,
        pause_on_startup,
        exit_after_skip,
        profiling,
    })
}

struct Args {
    rom: PathBuf,
    skip_to_frame: Option<u32>,
    pause_on_startup: bool,
    exit_after_skip: bool,
    profiling: bool,
}
<|endoftext|>


<commit_before>// Copyright (C) 2021, Cloudflare, Inc.
// 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.

use serde::Deserialize;
use serde::Serialize;

use super::RawInfo;
use crate::Bytes;

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum H3Owner {
    Local,
    Remote,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum H3StreamType {
    Data,
    Control,
    Push,
    Reserved,
    QpackEncode,
    QpackDecode,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum H3PushDecision {
    Claimed,
    Abandoned,
}

#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Http3EventType {
    ParametersSet,
    ParametersRestored,
    StreamTypeSet,
    FrameCreated,
    FrameParsed,
    PushResolved,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum ApplicationError {
    HttpNoError,
    HttpGeneralProtocolError,
    HttpInternalError,
    HttpRequestCancelled,
    HttpIncompleteRequest,
    HttpConnectError,
    HttpFrameError,
    HttpExcessiveLoad,
    HttpVersionFallback,
    HttpIdError,
    HttpStreamCreationError,
    HttpClosedCriticalStream,
    HttpEarlyResponse,
    HttpMissingSettings,
    HttpUnexpectedFrame,
    HttpRequestRejection,
    HttpSettingsError,
    Unknown,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct HttpHeader {
    pub name: String,
    pub value: String,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct Setting {
    pub name: String,
    pub value: String,
}

// ================================================================== //
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Http3FrameTypeName {
    Data,
    Headers,
    CancelPush,
    Settings,
    PushPromise,
    Goaway,
    MaxPushId,
    DuplicatePush,
    Reserved,
    Unknown,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub enum Http3Frame {
    Data {
        frame_type: Http3FrameTypeName,

        raw: Option<Bytes>,
    },

    Headers {
        frame_type: Http3FrameTypeName,
        headers: Vec<HttpHeader>,
    },

    CancelPush {
        frame_type: Http3FrameTypeName,
        push_id: String,
    },

    Settings {
        frame_type: Http3FrameTypeName,
        settings: Vec<Setting>,
    },

    PushPromise {
        frame_type: Http3FrameTypeName,
        push_id: String,
        headers: Vec<HttpHeader>,
    },

    Goaway {
        frame_type: Http3FrameTypeName,
        stream_id: String,
    },

    MaxPushId {
        frame_type: Http3FrameTypeName,
        push_id: String,
    },

    DuplicatePush {
        frame_type: Http3FrameTypeName,
        push_id: String,
    },

    Reserved {
        frame_type: Http3FrameTypeName,
    },

    Unknown {
        frame_type: Http3FrameTypeName,
    },
}

impl Http3Frame {
    pub fn data(raw: Option<Bytes>) -> Self {
        Http3Frame::Data {
            frame_type: Http3FrameTypeName::Data,
            raw,
        }
    }

    pub fn headers(headers: Vec<HttpHeader>) -> Self {
        Http3Frame::Headers {
            frame_type: Http3FrameTypeName::Headers,
            headers,
        }
    }

    pub fn cancel_push(push_id: String) -> Self {
        Http3Frame::CancelPush {
            frame_type: Http3FrameTypeName::CancelPush,
            push_id,
        }
    }

    pub fn settings(settings: Vec<Setting>) -> Self {
        Http3Frame::Settings {
            frame_type: Http3FrameTypeName::Settings,
            settings,
        }
    }

    pub fn push_promise(push_id: String, headers: Vec<HttpHeader>) -> Self {
        Http3Frame::PushPromise {
            frame_type: Http3FrameTypeName::PushPromise,
            push_id,
            headers,
        }
    }

    pub fn goaway(stream_id: String) -> Self {
        Http3Frame::Goaway {
            frame_type: Http3FrameTypeName::Goaway,
            stream_id,
        }
    }

    pub fn max_push_id(push_id: String) -> Self {
        Http3Frame::MaxPushId {
            frame_type: Http3FrameTypeName::MaxPushId,
            push_id,
        }
    }

    pub fn duplicate_push(push_id: String) -> Self {
        Http3Frame::DuplicatePush {
            frame_type: Http3FrameTypeName::DuplicatePush,
            push_id,
        }
    }

    pub fn reserved() -> Self {
        Http3Frame::Reserved {
            frame_type: Http3FrameTypeName::Reserved,
        }
    }

    pub fn unknown() -> Self {
        Http3Frame::Unknown {
            frame_type: Http3FrameTypeName::Unknown,
        }
    }
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3ParametersSet {
    pub owner: Option<H3Owner>,

    pub max_header_list_size: Option<u64>,
    pub max_table_capacity: Option<u64>,
    pub blocked_streams_count: Option<u64>,

    // qlog-defined
    pub waits_for_settings: Option<bool>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3ParametersRestored {
    pub max_header_list_size: Option<u64>,
    pub max_table_capacity: Option<u64>,
    pub blocked_streams_count: Option<u64>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3StreamTypeSet {
    pub stream_id: u64,
    pub owner: Option<H3Owner>,

    pub old: Option<H3StreamType>,
    pub new: H3StreamType,

    pub associated_push_id: Option<u64>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3FrameCreated {
    pub stream_id: u64,
    pub length: Option<u64>,
    pub frame: Http3Frame,

    pub raw: Option<RawInfo>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3FrameParsed {
    pub stream_id: u64,
    pub length: Option<u64>,
    pub frame: Http3Frame,

    pub raw: Option<RawInfo>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3PushResolved {
    push_id: Option<u64>,
    stream_id: Option<u64>,

    decision: Option<H3PushDecision>,
}
<commit_msg>qlog: update HTTP/3 event definitions<commit_after>// Copyright (C) 2021, Cloudflare, Inc.
// 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.

use serde::Deserialize;
use serde::Serialize;

use super::RawInfo;
use crate::Bytes;

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum H3Owner {
    Local,
    Remote,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum H3StreamType {
    Data,
    Control,
    Push,
    QpackEncode,
    QpackDecode,
    Reserved,
    Unknown,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum H3PushDecision {
    Claimed,
    Abandoned,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum H3PriorityTargetStreamType {
    Request,
    Push,
}

#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Http3EventType {
    ParametersSet,
    ParametersRestored,
    StreamTypeSet,
    FrameCreated,
    FrameParsed,
    PushResolved,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum ApplicationError {
    HttpNoError,
    HttpGeneralProtocolError,
    HttpInternalError,
    HttpRequestCancelled,
    HttpIncompleteRequest,
    HttpConnectError,
    HttpFrameError,
    HttpExcessiveLoad,
    HttpVersionFallback,
    HttpIdError,
    HttpStreamCreationError,
    HttpClosedCriticalStream,
    HttpEarlyResponse,
    HttpMissingSettings,
    HttpUnexpectedFrame,
    HttpRequestRejection,
    HttpSettingsError,
    Unknown,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct HttpHeader {
    pub name: String,
    pub value: String,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct Setting {
    pub name: String,
    pub value: u64,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Http3FrameTypeName {
    Data,
    Headers,
    CancelPush,
    Settings,
    PushPromise,
    Goaway,
    MaxPushId,
    DuplicatePush,
    Reserved,
    Unknown,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
#[serde(tag = "frame_type")]
#[serde(rename_all = "snake_case")]
// Strictly, the qlog spec says that all these frame types have a frame_type
// field. But instead of making that a rust object property, just use serde to
// ensure it goes out on the wire. This means that deserialization of frames
// also works automatically.
pub enum Http3Frame {
    Data {
        raw: Option<Bytes>,
    },

    Headers {
        headers: Vec<HttpHeader>,
    },

    CancelPush {
        push_id: u64,
    },

    Settings {
        settings: Vec<Setting>,
    },

    PushPromise {
        push_id: u64,
        headers: Vec<HttpHeader>,
    },

    Goaway {
        id: u64,
    },

    MaxPushId {
        push_id: u64,
    },

    PriorityUpdate {
        target_stream_type: H3PriorityTargetStreamType,
        prioritized_element_id: u64,
        priority_field_value: String,
    },

    Reserved {
        length: Option<u64>,
    },

    Unknown {
        raw_frame_type: u64,
        raw_length: Option<u32>,
        raw: Option<Bytes>,
    },
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3ParametersSet {
    pub owner: Option<H3Owner>,

    pub max_header_list_size: Option<u64>,
    pub max_table_capacity: Option<u64>,
    pub blocked_streams_count: Option<u64>,

    // qlog-defined
    pub waits_for_settings: Option<bool>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3ParametersRestored {
    pub max_header_list_size: Option<u64>,
    pub max_table_capacity: Option<u64>,
    pub blocked_streams_count: Option<u64>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3StreamTypeSet {
    pub stream_id: u64,
    pub owner: Option<H3Owner>,

    pub old: Option<H3StreamType>,
    pub new: H3StreamType,

    pub associated_push_id: Option<u64>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3FrameCreated {
    pub stream_id: u64,
    pub length: Option<u64>,
    pub frame: Http3Frame,

    pub raw: Option<RawInfo>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3FrameParsed {
    pub stream_id: u64,
    pub length: Option<u64>,
    pub frame: Http3Frame,

    pub raw: Option<RawInfo>,
}

#[serde_with::skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct H3PushResolved {
    push_id: Option<u64>,
    stream_id: Option<u64>,

    decision: Option<H3PushDecision>,
}
<|endoftext|>


<commit_before>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://rust-random.github.io/rand/")]

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

//! Generating random samples from probability distributions.
//!
//! ## Re-exports
//!
//! This crate is a super-set of the [`rand::distributions`] module. See the
//! [`rand::distributions`] module documentation for an overview of the core
//! [`Distribution`] trait and implementations.
//!
//! The following are re-exported:
//!
//! - The [`Distribution`] trait and [`DistIter`] helper type
//! - The [`Standard`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`], [`Open01`] and [`Bernoulli`] distributions
//! - The [`weighted`] sub-module
//!
//! ## Distributions
//!
//! This crate provides the following probability distributions:
//!
//! - Related to real-valued quantities that grow linearly
//!   (e.g. errors, offsets):
//!   - [`Normal`] distribution, and [`StandardNormal`] as a primitive
//!   - [`Cauchy`] distribution
//! - Related to Bernoulli trials (yes/no events, with a given probability):
//!   - [`Binomial`] distribution
//! - Related to positive real-valued quantities that grow exponentially
//!   (e.g. prices, incomes, populations):
//!   - [`LogNormal`] distribution
//! - Related to the occurrence of independent events at a given rate:
//!   - [`Pareto`] distribution
//!   - [`Poisson`] distribution
//!   - [`Exp`]onential distribution, and [`Exp1`] as a primitive
//!   - [`Weibull`] distribution
//! - Gamma and derived distributions:
//!   - [`Gamma`] distribution
//!   - [`ChiSquared`] distribution
//!   - [`StudentT`] distribution
//!   - [`FisherF`] distribution
//! - Triangular distribution:
//!   - [`Beta`] distribution
//!   - [`Triangular`] distribution
//! - Multivariate probability distributions
//!   - [`Dirichlet`] distribution
//!   - [`UnitSphereSurface`] distribution
//!   - [`UnitCircle`] distribution

pub use rand::distributions::{Distribution, DistIter, Standard,
    Alphanumeric, Uniform, OpenClosed01, Open01, Bernoulli, weighted};

pub use self::unit_sphere::UnitSphereSurface;
pub use self::unit_circle::UnitCircle;
pub use self::gamma::{Gamma, Error as GammaError, ChiSquared, ChiSquaredError,
    FisherF, FisherFError, StudentT, Beta, BetaError};
pub use self::normal::{Normal, Error as NormalError, LogNormal, StandardNormal};
pub use self::exponential::{Exp, Error as ExpError, Exp1};
pub use self::pareto::{Pareto, Error as ParetoError};
pub use self::poisson::{Poisson, Error as PoissonError};
pub use self::binomial::{Binomial, Error as BinomialError};
pub use self::cauchy::{Cauchy, Error as CauchyError};
pub use self::dirichlet::{Dirichlet, Error as DirichletError};
pub use self::triangular::{Triangular, Error as TriangularError};
pub use self::weibull::{Weibull, Error as WeibullError};

mod unit_sphere;
mod unit_circle;
mod gamma;
mod normal;
mod exponential;
mod pareto;
mod poisson;
mod binomial;
mod cauchy;
mod dirichlet;
mod triangular;
mod weibull;
mod utils;
mod ziggurat_tables;

#[cfg(test)]
mod test {
    use rand::{RngCore, SeedableRng, rngs::StdRng};

    pub fn rng(seed: u64) -> impl RngCore {
        StdRng::seed_from_u64(seed)
    }
}
<commit_msg>rand_distr: notes on testing<commit_after>// Copyright 2019 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://rust-random.github.io/rand/")]

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]

//! Generating random samples from probability distributions.
//!
//! ## Re-exports
//!
//! This crate is a super-set of the [`rand::distributions`] module. See the
//! [`rand::distributions`] module documentation for an overview of the core
//! [`Distribution`] trait and implementations.
//!
//! The following are re-exported:
//!
//! - The [`Distribution`] trait and [`DistIter`] helper type
//! - The [`Standard`], [`Alphanumeric`], [`Uniform`], [`OpenClosed01`], [`Open01`] and [`Bernoulli`] distributions
//! - The [`weighted`] sub-module
//!
//! ## Distributions
//!
//! This crate provides the following probability distributions:
//!
//! - Related to real-valued quantities that grow linearly
//!   (e.g. errors, offsets):
//!   - [`Normal`] distribution, and [`StandardNormal`] as a primitive
//!   - [`Cauchy`] distribution
//! - Related to Bernoulli trials (yes/no events, with a given probability):
//!   - [`Binomial`] distribution
//! - Related to positive real-valued quantities that grow exponentially
//!   (e.g. prices, incomes, populations):
//!   - [`LogNormal`] distribution
//! - Related to the occurrence of independent events at a given rate:
//!   - [`Pareto`] distribution
//!   - [`Poisson`] distribution
//!   - [`Exp`]onential distribution, and [`Exp1`] as a primitive
//!   - [`Weibull`] distribution
//! - Gamma and derived distributions:
//!   - [`Gamma`] distribution
//!   - [`ChiSquared`] distribution
//!   - [`StudentT`] distribution
//!   - [`FisherF`] distribution
//! - Triangular distribution:
//!   - [`Beta`] distribution
//!   - [`Triangular`] distribution
//! - Multivariate probability distributions
//!   - [`Dirichlet`] distribution
//!   - [`UnitSphereSurface`] distribution
//!   - [`UnitCircle`] distribution

pub use rand::distributions::{Distribution, DistIter, Standard,
    Alphanumeric, Uniform, OpenClosed01, Open01, Bernoulli, weighted};

pub use self::unit_sphere::UnitSphereSurface;
pub use self::unit_circle::UnitCircle;
pub use self::gamma::{Gamma, Error as GammaError, ChiSquared, ChiSquaredError,
    FisherF, FisherFError, StudentT, Beta, BetaError};
pub use self::normal::{Normal, Error as NormalError, LogNormal, StandardNormal};
pub use self::exponential::{Exp, Error as ExpError, Exp1};
pub use self::pareto::{Pareto, Error as ParetoError};
pub use self::poisson::{Poisson, Error as PoissonError};
pub use self::binomial::{Binomial, Error as BinomialError};
pub use self::cauchy::{Cauchy, Error as CauchyError};
pub use self::dirichlet::{Dirichlet, Error as DirichletError};
pub use self::triangular::{Triangular, Error as TriangularError};
pub use self::weibull::{Weibull, Error as WeibullError};

mod unit_sphere;
mod unit_circle;
mod gamma;
mod normal;
mod exponential;
mod pareto;
mod poisson;
mod binomial;
mod cauchy;
mod dirichlet;
mod triangular;
mod weibull;
mod utils;
mod ziggurat_tables;

#[cfg(test)]
mod test {
    // Notes on testing
    //
    // Testing random number distributions correctly is hard. The following
    // testing is desired:
    //
    // - Construction: test initialisation with a few valid parameter sets.
    // - Erroneous usage: test that incorrect usage generates an error.
    // - Vector: test that usage with fixed inputs (including RNG) generates a
    //   fixed output sequence on all platforms.
    // - Correctness at fixed points (optional): using a specific mock RNG,
    //   check that specific values are sampled (e.g. end-points and median of
    //   distribution).
    // - Correctness of PDF (extra): generate a histogram of samples within a
    //   certain range, and check this approximates the PDF. These tests are
    //   expected to be expensive, and should be behind a feature-gate.
    //
    // TODO: Vector and correctness tests are largely absent so far.
    // NOTE: Some distributions have tests checking only that samples can be
    // generated. This is redundant with vector and correctness tests.

    use rand::{RngCore, SeedableRng, rngs::StdRng};

    /// Construct a deterministic RNG with the given seed
    pub fn rng(seed: u64) -> impl RngCore {
        StdRng::seed_from_u64(seed)
    }
}
<|endoftext|>


<commit_before>//! Provides the heap allocator for the kernel.

mod linked_list_allocator;

use self::linked_list_allocator::LinkedListAllocator;
use alloc::allocator::{GlobalAlloc, Layout, Opaque};
use arch::{self, Architecture};
use memory::{Address, VirtualAddress};
use sync::mutex::Mutex;

pub struct Allocator;

unsafe impl GlobalAlloc for Allocator {
    // TODO: Read more on this trait and possibly make it more efficient.
    unsafe fn alloc(&self, layout: Layout) -> *mut Opaque {
        ALLOCATOR
            .lock()
            .allocate_first_fit(layout.size(), layout.align()) as *mut Opaque
    }

    unsafe fn dealloc(&self, ptr: *mut Opaque, layout: Layout) {
        ALLOCATOR
            .lock()
            .free(ptr as *mut u8, layout.size(), layout.align());
    }
}

lazy_static! {
    /// The kernel heap allocator.
    static ref ALLOCATOR: Mutex<LinkedListAllocator> =
        Mutex::new(LinkedListAllocator::new(arch::Current::HEAP_AREA));
}

/// Aligns the given address to the given alignment.
///
/// The alignment must be a power of two.
fn align(address: VirtualAddress, alignment: usize) -> VirtualAddress {
    debug_assert!(alignment.is_power_of_two());

    if address.as_usize() % alignment == 0 {
        address
    } else {
        let alignment_bitmask = !(alignment - 1);
        VirtualAddress::from_usize((address.as_usize() & alignment_bitmask) + alignment)
    }
}
<commit_msg>Fix for GlobalAlloc on latest nightly<commit_after>//! Provides the heap allocator for the kernel.

mod linked_list_allocator;

use self::linked_list_allocator::LinkedListAllocator;
use alloc::allocator::{GlobalAlloc, Layout};
use arch::{self, Architecture};
use memory::{Address, VirtualAddress};
use sync::mutex::Mutex;

pub struct Allocator;

unsafe impl GlobalAlloc for Allocator {
    // TODO: Read more on this trait and possibly make it more efficient.
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        ALLOCATOR
            .lock()
            .allocate_first_fit(layout.size(), layout.align())
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        ALLOCATOR.lock().free(ptr, layout.size(), layout.align());
    }
}

lazy_static! {
    /// The kernel heap allocator.
    static ref ALLOCATOR: Mutex<LinkedListAllocator> =
        Mutex::new(LinkedListAllocator::new(arch::Current::HEAP_AREA));
}

/// Aligns the given address to the given alignment.
///
/// The alignment must be a power of two.
fn align(address: VirtualAddress, alignment: usize) -> VirtualAddress {
    debug_assert!(alignment.is_power_of_two());

    if address.as_usize() % alignment == 0 {
        address
    } else {
        let alignment_bitmask = !(alignment - 1);
        VirtualAddress::from_usize((address.as_usize() & alignment_bitmask) + alignment)
    }
}
<|endoftext|>


<commit_before>use libc::{c_schar, c_int};

use crate::code::{PyCodeObject};
#[cfg(not(Py_3_11))]
use crate::code::CO_MAXBLOCKS;
use crate::object::*;
use crate::pystate::PyThreadState;

#[cfg(not(Py_LIMITED_API))]
pub type PyFrameState = c_schar;

#[cfg(not(Py_LIMITED_API))]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyTryBlock {
    pub b_type: c_int,
    pub b_handler: c_int,
    pub b_level: c_int,
}

/// In Python > 3.11, frame object internals are always private
///
/// This improves performance by creating frame object lazily.
/// There are now getter methods to get info from the frame.
#[cfg(any(Py_LIMITED_API, Py_3_11))]
#[repr(C)]
pub struct PyFrameObject {
    _private: [u8; 0],
}

#[cfg(all(not(Py_LIMITED_API), not(Py_3_11)))]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyFrameObject {
    pub ob_base: PyVarObject,
    pub f_back: *mut PyFrameObject,       /* previous frame, or NULL */
    pub f_code: *mut PyCodeObject,        /* code segment */
    pub f_builtins: *mut PyObject,        /* builtin symbol table (PyDictObject) */
    pub f_globals: *mut PyObject,         /* global symbol table (PyDictObject) */
    pub f_locals: *mut PyObject,          /* local symbol table (any mapping) */
    pub f_valuestack: *mut *mut PyObject, /* points after the last local */
    /* Next free slot in f_valuestack.  Frame creation sets to f_valuestack.
    Frame evaluation usually NULLs it, but a frame that yields sets it
    to the current stack top. */
    #[cfg(not(Py_3_10))]
    pub f_stacktop: *mut *mut PyObject,
    pub f_trace: *mut PyObject, /* Trace function */
    #[cfg(Py_3_10)]
    pub f_stackdepth: c_int,

    #[cfg(not(Py_3_7))]
    pub f_exc_type: *mut PyObject,
    #[cfg(not(Py_3_7))]
    pub f_exc_value: *mut PyObject,
    #[cfg(not(Py_3_7))]
    pub f_exc_traceback: *mut PyObject,

    #[cfg(Py_3_7)]
    pub f_trace_lines: c_char,
    #[cfg(Py_3_7)]
    pub f_trace_opcodes: c_char,

    #[cfg(not(Py_3_4))]
    pub f_tstate: *mut PyThreadState,

    #[cfg(Py_3_4)]
    pub f_gen: *mut PyObject,

    pub f_lasti: c_int, /* Last instruction if called */
    /* Call PyFrame_GetLineNumber() instead of reading this field
     directly.  As of 2.3 f_lineno is only valid when tracing is
     active (i.e. when f_trace is set).  At other times we use
     PyCode_Addr2Line to calculate the line from the current
    bytecode index. */
    pub f_lineno: c_int, /* Current line number. Only valid if non-zero */
    pub f_iblock: c_int, /* index in f_blockstack */
    #[cfg(all(Py_3_4, not(Py_3_10)))]
    pub f_executing: c_char, /* whether the frame is still executing */
    #[cfg(Py_3_10)]
    pub f_state: PyFrameState,  /* What state the frame is in */
    pub f_blockstack: [PyTryBlock; CO_MAXBLOCKS], /* for try and loop blocks */
    pub f_localsplus: [*mut PyObject; 1], /* locals+stack, dynamically sized */
}

#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub static mut PyFrame_Type: PyTypeObject;
}

#[cfg(not(Py_LIMITED_API))]
#[inline]
pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int {
    (Py_TYPE(op) == &mut PyFrame_Type) as c_int
}

#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub fn PyFrame_New(
        tstate: *mut PyThreadState,
        code: *mut PyCodeObject,
        globals: *mut PyObject,
        locals: *mut PyObject,
    ) -> *mut PyFrameObject;

    #[cfg(not(Py_3_11))]
    pub fn PyFrame_BlockSetup(
        f: *mut PyFrameObject,
        _type: c_int,
        handler: c_int,
        level: c_int,
    ) -> ();
    #[cfg(not(Py_3_11))]
    pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock;

    pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int) -> ();
    #[cfg(Py_3_4)]
    pub fn PyFrame_FastToLocalsWithError(f: *mut PyFrameObject) -> c_int;
    pub fn PyFrame_FastToLocals(f: *mut PyFrameObject) -> ();

    #[cfg(not(Py_3_9))]
    pub fn PyFrame_ClearFreeList() -> c_int;

    #[cfg(Py_3_9)]
    pub fn PyFrame_GetBack(frame: *mut PyFrameObject) -> *mut PyFrameObject;

    #[cfg(Py_3_11)]
    pub fn PyFrame_GetBuiltins(frame: *mut PyFrameObject) -> *mut PyObject;

    #[cfg(Py_3_11)]
    pub fn PyFrame_GetGenerator(frame: *mut PyFrameObject) -> *mut PyObject;

    #[cfg(Py_3_11)]
    pub fn PyFrame_GetGlobals(frame: *mut PyFrameObject) -> *mut PyObject;

   #[cfg(Py_3_11)]
    pub fn PyFrame_GetLasti(frame: *mut PyFrameObject) -> c_int;

   #[cfg(Py_3_11)]
    pub fn PyFrame_GetLocals(frame: *mut PyFrameObject) -> *mut PyObject;
}

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int;

    #[cfg(Py_3_9)]
    pub fn PyFrame_GetCode(frame: *mut PyFrameObject) -> *mut PyCodeObject;
}
<commit_msg>Fix c_char import on versions < 3.11<commit_after>use libc::{c_schar, c_int};
#[cfg(not(Py_3_11))]
use libc::c_char;

use crate::code::{PyCodeObject};
#[cfg(not(Py_3_11))]
use crate::code::CO_MAXBLOCKS;
use crate::object::*;
use crate::pystate::PyThreadState;

#[cfg(not(Py_LIMITED_API))]
pub type PyFrameState = c_schar;

#[cfg(not(Py_LIMITED_API))]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyTryBlock {
    pub b_type: c_int,
    pub b_handler: c_int,
    pub b_level: c_int,
}

/// In Python > 3.11, frame object internals are always private
///
/// This improves performance by creating frame object lazily.
/// There are now getter methods to get info from the frame.
#[cfg(any(Py_LIMITED_API, Py_3_11))]
#[repr(C)]
pub struct PyFrameObject {
    _private: [u8; 0],
}

#[cfg(all(not(Py_LIMITED_API), not(Py_3_11)))]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyFrameObject {
    pub ob_base: PyVarObject,
    pub f_back: *mut PyFrameObject,       /* previous frame, or NULL */
    pub f_code: *mut PyCodeObject,        /* code segment */
    pub f_builtins: *mut PyObject,        /* builtin symbol table (PyDictObject) */
    pub f_globals: *mut PyObject,         /* global symbol table (PyDictObject) */
    pub f_locals: *mut PyObject,          /* local symbol table (any mapping) */
    pub f_valuestack: *mut *mut PyObject, /* points after the last local */
    /* Next free slot in f_valuestack.  Frame creation sets to f_valuestack.
    Frame evaluation usually NULLs it, but a frame that yields sets it
    to the current stack top. */
    #[cfg(not(Py_3_10))]
    pub f_stacktop: *mut *mut PyObject,
    pub f_trace: *mut PyObject, /* Trace function */
    #[cfg(Py_3_10)]
    pub f_stackdepth: c_int,

    #[cfg(not(Py_3_7))]
    pub f_exc_type: *mut PyObject,
    #[cfg(not(Py_3_7))]
    pub f_exc_value: *mut PyObject,
    #[cfg(not(Py_3_7))]
    pub f_exc_traceback: *mut PyObject,

    #[cfg(Py_3_7)]
    pub f_trace_lines: c_char,
    #[cfg(Py_3_7)]
    pub f_trace_opcodes: c_char,

    #[cfg(not(Py_3_4))]
    pub f_tstate: *mut PyThreadState,

    #[cfg(Py_3_4)]
    pub f_gen: *mut PyObject,

    pub f_lasti: c_int, /* Last instruction if called */
    /* Call PyFrame_GetLineNumber() instead of reading this field
     directly.  As of 2.3 f_lineno is only valid when tracing is
     active (i.e. when f_trace is set).  At other times we use
     PyCode_Addr2Line to calculate the line from the current
    bytecode index. */
    pub f_lineno: c_int, /* Current line number. Only valid if non-zero */
    pub f_iblock: c_int, /* index in f_blockstack */
    #[cfg(all(Py_3_4, not(Py_3_10)))]
    pub f_executing: c_char, /* whether the frame is still executing */
    #[cfg(Py_3_10)]
    pub f_state: PyFrameState,  /* What state the frame is in */
    pub f_blockstack: [PyTryBlock; CO_MAXBLOCKS], /* for try and loop blocks */
    pub f_localsplus: [*mut PyObject; 1], /* locals+stack, dynamically sized */
}

#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub static mut PyFrame_Type: PyTypeObject;
}

#[cfg(not(Py_LIMITED_API))]
#[inline]
pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int {
    (Py_TYPE(op) == &mut PyFrame_Type) as c_int
}

#[cfg(not(Py_LIMITED_API))]
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub fn PyFrame_New(
        tstate: *mut PyThreadState,
        code: *mut PyCodeObject,
        globals: *mut PyObject,
        locals: *mut PyObject,
    ) -> *mut PyFrameObject;

    #[cfg(not(Py_3_11))]
    pub fn PyFrame_BlockSetup(
        f: *mut PyFrameObject,
        _type: c_int,
        handler: c_int,
        level: c_int,
    ) -> ();
    #[cfg(not(Py_3_11))]
    pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock;

    pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int) -> ();
    #[cfg(Py_3_4)]
    pub fn PyFrame_FastToLocalsWithError(f: *mut PyFrameObject) -> c_int;
    pub fn PyFrame_FastToLocals(f: *mut PyFrameObject) -> ();

    #[cfg(not(Py_3_9))]
    pub fn PyFrame_ClearFreeList() -> c_int;

    #[cfg(Py_3_9)]
    pub fn PyFrame_GetBack(frame: *mut PyFrameObject) -> *mut PyFrameObject;

    #[cfg(Py_3_11)]
    pub fn PyFrame_GetBuiltins(frame: *mut PyFrameObject) -> *mut PyObject;

    #[cfg(Py_3_11)]
    pub fn PyFrame_GetGenerator(frame: *mut PyFrameObject) -> *mut PyObject;

    #[cfg(Py_3_11)]
    pub fn PyFrame_GetGlobals(frame: *mut PyFrameObject) -> *mut PyObject;

   #[cfg(Py_3_11)]
    pub fn PyFrame_GetLasti(frame: *mut PyFrameObject) -> c_int;

   #[cfg(Py_3_11)]
    pub fn PyFrame_GetLocals(frame: *mut PyFrameObject) -> *mut PyObject;
}

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
    pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int;

    #[cfg(Py_3_9)]
    pub fn PyFrame_GetCode(frame: *mut PyFrameObject) -> *mut PyCodeObject;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Genymobile
 *
 * 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.
 */

use std::cell::RefCell;
use std::io;
use std::ptr;
use std::rc::{Rc, Weak};
use log::Level;

use super::binary;
use super::client::{Client, ClientChannel};
use super::connection::{Connection, ConnectionId};
use super::ipv4_header::Protocol;
use super::ipv4_packet::Ipv4Packet;
use super::selector::Selector;
use super::tcp_connection::TcpConnection;
use super::udp_connection::UdpConnection;

const TAG: &'static str = "Router";

pub struct Router {
    client: Weak<RefCell<Client>>,
    // there are typically only few connections per client, HashMap would be less efficient
    connections: Vec<Rc<RefCell<Connection>>>,
}

impl Router {
    pub fn new() -> Self {
        Self {
            client: Weak::new(),
            connections: Vec::new(),
        }
    }

    // expose client initialization after construction to break cyclic initialization dependencies
    pub fn set_client(&mut self, client: Weak<RefCell<Client>>) {
        self.client = client;
    }

    pub fn send_to_network(
        &mut self,
        selector: &mut Selector,
        client_channel: &mut ClientChannel,
        ipv4_packet: &Ipv4Packet,
    ) {
        if ipv4_packet.is_valid() {
            match self.connection(selector, ipv4_packet) {
                Ok(index) => {
                    let closed = {
                        let connection_ref = self.connections.get_mut(index).unwrap();
                        let mut connection = connection_ref.borrow_mut();
                        connection.send_to_network(selector, client_channel, ipv4_packet);
                        connection.is_closed()
                    };
                    if closed {
                        // the connection is closed, remove it
                        self.connections.swap_remove(index);
                    }
                }
                Err(err) => error!(target: TAG, "Cannot create route, dropping packet: {}", err),
            }
        } else {
            warn!(target: TAG, "Dropping invalid packet");
            if log_enabled!(target: TAG, Level::Trace) {
                trace!(target: TAG, "{}", binary::to_string(ipv4_packet.raw()));
            }
        }
    }

    fn connection(
        &mut self,
        selector: &mut Selector,
        ipv4_packet: &Ipv4Packet,
    ) -> io::Result<usize> {
        let (ipv4_header_data, transport_header_data) = ipv4_packet.headers_data();
        let transport_header_data = transport_header_data.expect("No transport");
        let id = ConnectionId::from_headers(ipv4_header_data, transport_header_data);
        let index = match self.find_index(&id) {
            Some(index) => index,
            None => {
                let connection =
                    Self::create_connection(selector, id, self.client.clone(), ipv4_packet)?;
                let index = self.connections.len();
                self.connections.push(connection);
                index
            }
        };
        Ok(index)
    }

    fn create_connection(
        selector: &mut Selector,
        id: ConnectionId,
        client: Weak<RefCell<Client>>,
        ipv4_packet: &Ipv4Packet,
    ) -> io::Result<Rc<RefCell<Connection>>> {
        let (ipv4_header, transport_header) = ipv4_packet.headers();
        let transport_header = transport_header.expect("No transport");
        match id.protocol() {
            Protocol::Tcp => Ok(TcpConnection::new(
                selector,
                id,
                client,
                ipv4_header,
                transport_header,
            )?),
            Protocol::Udp => Ok(UdpConnection::new(
                selector,
                id,
                client,
                ipv4_header,
                transport_header,
            )?),
            p => Err(io::Error::new(
                io::ErrorKind::Other,
                format!("Unsupported protocol: {:?}", p),
            )),
        }
    }

    fn find_index(&self, id: &ConnectionId) -> Option<usize> {
        self.connections.iter().position(|connection| {
            connection.borrow().id() == id
        })
    }

    pub fn remove(&mut self, connection: &Connection) {
        let index = self.connections
            .iter()
            .position(|item| {
                // compare pointers to find the connection to remove
                ptr::eq(connection, item.as_ptr())
            })
            .expect("Removing an unknown connection");
        self.connections.swap_remove(index);
    }

    pub fn clear(&mut self, selector: &mut Selector) {
        for connection in &mut self.connections {
            connection.borrow_mut().close(selector);
        }
        self.connections.clear();
    }

    pub fn clean_expired_connections(&mut self, selector: &mut Selector) {
        // remove the last items first, otherwise i might not be less than len() on swap_remove(i)
        for i in (0..self.connections.len()).rev() {
            let expired = {
                let mut connection = self.connections[i].borrow_mut();
                if connection.is_expired() {
                    debug!(
                        target: TAG,
                        "Removed expired connection: {}",
                        connection.id()
                    );
                    connection.close(selector);
                    true
                } else {
                    false
                }
            };
            if expired {
                self.connections.swap_remove(i);
            }
        }
    }
}
<commit_msg>Ignore double-removal of a connection<commit_after>/*
 * Copyright (C) 2017 Genymobile
 *
 * 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.
 */

use std::cell::RefCell;
use std::io;
use std::ptr;
use std::rc::{Rc, Weak};
use log::Level;

use super::binary;
use super::client::{Client, ClientChannel};
use super::connection::{Connection, ConnectionId};
use super::ipv4_header::Protocol;
use super::ipv4_packet::Ipv4Packet;
use super::selector::Selector;
use super::tcp_connection::TcpConnection;
use super::udp_connection::UdpConnection;

const TAG: &'static str = "Router";

pub struct Router {
    client: Weak<RefCell<Client>>,
    // there are typically only few connections per client, HashMap would be less efficient
    connections: Vec<Rc<RefCell<Connection>>>,
}

impl Router {
    pub fn new() -> Self {
        Self {
            client: Weak::new(),
            connections: Vec::new(),
        }
    }

    // expose client initialization after construction to break cyclic initialization dependencies
    pub fn set_client(&mut self, client: Weak<RefCell<Client>>) {
        self.client = client;
    }

    pub fn send_to_network(
        &mut self,
        selector: &mut Selector,
        client_channel: &mut ClientChannel,
        ipv4_packet: &Ipv4Packet,
    ) {
        if ipv4_packet.is_valid() {
            match self.connection(selector, ipv4_packet) {
                Ok(index) => {
                    let closed = {
                        let connection_ref = self.connections.get_mut(index).unwrap();
                        let mut connection = connection_ref.borrow_mut();
                        connection.send_to_network(selector, client_channel, ipv4_packet);
                        connection.is_closed()
                    };
                    if closed {
                        // the connection is closed, remove it
                        self.connections.swap_remove(index);
                    }
                }
                Err(err) => error!(target: TAG, "Cannot create route, dropping packet: {}", err),
            }
        } else {
            warn!(target: TAG, "Dropping invalid packet");
            if log_enabled!(target: TAG, Level::Trace) {
                trace!(target: TAG, "{}", binary::to_string(ipv4_packet.raw()));
            }
        }
    }

    fn connection(
        &mut self,
        selector: &mut Selector,
        ipv4_packet: &Ipv4Packet,
    ) -> io::Result<usize> {
        let (ipv4_header_data, transport_header_data) = ipv4_packet.headers_data();
        let transport_header_data = transport_header_data.expect("No transport");
        let id = ConnectionId::from_headers(ipv4_header_data, transport_header_data);
        let index = match self.find_index(&id) {
            Some(index) => index,
            None => {
                let connection =
                    Self::create_connection(selector, id, self.client.clone(), ipv4_packet)?;
                let index = self.connections.len();
                self.connections.push(connection);
                index
            }
        };
        Ok(index)
    }

    fn create_connection(
        selector: &mut Selector,
        id: ConnectionId,
        client: Weak<RefCell<Client>>,
        ipv4_packet: &Ipv4Packet,
    ) -> io::Result<Rc<RefCell<Connection>>> {
        let (ipv4_header, transport_header) = ipv4_packet.headers();
        let transport_header = transport_header.expect("No transport");
        match id.protocol() {
            Protocol::Tcp => Ok(TcpConnection::new(
                selector,
                id,
                client,
                ipv4_header,
                transport_header,
            )?),
            Protocol::Udp => Ok(UdpConnection::new(
                selector,
                id,
                client,
                ipv4_header,
                transport_header,
            )?),
            p => Err(io::Error::new(
                io::ErrorKind::Other,
                format!("Unsupported protocol: {:?}", p),
            )),
        }
    }

    fn find_index(&self, id: &ConnectionId) -> Option<usize> {
        self.connections.iter().position(|connection| {
            connection.borrow().id() == id
        })
    }

    pub fn remove(&mut self, connection: &Connection) {
        let index = self.connections.iter().position(|item| {
            // compare pointers to find the connection to remove
            ptr::eq(connection, item.as_ptr())
        });
        // the connection may have already been removed by send_to_network()
        if let Some(index) = index {
            self.connections.swap_remove(index);
        }
    }

    pub fn clear(&mut self, selector: &mut Selector) {
        for connection in &mut self.connections {
            connection.borrow_mut().close(selector);
        }
        self.connections.clear();
    }

    pub fn clean_expired_connections(&mut self, selector: &mut Selector) {
        // remove the last items first, otherwise i might not be less than len() on swap_remove(i)
        for i in (0..self.connections.len()).rev() {
            let expired = {
                let mut connection = self.connections[i].borrow_mut();
                if connection.is_expired() {
                    debug!(
                        target: TAG,
                        "Removed expired connection: {}",
                        connection.id()
                    );
                    connection.close(selector);
                    true
                } else {
                    false
                }
            };
            if expired {
                self.connections.swap_remove(i);
            }
        }
    }
}
<|endoftext|>


<commit_before>use parser::{
    graph_triples::{relations::Range, Pairs},
    utils::apply_tags,
};
use std::{collections::HashMap, path::Path, sync::Mutex};

// Re-exports for the convenience of crates implementing a Tree-sitter
// based parser
pub use parser::*;
pub use path_utils;

/// A parser based on `tree-sitter`
///
/// This simply encapsulates a `tree-sitter` usage pattern to
/// avoid repetitive boiler plate code in the language-specific sub-modules.
pub struct TreesitterParser {
    /// The `tree-sitter` parser
    inner: Mutex<tree_sitter::Parser>,

    /// The `tree-sitter` query
    query: tree_sitter::Query,
}

impl TreesitterParser {
    /// Create a new compiler for a language with a pre-defined query
    ///
    /// # Arguments
    ///
    /// - `language`: The `tree-sitter` language definition
    /// - `query`: The `tree-sitter` query definition
    pub fn new(language: tree_sitter::Language, query: &str) -> TreesitterParser {
        let mut parser = tree_sitter::Parser::new();
        parser
            .set_language(language)
            .expect("Should be able to set language");
        let parser = Mutex::new(parser);

        let query = tree_sitter::Query::new(language, query).expect("Query should compile");

        TreesitterParser {
            inner: parser,
            query,
        }
    }

    /// Parse some code and return a tree
    ///
    /// # Arguments
    ///
    /// - `code`: The code to parse
    ///
    /// # Returns
    ///
    /// The parsed syntax tree.
    pub fn parse(&self, code: &[u8]) -> tree_sitter::Tree {
        self.inner
            .lock()
            .expect("Unable to lock parser")
            .parse(code, None)
            .expect("Should be a tree result")
    }

    /// Query a parse tree
    ///
    /// # Arguments
    ///
    /// - `code`: The code to parse
    /// - `tree`: The `tree-sitter` parse tree
    ///
    /// # Returns
    ///
    /// A vector of `(pattern, captures)` enumerating the matches for
    /// patterns in the query.
    pub fn query<'tree>(
        &self,
        code: &[u8],
        tree: &'tree tree_sitter::Tree,
    ) -> Vec<(usize, Vec<Capture<'tree>>)> {
        let mut cursor = tree_sitter::QueryCursor::new();
        let matches = cursor.matches(&self.query, tree.root_node(), code);

        let capture_names = self.query.capture_names();
        matches
            .map(|query_match| {
                let pattern = query_match.pattern_index;
                let captures = query_match
                    .captures
                    .iter()
                    .map(|capture| {
                        let start = capture.node.start_position();
                        let end = capture.node.end_position();
                        Capture::new(
                            capture.index,
                            capture_names[capture.index as usize].clone(),
                            capture.node,
                            (start.row, start.column, end.row, end.column),
                            capture
                                .node
                                .utf8_text(code)
                                .expect("Should be able to get text")
                                .to_string(),
                        )
                    })
                    .collect();
                (pattern, captures)
            })
            .collect()
    }
}

/// A capture resulting from a `tree-sitter` query
pub struct Capture<'tree> {
    #[allow(dead_code)]
    /// The index of the capture in the pattern
    index: u32,

    /// The name of the capture in the pattern
    name: String,

    /// The captured node
    pub node: tree_sitter::Node<'tree>,

    /// The captured range
    pub range: Range,

    /// The captured text
    pub text: String,
}

impl<'tree> Capture<'tree> {
    pub fn new(
        index: u32,
        name: String,
        node: tree_sitter::Node<'tree>,
        range: Range,
        text: String,
    ) -> Capture {
        Capture {
            index,
            name,
            node,
            range,
            text,
        }
    }
}

/// Convert a vector of `Capture`s into a `HashMap` of captures
///
/// This relies on captures using the names `@arg` (for non-keyword args)
/// and `@arg_name` and `@arg_value` pairs (for keyword args).
pub fn captures_as_args_map<'tree>(
    captures: &'tree [Capture],
) -> HashMap<String, &'tree Capture<'tree>> {
    let mut map = HashMap::new();

    let mut index = 0;
    let mut name = String::new();
    for capture in captures {
        match capture.name.as_str() {
            "arg" => {
                map.insert(index.to_string(), capture);
                index += 1;
            }
            "arg_name" => {
                name = capture.text.clone();
            }
            "arg_value" => {
                map.insert(name.clone(), capture);
            }
            _ => {}
        }
    }

    map
}

/// Get the text of a child node
///
/// Returns an empty string if the child does not exists, or the text could
/// not be obtained
pub fn child_text<'tree>(
    node: tree_sitter::Node<'tree>,
    name: &str,
    code: &'tree [u8],
) -> &'tree str {
    node.child_by_field_name(name)
        .and_then(|child| child.utf8_text(code).ok())
        .unwrap_or("")
}

/// Create a [`ParseInfo`] instance from a Treesitter parse tree and pattern matches
///
/// Applies manual tags (e.g. `@uses`) in a comments to the relations derived from
/// semantic code analysis.
///
/// # Arguments
///
/// - `path`: The path of the subject code resource
/// - `lang`: The language (used for creating `Resource::Module` variants)
/// - `code`: The code that was parsed
/// - `matches`: The matches from querying the code
/// - `comment_pattern`: The index of the pattern from which to extract tags
/// - `relations`: The relation pairs
///
/// Assumes that the first capture has the text content of the comment.
/// If the tag ends in `only` then all existing relations of that type
/// will be removed from `relations`.
pub fn parse_info(
    path: &Path,
    lang: &str,
    code: &[u8],
    matches: Vec<(usize, Vec<Capture>)>,
    comment_pattern: usize,
    relations: Pairs,
) -> ParseInfo {
    let mut parse_info = ParseInfo {
        relations,
        code_digest: ParseInfo::sha256_digest(&std::str::from_utf8(code).unwrap_or_default()),
        ..Default::default()
    };

    for (pattern_, captures) in matches {
        if pattern_ != comment_pattern {
            continue;
        }

        let comment = &captures[0];
        apply_tags(
            path,
            lang,
            comment.range.0,
            &comment.text,
            None,
            &mut parse_info,
        )
    }

    parse_info
}
<commit_msg>fix(Parsers): Remove carriage returns from code<commit_after>use parser::{
    graph_triples::{relations::Range, Pairs},
    utils::apply_tags,
};
use std::{collections::HashMap, path::Path, sync::Mutex};

// Re-exports for the convenience of crates implementing a Tree-sitter
// based parser
pub use parser::*;
pub use path_utils;

/// A parser based on `tree-sitter`
///
/// This simply encapsulates a `tree-sitter` usage pattern to
/// avoid repetitive boiler plate code in the language-specific sub-modules.
pub struct TreesitterParser {
    /// The `tree-sitter` parser
    inner: Mutex<tree_sitter::Parser>,

    /// The `tree-sitter` query
    query: tree_sitter::Query,
}

impl TreesitterParser {
    /// Create a new compiler for a language with a pre-defined query
    ///
    /// # Arguments
    ///
    /// - `language`: The `tree-sitter` language definition
    /// - `query`: The `tree-sitter` query definition
    pub fn new(language: tree_sitter::Language, query: &str) -> TreesitterParser {
        let mut parser = tree_sitter::Parser::new();
        parser
            .set_language(language)
            .expect("Should be able to set language");
        let parser = Mutex::new(parser);

        let query = tree_sitter::Query::new(language, query).expect("Query should compile");

        TreesitterParser {
            inner: parser,
            query,
        }
    }

    /// Parse some code and return a tree
    ///
    /// # Arguments
    ///
    /// - `code`: The code to parse
    ///
    /// # Returns
    ///
    /// The parsed syntax tree.
    pub fn parse(&self, code: &[u8]) -> tree_sitter::Tree {
        self.inner
            .lock()
            .expect("Unable to lock parser")
            .parse(code, None)
            .expect("Should be a tree result")
    }

    /// Query a parse tree
    ///
    /// # Arguments
    ///
    /// - `code`: The code to parse
    /// - `tree`: The `tree-sitter` parse tree
    ///
    /// # Returns
    ///
    /// A vector of `(pattern, captures)` enumerating the matches for
    /// patterns in the query.
    pub fn query<'tree>(
        &self,
        code: &[u8],
        tree: &'tree tree_sitter::Tree,
    ) -> Vec<(usize, Vec<Capture<'tree>>)> {
        let mut cursor = tree_sitter::QueryCursor::new();
        let matches = cursor.matches(&self.query, tree.root_node(), code);

        let capture_names = self.query.capture_names();
        matches
            .map(|query_match| {
                let pattern = query_match.pattern_index;
                let captures = query_match
                    .captures
                    .iter()
                    .map(|capture| {
                        let start = capture.node.start_position();
                        let end = capture.node.end_position();
                        Capture::new(
                            capture.index,
                            capture_names[capture.index as usize].clone(),
                            capture.node,
                            (start.row, start.column, end.row, end.column),
                            capture
                                .node
                                .utf8_text(code)
                                .expect("Should be able to get text")
                                .to_string(),
                        )
                    })
                    .collect();
                (pattern, captures)
            })
            .collect()
    }
}

/// A capture resulting from a `tree-sitter` query
pub struct Capture<'tree> {
    #[allow(dead_code)]
    /// The index of the capture in the pattern
    index: u32,

    /// The name of the capture in the pattern
    name: String,

    /// The captured node
    pub node: tree_sitter::Node<'tree>,

    /// The captured range
    pub range: Range,

    /// The captured text
    pub text: String,
}

impl<'tree> Capture<'tree> {
    pub fn new(
        index: u32,
        name: String,
        node: tree_sitter::Node<'tree>,
        range: Range,
        text: String,
    ) -> Capture {
        Capture {
            index,
            name,
            node,
            range,
            text,
        }
    }
}

/// Convert a vector of `Capture`s into a `HashMap` of captures
///
/// This relies on captures using the names `@arg` (for non-keyword args)
/// and `@arg_name` and `@arg_value` pairs (for keyword args).
pub fn captures_as_args_map<'tree>(
    captures: &'tree [Capture],
) -> HashMap<String, &'tree Capture<'tree>> {
    let mut map = HashMap::new();

    let mut index = 0;
    let mut name = String::new();
    for capture in captures {
        match capture.name.as_str() {
            "arg" => {
                map.insert(index.to_string(), capture);
                index += 1;
            }
            "arg_name" => {
                name = capture.text.clone();
            }
            "arg_value" => {
                map.insert(name.clone(), capture);
            }
            _ => {}
        }
    }

    map
}

/// Get the text of a child node
///
/// Returns an empty string if the child does not exists, or the text could
/// not be obtained
pub fn child_text<'tree>(
    node: tree_sitter::Node<'tree>,
    name: &str,
    code: &'tree [u8],
) -> &'tree str {
    node.child_by_field_name(name)
        .and_then(|child| child.utf8_text(code).ok())
        .unwrap_or("")
}

/// Create a [`ParseInfo`] instance from a Treesitter parse tree and pattern matches
///
/// Applies manual tags (e.g. `@uses`) in a comments to the relations derived from
/// semantic code analysis.
///
/// # Arguments
///
/// - `path`: The path of the subject code resource
/// - `lang`: The language (used for creating `Resource::Module` variants)
/// - `code`: The code that was parsed
/// - `matches`: The matches from querying the code
/// - `comment_pattern`: The index of the pattern from which to extract tags
/// - `relations`: The relation pairs
///
/// Assumes that the first capture has the text content of the comment.
/// If the tag ends in `only` then all existing relations of that type
/// will be removed from `relations`.
pub fn parse_info(
    path: &Path,
    lang: &str,
    code: &[u8],
    matches: Vec<(usize, Vec<Capture>)>,
    comment_pattern: usize,
    relations: Pairs,
) -> ParseInfo {
    // Remove carriage returns from code to avoid cross platform
    // differences in code before calculating digest
    let code = std::str::from_utf8(code)
        .unwrap_or_default()
        .replace("\r", "");

    let mut parse_info = ParseInfo {
        relations,
        code_digest: ParseInfo::sha256_digest(&code),
        ..Default::default()
    };

    for (pattern_, captures) in matches {
        if pattern_ != comment_pattern {
            continue;
        }

        let comment = &captures[0];
        apply_tags(
            path,
            lang,
            comment.range.0,
            &comment.text,
            None,
            &mut parse_info,
        )
    }

    parse_info
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::path::Path;
use std::process::Command;

fn main() {
    if env::var("SKIP_GRAPHQL_SCHEMA").unwrap_or("0".to_owned()) == "1" {
        return
    }

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir);

    let schema_path = out_path.join("graphql-schema.json");

    let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src_path = Path::new(&src_dir);

    Command::new(env::var("CARGO").unwrap())
        .args(&[
            "install",
            "--path", src_dir.as_ref(),
            "--bin", "turingarena-graphql-schema",
            "--root", out_path.to_str().unwrap(),
            "--force",
            "--debug",
            "--offline",
            "--no-default-features",
        ])
        .env("CARGO_TARGET_DIR", out_path.join("graphql-schema-target").to_str().unwrap())
        .env("SKIP_GRAPHQL_SCHEMA", "1")
        .status()
        .unwrap();

    Command::new(env::var("CARGO").unwrap())
        .args(&[
            "install",
            "graphql_client_cli",
            "--root", out_path.to_str().unwrap(),
            "--force",
        ])
        .env("CARGO_TARGET_DIR", out_path.join("graphql-client-cli-target").to_str().unwrap())
        .status()
        .unwrap();

    let schema_file = File::create(&schema_path).unwrap();

    Command::new(out_path.join("bin").join("turingarena-graphql-schema"))
        .stdout(schema_file)
        .status()
        .unwrap();

    Command::new(out_path.join("bin").join("graphql-client"))
        .args(&[
            "generate",
            "--output-directory", out_path.to_str().unwrap(),
            "--schema-path", schema_path.to_str().unwrap(),
            src_path.join("src").join("operations.graphql").to_str().unwrap(),
        ])
        .status()
        .unwrap();
}
<commit_msg>contest: gen GraphQL client only under `admin-cli`<commit_after>use std::env;
use std::fs::File;
use std::path::Path;
use std::process::Command;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir);

    let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src_path = Path::new(&src_dir);

    if env::var_os("CARGO_FEATURE_CLI_ADMIN").is_some() {
        let schema_path = out_path.join("graphql-schema.json");

        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "--path", src_dir.as_ref(),
                "--bin", "turingarena-graphql-schema",
                "--root", out_path.to_str().unwrap(),
                "--force",
                "--debug",
                "--offline",
                "--no-default-features",
            ])
            .env("CARGO_TARGET_DIR", out_path.join("graphql-schema-target").to_str().unwrap())
            .status()
            .unwrap();

        let schema_file = File::create(&schema_path).unwrap();

        Command::new(out_path.join("bin").join("turingarena-graphql-schema"))
            .stdout(schema_file)
            .status()
            .unwrap();

        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "graphql_client_cli",
                "--root", out_path.to_str().unwrap(),
                "--force",
            ])
            .env("CARGO_TARGET_DIR", out_path.join("graphql-client-cli-target").to_str().unwrap())
            .status()
            .unwrap();

        Command::new(out_path.join("bin").join("graphql-client"))
            .args(&[
                "generate",
                "--output-directory", out_path.to_str().unwrap(),
                "--schema-path", schema_path.to_str().unwrap(),
                src_path.join("src").join("operations.graphql").to_str().unwrap(),
            ])
            .status()
            .unwrap();
    }

}
<|endoftext|>