<commit_before>mod grab;
mod manager;

pub use grab::*;
pub use manager::*;
use wayland_server::protocol::wl_surface::WlSurface;

use crate::{
    backend::renderer::{utils::draw_surface_tree, ImportAll, Renderer},
    utils::{IsAlive, Logical, Physical, Point, Rectangle, Scale},
    wayland::{
        compositor::with_states,
        shell::xdg::{PopupSurface, SurfaceCachedState, XdgPopupSurfaceData},
    },
};

/// Represents a popup surface
#[derive(Debug, Clone)]
pub enum PopupKind {
    /// xdg-shell [`PopupSurface`]
    Xdg(PopupSurface),
}

impl IsAlive for PopupKind {
    fn alive(&self) -> bool {
        match self {
            PopupKind::Xdg(ref p) => p.alive(),
        }
    }
}

impl From<PopupKind> for WlSurface {
    fn from(p: PopupKind) -> Self {
        p.wl_surface().clone()
    }
}

impl PopupKind {
    /// Retrieves the underlying [`WlSurface`]
    pub fn wl_surface(&self) -> &WlSurface {
        match *self {
            PopupKind::Xdg(ref t) => t.wl_surface(),
        }
    }

    fn parent(&self) -> Option<WlSurface> {
        match *self {
            PopupKind::Xdg(ref t) => t.get_parent_surface(),
        }
    }

    /// Returns the surface geometry as set by the client using `xdg_surface::set_window_geometry`
    pub fn geometry(&self) -> Rectangle<i32, Logical> {
        let wl_surface = self.wl_surface();

        with_states(wl_surface, |states| {
            states
                .cached_state
                .current::<SurfaceCachedState>()
                .geometry
                .unwrap_or_default()
        })
    }

    fn send_done(&self) {
        match *self {
            PopupKind::Xdg(ref t) => t.send_popup_done(),
        }
    }

    fn location(&self) -> Point<i32, Logical> {
        let wl_surface = self.wl_surface();

        with_states(wl_surface, |states| {
            states
                .data_map
                .get::<XdgPopupSurfaceData>()
                .unwrap()
                .lock()
                .unwrap()
                .current
                .geometry
        })
        .loc
    }
}

impl From<PopupSurface> for PopupKind {
    fn from(p: PopupSurface) -> PopupKind {
        PopupKind::Xdg(p)
    }
}

/// Renders popups of a given [`WlSurface`] using a provided renderer and frame.
///
/// - `surface_location` os the location the surface would been draw at
/// - `offset` will further offset the popups location (e.g. window popups should be offset by the windows geometry)
/// - `scale` needs to be equivalent to the fractional scale the rendered result should have.
/// - `damage` is the set of regions of the layer surface that should be drawn.
///
/// Note: This function will render nothing, if you are not using
/// [`crate::backend::renderer::utils::on_commit_buffer_handler`]
/// to let smithay handle buffer management.
#[allow(clippy::too_many_arguments)]
pub fn draw_popups<R, P1, P2, S>(
    renderer: &mut R,
    frame: &mut <R as Renderer>::Frame,
    for_surface: &WlSurface,
    surface_location: P1,
    offset: P2,
    scale: S,
    damage: &[Rectangle<i32, Physical>],
    log: &slog::Logger,
) -> Result<(), <R as Renderer>::Error>
where
    R: Renderer + ImportAll,
    <R as Renderer>::TextureId: 'static,
    P1: Into<Point<f64, Physical>>,
    P2: Into<Point<i32, Logical>>,
    S: Into<Scale<f64>>,
{
    let location = surface_location.into();
    let offset = offset.into();
    let scale = scale.into();
    for (popup, p_location) in PopupManager::popups_for_surface(for_surface) {
        let surface = popup.wl_surface();
        let offset = (offset + p_location - popup.geometry().loc)
            .to_f64()
            .to_physical(scale);
        draw_surface_tree(renderer, frame, surface, scale, location + offset, damage, log)?;
    }
    Ok(())
}
<commit_msg>popup: Derive PartialEq for PopupKind<commit_after>mod grab;
mod manager;

pub use grab::*;
pub use manager::*;
use wayland_server::protocol::wl_surface::WlSurface;

use crate::{
    backend::renderer::{utils::draw_surface_tree, ImportAll, Renderer},
    utils::{IsAlive, Logical, Physical, Point, Rectangle, Scale},
    wayland::{
        compositor::with_states,
        shell::xdg::{PopupSurface, SurfaceCachedState, XdgPopupSurfaceData},
    },
};

/// Represents a popup surface
#[derive(Debug, Clone, PartialEq)]
pub enum PopupKind {
    /// xdg-shell [`PopupSurface`]
    Xdg(PopupSurface),
}

impl IsAlive for PopupKind {
    fn alive(&self) -> bool {
        match self {
            PopupKind::Xdg(ref p) => p.alive(),
        }
    }
}

impl From<PopupKind> for WlSurface {
    fn from(p: PopupKind) -> Self {
        p.wl_surface().clone()
    }
}

impl PopupKind {
    /// Retrieves the underlying [`WlSurface`]
    pub fn wl_surface(&self) -> &WlSurface {
        match *self {
            PopupKind::Xdg(ref t) => t.wl_surface(),
        }
    }

    fn parent(&self) -> Option<WlSurface> {
        match *self {
            PopupKind::Xdg(ref t) => t.get_parent_surface(),
        }
    }

    /// Returns the surface geometry as set by the client using `xdg_surface::set_window_geometry`
    pub fn geometry(&self) -> Rectangle<i32, Logical> {
        let wl_surface = self.wl_surface();

        with_states(wl_surface, |states| {
            states
                .cached_state
                .current::<SurfaceCachedState>()
                .geometry
                .unwrap_or_default()
        })
    }

    fn send_done(&self) {
        match *self {
            PopupKind::Xdg(ref t) => t.send_popup_done(),
        }
    }

    fn location(&self) -> Point<i32, Logical> {
        let wl_surface = self.wl_surface();

        with_states(wl_surface, |states| {
            states
                .data_map
                .get::<XdgPopupSurfaceData>()
                .unwrap()
                .lock()
                .unwrap()
                .current
                .geometry
        })
        .loc
    }
}

impl From<PopupSurface> for PopupKind {
    fn from(p: PopupSurface) -> PopupKind {
        PopupKind::Xdg(p)
    }
}

/// Renders popups of a given [`WlSurface`] using a provided renderer and frame.
///
/// - `surface_location` os the location the surface would been draw at
/// - `offset` will further offset the popups location (e.g. window popups should be offset by the windows geometry)
/// - `scale` needs to be equivalent to the fractional scale the rendered result should have.
/// - `damage` is the set of regions of the layer surface that should be drawn.
///
/// Note: This function will render nothing, if you are not using
/// [`crate::backend::renderer::utils::on_commit_buffer_handler`]
/// to let smithay handle buffer management.
#[allow(clippy::too_many_arguments)]
pub fn draw_popups<R, P1, P2, S>(
    renderer: &mut R,
    frame: &mut <R as Renderer>::Frame,
    for_surface: &WlSurface,
    surface_location: P1,
    offset: P2,
    scale: S,
    damage: &[Rectangle<i32, Physical>],
    log: &slog::Logger,
) -> Result<(), <R as Renderer>::Error>
where
    R: Renderer + ImportAll,
    <R as Renderer>::TextureId: 'static,
    P1: Into<Point<f64, Physical>>,
    P2: Into<Point<i32, Logical>>,
    S: Into<Scale<f64>>,
{
    let location = surface_location.into();
    let offset = offset.into();
    let scale = scale.into();
    for (popup, p_location) in PopupManager::popups_for_surface(for_surface) {
        let surface = popup.wl_surface();
        let offset = (offset + p_location - popup.geometry().loc)
            .to_f64()
            .to_physical(scale);
        draw_surface_tree(renderer, frame, surface, scale, location + offset, damage, log)?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate libimagrt;
extern crate libimagentrytag;
extern crate libimagutil;
#[macro_use] extern crate version;

use clap::Shell;
use libimagrt::runtime::Runtime;

/// This macro generates mods with the given '$modulename',
/// whose content is the file given with `$path`.
/// In this case, It is used specifically to include the
/// `ui.rs` files of the imag binaries.
/// The imag project (accidentally?) followed the convention
/// to write a `ui.rs` containing the function
/// `fn build_ui(app : App) -> App`.
/// This macro allows us to use the same named functions by
/// putting them each into their own module.
macro_rules! gen_mods_buildui {
    ($(($path:expr, $modulename:ident)$(,)*)*) => (
        $(
            mod $modulename {
                include!($path);
            }
         )*
        )
}

/// This macro reduces boilerplate code.
///
/// For example: `build_subcommand!("counter", imagcounter)`
/// will result in the following code:
/// ```ignore
/// imagcounter::build_ui(Runtime::get_default_cli_builder(
///     "counter",
///     &version!()[..],
///     "counter"))
/// ```
macro_rules! build_subcommand {
    ($name:expr, $module:ident) => (
        $module::build_ui(Runtime::get_default_cli_builder(
                $name,
                &version!()[..],
                $name))
    )
}

// Actually generates the module.
gen_mods_buildui!(
    ("../imag-bookmark/src/ui.rs",  imagbookmark),
    ("../imag-counter/src/ui.rs",   imagcounter),
    ("../imag-diary/src/ui.rs",     imagdiary),
    ("../imag-link/src/ui.rs",      imaglink),
    ("../imag-notes/src/ui.rs",     imagnotes),
    ("../imag-ref/src/ui.rs",       imagref),
    ("../imag-store/src/ui.rs",     imagstore),
    ("../imag-tag/src/ui.rs",       imagtag),
    ("../imag-todo/src/ui.rs",      imagtodo),
    ("../imag-view/src/ui.rs",      imagview)
);

fn main() {
    // Make the `imag`-App...
    let mut app = Runtime::get_default_cli_builder(
        "imag",
        &version!()[..],
        "imag")
        // and add all the subapps as subcommands.
        .subcommand(build_subcommand!("bookmark",   imagbookmark))
        .subcommand(build_subcommand!("counter",    imagcounter))
        .subcommand(build_subcommand!("diary",      imagdiary))
        .subcommand(build_subcommand!("link",       imaglink))
        .subcommand(build_subcommand!("notes",      imagnotes))
        .subcommand(build_subcommand!("ref",        imagref))
        .subcommand(build_subcommand!("store",      imagstore))
        .subcommand(build_subcommand!("tag",        imagtag))
        .subcommand(build_subcommand!("todo",       imagtodo))
        .subcommand(build_subcommand!("view",       imagview));

    // Actually generates the completion files
    app.gen_completions("imag", Shell::Bash, env!("OUT_DIR"));
    app.gen_completions("imag", Shell::Fish, env!("OUT_DIR"));
    app.gen_completions("imag", Shell::Zsh, env!("OUT_DIR"));

}

<commit_msg>Add comment for `&version!()[..]`<commit_after>extern crate clap;
extern crate libimagrt;
extern crate libimagentrytag;
extern crate libimagutil;
#[macro_use] extern crate version;

use clap::Shell;
use libimagrt::runtime::Runtime;

/// This macro generates mods with the given '$modulename',
/// whose content is the file given with `$path`.
/// In this case, It is used specifically to include the
/// `ui.rs` files of the imag binaries.
/// The imag project (accidentally?) followed the convention
/// to write a `ui.rs` containing the function
/// `fn build_ui(app : App) -> App`.
/// This macro allows us to use the same named functions by
/// putting them each into their own module.
macro_rules! gen_mods_buildui {
    ($(($path:expr, $modulename:ident)$(,)*)*) => (
        $(
            mod $modulename {
                include!($path);
            }
         )*
        )
}

/// This macro reduces boilerplate code.
///
/// For example: `build_subcommand!("counter", imagcounter)`
/// will result in the following code:
/// ```ignore
/// imagcounter::build_ui(Runtime::get_default_cli_builder(
///     "counter",
///     &version!()[..],
///     "counter"))
/// ```
/// As for the `&version!()[..]` part, it does not matter
/// which version the subcommand is getting here, as the
/// output of this script is a completion script, which
/// does not contain information about the version at all.
macro_rules! build_subcommand {
    ($name:expr, $module:ident) => (
        $module::build_ui(Runtime::get_default_cli_builder(
                $name,
                &version!()[..],
                $name))
    )
}

// Actually generates the module.
gen_mods_buildui!(
    ("../imag-bookmark/src/ui.rs",  imagbookmark),
    ("../imag-counter/src/ui.rs",   imagcounter),
    ("../imag-diary/src/ui.rs",     imagdiary),
    ("../imag-link/src/ui.rs",      imaglink),
    ("../imag-notes/src/ui.rs",     imagnotes),
    ("../imag-ref/src/ui.rs",       imagref),
    ("../imag-store/src/ui.rs",     imagstore),
    ("../imag-tag/src/ui.rs",       imagtag),
    ("../imag-todo/src/ui.rs",      imagtodo),
    ("../imag-view/src/ui.rs",      imagview)
);

fn main() {
    // Make the `imag`-App...
    let mut app = Runtime::get_default_cli_builder(
        "imag",
        &version!()[..],
        "imag")
        // and add all the subapps as subcommands.
        .subcommand(build_subcommand!("bookmark",   imagbookmark))
        .subcommand(build_subcommand!("counter",    imagcounter))
        .subcommand(build_subcommand!("diary",      imagdiary))
        .subcommand(build_subcommand!("link",       imaglink))
        .subcommand(build_subcommand!("notes",      imagnotes))
        .subcommand(build_subcommand!("ref",        imagref))
        .subcommand(build_subcommand!("store",      imagstore))
        .subcommand(build_subcommand!("tag",        imagtag))
        .subcommand(build_subcommand!("todo",       imagtodo))
        .subcommand(build_subcommand!("view",       imagview));

    // Actually generates the completion files
    app.gen_completions("imag", Shell::Bash, env!("OUT_DIR"));
    app.gen_completions("imag", Shell::Fish, env!("OUT_DIR"));
    app.gen_completions("imag", Shell::Zsh, env!("OUT_DIR"));

}

<|endoftext|>


<commit_before>use std::vec::Vec;
use tokens::*;
use lexer::*;
use symbol_table::*;
use support::*;
use plp::PLPWriter;

pub fn compile_class(tokens: &Vec<Token>, start_index: usize) -> (usize, String)
{
    let invalid_types = get_invalid_token_types();
    let invalid_values = get_invalid_token_values();

    let mut plp_string: String = String::new();
    let mut current_index: usize = start_index;

    if tokens[current_index].value != "{" { panic!("Expected '{{' received: {}", tokens[current_index].value); }
    else { current_index += 1; }

    for (index, token) in tokens.iter().enumerate()
    {
        // Handle forward skipping
        if index < current_index { continue; }
        else { current_index = index; }

        // TODO: encapsulate into token_rules.validate(token)
        // Panic! if token type is invalid
        if invalid_types.contains(&token.name)
        {
            panic!("Unsupported token type: {}", token.name);
        }
        // Panic! if token value is invalid
        else if invalid_values.contains(&&*token.value)
        {
            panic!("Unsupported token value: {}", token.value);
        }

        if token.value == "class"
        {
            // parse class body
            let (end_index, compiled_class) = compile_class(&tokens, index + 1);
            plp_string.push_str(&*compiled_class);

            current_index = end_index;
        }
        else if token.name == "type" // || token.name == "identifier"
        {
            // look ahead
            // parse variable declaration
            // OR parse method declaration
        }
        else if token.value == "if"
        {
            // parse if body
            // Unsupported for now
        }
        else if token.name == "construct.conditional"
        {
            // parse conditional
            // Unsupported for now
        }
        else
        {
            panic!("Unexpected token: {}\t{}", token.name, token.value);
        }
    }

    (current_index + 1, plp_string)
}

/// Write PLP code to evaluate the given symbol sequence, and load the result into a specific register
/// A sequence can be:
/// * a  simple variable reference,
/// * a method call,
/// * a variable accessed from another symbol (e.g. foo.bar or Foo.staticBar),
/// * a method accessed from another symbol (e.g. foo.bar() or Foo.staticBar()), or
/// * a complex chain of the above (e.g. foo.method().valueInReturnValue.value.method())
///
/// The start index should be the first symbol in the sequence
/// @return (plp_code, the first index AFTER this symbol sequence)
pub fn compile_symbol_sequence( tokens: &Vec<Token>,
                            start: usize,
                            current_namespace: &str,
                            temp_register: &str, // indirect
                            load_registers: (&str, &str),
                            target_register: &str,
                            symbols: &StaticSymbolTable)
                            -> (String, usize)
{
    // TODO: handle array access

    let mut plp = PLPWriter::new();
    let mut index = start;
    while index < (tokens.len() - 1)
    {
        let token = &tokens[index];

        if token.name == "identifier"
        {
            let lookahead_token = &tokens[index + 1];

            // Method call
            if lookahead_token.value == "("
            {
                // compile the method and append it directly to the compiled plp code
                let (method_code, return_type, new_index) = compile_method_call(tokens, index, current_namespace, temp_register, load_registers, symbols);
                plp.code.push_str(&*method_code);
                index = new_index;
            }
            // Variable read
            else
            {
                let symbol = symbols.lookup_variable(current_namespace, &*token.value).unwrap();
                match symbol.location
                {
                    SymbolLocation::Register(name) => {
                            plp.mov(target_register, name);
                        },
                    SymbolLocation::Memory(address) => {
                            plp.li(load_registers.0, address.label_name);
                            plp.lw(target_register, address.offset, load_registers.0);
                        },
                    SymbolLocation::InstancedMemory(offset) => {
                            plp.lw(target_register, offset, target_register);
                        },
                    SymbolLocation::Structured => {
                            // TODO: append to namespace
                        },
                };

                index += 1;
            }
        }
        else if token.value == "."
        {
            // Access references are handled when it's children are parsed (in the if block above)
            // so skip this token
            index += 1;
            continue;
        }
        else
        {
            break;
        }
    }
    // first index AFTER the sequence
    index += 1;

    // TODO: compile

    (plp.code, index)
}

/// The range should start at the method identifier
/// The returned end_index will be the index AFTER the closing parenthesis
/// @return (code, return_type, end_index)
pub fn compile_method_call( tokens: &Vec<Token>,
                            start: usize,
                            current_namespace: &str,
                            arg_register: &str,
                            load_registers: (&str, &str),
                            symbols: &StaticSymbolTable)
                            -> (String, String, usize)
{
    let mut plp = PLPWriter::new();

    // start at the token AFTER the open parenthesis
    let mut index = start + 2;

    // Index OF the closing parenthesis
    let end_index = identify_body_bounds(&tokens, index, ("(", ")")).unwrap();

    // TODO: Keep track of argument types, in order, to determine the method signature
    let mut argument_types: Vec<String> = Vec::new();

    while index < end_index
    {
        let token = &tokens[index];
        if token.value == "("
        {
            panic!("Parenthesis surrounding expression currently unsupported");
        }
        else if token.value == ","
        {
            // Skip commas, arguments are separated by the stack divisors
            index += 1;
            continue;
        }
        else
        {
            // Load argument into arg_register
            let (code, argument_type, new_index) = compile_arithmetic_statement(tokens, index, current_namespace, "$t9", load_registers, arg_register, symbols);
            plp.code.push_str(&*code);
            index = new_index;

            // Push argument_type to argument_types
            argument_types.push(argument_type.clone());

            // Push argument to the stack
            plp.push(arg_register);
        }
    }

    // Find nested method calls
    // Handle each argument one at a time, and push each to the stack

    // TODO: determine namespace from caller and current_namespace
    let namespace = "";

    let id_token = &tokens[start];
    let method_name = &*id_token.value;
    // TODO: determine if method is static
    // TODO: if function is non-static, push $this to stack

    let method_symbol = symbols.lookup_function(namespace, method_name, &argument_types).unwrap();
    let return_type = match method_symbol.symbol_class
    {
        SymbolClass::Variable(variable_type) => {
                panic!("Expected Function found Variable");
            },
        SymbolClass::Function(return_type, argument_types) => return_type,
        SymbolClass::Structure(subtype) => {
                panic!("Expected Function found Structure");
            }
    };
    match method_symbol.location
    {
        SymbolLocation::Register(name) => {
                panic!("Found method at a Register instead of a constant Memory address");
            },
        SymbolLocation::Memory(address) => {
                plp.call(address.label_name);
            },
        SymbolLocation::InstancedMemory(offset) => {
                panic!("Found method at InstancedMemory instead of a constant Memory address");
            },
        SymbolLocation::Structured => {
                // TODO: call constructor
                panic!("Constructors currently unsupported");
            },
    };

    //Return index AFTER the closing parenthesis
    return (plp.code, return_type.to_string(), end_index + 1);
}

/// @return (code, result_type, end_index)
pub fn compile_arithmetic_statement(tokens: &Vec<Token>,            // used
	                                start: usize,                   // used
	                                current_namespace: &str,        // indirect
	                                temp_register: &str,   			// used
	                                load_registers: (&str, &str),	// indirect
	                                target_register: &str,			// used
	                                symbols: &StaticSymbolTable)	// indirect
	                                -> (String, String, usize)
{
    // TODO: handle parenthesis
    // TODO: handle order of operations
    let mut plp = PLPWriter::new();

    // Evaluate first symbol and store it in target_register, then push the result to the stack
    let mut index = compile_evaluation(tokens, start, current_namespace, temp_register, load_registers, target_register, symbols, &mut plp);
	plp.push(target_register);

    // loop until arithmetic sequence ends
	let operator_token = &tokens[index];
    if operator_token.name.starts_with("operator")
    {
        // PRESUMPTION: The first operand is at the top of the stack

        // Evaluate the second operand and store the result in temp_register
        let (code, operand_type, new_index) = compile_arithmetic_statement(tokens, index + 1, current_namespace, temp_register, load_registers, temp_register, symbols);
		index = new_index;
		plp.code.push_str(&*code);

		// Retreive the first operand from the stack and store it in target_register
		plp.pop(target_register);

        // Perform the operation on the first (target_register) and second operand (temp_register) and store the result in target_register
        let code = compile_arithmetic_operation(&operator_token, (target_register, temp_register), target_register);
		plp.code.push_str(&*code);
    }

    // TODO: determine real type instead of "Number"
    (plp.code, "Number".to_string(),index)
}

/// Evaluates either a literal, or a sequence of symbols (variables, accessors, method calls, etc)
///
/// Writes to the specified PLPWriter code to evaluate a value triggered by the start token
/// If the token is a literal, the literal value will be loaded into the target_register
/// If the token is an identifier, it will be evaluated based on what the symbol represents
/// * If the symbol represents a method, the method will be called and the result stored in target_register
/// * If the symbol represents a variable, or a chain of accessors, the sequence will be evaluated and the result stored in target_register
///
/// This method will compile plp code directly to a PLPWriter as specified
///
/// @return
pub fn compile_evaluation(  tokens: &Vec<Token>,            // used
                            start: usize,                   // used
                            current_namespace: &str,        // indirect-------------
                            temp_register: &str,            // used
                            load_registers: (&str, &str),   // indirect-------------
                            target_register: &str,          // used
                            symbols: &StaticSymbolTable,    // indirect-------------
                            plp: &mut PLPWriter)            // used
                            -> usize
{
    let mut token = &tokens[start];
    let mut end_index = start;

    if token.name.starts_with("literal")
    {
        let value = &*token.value;
        plp.li(target_register, value);

        end_index += 1;
    }
    else if token.name == "identifier"
    {
        // handle identifier
        let (access_code, new_index) = compile_symbol_sequence(tokens, start, current_namespace, temp_register, load_registers, target_register, symbols);
        plp.code.push_str(&*access_code);

        end_index = new_index;
    }
    else if token.value == "("
    {
        // TODO: find end bounds and evaluate parenthetical expression
        panic!("Unexpected token: {}\t{}", token.name, token.value);
    }
    else
    {
        panic!("Unexpected token: {}\t{}", token.name, token.value);
    }

    end_index
}

/// Writes plp code to perform a binary operation on two registers, and store the result in a third register
/// The specified registers need not be unique, and may all be the same if desired
/// This method performs only a single operation, and does not check for register validity
/// The register arguments are assumed to be prefaced with '$'
pub fn compile_arithmetic_operation(operator: &Token, operand_registers: (&str, &str), result_register: &str) -> String
{
    let mut plp = PLPWriter::new();

    match &*operator.value
    {
        "+" => plp.addu(result_register, operand_registers.0, operand_registers.1),
        "-" => plp.subu(result_register, operand_registers.0, operand_registers.1),
        "*" => plp.mullo(result_register, operand_registers.0, operand_registers.1),
         _  => panic!("Unsupported operator: {}: {}", operator.name, operator.value)
    };

    return plp.code;
}
<commit_msg>Handle parenthetical operations<commit_after>use std::vec::Vec;
use tokens::*;
use lexer::*;
use symbol_table::*;
use support::*;
use plp::PLPWriter;

pub fn compile_class(tokens: &Vec<Token>, start_index: usize) -> (usize, String)
{
    let invalid_types = get_invalid_token_types();
    let invalid_values = get_invalid_token_values();

    let mut plp_string: String = String::new();
    let mut current_index: usize = start_index;

    if tokens[current_index].value != "{" { panic!("Expected '{{' received: {}", tokens[current_index].value); }
    else { current_index += 1; }

    for (index, token) in tokens.iter().enumerate()
    {
        // Handle forward skipping
        if index < current_index { continue; }
        else { current_index = index; }

        // TODO: encapsulate into token_rules.validate(token)
        // Panic! if token type is invalid
        if invalid_types.contains(&token.name)
        {
            panic!("Unsupported token type: {}", token.name);
        }
        // Panic! if token value is invalid
        else if invalid_values.contains(&&*token.value)
        {
            panic!("Unsupported token value: {}", token.value);
        }

        if token.value == "class"
        {
            // parse class body
            let (end_index, compiled_class) = compile_class(&tokens, index + 1);
            plp_string.push_str(&*compiled_class);

            current_index = end_index;
        }
        else if token.name == "type" // || token.name == "identifier"
        {
            // look ahead
            // parse variable declaration
            // OR parse method declaration
        }
        else if token.value == "if"
        {
            // parse if body
            // Unsupported for now
        }
        else if token.name == "construct.conditional"
        {
            // parse conditional
            // Unsupported for now
        }
        else
        {
            panic!("Unexpected token: {}\t{}", token.name, token.value);
        }
    }

    (current_index + 1, plp_string)
}

/// Write PLP code to evaluate the given symbol sequence, and load the result into a specific register
/// A sequence can be:
/// * a  simple variable reference,
/// * a method call,
/// * a variable accessed from another symbol (e.g. foo.bar or Foo.staticBar),
/// * a method accessed from another symbol (e.g. foo.bar() or Foo.staticBar()), or
/// * a complex chain of the above (e.g. foo.method().valueInReturnValue.value.method())
///
/// The start index should be the first symbol in the sequence
/// @return (plp_code, the first index AFTER this symbol sequence)
pub fn compile_symbol_sequence( tokens: &Vec<Token>,
                            start: usize,
                            current_namespace: &str,
                            temp_register: &str, // indirect
                            load_registers: (&str, &str),
                            target_register: &str,
                            symbols: &StaticSymbolTable)
                            -> (String, usize)
{
    // TODO: handle array access

    // TODO: push $this to stack

    let mut plp = PLPWriter::new();
    let mut index = start;
    while index < (tokens.len() - 1)
    {
        let token = &tokens[index];

        // PRESUMPTION: there is a reference on the stack, unless this is the first symbol AND the scope is static
        if token.name == "identifier"
        {
            let lookahead_token = &tokens[index + 1];

            // Method call
            if lookahead_token.value == "("
            {
                // compile the method and append it directly to the compiled plp code
                let (method_code, return_type, new_index) = compile_method_call(tokens, index, current_namespace, temp_register, load_registers, symbols);
                plp.code.push_str(&*method_code);
                index = new_index;

                // TODO: pop previous reference from stack
                // TODO: if next token is "." then push value to stack
            }
            // Variable read
            else
            {
                let symbol = symbols.lookup_variable(current_namespace, &*token.value).unwrap();
                match symbol.location
                {
                    SymbolLocation::Register(name) => {
                            plp.mov(target_register, name);
                        },
                    SymbolLocation::Memory(address) => {
                            plp.li(load_registers.0, address.label_name);
                            plp.lw(target_register, address.offset, load_registers.0);
                        },
                    SymbolLocation::InstancedMemory(offset) => {
                            plp.lw(target_register, offset, target_register);
                        },
                    SymbolLocation::Structured => {
                            // TODO: append to namespace
                        },
                };

                // TODO: pop previous reference from stack
                // TODO: if next token is "." then push value to stack

                index += 1;
            }
        }
        else if token.value == "."
        {
            // Access references are handled when it's children are parsed (in the if block above)
            // so skip this token
            index += 1;
            continue;
        }
        else
        {
            break;
        }
    }
    // first index AFTER the sequence
    index += 1;

    (plp.code, index)
}

/// The range should start at the method identifier
/// The returned end_index will be the index AFTER the closing parenthesis
/// @return (code, return_type, end_index)
pub fn compile_method_call( tokens: &Vec<Token>,
                            start: usize,
                            current_namespace: &str,
                            arg_register: &str,
                            load_registers: (&str, &str),
                            symbols: &StaticSymbolTable)
                            -> (String, String, usize)
{
    let mut plp = PLPWriter::new();

    // start at the token AFTER the open parenthesis
    let mut index = start + 2;

    // Index OF the closing parenthesis
    let end_index = identify_body_bounds(&tokens, index, ("(", ")")).unwrap();

    // TODO: Keep track of argument types, in order, to determine the method signature
    let mut argument_types: Vec<String> = Vec::new();

    while index < end_index
    {
        let token = &tokens[index];
        if token.value == "("
        {
            panic!("Parenthesis surrounding expression currently unsupported");
        }
        else if token.value == ","
        {
            // Skip commas, arguments are separated by the stack divisors
            index += 1;
            continue;
        }
        else
        {
            // Load argument into arg_register
            let (code, argument_type, new_index) = compile_arithmetic_statement(tokens, index, current_namespace, "$t9", load_registers, arg_register, symbols);
            plp.code.push_str(&*code);
            index = new_index;

            // Push argument_type to argument_types
            argument_types.push(argument_type.clone());

            // Push argument to the stack
            plp.push(arg_register);
        }
    }

    // Find nested method calls
    // Handle each argument one at a time, and push each to the stack

    // TODO: determine namespace from caller and current_namespace
    let namespace = "";

    let id_token = &tokens[start];
    let method_name = &*id_token.value;
    // TODO: determine if method is static
    // TODO: if function is non-static, push $this to stack

    let method_symbol = symbols.lookup_function(namespace, method_name, &argument_types).unwrap();
    let return_type = match method_symbol.symbol_class
    {
        SymbolClass::Variable(variable_type) => {
                panic!("Expected Function found Variable");
            },
        SymbolClass::Function(return_type, argument_types) => return_type,
        SymbolClass::Structure(subtype) => {
                panic!("Expected Function found Structure");
            }
    };
    match method_symbol.location
    {
        SymbolLocation::Register(name) => {
                panic!("Found method at a Register instead of a constant Memory address");
            },
        SymbolLocation::Memory(address) => {
                plp.call(address.label_name);
            },
        SymbolLocation::InstancedMemory(offset) => {
                panic!("Found method at InstancedMemory instead of a constant Memory address");
            },
        SymbolLocation::Structured => {
                // TODO: call constructor
                panic!("Constructors currently unsupported");
            },
    };

    //Return index AFTER the closing parenthesis
    return (plp.code, return_type.to_string(), end_index + 1);
}

/// @return (code, result_type, end_index)
pub fn compile_arithmetic_statement(tokens: &Vec<Token>,            // used
	                                start: usize,                   // used
	                                current_namespace: &str,        // indirect
	                                temp_register: &str,   			// used
	                                load_registers: (&str, &str),	// indirect
	                                target_register: &str,			// used
	                                symbols: &StaticSymbolTable)	// indirect
	                                -> (String, String, usize)
{
    // TODO: handle order of operations
    let mut plp = PLPWriter::new();
    let first_token = &tokens[start];

    if first_token.value == "("
    {
        let (code, result_type, end_index) = compile_arithmetic_statement(tokens, start + 1, current_namespace, temp_register, load_registers, temp_register, symbols);
        // Return index AFTER closing parenthesis
        return (code, result_type, end_index + 1);
    }
    else
    {
        // Evaluate first symbol and store it in target_register, then push the result to the stack
        let mut index = compile_evaluation(tokens, start, current_namespace, temp_register, load_registers, target_register, symbols, &mut plp);
    	plp.push(target_register);

        // loop until arithmetic sequence ends
    	let operator_token = &tokens[index];
        if operator_token.name.starts_with("operator")
        {
            // PRESUMPTION: The first operand is at the top of the stack

            // Evaluate the second operand and store the result in temp_register
            let (code, operand_type, new_index) = compile_arithmetic_statement(tokens, index + 1, current_namespace, temp_register, load_registers, temp_register, symbols);
    		index = new_index;
    		plp.code.push_str(&*code);

    		// Retreive the first operand from the stack and store it in target_register
    		plp.pop(target_register);

            // Perform the operation on the first (target_register) and second operand (temp_register) and store the result in target_register
            let code = compile_arithmetic_operation(&operator_token, (target_register, temp_register), target_register);
    		plp.code.push_str(&*code);

            // push the value to the stack, for the next operand
            plp.push(target_register);
        }

        // Load the final result into target_register
        plp.pop(target_register);

        // TODO: determine real type instead of "Number"
        return (plp.code, "Number".to_string(),index);
    }
}

/// Evaluates either a literal, or a sequence of symbols (variables, accessors, method calls, etc)
///
/// Writes to the specified PLPWriter code to evaluate a value triggered by the start token
/// If the token is a literal, the literal value will be loaded into the target_register
/// If the token is an identifier, it will be evaluated based on what the symbol represents
/// * If the symbol represents a method, the method will be called and the result stored in target_register
/// * If the symbol represents a variable, or a chain of accessors, the sequence will be evaluated and the result stored in target_register
///
/// This method will compile plp code directly to a PLPWriter as specified
///
/// @return
pub fn compile_evaluation(  tokens: &Vec<Token>,            // used
                            start: usize,                   // used
                            current_namespace: &str,        // indirect-------------
                            temp_register: &str,            // used
                            load_registers: (&str, &str),   // indirect-------------
                            target_register: &str,          // used
                            symbols: &StaticSymbolTable,    // indirect-------------
                            plp: &mut PLPWriter)            // used
                            -> usize
{
    let mut token = &tokens[start];
    let mut end_index = start;

    if token.name.starts_with("literal")
    {
        let value = &*token.value;
        plp.li(target_register, value);

        end_index += 1;
    }
    else if token.name == "identifier"
    {
        // handle identifier
        let (access_code, new_index) = compile_symbol_sequence(tokens, start, current_namespace, temp_register, load_registers, target_register, symbols);
        plp.code.push_str(&*access_code);

        end_index = new_index;
    }
    else if token.value == "("
    {
        // TODO: find end bounds and evaluate parenthetical expression
        panic!("Unexpected token: {}\t{}", token.name, token.value);
    }
    else
    {
        panic!("Unexpected token: {}\t{}", token.name, token.value);
    }

    end_index
}

/// Writes plp code to perform a binary operation on two registers, and store the result in a third register
/// The specified registers need not be unique, and may all be the same if desired
/// This method performs only a single operation, and does not check for register validity
/// The register arguments are assumed to be prefaced with '$'
pub fn compile_arithmetic_operation(operator: &Token, operand_registers: (&str, &str), result_register: &str) -> String
{
    let mut plp = PLPWriter::new();

    match &*operator.value
    {
        "+" => plp.addu(result_register, operand_registers.0, operand_registers.1),
        "-" => plp.subu(result_register, operand_registers.0, operand_registers.1),
        "*" => plp.mullo(result_register, operand_registers.0, operand_registers.1),
         _  => panic!("Unsupported operator: {}: {}", operator.name, operator.value)
    };

    return plp.code;
}
<|endoftext|>


<commit_before>use ast::node::Node;
use sass::rule::SassRule;
use error::Result;

use std::io::Write;

pub trait Streamable {
    fn stream(&self, output: &mut Write, style: &SassOutputStyle)
             -> Result<()>;
}

pub trait SassOutputStyle {
    fn rule_separator(&self) -> String {
        String::from("\n\n")
    }

    fn selector_separator(&self) -> String {
        String::from(", ")
    }

    fn selector_string(&self, rule: &SassRule, parents: &str) -> String {
        let separator = self.selector_separator();
        if parents.is_empty() {
            rule.selectors.iter()
                          .map(|s| s.token.to_string())
                          .collect::<Vec<_>>().join(&separator)
        } else {
            parents.split(",").map(|p| {
                rule.selectors.iter().map(|s| {
                    if s.token.to_string().contains("&") {
                        s.token.to_string().replace("&", p.trim())
                    } else {
                        format!("{} {}", p.trim(), s.token)
                    }
                }).collect::<Vec<_>>().join(&separator)
            }).collect::<Vec<_>>().join(&separator)
        }
    }

    fn selector_brace_separator(&self) -> String {
        String::from(" ")
    }

    fn brace_property_separator(&self) -> String {
        String::from("")
    }

    fn before_property(&self, _nesting: &str) -> String {
        String::from("\n")
    }

    fn after_property(&self) -> String {
        String::from("")
    }

    fn property_brace_separator(&self) -> String {
        String::from("")
    }

    fn rule_and_child_rules_separator(&self, _nesting: &str) -> String {
        String::from("")
    }

    fn child_rule_separator(&self, _has_properties: bool) -> String {
        String::from("\n")
    }

    fn property(&self, name: &str, value: &str) -> String {
        format!("  {}: {};", name, value)
    }

    fn before_comment(&self) -> String {
        String::new()
    }

    fn comment(&self, content: &str) -> String {
        String::from(content)
    }

    fn after_comment(&self) -> String {
        String::from("\n")
    }

    fn filter_child_properties<'a>(&self, children: &[Node])
       -> Vec<Node> {
        children.iter().cloned().collect()
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Expanded {}

impl SassOutputStyle for Expanded {
    fn brace_property_separator(&self) -> String {
        String::from("")
    }

    fn property_brace_separator(&self) -> String {
        String::from("\n")
    }

    fn rule_and_child_rules_separator(&self, _nesting: &str) -> String {
        String::from("\n")
    }

    fn before_comment(&self) -> String {
        String::from("  ")
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Nested {}

impl SassOutputStyle for Nested {
    fn brace_property_separator(&self) -> String {
        String::from("\n")
    }

    fn before_property(&self, nesting: &str) -> String {
        String::from(nesting)
    }

    fn after_property(&self) -> String {
        String::from("\n")
    }

    fn property_brace_separator(&self) -> String {
        String::from(" ")
    }

    fn rule_and_child_rules_separator(&self, nesting: &str) -> String {
        format!("\n{}", nesting)
    }

    fn child_rule_separator(&self, has_properties: bool) -> String {
        if has_properties {
            String::from("\n  ")
        } else {
            String::from("\n")
        }
    }

    fn before_comment(&self) -> String {
        String::from("  ")
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Compact {}

impl SassOutputStyle for Compact {
    fn brace_property_separator(&self) -> String {
        String::from(" ")
    }

    fn before_property(&self, _nesting: &str) -> String {
        String::from("")
    }

    fn after_property(&self) -> String {
        String::from(" ")
    }

    fn property_brace_separator(&self) -> String {
        String::from(" ")
    }

    fn rule_and_child_rules_separator(&self, _nesting: &str) -> String {
        String::from("\n")
    }

    fn property(&self, name: &str, value: &str) -> String {
        format!("{}: {};", name, value)
    }

    fn comment(&self, content: &str) -> String {
        String::from(content.lines()
                            .map(|s| s.trim())
                            .collect::<Vec<_>>()
                            .join(" "))
    }

}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Compressed {}

impl SassOutputStyle for Compressed {
    fn rule_separator(&self) -> String {
        String::from("")
    }

    fn selector_separator(&self) -> String {
        String::from(",")
    }

    fn selector_brace_separator(&self) -> String {
        String::from("")
    }

    fn before_property(&self, _nesting: &str) -> String {
        String::from("")
    }

    fn after_property(&self) -> String {
        String::from(";")
    }

    fn child_rule_separator(&self, _has_properties: bool) -> String {
        String::from("")
    }

    fn property(&self, name: &str, value: &str) -> String {
        format!("{}:{}", name, value)
    }

    fn comment(&self, _content: &str) -> String {
        String::new()
    }

    fn after_comment(&self) -> String {
        String::new()
    }

    fn selector_string(&self, rule: &SassRule, parents: &str) -> String {
        let separator: String = self.selector_separator();
        let s = if parents.is_empty() {
            rule.selectors.iter()
                          .map(|s| s.token.to_string())
                          .collect::<Vec<_>>().join(&separator)
        } else {
            parents.split(",").map(|p| {
                rule.selectors.iter().map(|s| {
                    if s.token.to_string().contains("&") {
                        s.token.to_string().replace("&", p.trim())
                    } else {
                        format!("{} {}", p.trim(), s.token)
                    }
                }).collect::<Vec<_>>().join(&separator)
            }).collect::<Vec<_>>().join(&separator)
        };
        self.compress_selectors(s)
    }

    fn filter_child_properties(&self, children: &[Node])
       -> Vec<Node> {
        children.iter().filter(|p|
            match **p {
                Node::Comment(..) => false,
                _ => true,
            }
        ).cloned().collect()
    }
}

impl Compressed {
    fn compress_selectors(&self, selector_string: String) -> String {
        selector_string.replace(" > ", ">").replace(" + ", "+")
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Debug {}

impl SassOutputStyle for Debug {
    fn property(&self, name: &str, value: &str) -> String {
        format!("Property({}, {})", name, value)
    }
}
<commit_msg>omg i do need to filter here<commit_after>use ast::node::Node;
use sass::rule::SassRule;
use error::Result;

use std::io::Write;

pub trait Streamable {
    fn stream(&self, output: &mut Write, style: &SassOutputStyle)
             -> Result<()>;
}

pub trait SassOutputStyle {
    fn rule_separator(&self) -> String {
        String::from("\n\n")
    }

    fn selector_separator(&self) -> String {
        String::from(", ")
    }

    fn selector_string(&self, rule: &SassRule, parents: &str) -> String {
        let separator = self.selector_separator();
        if parents.is_empty() {
            rule.selectors.iter()
                          .map(|s| s.token.to_string())
                          .collect::<Vec<_>>().join(&separator)
        } else {
            parents.split(",").map(|p| {
                rule.selectors.iter().map(|s| {
                    if s.token.to_string().contains("&") {
                        s.token.to_string().replace("&", p.trim())
                    } else {
                        format!("{} {}", p.trim(), s.token)
                    }
                }).collect::<Vec<_>>().join(&separator)
            }).collect::<Vec<_>>().join(&separator)
        }
    }

    fn selector_brace_separator(&self) -> String {
        String::from(" ")
    }

    fn brace_property_separator(&self) -> String {
        String::from("")
    }

    fn before_property(&self, _nesting: &str) -> String {
        String::from("\n")
    }

    fn after_property(&self) -> String {
        String::from("")
    }

    fn property_brace_separator(&self) -> String {
        String::from("")
    }

    fn rule_and_child_rules_separator(&self, _nesting: &str) -> String {
        String::from("")
    }

    fn child_rule_separator(&self, _has_properties: bool) -> String {
        String::from("\n")
    }

    fn property(&self, name: &str, value: &str) -> String {
        format!("  {}: {};", name, value)
    }

    fn before_comment(&self) -> String {
        String::new()
    }

    fn comment(&self, content: &str) -> String {
        String::from(content)
    }

    fn after_comment(&self) -> String {
        String::from("\n")
    }

    fn filter_child_properties<'a>(&self, children: &[Node])
       -> Vec<Node> {
        children.iter().filter(|c|
            match **c {
                Node::Rule(..)     => false,
                Node::Comment(..)  => true,
                Node::Property(..) => true,
                Node::Variable(..) => true,
            }
        ).cloned().collect()
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Expanded {}

impl SassOutputStyle for Expanded {
    fn brace_property_separator(&self) -> String {
        String::from("")
    }

    fn property_brace_separator(&self) -> String {
        String::from("\n")
    }

    fn rule_and_child_rules_separator(&self, _nesting: &str) -> String {
        String::from("\n")
    }

    fn before_comment(&self) -> String {
        String::from("  ")
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Nested {}

impl SassOutputStyle for Nested {
    fn brace_property_separator(&self) -> String {
        String::from("\n")
    }

    fn before_property(&self, nesting: &str) -> String {
        String::from(nesting)
    }

    fn after_property(&self) -> String {
        String::from("\n")
    }

    fn property_brace_separator(&self) -> String {
        String::from(" ")
    }

    fn rule_and_child_rules_separator(&self, nesting: &str) -> String {
        format!("\n{}", nesting)
    }

    fn child_rule_separator(&self, has_properties: bool) -> String {
        if has_properties {
            String::from("\n  ")
        } else {
            String::from("\n")
        }
    }

    fn before_comment(&self) -> String {
        String::from("  ")
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Compact {}

impl SassOutputStyle for Compact {
    fn brace_property_separator(&self) -> String {
        String::from(" ")
    }

    fn before_property(&self, _nesting: &str) -> String {
        String::from("")
    }

    fn after_property(&self) -> String {
        String::from(" ")
    }

    fn property_brace_separator(&self) -> String {
        String::from(" ")
    }

    fn rule_and_child_rules_separator(&self, _nesting: &str) -> String {
        String::from("\n")
    }

    fn property(&self, name: &str, value: &str) -> String {
        format!("{}: {};", name, value)
    }

    fn comment(&self, content: &str) -> String {
        String::from(content.lines()
                            .map(|s| s.trim())
                            .collect::<Vec<_>>()
                            .join(" "))
    }

}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Compressed {}

impl SassOutputStyle for Compressed {
    fn rule_separator(&self) -> String {
        String::from("")
    }

    fn selector_separator(&self) -> String {
        String::from(",")
    }

    fn selector_brace_separator(&self) -> String {
        String::from("")
    }

    fn before_property(&self, _nesting: &str) -> String {
        String::from("")
    }

    fn after_property(&self) -> String {
        String::from(";")
    }

    fn child_rule_separator(&self, _has_properties: bool) -> String {
        String::from("")
    }

    fn property(&self, name: &str, value: &str) -> String {
        format!("{}:{}", name, value)
    }

    fn comment(&self, _content: &str) -> String {
        String::new()
    }

    fn after_comment(&self) -> String {
        String::new()
    }

    fn selector_string(&self, rule: &SassRule, parents: &str) -> String {
        let separator: String = self.selector_separator();
        let s = if parents.is_empty() {
            rule.selectors.iter()
                          .map(|s| s.token.to_string())
                          .collect::<Vec<_>>().join(&separator)
        } else {
            parents.split(",").map(|p| {
                rule.selectors.iter().map(|s| {
                    if s.token.to_string().contains("&") {
                        s.token.to_string().replace("&", p.trim())
                    } else {
                        format!("{} {}", p.trim(), s.token)
                    }
                }).collect::<Vec<_>>().join(&separator)
            }).collect::<Vec<_>>().join(&separator)
        };
        self.compress_selectors(s)
    }

    fn filter_child_properties(&self, children: &[Node])
       -> Vec<Node> {
        children.iter().filter(|p|
            match **p {
                Node::Comment(..) => false,
                _ => true,
            }
        ).cloned().collect()
    }
}

impl Compressed {
    fn compress_selectors(&self, selector_string: String) -> String {
        selector_string.replace(" > ", ">").replace(" + ", "+")
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Debug {}

impl SassOutputStyle for Debug {
    fn property(&self, name: &str, value: &str) -> String {
        format!("Property({}, {})", name, value)
    }
}
<|endoftext|>


<commit_before>use bytes::BytesMut;

use asnom::common::TagClass;
use asnom::IResult;
use asnom::parse::{parse_uint, parse_tag};
use asnom::structure::{PL, StructureTag};
use asnom::structures::{ASNTag, Boolean, Integer, OctetString, Sequence, Tag};
use asnom::universal::Types;
use asnom::write;

#[derive(Clone, Debug)]
pub struct RawControl {
    ctype: String,
    crit: bool,
    val: Option<Vec<u8>>,
}

#[derive(Clone, Debug)]
pub struct PagedResults {
    size: i32,
    cookie: Vec<u8>,
}

impl PagedResults {
    pub fn req(size: i32, cookie: &[u8], crit: bool) -> StructureTag {
        let cval = Tag::Sequence(Sequence {
            inner: vec![
                Tag::Integer(Integer {
                    inner: size as i64,
                    .. Default::default()
                }),
                Tag::OctetString(OctetString {
                    inner: Vec::from(cookie),
                    .. Default::default()
                }),
            ],
            .. Default::default()
        }).into_structure();
        let mut buf = BytesMut::with_capacity(cookie.len() + 16);
        write::encode_into(&mut buf, cval).expect("encoded");
        construct_control("1.2.840.113556.1.4.319", crit, Some(Vec::from(&buf[..])))
    }
}

#[derive(Clone, Debug)]
pub enum Control {
    PagedResults(PagedResults, bool),
    Raw(RawControl),
}

pub fn construct_control(oid: &str, crit: bool, val: Option<Vec<u8>>) -> StructureTag {
    let mut seq = vec![
        Tag::OctetString(OctetString {
            inner: Vec::from(oid.as_bytes()),
            .. Default::default()
        })
    ];
    if crit {
        seq.push(Tag::Boolean(Boolean {
            inner: true,
            .. Default::default()
        }));
    }
    if let Some(val) = val {
        seq.push(Tag::OctetString(OctetString {
            inner: val,
            .. Default::default()
        }));
    }
    Tag::Sequence(Sequence {
        inner: seq,
        .. Default::default()
    }).into_structure()
}

pub fn parse_controls(t: StructureTag) -> Vec<Control> {
    let tags = t.expect_constructed().expect("result sequence").into_iter();
    let mut ctrls = Vec::new();
    for ctrl in tags {
        let mut components = ctrl.expect_constructed().expect("components").into_iter();
        let ctype = String::from_utf8(components.next().expect("element").expect_primitive().expect("octet string")).expect("control type");
        let next = components.next();
        let (crit, maybe_val) = match next {
            None => (false, None),
            Some(c) => match c {
                StructureTag { id, class: _, ref payload } if id == Types::Boolean as u64 => match *payload {
                    PL::P(ref v) => (v[0] != 0, components.next()),
                    PL::C(_) => panic!("decoding error"),
                },
                StructureTag { id, class: _, payload: _ } if id == Types::OctetString as u64 => (false, Some(c.clone())),
                _ => panic!("decoding error"),
            },
        };
        let val = match maybe_val {
            None => None,
            Some(v) => Some(Vec::from(v.expect_primitive().expect("octet string"))),
        };
        let parsed = match &*ctype {
            "1.2.840.113556.1.4.319" => {
                let mut pr_comps = match parse_tag(val.expect("paged results control value").as_ref()) {
                    IResult::Done(_, tag) => tag,
                    _ => panic!("failed to parse paged results value components"),
                }.expect_constructed().expect("paged results components").into_iter();
                let size = match parse_uint(pr_comps.next().expect("element")
                        .match_class(TagClass::Universal)
                        .and_then(|t| t.match_id(Types::Integer as u64))
                        .and_then(|t| t.expect_primitive()).expect("paged results size")
                        .as_slice()) {
                    IResult::Done(_, size) => size as i32,
                    _ => panic!("failed to parse size"),
                };
                let cookie = pr_comps.next().expect("element").expect_primitive().expect("octet string");
                Control::PagedResults(PagedResults { size: size, cookie: cookie }, crit)
            }
            _ => Control::Raw(RawControl { ctype: ctype, crit: crit, val: val }),
        };
        ctrls.push(parsed);
    }
    ctrls
}
<commit_msg>Fix visibility of PagedResults fields<commit_after>use bytes::BytesMut;

use asnom::common::TagClass;
use asnom::IResult;
use asnom::parse::{parse_uint, parse_tag};
use asnom::structure::{PL, StructureTag};
use asnom::structures::{ASNTag, Boolean, Integer, OctetString, Sequence, Tag};
use asnom::universal::Types;
use asnom::write;

#[derive(Clone, Debug)]
pub struct RawControl {
    ctype: String,
    crit: bool,
    val: Option<Vec<u8>>,
}

#[derive(Clone, Debug)]
pub struct PagedResults {
    pub size: i32,
    pub cookie: Vec<u8>,
}

impl PagedResults {
    pub fn req(size: i32, cookie: &[u8], crit: bool) -> StructureTag {
        let cval = Tag::Sequence(Sequence {
            inner: vec![
                Tag::Integer(Integer {
                    inner: size as i64,
                    .. Default::default()
                }),
                Tag::OctetString(OctetString {
                    inner: Vec::from(cookie),
                    .. Default::default()
                }),
            ],
            .. Default::default()
        }).into_structure();
        let mut buf = BytesMut::with_capacity(cookie.len() + 16);
        write::encode_into(&mut buf, cval).expect("encoded");
        construct_control("1.2.840.113556.1.4.319", crit, Some(Vec::from(&buf[..])))
    }
}

#[derive(Clone, Debug)]
pub enum Control {
    PagedResults(PagedResults, bool),
    Raw(RawControl),
}

pub fn construct_control(oid: &str, crit: bool, val: Option<Vec<u8>>) -> StructureTag {
    let mut seq = vec![
        Tag::OctetString(OctetString {
            inner: Vec::from(oid.as_bytes()),
            .. Default::default()
        })
    ];
    if crit {
        seq.push(Tag::Boolean(Boolean {
            inner: true,
            .. Default::default()
        }));
    }
    if let Some(val) = val {
        seq.push(Tag::OctetString(OctetString {
            inner: val,
            .. Default::default()
        }));
    }
    Tag::Sequence(Sequence {
        inner: seq,
        .. Default::default()
    }).into_structure()
}

pub fn parse_controls(t: StructureTag) -> Vec<Control> {
    let tags = t.expect_constructed().expect("result sequence").into_iter();
    let mut ctrls = Vec::new();
    for ctrl in tags {
        let mut components = ctrl.expect_constructed().expect("components").into_iter();
        let ctype = String::from_utf8(components.next().expect("element").expect_primitive().expect("octet string")).expect("control type");
        let next = components.next();
        let (crit, maybe_val) = match next {
            None => (false, None),
            Some(c) => match c {
                StructureTag { id, class: _, ref payload } if id == Types::Boolean as u64 => match *payload {
                    PL::P(ref v) => (v[0] != 0, components.next()),
                    PL::C(_) => panic!("decoding error"),
                },
                StructureTag { id, class: _, payload: _ } if id == Types::OctetString as u64 => (false, Some(c.clone())),
                _ => panic!("decoding error"),
            },
        };
        let val = match maybe_val {
            None => None,
            Some(v) => Some(Vec::from(v.expect_primitive().expect("octet string"))),
        };
        let parsed = match &*ctype {
            "1.2.840.113556.1.4.319" => {
                let mut pr_comps = match parse_tag(val.expect("paged results control value").as_ref()) {
                    IResult::Done(_, tag) => tag,
                    _ => panic!("failed to parse paged results value components"),
                }.expect_constructed().expect("paged results components").into_iter();
                let size = match parse_uint(pr_comps.next().expect("element")
                        .match_class(TagClass::Universal)
                        .and_then(|t| t.match_id(Types::Integer as u64))
                        .and_then(|t| t.expect_primitive()).expect("paged results size")
                        .as_slice()) {
                    IResult::Done(_, size) => size as i32,
                    _ => panic!("failed to parse size"),
                };
                let cookie = pr_comps.next().expect("element").expect_primitive().expect("octet string");
                Control::PagedResults(PagedResults { size: size, cookie: cookie }, crit)
            }
            _ => Control::Raw(RawControl { ctype: ctype, crit: crit, val: val }),
        };
        ctrls.push(parsed);
    }
    ctrls
}
<|endoftext|>


<commit_before>//! This module provides an oct-tree of `Cube`s, which are the basic building
//! blocks of **Bismuth**. The tree is internally comprised of `Node`s.
//! `BranchNode`s contain links to sub-trees and `LeafNode`s contain geometric
//! data associated with their respective spatial partition. However, `Node`s do
//! not contain any spatial data (origin, partition, etc.); instead, this is
//! calculated during traversals by `Cube`, which acts as a recursive view over
//! the `Node`s in the tree and provides the primary interface for interacting
//! with trees.
//!
//! Leaf `Cube`s provide the geometric and spatial data that together represent
//! the shape and layout of the game world.
//!
//! `Cube`s reference `Node`s in the tree, and abstract over the mutability of
//! those references. This module exposes the `CubeRef` and `CubeMut` type
//! definitions for immutable and mutable `Cube`s, respectively.
//!
//! Because `Cube`s reference `Node`s and `Node`s may reference other `Node`s
//! in a tree, orphan types are provided that only expose payloads and no links.
//! This is useful when collecting `Cube`s, because otherwise the references
//! into the rest of the tree would lead to aliasing. `OrphanCubeRef` and
//! `OrphanCubeMut` are the orphan analogues of `CubeRef` and `CubeMut`,
//! respectively. Orphans of course do not support indexing or traversal.
//!
//! `Root` can be used to create a new tree, and owns the root `Node`. `Root`s
//! expose `Cube`s to manipulate the tree.
//!
//! # Examples
//!
//! Subdividing and iterating over the cubes in a tree:
//!
//! ```
//! use bismuth::cube::{LogWidth, Root, Spatial};
//!
//! let mut root = Root::new(LogWidth::max_value());
//! let _ = root.to_cube_mut().subdivide();
//! for cube in root.to_cube().iter() {
//!     println!("origin: {}; width: {}",
//!              cube.partition().origin(),
//!              cube.partition().width().to_inner());
//! }
//! ```

mod edit;
mod geometry;
mod space;
mod tree;

use self::tree::{Cube, OrphanCube};

pub use self::edit::Cursor;
pub use self::geometry::{Edge, Geometry, Offset};
pub use self::space::{AABB, Axis, Direction, LogWidth, Orientation, Partition, Spatial};
pub use self::tree::{BranchNode, BranchPayload, LeafNode, LeafPayload, Node, OrphanNode, Root};

pub type CubeRef<'a> = Cube<'a, &'a Node>;
pub type CubeMut<'a> = Cube<'a, &'a mut Node>;
pub type OrphanCubeRef<'a> = OrphanCube<'a, &'a LeafPayload, &'a BranchPayload>;
pub type OrphanCubeMut<'a> = OrphanCube<'a, &'a mut LeafPayload, &'a mut BranchPayload>;

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Break up first paragraph of `cube` module docs.<commit_after>//! This module provides an oct-tree of `Cube`s, which are the basic building
//! blocks of **Bismuth**.
//!
//! The tree is internally comprised of `Node`s. `BranchNode`s contain links to
//! sub-trees and `LeafNode`s contain geometric data associated with their
//! respective spatial partition. However, `Node`s do not contain any spatial
//! data (origin, partition, etc.); instead, this is calculated during
//! traversals by `Cube`, which acts as a recursive view over the `Node`s in the
//! tree and provides the primary interface for interacting with trees.
//!
//! Leaf `Cube`s provide the geometric and spatial data that together represent
//! the shape and layout of the game world.
//!
//! `Cube`s reference `Node`s in the tree, and abstract over the mutability of
//! those references. This module exposes the `CubeRef` and `CubeMut` type
//! definitions for immutable and mutable `Cube`s, respectively.
//!
//! Because `Cube`s reference `Node`s and `Node`s may reference other `Node`s
//! in a tree, orphan types are provided that only expose payloads and no links.
//! This is useful when collecting `Cube`s, because otherwise the references
//! into the rest of the tree would lead to aliasing. `OrphanCubeRef` and
//! `OrphanCubeMut` are the orphan analogues of `CubeRef` and `CubeMut`,
//! respectively. Orphans of course do not support indexing or traversal.
//!
//! `Root` can be used to create a new tree, and owns the root `Node`. `Root`s
//! expose `Cube`s to manipulate the tree.
//!
//! # Examples
//!
//! Subdividing and iterating over the cubes in a tree:
//!
//! ```
//! use bismuth::cube::{LogWidth, Root, Spatial};
//!
//! let mut root = Root::new(LogWidth::max_value());
//! let _ = root.to_cube_mut().subdivide();
//! for cube in root.to_cube().iter() {
//!     println!("origin: {}; width: {}",
//!              cube.partition().origin(),
//!              cube.partition().width().to_inner());
//! }
//! ```

mod edit;
mod geometry;
mod space;
mod tree;

use self::tree::{Cube, OrphanCube};

pub use self::edit::Cursor;
pub use self::geometry::{Edge, Geometry, Offset};
pub use self::space::{AABB, Axis, Direction, LogWidth, Orientation, Partition, Spatial};
pub use self::tree::{BranchNode, BranchPayload, LeafNode, LeafPayload, Node, OrphanNode, Root};

pub type CubeRef<'a> = Cube<'a, &'a Node>;
pub type CubeMut<'a> = Cube<'a, &'a mut Node>;
pub type OrphanCubeRef<'a> = OrphanCube<'a, &'a LeafPayload, &'a BranchPayload>;
pub type OrphanCubeMut<'a> = OrphanCube<'a, &'a mut LeafPayload, &'a mut BranchPayload>;

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>


<commit_before>use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{BinaryHeap, HashMap};

use std::hash::Hash;

use super::visit::{EdgeRef, IntoEdges, VisitMap, Visitable};
use crate::algo::Measure;
use crate::scored::MinScored;

/// \[Generic\] Dijkstra's shortest path algorithm.
///
/// Compute the length of the shortest path from `start` to every reachable
/// node.
///
/// The graph should be `Visitable` and implement `IntoEdges`. The function
/// `edge_cost` should return the cost for a particular edge, which is used
/// to compute path costs. Edge costs must be non-negative.
///
/// If `goal` is not `None`, then the algorithm terminates once the `goal` node's
/// cost is calculated.
///
/// Returns a `HashMap` that maps `NodeId` to path cost.
/// # Example
/// ```rust
/// use petgraph::Graph;
/// use petgraph::algo::dijkstra;
/// use petgraph::prelude::*;
/// use std::collections::HashMap;
///
/// let mut graph : Graph<(),(),Directed>= Graph::new();
/// let a = graph.add_node(()); // node with no weight
/// let b = graph.add_node(());
/// let c = graph.add_node(());
/// let d = graph.add_node(());
/// let e = graph.add_node(());
/// let f = graph.add_node(());
/// let g = graph.add_node(());
/// let h = graph.add_node(());
/// // z will be in another connected component
/// let z = graph.add_node(());
///
/// graph.extend_with_edges(&[
///     (a, b),
///     (b, c),
///     (c, d),
///     (d, a),
///     (e, f),
///     (b, e),
///     (f, g),
///     (g, h),
///     (h, e)
/// ]);
/// // a ----> b ----> e ----> f
/// // ^       |       ^       |
/// // |       v       |       v
/// // d <---- c       h <---- g
///
/// let expected_res: HashMap<NodeIndex, usize> = [
///      (a, 3),
///      (b, 0),
///      (c, 1),
///      (d, 2),
///      (e, 1),
///      (f, 2),
///      (g, 3),
///      (h, 4)
///     ].iter().cloned().collect();
/// let res = dijkstra(&graph,b,None, |_| 1);
/// assert_eq!(res, expected_res);
/// // z is not inside res because there is not path from b to z.
/// ```
pub fn dijkstra<G, F, K>(
    graph: G,
    start: G::NodeId,
    goal: Option<G::NodeId>,
    mut edge_cost: F,
) -> HashMap<G::NodeId, K>
where
    G: IntoEdges + Visitable,
    G::NodeId: Eq + Hash,
    F: FnMut(G::EdgeRef) -> K,
    K: Measure + Copy,
{
    let mut visited = graph.visit_map();
    let mut scores = HashMap::new();
    //let mut predecessor = HashMap::new();
    let mut visit_next = BinaryHeap::new();
    let zero_score = K::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(zero_score, start));
    while let Some(MinScored(node_score, node)) = visit_next.pop() {
        if visited.is_visited(&node) {
            continue;
        }
        if goal.as_ref() == Some(&node) {
            break;
        }
        for edge in graph.edges(node) {
            let next = edge.target();
            if visited.is_visited(&next) {
                continue;
            }
            let mut next_score = node_score + edge_cost(edge);
            match scores.entry(next) {
                Occupied(ent) => {
                    if next_score < *ent.get() {
                        *ent.into_mut() = next_score;
                    //predecessor.insert(next.clone(), node.clone());
                    } else {
                        next_score = *ent.get();
                    }
                }
                Vacant(ent) => {
                    ent.insert(next_score);
                    //predecessor.insert(next.clone(), node.clone());
                }
            }
            visit_next.push(MinScored(next_score, next));
        }
        visited.visit(node);
    }
    scores
}
<commit_msg> Dijkstra: only add next node into the heap when needed<commit_after>use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{BinaryHeap, HashMap};

use std::hash::Hash;

use super::visit::{EdgeRef, IntoEdges, VisitMap, Visitable};
use crate::algo::Measure;
use crate::scored::MinScored;

/// \[Generic\] Dijkstra's shortest path algorithm.
///
/// Compute the length of the shortest path from `start` to every reachable
/// node.
///
/// The graph should be `Visitable` and implement `IntoEdges`. The function
/// `edge_cost` should return the cost for a particular edge, which is used
/// to compute path costs. Edge costs must be non-negative.
///
/// If `goal` is not `None`, then the algorithm terminates once the `goal` node's
/// cost is calculated.
///
/// Returns a `HashMap` that maps `NodeId` to path cost.
/// # Example
/// ```rust
/// use petgraph::Graph;
/// use petgraph::algo::dijkstra;
/// use petgraph::prelude::*;
/// use std::collections::HashMap;
///
/// let mut graph : Graph<(),(),Directed>= Graph::new();
/// let a = graph.add_node(()); // node with no weight
/// let b = graph.add_node(());
/// let c = graph.add_node(());
/// let d = graph.add_node(());
/// let e = graph.add_node(());
/// let f = graph.add_node(());
/// let g = graph.add_node(());
/// let h = graph.add_node(());
/// // z will be in another connected component
/// let z = graph.add_node(());
///
/// graph.extend_with_edges(&[
///     (a, b),
///     (b, c),
///     (c, d),
///     (d, a),
///     (e, f),
///     (b, e),
///     (f, g),
///     (g, h),
///     (h, e)
/// ]);
/// // a ----> b ----> e ----> f
/// // ^       |       ^       |
/// // |       v       |       v
/// // d <---- c       h <---- g
///
/// let expected_res: HashMap<NodeIndex, usize> = [
///      (a, 3),
///      (b, 0),
///      (c, 1),
///      (d, 2),
///      (e, 1),
///      (f, 2),
///      (g, 3),
///      (h, 4)
///     ].iter().cloned().collect();
/// let res = dijkstra(&graph,b,None, |_| 1);
/// assert_eq!(res, expected_res);
/// // z is not inside res because there is not path from b to z.
/// ```
pub fn dijkstra<G, F, K>(
    graph: G,
    start: G::NodeId,
    goal: Option<G::NodeId>,
    mut edge_cost: F,
) -> HashMap<G::NodeId, K>
where
    G: IntoEdges + Visitable,
    G::NodeId: Eq + Hash,
    F: FnMut(G::EdgeRef) -> K,
    K: Measure + Copy,
{
    let mut visited = graph.visit_map();
    let mut scores = HashMap::new();
    //let mut predecessor = HashMap::new();
    let mut visit_next = BinaryHeap::new();
    let zero_score = K::default();
    scores.insert(start, zero_score);
    visit_next.push(MinScored(zero_score, start));
    while let Some(MinScored(node_score, node)) = visit_next.pop() {
        if visited.is_visited(&node) {
            continue;
        }
        if goal.as_ref() == Some(&node) {
            break;
        }
        for edge in graph.edges(node) {
            let next = edge.target();
            if visited.is_visited(&next) {
                continue;
            }
            let next_score = node_score + edge_cost(edge);
            match scores.entry(next) {
                Occupied(ent) => {
                    if next_score < *ent.get() {
                        *ent.into_mut() = next_score;
                        visit_next.push(MinScored(next_score, next));
                        //predecessor.insert(next.clone(), node.clone());
                    }
                }
                Vacant(ent) => {
                    ent.insert(next_score);
                    visit_next.push(MinScored(next_score, next));
                    //predecessor.insert(next.clone(), node.clone());
                }
            }
        }
        visited.visit(node);
    }
    scores
}
<|endoftext|>


<commit_before>//! A [TOML]-parsing library
//!
//! This library implements a [TOML] v0.5.0 compatible parser,
//! primarily supporting the [`serde`] library for encoding/decoding
//! various types in Rust
//!
//! **NOTE:** Unlike the core `toml_edit` API, this is not format preserving but is a drop-in
//! replacement for [toml-rs](https://github.com/alexcrichton/toml-rs) for those needing both
//! `toml_edit` and `toml-rs` but want either consistency in behavior or to reduce their
//! dependencies.
//!
//! TOML itself is a simple, ergonomic, and readable configuration format:
//!
//! ```toml
//! [package]
//! name = "toml"
//! version = "0.4.2"
//! authors = ["Alex Crichton <alex@alexcrichton.com>"]
//!
//! [dependencies]
//! serde = "1.0"
//! ```
//!
//! The TOML format tends to be relatively common throughout the Rust community
//! for configuration, notably being used by [Cargo], Rust's package manager.
//!
//! ## TOML values
//!
//! A value in TOML is represented with the [`Value`] enum in this crate.
//!
//! TOML is similar to JSON with the notable addition of a [`Datetime`]
//! type. In general, TOML and JSON are interchangeable in terms of
//! formats.
//!
//! ## Parsing TOML
//!
//! The easiest way to parse a TOML document is via the [`Value`] type:
//!
//! ```rust
//! use toml_edit::easy::Value;
//!
//! let value = "foo = 'bar'".parse::<Value>().unwrap();
//!
//! assert_eq!(value["foo"].as_str(), Some("bar"));
//! ```
//!
//! The [`Value`] type implements a number of convenience methods and
//! traits; the example above uses [`FromStr`] to parse a [`str`] into a
//! [`Value`].
//!
//! ## Deserialization and Serialization
//!
//! This crate supports [`serde`] 1.0 with a number of
//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and
//! `Serializer` traits. Namely, you'll find:
//!
//! * `Deserialize for Value`
//! * `Serialize for Value`
//! * `Deserialize for Datetime`
//! * `Serialize for Datetime`
//! * `Deserializer for de::Deserializer`
//! * `Serializer for ser::Serializer`
//! * `Deserializer for Value`
//!
//! This means that you can use Serde to deserialize/serialize the
//! [`Value`] type as well as the [`Datetime`] type in this crate. You can also
//! use the [`Deserializer`], [`Serializer`], or [`Value`] type itself to act as
//! a deserializer/serializer for arbitrary types.
//!
//! An example of deserializing with TOML is:
//!
//! ```rust
//! use serde::Deserialize;
//!
//! #[derive(Deserialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Deserialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! let config: Config = toml_edit::easy::from_str(r#"
//!     ip = '127.0.0.1'
//!
//!     [keys]
//!     github = 'xxxxxxxxxxxxxxxxx'
//!     travis = 'yyyyyyyyyyyyyyyyy'
//! "#).unwrap();
//!
//! assert_eq!(config.ip, "127.0.0.1");
//! assert_eq!(config.port, None);
//! assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx");
//! assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy");
//! ```
//!
//! You can serialize types in a similar fashion:
//!
//! ```rust
//! use serde::Serialize;
//!
//! #[derive(Serialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Serialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! let config = Config {
//!     ip: "127.0.0.1".to_string(),
//!     port: None,
//!     keys: Keys {
//!         github: "xxxxxxxxxxxxxxxxx".to_string(),
//!         travis: Some("yyyyyyyyyyyyyyyyy".to_string()),
//!     },
//! };
//!
//! let toml = toml_edit::easy::to_string(&config).unwrap();
//! ```
//!
//! [TOML]: https://github.com/toml-lang/toml
//! [Cargo]: https://crates.io/
//! [`serde`]: https://serde.rs/

mod datetime;

#[doc(hidden)]
pub mod macros;
pub mod map;
pub mod value;

pub use crate::de;
pub use crate::ser;
pub use crate::toml;
#[doc(no_inline)]
pub use de::{from_document, from_slice, from_str, Deserializer};
#[doc(no_inline)]
pub use ser::{to_document, to_string, to_string_pretty, to_vec, Serializer};
#[doc(no_inline)]
pub use value::Value;
<commit_msg>docs: Fix links<commit_after>//! A [TOML]-parsing library
//!
//! This library implements a [TOML] v0.5.0 compatible parser,
//! primarily supporting the [`serde`] library for encoding/decoding
//! various types in Rust
//!
//! **NOTE:** Unlike the core `toml_edit` API, this is not format preserving but is a drop-in
//! replacement for [toml-rs](https://github.com/alexcrichton/toml-rs) for those needing both
//! `toml_edit` and `toml-rs` but want either consistency in behavior or to reduce their
//! dependencies.
//!
//! TOML itself is a simple, ergonomic, and readable configuration format:
//!
//! ```toml
//! [package]
//! name = "toml"
//! version = "0.4.2"
//! authors = ["Alex Crichton <alex@alexcrichton.com>"]
//!
//! [dependencies]
//! serde = "1.0"
//! ```
//!
//! The TOML format tends to be relatively common throughout the Rust community
//! for configuration, notably being used by [Cargo], Rust's package manager.
//!
//! ## TOML values
//!
//! A value in TOML is represented with the [`Value`] enum in this crate.
//!
//! TOML is similar to JSON with the notable addition of a [`Datetime`][crate::Datetime]
//! type. In general, TOML and JSON are interchangeable in terms of
//! formats.
//!
//! ## Parsing TOML
//!
//! The easiest way to parse a TOML document is via the [`Value`] type:
//!
//! ```rust
//! use toml_edit::easy::Value;
//!
//! let value = "foo = 'bar'".parse::<Value>().unwrap();
//!
//! assert_eq!(value["foo"].as_str(), Some("bar"));
//! ```
//!
//! The [`Value`] type implements a number of convenience methods and
//! traits; the example above uses [`FromStr`][std::str::FromStr] to parse a [`str`] into a
//! [`Value`].
//!
//! ## Deserialization and Serialization
//!
//! This crate supports [`serde`] 1.0 with a number of
//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and
//! `Serializer` traits. Namely, you'll find:
//!
//! * `Deserialize for Value`
//! * `Serialize for Value`
//! * `Deserialize for Datetime`
//! * `Serialize for Datetime`
//! * `Deserializer for de::Deserializer`
//! * `Serializer for ser::Serializer`
//! * `Deserializer for Value`
//!
//! This means that you can use Serde to deserialize/serialize the
//! [`Value`] type as well as the [`Datetime`][crate::Datetime] type in this crate. You can also
//! use the [`Deserializer`], [`Serializer`], or [`Value`] type itself to act as
//! a deserializer/serializer for arbitrary types.
//!
//! An example of deserializing with TOML is:
//!
//! ```rust
//! use serde::Deserialize;
//!
//! #[derive(Deserialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Deserialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! let config: Config = toml_edit::easy::from_str(r#"
//!     ip = '127.0.0.1'
//!
//!     [keys]
//!     github = 'xxxxxxxxxxxxxxxxx'
//!     travis = 'yyyyyyyyyyyyyyyyy'
//! "#).unwrap();
//!
//! assert_eq!(config.ip, "127.0.0.1");
//! assert_eq!(config.port, None);
//! assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx");
//! assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy");
//! ```
//!
//! You can serialize types in a similar fashion:
//!
//! ```rust
//! use serde::Serialize;
//!
//! #[derive(Serialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Serialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! let config = Config {
//!     ip: "127.0.0.1".to_string(),
//!     port: None,
//!     keys: Keys {
//!         github: "xxxxxxxxxxxxxxxxx".to_string(),
//!         travis: Some("yyyyyyyyyyyyyyyyy".to_string()),
//!     },
//! };
//!
//! let toml = toml_edit::easy::to_string(&config).unwrap();
//! ```
//!
//! [TOML]: https://github.com/toml-lang/toml
//! [Cargo]: https://crates.io/
//! [`serde`]: https://serde.rs/

mod datetime;

#[doc(hidden)]
pub mod macros;
pub mod map;
pub mod value;

pub use crate::de;
pub use crate::ser;
pub use crate::toml;
#[doc(no_inline)]
pub use de::{from_document, from_slice, from_str, Deserializer};
#[doc(no_inline)]
pub use ser::{to_document, to_string, to_string_pretty, to_vec, Serializer};
#[doc(no_inline)]
pub use value::Value;
<|endoftext|>


<commit_before>// edition:2018
#![crate_type = "lib"]
#![feature(type_ascription)]
use std::future::Future;
use std::pin::Pin;

// This tests the parser for "x as Y[z]". It errors, but we want to give useful
// errors and parse such that further code gives useful errors.
pub fn index_after_as_cast() {
    vec![1, 2, 3] as Vec<i32>[0];
    //~^ ERROR: casts cannot be followed by indexing
    vec![1, 2, 3]: Vec<i32>[0];
    //~^ ERROR: casts cannot be followed by indexing
}

pub fn index_after_cast_to_index() {
    (&[0]) as &[i32][0];
    //~^ ERROR: casts cannot be followed by indexing
    (&[0i32]): &[i32; 1][0];
    //~^ ERROR: casts cannot be followed by indexing
}

pub fn cast_after_cast() {
    if 5u64 as i32 as u16 == 0u16 {

    }
    if 5u64: u64: u64 == 0u64 {

    }
    let _ = 5u64: u64: u64 as u8 as i8 == 9i8;
    let _ = 0i32: i32: i32;
    let _ = 0 as i32: i32;
    let _ = 0i32: i32 as i32;
    let _ = 0 as i32 as i32;
    let _ = 0i32: i32: i32 as u32 as i32;
}

// this tests that the precedence for `!x as Y.Z` is still what we expect
pub fn precedence() {
    let x: i32 = &vec![1, 2, 3] as &Vec<i32>[0];
    //~^ ERROR: casts cannot be followed by indexing
}

pub fn method_calls() {
    0 as i32.max(0);
    //~^ ERROR: casts cannot be followed by a method call
    0: i32.max(0);
    //~^ ERROR: casts cannot be followed by a method call
}

pub fn complex() {
    let _ = format!(
        "{} and {}",
        if true { 33 } else { 44 } as i32.max(0),
        //~^ ERROR: casts cannot be followed by a method call
        if true { 33 } else { 44 }: i32.max(0)
        //~^ ERROR: casts cannot be followed by a method call
    );
}

pub fn in_condition() {
    if 5u64 as i32.max(0) == 0 {
        //~^ ERROR: casts cannot be followed by a method call
    }
    if 5u64: u64.max(0) == 0 {
        //~^ ERROR: casts cannot be followed by a method call
    }
}

pub fn inside_block() {
    let _ = if true {
        5u64 as u32.max(0) == 0
        //~^ ERROR: casts cannot be followed by a method call
    } else { false };
    let _ = if true {
        5u64: u64.max(0) == 0
        //~^ ERROR: casts cannot be followed by a method call
    } else { false };
}

static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]);
//~^ ERROR: casts cannot be followed by indexing

static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]);
//~^ ERROR: casts cannot be followed by indexing

pub fn cast_then_try() -> Result<u64,u64> {
    Err(0u64) as Result<u64,u64>?;
    //~^ ERROR: casts cannot be followed by ?
    Err(0u64): Result<u64,u64>?;
    //~^ ERROR: casts cannot be followed by ?
    Ok(1)
}

pub fn cast_then_call() {
    type F = fn(u8);
    // type ascription won't actually do [unique drop fn type] -> fn(u8) casts.
    let drop_ptr = drop as fn(u8);
    drop as F();
    //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214]
    drop_ptr: F();
    //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214]
}

pub fn cast_to_fn_should_work() {
    let drop_ptr = drop as fn(u8);
    drop as fn(u8);
    drop_ptr: fn(u8);
}

pub fn parens_after_cast_error() {
    let drop_ptr = drop as fn(u8);
    drop as fn(u8)(0);
    //~^ ERROR: casts cannot be followed by a function call
    drop_ptr: fn(u8)(0);
    //~^ ERROR: casts cannot be followed by a function call
}

pub async fn cast_then_await() {
    Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>.await;
    //~^ ERROR: casts cannot be followed by `.await`

    Box::pin(noop()): Pin<Box<_>>.await;
    //~^ ERROR: casts cannot be followed by `.await`
}

pub async fn noop() {}

#[derive(Default)]
pub struct Foo {
    pub bar: u32,
}

pub fn struct_field() {
    Foo::default() as Foo.bar;
    //~^ ERROR: cannot be followed by a field access
    Foo::default(): Foo.bar;
    //~^ ERROR: cannot be followed by a field access
}
<commit_msg>Remove trailing whitespace<commit_after>// edition:2018
#![crate_type = "lib"]
#![feature(type_ascription)]
use std::future::Future;
use std::pin::Pin;

// This tests the parser for "x as Y[z]". It errors, but we want to give useful
// errors and parse such that further code gives useful errors.
pub fn index_after_as_cast() {
    vec![1, 2, 3] as Vec<i32>[0];
    //~^ ERROR: casts cannot be followed by indexing
    vec![1, 2, 3]: Vec<i32>[0];
    //~^ ERROR: casts cannot be followed by indexing
}

pub fn index_after_cast_to_index() {
    (&[0]) as &[i32][0];
    //~^ ERROR: casts cannot be followed by indexing
    (&[0i32]): &[i32; 1][0];
    //~^ ERROR: casts cannot be followed by indexing
}

pub fn cast_after_cast() {
    if 5u64 as i32 as u16 == 0u16 {

    }
    if 5u64: u64: u64 == 0u64 {

    }
    let _ = 5u64: u64: u64 as u8 as i8 == 9i8;
    let _ = 0i32: i32: i32;
    let _ = 0 as i32: i32;
    let _ = 0i32: i32 as i32;
    let _ = 0 as i32 as i32;
    let _ = 0i32: i32: i32 as u32 as i32;
}

// this tests that the precedence for `!x as Y.Z` is still what we expect
pub fn precedence() {
    let x: i32 = &vec![1, 2, 3] as &Vec<i32>[0];
    //~^ ERROR: casts cannot be followed by indexing
}

pub fn method_calls() {
    0 as i32.max(0);
    //~^ ERROR: casts cannot be followed by a method call
    0: i32.max(0);
    //~^ ERROR: casts cannot be followed by a method call
}

pub fn complex() {
    let _ = format!(
        "{} and {}",
        if true { 33 } else { 44 } as i32.max(0),
        //~^ ERROR: casts cannot be followed by a method call
        if true { 33 } else { 44 }: i32.max(0)
        //~^ ERROR: casts cannot be followed by a method call
    );
}

pub fn in_condition() {
    if 5u64 as i32.max(0) == 0 {
        //~^ ERROR: casts cannot be followed by a method call
    }
    if 5u64: u64.max(0) == 0 {
        //~^ ERROR: casts cannot be followed by a method call
    }
}

pub fn inside_block() {
    let _ = if true {
        5u64 as u32.max(0) == 0
        //~^ ERROR: casts cannot be followed by a method call
    } else { false };
    let _ = if true {
        5u64: u64.max(0) == 0
        //~^ ERROR: casts cannot be followed by a method call
    } else { false };
}

static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]);
//~^ ERROR: casts cannot be followed by indexing

static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]);
//~^ ERROR: casts cannot be followed by indexing

pub fn cast_then_try() -> Result<u64,u64> {
    Err(0u64) as Result<u64,u64>?;
    //~^ ERROR: casts cannot be followed by ?
    Err(0u64): Result<u64,u64>?;
    //~^ ERROR: casts cannot be followed by ?
    Ok(1)
}

pub fn cast_then_call() {
    type F = fn(u8);
    // type ascription won't actually do [unique drop fn type] -> fn(u8) casts.
    let drop_ptr = drop as fn(u8);
    drop as F();
    //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214]
    drop_ptr: F();
    //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214]
}

pub fn cast_to_fn_should_work() {
    let drop_ptr = drop as fn(u8);
    drop as fn(u8);
    drop_ptr: fn(u8);
}

pub fn parens_after_cast_error() {
    let drop_ptr = drop as fn(u8);
    drop as fn(u8)(0);
    //~^ ERROR: casts cannot be followed by a function call
    drop_ptr: fn(u8)(0);
    //~^ ERROR: casts cannot be followed by a function call
}

pub async fn cast_then_await() {
    Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>.await;
    //~^ ERROR: casts cannot be followed by `.await`

    Box::pin(noop()): Pin<Box<_>>.await;
    //~^ ERROR: casts cannot be followed by `.await`
}

pub async fn noop() {}

#[derive(Default)]
pub struct Foo {
    pub bar: u32,
}

pub fn struct_field() {
    Foo::default() as Foo.bar;
    //~^ ERROR: cannot be followed by a field access
    Foo::default(): Foo.bar;
    //~^ ERROR: cannot be followed by a field access
}
<|endoftext|>


<commit_before>use std::io::stdout;
use std::io::Write;

use lister::Lister;
use result::Result;

use libimagstore::store::FileLockEntry;
use libimagstore::store::Entry;

pub struct CoreLister<'a> {
    lister: &'a Fn(&Entry) -> String,
}

impl<'a> CoreLister<'a> {

    pub fn new(lister: &'a Fn(&Entry) -> String) -> CoreLister<'a> {
        CoreLister {
            lister: lister,
        }
    }

}

impl<'a> Lister for CoreLister<'a> {

    fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> {
        use error::ListError as LE;
        use error::ListErrorKind as LEK;

        entries.fold(Ok(()), |accu, entry| {
            accu.and_then(|_| {
                    write!(stdout(), "{:?}\n", (self.lister)(&entry))
                        .map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e))))
                })
            })
    }

}

<commit_msg>Add counter in libimagentrylist::listers::Core<commit_after>use std::io::stdout;
use std::io::Write;

use lister::Lister;
use result::Result;

use libimagstore::store::FileLockEntry;
use libimagstore::store::Entry;

pub struct CoreLister<'a> {
    lister: &'a Fn(&Entry) -> String,
}

impl<'a> CoreLister<'a> {

    pub fn new(lister: &'a Fn(&Entry) -> String) -> CoreLister<'a> {
        CoreLister {
            lister: lister,
        }
    }

}

impl<'a> Lister for CoreLister<'a> {

    fn list<'b, I: Iterator<Item = FileLockEntry<'b>>>(&self, entries: I) -> Result<()> {
        use error::ListError as LE;
        use error::ListErrorKind as LEK;

        debug!("Called list()");
        let (r, n) = entries
            .fold((Ok(()), 0), |(accu, i), entry| {
                debug!("fold({:?}, {:?})", accu, entry);
                let r = accu.and_then(|_| {
                        debug!("Listing Entry: {:?}", entry);
                        write!(stdout(), "{:?}\n", (self.lister)(&entry))
                            .map_err(|e| LE::new(LEK::FormatError, Some(Box::new(e))))
                    });
                (r, i + 1)
            });
        debug!("Iterated over {} entries", n);
        r
    }

}

<|endoftext|>