<commit_before>// Copyright © 2018 Cormac O'Brien
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use std::mem;

use client::Client;
use client::render::Palette;
use client::render::Vertex2d;
use client::render::bitmap::BitmapTexture;
use client::render::pipeline2d;
use common::net::ClientStat;
use common::net::ItemFlags;
use common::net::MAX_ITEMS;
use common::wad::Wad;

use cgmath::Matrix4;
use cgmath::SquareMatrix;
use chrono::Duration;
use flame;
use gfx::CommandBuffer;
use gfx::Encoder;
use gfx::Factory;
use gfx::IndexBuffer;
use gfx::Slice;
use gfx::format::R8_G8_B8_A8;
use gfx::handle::Buffer;
use gfx::handle::ShaderResourceView;
use gfx::handle::Texture;
use gfx::pso::PipelineData;
use gfx::pso::PipelineState;
use gfx_device_gl::Resources;

use failure::Error;

// these have to be wound clockwise
// t-texcoords are currently inverted because bitmaps are defined with t=0 at the top
static FULLSCREEN_QUAD: [Vertex2d; 6] = [
    Vertex2d { pos: [-1.0, -1.0], texcoord: [0.0, 1.0] }, // bottom left
    Vertex2d { pos: [-1.0, 1.0], texcoord: [0.0, 0.0] }, // top left
    Vertex2d { pos: [1.0, 1.0], texcoord: [1.0, 0.0] }, // top right
    Vertex2d { pos: [-1.0, -1.0], texcoord: [0.0, 1.0] }, // bottom left
    Vertex2d { pos: [1.0, 1.0], texcoord: [1.0, 0.0] }, // top right
    Vertex2d { pos: [1.0, -1.0], texcoord: [1.0, 1.0] }, // bottom right
];

static FULLSCREEN_SLICE: Slice<Resources> = Slice {
    start: 0,
    end: 6,
    base_vertex: 0,
    instances: None,
    buffer: IndexBuffer::Auto,
};

enum WeaponSlots {
    Shotgun = 0,
    SuperShotgun = 1,
    Nailgun = 2,
    SuperNailgun = 3,
    RocketLauncher = 4,
    GrenadeLauncher = 5,
    LightningGun = 6,
}

enum AmmoSlots {
    Shells = 0,
    Nails = 1,
    Rockets = 2,
    Cells = 3,
}

pub struct HudRenderer {
    digits: Box<[BitmapTexture]>,
    minus: BitmapTexture,
    alt_digits: Box<[BitmapTexture]>,
    alt_minus: BitmapTexture,
    colon: BitmapTexture,
    slash: BitmapTexture,

    weapons: Box<[Box<[BitmapTexture]>]>,
    ammo: Box<[BitmapTexture]>,
    armor: Box<[BitmapTexture]>,
    items: Box<[BitmapTexture]>,
    faces: Box<[BitmapTexture]>,
    pain_faces: Box<[BitmapTexture]>,

    face_invis: BitmapTexture,
    face_invuln: BitmapTexture,
    face_invis_invuln: BitmapTexture,
    face_quad: BitmapTexture,
    sbar: BitmapTexture,
    ibar: BitmapTexture,
    scorebar: BitmapTexture,

    vertex_buffer: Buffer<Resources, Vertex2d>,
}

impl HudRenderer {
    pub fn new<F>(
        gfx_wad: &Wad,
        palette: &Palette,
        factory: &mut F
    ) -> Result<HudRenderer, Error>
    where
        F: Factory<Resources>
    {
        use gfx::traits::FactoryExt;
        let vertex_buffer = factory.create_vertex_buffer(&FULLSCREEN_QUAD);

        let mut digits = Vec::new();
        let mut alt_digits = Vec::new();

        // just to make the following code a bit less painful
        let mut qpic_to_bitmap = |name: &str| -> Result<BitmapTexture, Error> {
            let qpic = gfx_wad.open_qpic(name)?;
            BitmapTexture::from_qpic(factory, &qpic, palette)
        };

        for i in 0..10 {
            digits.push(qpic_to_bitmap(&format!("NUM_{}", i))?);
            alt_digits.push(qpic_to_bitmap(&format!("ANUM_{}", i))?);
        }

        let minus = qpic_to_bitmap("NUM_MINUS")?;
        let alt_minus = qpic_to_bitmap("ANUM_MINUS")?;
        let colon = qpic_to_bitmap("NUM_COLON")?;
        let slash = qpic_to_bitmap("NUM_SLASH")?;

        let weapon_names = vec![
            "SHOTGUN",
            "SSHOTGUN",
            "NAILGUN",
            "SNAILGUN",
            "RLAUNCH",
            "SRLAUNCH",
            "LIGHTNG"
        ];

        let weapon_prefixes = vec!["", "2", "A1", "A2", "A3", "A4", "A5"];

        let mut weapons = Vec::new();

        for w_name in &weapon_names {
            let mut weapon_frames = Vec::new();

            for w_prefix in &weapon_prefixes {
                weapon_frames.push(qpic_to_bitmap(&format!("INV{}_{}", w_prefix, w_name))?);
            }

            weapons.push(weapon_frames.into_boxed_slice());
        }

        let ammo_names = vec!["SHELLS", "NAILS", "ROCKET", "CELLS"];
        let mut ammo = Vec::new();
        for ammo_name in &ammo_names {
            ammo.push(qpic_to_bitmap(&format!("SB_{}", ammo_name))?);
        }

        let mut armor = Vec::new();
        for i in 1..4 {
            armor.push(qpic_to_bitmap(&format!("SB_ARMOR{}", i))?);
        }

        let item_names = vec!["KEY1", "KEY2", "INVIS", "INVULN", "SUIT", "QUAD"];
        let mut items = Vec::new();
        for item_name in &item_names {
            items.push(qpic_to_bitmap(&format!("SB_{}", item_name))?);
        }

        let mut sigils = Vec::new();
        for i in 1..5 {
            sigils.push(qpic_to_bitmap(&format!("SB_SIGIL{}", i))?);
        }

        let mut faces = Vec::new();
        let mut pain_faces = Vec::new();
        for i in 1..6 {
            faces.push(qpic_to_bitmap(&format!("FACE{}", i))?);
            pain_faces.push(qpic_to_bitmap(&format!("FACE_P{}", i))?);
        }

        let face_invis = qpic_to_bitmap("FACE_INVIS")?;
        let face_invuln = qpic_to_bitmap("FACE_INVUL2")?;
        let face_invis_invuln = qpic_to_bitmap("FACE_INV2")?;
        let face_quad = qpic_to_bitmap("FACE_QUAD")?;

        let sbar = qpic_to_bitmap("SBAR")?;
        let ibar = qpic_to_bitmap("IBAR")?;
        let scorebar = qpic_to_bitmap("SCOREBAR")?;

        // TODO: use a cvar to determine HUD scaling (for now, do 2:1)

        Ok(HudRenderer {
            digits: digits.into_boxed_slice(),
            minus,
            alt_digits: alt_digits.into_boxed_slice(),
            alt_minus,
            colon,
            slash,

            weapons: weapons.into_boxed_slice(),
            ammo: ammo.into_boxed_slice(),
            armor: armor.into_boxed_slice(),
            items: items.into_boxed_slice(),
            faces: faces.into_boxed_slice(),
            pain_faces: pain_faces.into_boxed_slice(),

            face_invis,
            face_invuln,
            face_invis_invuln,
            face_quad,
            sbar,
            ibar,
            scorebar,

            vertex_buffer,
        })
    }

    pub fn render_bitmap<C>(
        &self,
        bitmap: &BitmapTexture,
        encoder: &mut Encoder<Resources, C>,
        pso: &PipelineState<Resources, <pipeline2d::Data<Resources> as PipelineData<Resources>>::Meta>,
        user_data: &mut pipeline2d::Data<Resources>,
        display_width: u32,
        display_height: u32,
        position_x: i32,
        position_y: i32,
    )
    where
        C: CommandBuffer<Resources>,
    {
        user_data.vertex_buffer = self.vertex_buffer.clone();
        user_data.transform = bitmap.transform(display_width, display_height, position_x, position_y).into();
        user_data.sampler.0 = bitmap.view();
        encoder.draw(&FULLSCREEN_SLICE, pso, user_data);
    }

    pub fn render<F, C>(
        &mut self,
        factory: &mut F,
        encoder: &mut Encoder<Resources, C>,
        pso: &PipelineState<Resources, <pipeline2d::Data<Resources> as PipelineData<Resources>>::Meta>,
        user_data: &mut pipeline2d::Data<Resources>,
        client: &Client,
        display_width: u32,
        display_height: u32,
    ) -> Result<(), Error>
    where
        F: Factory<Resources>,
        C: CommandBuffer<Resources>,
    {
        // TODO: scale using a cvar (`r_hudscale` or something)
        let display_width = display_width / 2;
        let display_height = display_height / 2;

        let _guard = flame::start_guard("HudRenderer::render");

        let sbar_x = (display_width - self.sbar.width()) as i32 / 2;
        let sbar_y = 0;

        self.render_bitmap(&self.sbar, encoder, pso, user_data, display_width, display_height, sbar_x, sbar_y);
        self.render_bitmap(&self.ibar, encoder, pso, user_data, display_width, display_height, sbar_x, sbar_y + self.ibar.height() as i32);

        // weapons
        for i in 0..8 {
            if client.items().contains(ItemFlags::from_bits(ItemFlags::SHOTGUN.bits() << i).unwrap()) {
                let get_time = client.item_get_time()[i];
                let delta = client.get_time() - get_time;
                let flash_on = if delta >= Duration::milliseconds(100) {
                    if client.active_weapon() as u32 == ItemFlags::SHOTGUN.bits() << i {
                        1
                    } else {
                        0
                    }
                } else {
                    (delta.num_milliseconds() * 100) as usize % 5 + 2
                };

                self.render_bitmap(
                    &self.weapons[i][flash_on],
                    encoder,
                    pso,
                    user_data,
                    display_width,
                    display_height,
                    sbar_x + 24 * i as i32,
                    sbar_y + self.sbar.height() as i32
                );
            }
        }

        // ammo
        for i in 0..4 {
            let ammo_str = format!("{: >3}", client.stats()[ClientStat::Shells as usize + i]);
            for (chr_id, chr) in ammo_str.chars().enumerate() {
                if chr != ' ' {
                    // TODO
                }
            }
        }

        Ok(())
    }
}
<commit_msg>Add item and sigil rendering to HUD<commit_after>// Copyright © 2018 Cormac O'Brien
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use std::mem;

use client::Client;
use client::render::Palette;
use client::render::Vertex2d;
use client::render::bitmap::BitmapTexture;
use client::render::pipeline2d;
use common::net::ClientStat;
use common::net::ItemFlags;
use common::net::MAX_ITEMS;
use common::wad::Wad;

use cgmath::Matrix4;
use cgmath::SquareMatrix;
use chrono::Duration;
use flame;
use gfx::CommandBuffer;
use gfx::Encoder;
use gfx::Factory;
use gfx::IndexBuffer;
use gfx::Slice;
use gfx::format::R8_G8_B8_A8;
use gfx::handle::Buffer;
use gfx::handle::ShaderResourceView;
use gfx::handle::Texture;
use gfx::pso::PipelineData;
use gfx::pso::PipelineState;
use gfx_device_gl::Resources;

use failure::Error;

// these have to be wound clockwise
// t-texcoords are currently inverted because bitmaps are defined with t=0 at the top
static FULLSCREEN_QUAD: [Vertex2d; 6] = [
    Vertex2d { pos: [-1.0, -1.0], texcoord: [0.0, 1.0] }, // bottom left
    Vertex2d { pos: [-1.0, 1.0], texcoord: [0.0, 0.0] }, // top left
    Vertex2d { pos: [1.0, 1.0], texcoord: [1.0, 0.0] }, // top right
    Vertex2d { pos: [-1.0, -1.0], texcoord: [0.0, 1.0] }, // bottom left
    Vertex2d { pos: [1.0, 1.0], texcoord: [1.0, 0.0] }, // top right
    Vertex2d { pos: [1.0, -1.0], texcoord: [1.0, 1.0] }, // bottom right
];

static FULLSCREEN_SLICE: Slice<Resources> = Slice {
    start: 0,
    end: 6,
    base_vertex: 0,
    instances: None,
    buffer: IndexBuffer::Auto,
};

enum WeaponSlots {
    Shotgun = 0,
    SuperShotgun = 1,
    Nailgun = 2,
    SuperNailgun = 3,
    RocketLauncher = 4,
    GrenadeLauncher = 5,
    LightningGun = 6,
}

enum AmmoSlots {
    Shells = 0,
    Nails = 1,
    Rockets = 2,
    Cells = 3,
}

pub struct HudRenderer {
    digits: Box<[BitmapTexture]>,
    minus: BitmapTexture,
    alt_digits: Box<[BitmapTexture]>,
    alt_minus: BitmapTexture,
    colon: BitmapTexture,
    slash: BitmapTexture,

    weapons: Box<[Box<[BitmapTexture]>]>,
    ammo: Box<[BitmapTexture]>,
    sigils: Box<[BitmapTexture]>,
    armor: Box<[BitmapTexture]>,
    items: Box<[BitmapTexture]>,
    faces: Box<[BitmapTexture]>,
    pain_faces: Box<[BitmapTexture]>,

    face_invis: BitmapTexture,
    face_invuln: BitmapTexture,
    face_invis_invuln: BitmapTexture,
    face_quad: BitmapTexture,
    sbar: BitmapTexture,
    ibar: BitmapTexture,
    scorebar: BitmapTexture,

    vertex_buffer: Buffer<Resources, Vertex2d>,
}

impl HudRenderer {
    pub fn new<F>(
        gfx_wad: &Wad,
        palette: &Palette,
        factory: &mut F
    ) -> Result<HudRenderer, Error>
    where
        F: Factory<Resources>
    {
        use gfx::traits::FactoryExt;
        let vertex_buffer = factory.create_vertex_buffer(&FULLSCREEN_QUAD);

        let mut digits = Vec::new();
        let mut alt_digits = Vec::new();

        // just to make the following code a bit less painful
        let mut qpic_to_bitmap = |name: &str| -> Result<BitmapTexture, Error> {
            let qpic = gfx_wad.open_qpic(name)?;
            BitmapTexture::from_qpic(factory, &qpic, palette)
        };

        for i in 0..10 {
            digits.push(qpic_to_bitmap(&format!("NUM_{}", i))?);
            alt_digits.push(qpic_to_bitmap(&format!("ANUM_{}", i))?);
        }

        let minus = qpic_to_bitmap("NUM_MINUS")?;
        let alt_minus = qpic_to_bitmap("ANUM_MINUS")?;
        let colon = qpic_to_bitmap("NUM_COLON")?;
        let slash = qpic_to_bitmap("NUM_SLASH")?;

        let weapon_names = vec![
            "SHOTGUN",
            "SSHOTGUN",
            "NAILGUN",
            "SNAILGUN",
            "RLAUNCH",
            "SRLAUNCH",
            "LIGHTNG"
        ];

        let weapon_prefixes = vec!["", "2", "A1", "A2", "A3", "A4", "A5"];

        let mut weapons = Vec::new();

        for w_name in &weapon_names {
            let mut weapon_frames = Vec::new();

            for w_prefix in &weapon_prefixes {
                weapon_frames.push(qpic_to_bitmap(&format!("INV{}_{}", w_prefix, w_name))?);
            }

            weapons.push(weapon_frames.into_boxed_slice());
        }

        let ammo_names = vec!["SHELLS", "NAILS", "ROCKET", "CELLS"];
        let mut ammo = Vec::new();
        for ammo_name in &ammo_names {
            ammo.push(qpic_to_bitmap(&format!("SB_{}", ammo_name))?);
        }

        let mut armor = Vec::new();
        for i in 1..4 {
            armor.push(qpic_to_bitmap(&format!("SB_ARMOR{}", i))?);
        }

        let item_names = vec!["KEY1", "KEY2", "INVIS", "INVULN", "SUIT", "QUAD"];
        let mut items = Vec::new();
        for item_name in &item_names {
            items.push(qpic_to_bitmap(&format!("SB_{}", item_name))?);
        }

        let mut sigils = Vec::new();
        for i in 1..5 {
            sigils.push(qpic_to_bitmap(&format!("SB_SIGIL{}", i))?);
        }

        let mut faces = Vec::new();
        let mut pain_faces = Vec::new();
        for i in 1..6 {
            faces.push(qpic_to_bitmap(&format!("FACE{}", i))?);
            pain_faces.push(qpic_to_bitmap(&format!("FACE_P{}", i))?);
        }

        let face_invis = qpic_to_bitmap("FACE_INVIS")?;
        let face_invuln = qpic_to_bitmap("FACE_INVUL2")?;
        let face_invis_invuln = qpic_to_bitmap("FACE_INV2")?;
        let face_quad = qpic_to_bitmap("FACE_QUAD")?;

        let sbar = qpic_to_bitmap("SBAR")?;
        let ibar = qpic_to_bitmap("IBAR")?;
        let scorebar = qpic_to_bitmap("SCOREBAR")?;

        // TODO: use a cvar to determine HUD scaling (for now, do 2:1)

        Ok(HudRenderer {
            digits: digits.into_boxed_slice(),
            minus,
            alt_digits: alt_digits.into_boxed_slice(),
            alt_minus,
            colon,
            slash,

            weapons: weapons.into_boxed_slice(),
            ammo: ammo.into_boxed_slice(),
            sigils: sigils.into_boxed_slice(),
            armor: armor.into_boxed_slice(),
            items: items.into_boxed_slice(),
            faces: faces.into_boxed_slice(),
            pain_faces: pain_faces.into_boxed_slice(),

            face_invis,
            face_invuln,
            face_invis_invuln,
            face_quad,
            sbar,
            ibar,
            scorebar,

            vertex_buffer,
        })
    }

    pub fn render_bitmap<C>(
        &self,
        bitmap: &BitmapTexture,
        encoder: &mut Encoder<Resources, C>,
        pso: &PipelineState<Resources, <pipeline2d::Data<Resources> as PipelineData<Resources>>::Meta>,
        user_data: &mut pipeline2d::Data<Resources>,
        display_width: u32,
        display_height: u32,
        position_x: i32,
        position_y: i32,
    )
    where
        C: CommandBuffer<Resources>,
    {
        user_data.vertex_buffer = self.vertex_buffer.clone();
        user_data.transform = bitmap.transform(display_width, display_height, position_x, position_y).into();
        user_data.sampler.0 = bitmap.view();
        encoder.draw(&FULLSCREEN_SLICE, pso, user_data);
    }

    pub fn render<F, C>(
        &mut self,
        factory: &mut F,
        encoder: &mut Encoder<Resources, C>,
        pso: &PipelineState<Resources, <pipeline2d::Data<Resources> as PipelineData<Resources>>::Meta>,
        user_data: &mut pipeline2d::Data<Resources>,
        client: &Client,
        display_width: u32,
        display_height: u32,
    ) -> Result<(), Error>
    where
        F: Factory<Resources>,
        C: CommandBuffer<Resources>,
    {
        // TODO: scale using a cvar (`r_hudscale` or something)
        let display_width = display_width / 2;
        let display_height = display_height / 2;

        let _guard = flame::start_guard("HudRenderer::render");

        let sbar_x = (display_width - self.sbar.width()) as i32 / 2;
        let sbar_y = 0;

        self.render_bitmap(&self.sbar, encoder, pso, user_data, display_width, display_height, sbar_x, sbar_y);
        self.render_bitmap(&self.ibar, encoder, pso, user_data, display_width, display_height, sbar_x, sbar_y + self.ibar.height() as i32);

        // weapons
        for i in 0..8 {
            if client.items().contains(ItemFlags::from_bits(ItemFlags::SHOTGUN.bits() << i).unwrap()) {
                let get_time = client.item_get_time()[i];
                let delta = client.get_time() - get_time;
                let flash_on = if delta >= Duration::milliseconds(100) {
                    if client.active_weapon() as u32 == ItemFlags::SHOTGUN.bits() << i {
                        1
                    } else {
                        0
                    }
                } else {
                    (delta.num_milliseconds() * 100) as usize % 5 + 2
                };

                self.render_bitmap(
                    &self.weapons[i][flash_on],
                    encoder,
                    pso,
                    user_data,
                    display_width,
                    display_height,
                    sbar_x + 24 * i as i32,
                    sbar_y + self.sbar.height() as i32
                );
            }
        }

        // ammo
        for i in 0..4 {
            let ammo_str = format!("{: >3}", client.stats()[ClientStat::Shells as usize + i]);
            for (chr_id, chr) in ammo_str.chars().enumerate() {
                if chr != ' ' {
                    // TODO
                }
            }
        }

        for i in 0..6 {
            if client.items().contains(ItemFlags::from_bits(ItemFlags::KEY_1.bits() << i).unwrap()) {
                let get_time = client.item_get_time()[17 + i];
                let delta = client.get_time() - get_time;

                // TODO: add !hipnotic as a condition
                if i > 1 {
                    self.render_bitmap(
                        &self.items[i],
                        encoder,
                        pso,
                        user_data,
                        display_width,
                        display_height,
                        sbar_x + 192 + 16 * i as i32,
                        sbar_y + self.sbar.height() as i32,
                    );
                }
            }
        }

        for i in 0..4 {
            if client.items().contains(ItemFlags::from_bits(ItemFlags::SIGIL_1.bits() << i).unwrap()) {
                let get_time = client.item_get_time()[28 + i];
                self.render_bitmap(
                    &self.sigils[i],
                    encoder,
                    pso,
                    user_data,
                    display_width,
                    display_height,
                    sbar_x + 288 + 8 * i as i32,
                    sbar_y + self.sbar.height() as i32,
                );
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::default::Default;
use std::collections::BTreeMap;

use quire::validate as V;

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct DebianRepo {
    pub url: String,
    pub suite: String,
    pub components: Vec<String>,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct AptKey {
    pub key_server: String,
    pub keys: Vec<String>,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct PacmanRepo {
    pub name: String,
    pub url: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct TarInfo {
    pub url: String,
    pub sha256: Option<String>,
    pub path: PathBuf,
    pub subdir: PathBuf,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct TarInstallInfo {
    pub url: String,
    pub sha256: Option<String>,
    pub subdir: Option<PathBuf>,
    pub script: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct GitInfo {
    pub url: String,
    pub revision: Option<String>,
    pub branch: Option<String>,
    pub path: PathBuf,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct GitInstallInfo {
    pub url: String,
    pub revision: Option<String>,
    pub branch: Option<String>,
    pub subdir: PathBuf,
    pub script: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct FileInfo {
    pub name: PathBuf,
    pub contents: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct UbuntuReleaseInfo {
    pub version: String,
    pub keep_chfn_command: bool,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct UbuntuRepoInfo {
    pub url: String,
    pub suite: String,
    pub components: Vec<String>,
}

#[derive(Default, Clone, RustcDecodable, Debug, RustcEncodable)]
pub struct PipSettings {
    pub find_links: Vec<String>,
    pub index_urls: Vec<String>,
    pub trusted_hosts: Vec<String>,
    pub dependencies: bool,
    pub cache_wheels: bool,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct GitSource {
    pub url: String,
    pub revision: Option<String>,
    pub branch: Option<String>,
}

#[derive(Clone, RustcDecodable, RustcEncodable, Debug)]
pub enum Source {
    Git(GitSource),
    Container(String),
    Directory,
}

#[derive(Clone, RustcDecodable, RustcEncodable, Debug)]
pub struct SubConfigInfo {
    pub source: Source,
    pub path: PathBuf,
    pub container: String,
    pub cache: Option<bool>,
    pub change_dir: Option<bool>,
}

#[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
pub enum Builder {
    // -- Generic --
    Sh(String),
    Cmd(Vec<String>),
    Env(BTreeMap<String, String>),
    Depends(PathBuf),
    Tar(TarInfo),
    TarInstall(TarInstallInfo),
    Git(GitInfo),
    GitInstall(GitInstallInfo),
    Text(BTreeMap<PathBuf, String>),
    //AddFile(FileInfo),
    Remove(PathBuf),
    EnsureDir(PathBuf),
    EmptyDir(PathBuf),
    CacheDirs(BTreeMap<PathBuf, String>),
    //Busybox,

    // -- Generic --
    Install(Vec<String>),
    BuildDeps(Vec<String>),
    Container(String),
    SubConfig(SubConfigInfo),

    // -- Ubuntu --
    Ubuntu(String),
    UbuntuRelease(UbuntuReleaseInfo),
    UbuntuRepo(UbuntuRepoInfo),
    UbuntuUniverse,
    //AddUbuntuPPA(String),

    // -- Ubuntu/Debian --
    //AddDebianRepo(DebianRepo),
    //AddAptKey(AptKey),

    // -- Arch --
    //ArchBase,
    //PacmanInstall(Vec<String>),
    //PacmanRemove(Vec<String>),
    //PacmanBuild(Path),
    //AddPacmanRepo(PacmanRepo),

    // -- Alpine --
    Alpine(String),
    //AlpineRemove(Vec<String>),

    // -- Docker --
    //DockerImage(String),
    //DockerPrivate(String),
    //Dockerfile(Path),

    // -- Languages --
    NpmInstall(Vec<String>),
    //PipRequirement(Path),
    //GemInstall(Vec<String>),

    // -- Python --
    PipConfig(PipSettings),
    Py2Install(Vec<String>),
    Py2Requirements(PathBuf),
    Py3Install(Vec<String>),
    Py3Requirements(PathBuf),
}

pub fn builder_validator<'x>() -> V::Enum<'x> {
    return V::Enum { options: vec![
        ("Install".to_string(), Box::new(V::Sequence {
            element: Box::new(V::Scalar {
            .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),
        ("BuildDeps".to_string(), Box::new(V::Sequence {
            element: Box::new(V::Scalar {
            .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),
        ("Container".to_string(), Box::new(V::Scalar {
        .. Default::default() }) as Box<V::Validator>),
        ("SubConfig".to_string(), Box::new(V::Structure {
            members: vec!(
                ("source".to_string(), Box::new(V::Enum { options: vec!(
                    ("Directory".to_string(),
                        Box::new(V::Nothing) as Box<V::Validator>),
                    ("Container".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                    ("Git".to_string(), Box::new(V::Structure { members: vec!(
                        ("url".to_string(), Box::new(V::Scalar {
                            .. Default::default() }) as Box<V::Validator>),
                        ("revision".to_string(), Box::new(V::Scalar {
                            optional: true,
                            .. Default::default() }) as Box<V::Validator>),
                        ("branch".to_string(), Box::new(V::Scalar {
                            optional: true,
                            .. Default::default() }) as Box<V::Validator>),
                        ), .. Default::default() }) as Box<V::Validator>),
                    ), optional: true,
                       default_tag: Some("Directory".to_string()),
                    .. Default::default() }) as Box<V::Validator>),
                ("path".to_string(), Box::new(V::Directory {
                    absolute: Some(false),
                    default: Some(PathBuf::from("vagga.yaml")),
                    .. Default::default() }) as Box<V::Validator>),
                ("container".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                ("cache".to_string(), Box::new(V::Scalar {
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
                ("change_dir".to_string(), Box::new(V::Scalar {
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
            ),
        .. Default::default() }) as Box<V::Validator>),
        ("Text".to_string(), Box::new(V::Mapping {
            key_element: Box::new(V::Directory {
                absolute: Some(true),
                .. Default::default() }) as Box<V::Validator>,
            value_element: Box::new(V::Scalar {
                .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),

        ("Ubuntu".to_string(), Box::new(V::Scalar {
        .. Default::default() }) as Box<V::Validator>),
        ("UbuntuRelease".to_string(), Box::new(V::Structure {
            members: vec!(
                ("version".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                ("keep_chfn_command".to_string(), Box::new(V::Scalar {
                    default: Some("false".to_string()),
                    .. Default::default() }) as Box<V::Validator>),
            ),
        .. Default::default() }) as Box<V::Validator>),
        ("UbuntuRepo".to_string(), Box::new(V::Structure {
            members: vec!(
                ("url".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                ("suite".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                ("components".to_string(), Box::new(V::Sequence {
                    element: Box::new(V::Scalar {
                        .. Default::default() }) as Box<V::Validator>,
                    .. Default::default() }) as Box<V::Validator>),
            ),
        .. Default::default() }) as Box<V::Validator>),
        ("UbuntuUniverse".to_string(), Box::new(V::Nothing) as Box<V::Validator>),
        ("Sh".to_string(), Box::new(V::Scalar {
        .. Default::default() }) as Box<V::Validator>),
        ("Cmd".to_string(), Box::new(V::Sequence {
            element: Box::new(V::Scalar {
            .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),
        ("Remove".to_string(), Box::new(V::Directory {
            absolute: Some(true),
        .. Default::default() }) as Box<V::Validator>),
        ("EnsureDir".to_string(), Box::new(V::Directory {
            absolute: Some(true),
        .. Default::default() }) as Box<V::Validator>),
        ("EmptyDir".to_string(), Box::new(V::Directory {
            absolute: Some(true),
        .. Default::default() }) as Box<V::Validator>),
        ("CacheDirs".to_string(), Box::new(V::Mapping {
            key_element: Box::new(V::Directory {
                absolute: Some(true),
                .. Default::default() }) as Box<V::Validator>,
            value_element: Box::new(V::Scalar {
                .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),
        ("Env".to_string(), Box::new(V::Mapping {
            key_element: Box::new(V::Scalar {
                .. Default::default() }) as Box<V::Validator>,
            value_element: Box::new(V::Scalar {
                .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),
        ("Depends".to_string(), Box::new(V::Scalar {
        .. Default::default() }) as Box<V::Validator>),
        ("Git".to_string(), Box::new(V::Structure {
            members: vec!(
                ("url".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                ("revision".to_string(), Box::new(V::Scalar {
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
                ("branch".to_string(), Box::new(V::Scalar {
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
                ("path".to_string(), Box::new(V::Directory {
                    absolute: Some(true),
                    .. Default::default() }) as Box<V::Validator>),
            ),
        .. Default::default() }) as Box<V::Validator>),
        ("GitInstall".to_string(), Box::new(V::Structure {
            members: vec!(
                ("url".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                ("revision".to_string(), Box::new(V::Scalar {
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
                ("branch".to_string(), Box::new(V::Scalar {
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
                ("subdir".to_string(), Box::new(V::Directory {
                    default: Some(PathBuf::from(".")),
                    absolute: Some(false),
                    .. Default::default() }) as Box<V::Validator>),
                ("script".to_string(), Box::new(V::Scalar {
                    default: Some("./configure --prefix=/usr\n\
                                   make\n\
                                   make install\n\
                                   ".to_string()),
                    .. Default::default() }) as Box<V::Validator>),
            ),
        .. Default::default() }) as Box<V::Validator>),
        ("Tar".to_string(), Box::new(V::Structure {
            members: vec!(
                ("url".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                ("sha256".to_string(), Box::new(V::Scalar {
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
                ("path".to_string(), Box::new(V::Directory {
                    absolute: Some(true),
                    default: Some(PathBuf::from("/")),
                    .. Default::default() }) as Box<V::Validator>),
                ("subdir".to_string(), Box::new(V::Directory {
                    default: Some(PathBuf::from("")),
                    absolute: Some(false),
                    .. Default::default() }) as Box<V::Validator>),
            ),
        .. Default::default() }) as Box<V::Validator>),
        ("TarInstall".to_string(), Box::new(V::Structure {
            members: vec!(
                ("url".to_string(), Box::new(V::Scalar {
                    .. Default::default() }) as Box<V::Validator>),
                ("sha256".to_string(), Box::new(V::Scalar {
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
                ("subdir".to_string(), Box::new(V::Directory {
                    optional: true,
                    absolute: Some(false),
                    .. Default::default() }) as Box<V::Validator>),
                ("script".to_string(), Box::new(V::Scalar {
                    default: Some("./configure --prefix=/usr\n\
                                   make\n\
                                   make install\n\
                                   ".to_string()),
                    .. Default::default() }) as Box<V::Validator>),
            ),
        .. Default::default() }) as Box<V::Validator>),

        ("Alpine".to_string(), Box::new(V::Scalar {
        .. Default::default() }) as Box<V::Validator>),

        // Python
        ("PipConfig".to_string(), Box::new(V::Structure {
            members: vec!(
                ("dependencies".to_string(), Box::new(V::Scalar {
                    default: Some("false".to_string()),
                    optional: true,
                    .. Default::default() }) as Box<V::Validator>),
                ("cache_wheels".to_string(), Box::new(V::Scalar {
                    default: Some("true".to_string()),
                    .. Default::default() }) as Box<V::Validator>),
                ("find_links".to_string(), Box::new(V::Sequence {
                    element: Box::new(V::Scalar {
                        .. Default::default() }) as Box<V::Validator>,
                    .. Default::default() }) as Box<V::Validator>),
                ("index_urls".to_string(), Box::new(V::Sequence {
                    element: Box::new(V::Scalar {
                        .. Default::default() }) as Box<V::Validator>,
                    .. Default::default() }) as Box<V::Validator>),
                ("trusted_hosts".to_string(), Box::new(V::Sequence {
                    element: Box::new(V::Scalar {
                        .. Default::default() }) as Box<V::Validator>,
                    .. Default::default() }) as Box<V::Validator>),
            ),
        .. Default::default() }) as Box<V::Validator>),
        ("Py2Install".to_string(), Box::new(V::Sequence {
            element: Box::new(V::Scalar {
            .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),
        ("Py2Requirements".to_string(), Box::new(V::Scalar {
            default: Some("requirements.txt".to_string()),
        .. Default::default() }) as Box<V::Validator>),
        ("Py3Install".to_string(), Box::new(V::Sequence {
            element: Box::new(V::Scalar {
            .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),
        ("Py3Requirements".to_string(), Box::new(V::Scalar {
            default: Some("requirements.txt".to_string()),
        .. Default::default() }) as Box<V::Validator>),

        // Node.js
        ("NpmInstall".to_string(), Box::new(V::Sequence {
            element: Box::new(V::Scalar {
            .. Default::default() }) as Box<V::Validator>,
        .. Default::default() }) as Box<V::Validator>),

    ], .. Default::default() }
}
<commit_msg>Converted builder configuration to new-style quire config<commit_after>use std::path::PathBuf;
use std::default::Default;
use std::collections::BTreeMap;

use quire::validate as V;

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct DebianRepo {
    pub url: String,
    pub suite: String,
    pub components: Vec<String>,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct AptKey {
    pub key_server: String,
    pub keys: Vec<String>,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct PacmanRepo {
    pub name: String,
    pub url: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct TarInfo {
    pub url: String,
    pub sha256: Option<String>,
    pub path: PathBuf,
    pub subdir: PathBuf,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct TarInstallInfo {
    pub url: String,
    pub sha256: Option<String>,
    pub subdir: Option<PathBuf>,
    pub script: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct GitInfo {
    pub url: String,
    pub revision: Option<String>,
    pub branch: Option<String>,
    pub path: PathBuf,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct GitInstallInfo {
    pub url: String,
    pub revision: Option<String>,
    pub branch: Option<String>,
    pub subdir: PathBuf,
    pub script: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct FileInfo {
    pub name: PathBuf,
    pub contents: String,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct UbuntuReleaseInfo {
    pub version: String,
    pub keep_chfn_command: bool,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct UbuntuRepoInfo {
    pub url: String,
    pub suite: String,
    pub components: Vec<String>,
}

#[derive(Default, Clone, RustcDecodable, Debug, RustcEncodable)]
pub struct PipSettings {
    pub find_links: Vec<String>,
    pub index_urls: Vec<String>,
    pub trusted_hosts: Vec<String>,
    pub dependencies: bool,
    pub cache_wheels: bool,
}

#[derive(RustcEncodable, RustcDecodable, Debug, Clone)]
pub struct GitSource {
    pub url: String,
    pub revision: Option<String>,
    pub branch: Option<String>,
}

#[derive(Clone, RustcDecodable, RustcEncodable, Debug)]
pub enum Source {
    Git(GitSource),
    Container(String),
    Directory,
}

#[derive(Clone, RustcDecodable, RustcEncodable, Debug)]
pub struct SubConfigInfo {
    pub source: Source,
    pub path: PathBuf,
    pub container: String,
    pub cache: Option<bool>,
    pub change_dir: Option<bool>,
}

#[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
pub enum Builder {
    // -- Generic --
    Sh(String),
    Cmd(Vec<String>),
    Env(BTreeMap<String, String>),
    Depends(PathBuf),
    Tar(TarInfo),
    TarInstall(TarInstallInfo),
    Git(GitInfo),
    GitInstall(GitInstallInfo),
    Text(BTreeMap<PathBuf, String>),
    //AddFile(FileInfo),
    Remove(PathBuf),
    EnsureDir(PathBuf),
    EmptyDir(PathBuf),
    CacheDirs(BTreeMap<PathBuf, String>),
    //Busybox,

    // -- Generic --
    Install(Vec<String>),
    BuildDeps(Vec<String>),
    Container(String),
    SubConfig(SubConfigInfo),

    // -- Ubuntu --
    Ubuntu(String),
    UbuntuRelease(UbuntuReleaseInfo),
    UbuntuRepo(UbuntuRepoInfo),
    UbuntuUniverse,
    //AddUbuntuPPA(String),

    // -- Ubuntu/Debian --
    //AddDebianRepo(DebianRepo),
    //AddAptKey(AptKey),

    // -- Arch --
    //ArchBase,
    //PacmanInstall(Vec<String>),
    //PacmanRemove(Vec<String>),
    //PacmanBuild(Path),
    //AddPacmanRepo(PacmanRepo),

    // -- Alpine --
    Alpine(String),
    //AlpineRemove(Vec<String>),

    // -- Docker --
    //DockerImage(String),
    //DockerPrivate(String),
    //Dockerfile(Path),

    // -- Languages --
    NpmInstall(Vec<String>),
    //PipRequirement(Path),
    //GemInstall(Vec<String>),

    // -- Python --
    PipConfig(PipSettings),
    Py2Install(Vec<String>),
    Py2Requirements(PathBuf),
    Py3Install(Vec<String>),
    Py3Requirements(PathBuf),
}

pub fn builder_validator<'x>() -> V::Enum<'x> {
    V::Enum::new()
    .option("Install", V::Sequence::new(V::Scalar::new()))
    .option("BuildDeps", V::Sequence::new(V::Scalar::new()))
    .option("Container", V::Scalar::new())
    .option("SubConfig", V::Structure::new()
        .member("source", V::Enum::new()
            .option("Directory", V::Nothing)
            .option("Container", V::Scalar::new())
            .option("Git", V::Structure::new()
                .member("url", V::Scalar::new())
                .member("revision", V::Scalar::new().optional())
                .member("branch", V::Scalar::new().optional()))
            .optional()
            .default_tag("Directory"))
        .member("path".to_string(), V::Directory::new()
            .is_absolute(false)
            .default("vagga.yaml"))
        .member("container", V::Scalar::new())
        .member("cache", V::Scalar::new().optional())
        .member("change_dir", V::Scalar::new().optional()))
    .option("Text", V::Mapping::new(
        V::Directory::new().is_absolute(true),
        V::Scalar::new()))
    .option("Ubuntu", V::Scalar::new())
    .option("UbuntuRelease", V::Structure::new()
        .member("version", V::Scalar::new())
        .member("keep_chfn_command", V::Scalar::new().default(false)))
    .option("UbuntuRepo", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("suite", V::Scalar::new())
        .member("components", V::Sequence::new(V::Scalar::new())))
    .option("UbuntuUniverse", V::Nothing)
    .option("Sh", V::Scalar::new())
    .option("Cmd", V::Sequence::new(V::Scalar::new()))
    .option("Remove", V::Directory::new().is_absolute(true))
    .option("EnsureDir", V::Directory::new().is_absolute(true))
    .option("EmptyDir", V::Directory::new().is_absolute(true))
    .option("CacheDirs", V::Mapping::new(
        V::Directory::new().is_absolute(true),
        V::Scalar::new()))
    .option("Env", V::Mapping::new(
        V::Scalar::new(),
        V::Scalar::new()))
    .option("Depends", V::Scalar::new())
    .option("Git", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("revision", V::Scalar::new().optional())
        .member("branch", V::Scalar::new().optional())
        .member("path", V::Directory::new().is_absolute(true)))
    .option("GitInstall", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("revision", V::Scalar::new().optional())
        .member("branch", V::Scalar::new().optional())
        .member("subdir", V::Directory::new()
            .default(".").is_absolute(false))
        .member("script", V::Scalar::new()
                .default("./configure --prefix=/usr\n\
                          make\n\
                          make install\n")))
    .option("Tar", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("sha256", V::Scalar::new().optional())
        .member("path", V::Directory::new().is_absolute(true).default("/"))
        .member("subdir", V::Directory::new().default("").is_absolute(false)))
    .option("TarInstall", V::Structure::new()
        .member("url", V::Scalar::new())
        .member("sha256", V::Scalar::new().optional())
        .member("subdir", V::Directory::new().optional().is_absolute(false))
        .member("script", V::Scalar::new()
                .default("./configure --prefix=/usr\n\
                          make\n\
                          make install\n")))
    .option("Alpine", V::Scalar::new())

    // Python
    .option("PipConfig", V::Structure::new()
        .member("dependencies", V::Scalar::new().default(false).optional())
        .member("cache_wheels", V::Scalar::new().default(true))
        .member("find_links", V::Sequence::new(V::Scalar::new()))
        .member("index_urls", V::Sequence::new(V::Scalar::new()))
        .member("trusted_hosts", V::Sequence::new(V::Scalar::new())))
    .option("Py2Install", V::Sequence::new(V::Scalar::new()))
    .option("Py2Requirements", V::Scalar::new()
        .default("requirements.txt"))
    .option("Py3Install", V::Sequence::new(V::Scalar::new()))
    .option("Py3Requirements",
        V::Scalar::new().default("requirements.txt"))

    // Node.js
    .option("NpmInstall", V::Sequence::new(V::Scalar::new()))
}
<|endoftext|>


<commit_before>use alloc::arc::Arc;
use alloc::boxed::Box;
use collections::{BTreeMap, Vec, VecDeque};
use spin::Mutex;

use arch;
use context::file::File;
use context::memory::{Grant, Memory, SharedMemory, Tls};
use scheme::{SchemeNamespace, FileHandle};
use syscall::data::Event;
use sync::{WaitMap, WaitQueue};

/// Unique identifier for a context (i.e. `pid`).
use ::core::sync::atomic::AtomicUsize;
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);

/// The status of a context - used for scheduling
/// See syscall::process::waitpid and the sync module for examples of usage
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Status {
    Runnable,
    Blocked,
    Exited(usize)
}

/// A context, which identifies either a process or a thread
#[derive(Debug)]
pub struct Context {
    /// The ID of this context
    pub id: ContextId,
    /// The ID of the parent context
    pub ppid: ContextId,
    /// The real user id
    pub ruid: u32,
    /// The real group id
    pub rgid: u32,
    /// The real namespace id
    pub rns: SchemeNamespace,
    /// The effective user id
    pub euid: u32,
    /// The effective group id
    pub egid: u32,
    /// The effective namespace id
    pub ens: SchemeNamespace,
    /// Status of context
    pub status: Status,
    /// Context running or not
    pub running: bool,
    /// CPU ID, if locked
    pub cpu_id: Option<usize>,
    /// Context is halting parent
    pub vfork: bool,
    /// Context is being waited on
    pub waitpid: Arc<WaitMap<ContextId, usize>>,
    /// Context should handle pending signals
    pub pending: VecDeque<u8>,
    /// Context should wake up at specified time
    pub wake: Option<(u64, u64)>,
    /// The architecture specific context
    pub arch: arch::context::Context,
    /// Kernel FX - used to store SIMD and FPU registers on context switch
    pub kfx: Option<Box<[u8]>>,
    /// Kernel stack
    pub kstack: Option<Box<[u8]>>,
    /// Executable image
    pub image: Vec<SharedMemory>,
    /// User heap
    pub heap: Option<SharedMemory>,
    /// User stack
    pub stack: Option<Memory>,
    /// User Thread local storage
    pub tls: Option<Tls>,
    /// User grants
    pub grants: Arc<Mutex<Vec<Grant>>>,
    /// The name of the context
    pub name: Arc<Mutex<Vec<u8>>>,
    /// The current working directory
    pub cwd: Arc<Mutex<Vec<u8>>>,
    /// Kernel events
    pub events: Arc<WaitQueue<Event>>,
    /// The process environment
    pub env: Arc<Mutex<BTreeMap<Box<[u8]>, Arc<Mutex<Vec<u8>>>>>>,
    /// The open files in the scheme
    pub files: Arc<Mutex<Vec<Option<File>>>>
}

impl Context {
    pub fn new(id: ContextId) -> Context {
        Context {
            id: id,
            ppid: ContextId::from(0),
            ruid: 0,
            rgid: 0,
            rns: SchemeNamespace::from(0),
            euid: 0,
            egid: 0,
            ens: SchemeNamespace::from(0),
            status: Status::Blocked,
            running: false,
            cpu_id: None,
            vfork: false,
            waitpid: Arc::new(WaitMap::new()),
            pending: VecDeque::new(),
            wake: None,
            arch: arch::context::Context::new(),
            kfx: None,
            kstack: None,
            image: Vec::new(),
            heap: None,
            stack: None,
            tls: None,
            grants: Arc::new(Mutex::new(Vec::new())),
            name: Arc::new(Mutex::new(Vec::new())),
            cwd: Arc::new(Mutex::new(Vec::new())),
            events: Arc::new(WaitQueue::new()),
            env: Arc::new(Mutex::new(BTreeMap::new())),
            files: Arc::new(Mutex::new(Vec::new()))
        }
    }

    /// Make a relative path absolute
    /// Given a cwd of "scheme:/path"
    /// This function will turn "foo" into "scheme:/path/foo"
    /// "/foo" will turn into "scheme:/foo"
    /// "bar:/foo" will be used directly, as it is already absolute
    pub fn canonicalize(&self, path: &[u8]) -> Vec<u8> {
        if path.iter().position(|&b| b == b':').is_none() {
            let cwd = self.cwd.lock();
            if path == b"." {
                cwd.clone()
            } else if path == b".." {
                cwd[..cwd[..cwd.len() - 1]
                                   .iter().rposition(|&b| b == b'/' || b == b':')
                                   .map_or(cwd.len(), |i| i + 1)]
                   .to_vec()
            } else if path.starts_with(b"./") {
                let mut canon = cwd.clone();
                if ! canon.ends_with(b"/") {
                    canon.push(b'/');
                }
                canon.extend_from_slice(&path[2..]);
                canon
            } else if path.starts_with(b"../") {
                let mut canon = cwd[..cwd[..cwd.len() - 1]
                                   .iter().rposition(|&b| b == b'/' || b == b':')
                                   .map_or(cwd.len(), |i| i + 1)]
                   .to_vec();
                canon.extend_from_slice(&path[3..]);
                canon
            } else if path.starts_with(b"/") {
                let mut canon = cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec();
                canon.extend_from_slice(&path);
                canon
            } else {
                let mut canon = cwd.clone();
                if ! canon.ends_with(b"/") {
                    canon.push(b'/');
                }
                canon.extend_from_slice(&path);
                canon
            }
        } else {
            path.to_vec()
        }
    }

    /// Block the context, and return true if it was runnable before being blocked
    pub fn block(&mut self) -> bool {
        if self.status == Status::Runnable {
            self.status = Status::Blocked;
            true
        } else {
            false
        }
    }

    /// Unblock context, and return true if it was blocked before being marked runnable
    pub fn unblock(&mut self) -> bool {
        if self.status == Status::Blocked {
            self.status = Status::Runnable;
            if let Some(cpu_id) = self.cpu_id {
                if cpu_id != ::cpu_id() {
                    // Send IPI if not on current CPU
                    // TODO: Make this more architecture independent
                    unsafe { arch::device::local_apic::LOCAL_APIC.ipi(cpu_id) };
                }
            }
            true
        } else {
            false
        }
    }

    /// Add a file to the lowest available slot.
    /// Return the file descriptor number or None if no slot was found
    pub fn add_file(&self, file: File) -> Option<FileHandle> {
        let mut files = self.files.lock();
        for (i, mut file_option) in files.iter_mut().enumerate() {
            if file_option.is_none() {
                *file_option = Some(file);
                return Some(FileHandle::from(i));
            }
        }
        let len = files.len();
        if len < super::CONTEXT_MAX_FILES {
            files.push(Some(file));
            Some(FileHandle::from(len))
        } else {
            None
        }
    }

    /// Get a file
    pub fn get_file(&self, i: FileHandle) -> Option<File> {
        let files = self.files.lock();
        if i.into() < files.len() {
            files[i.into()]
        } else {
            None
        }
    }

    /// Insert a file with a specific handle number. This is used by dup2
    /// Return the file descriptor number or None if the slot was not empty, or i was invalid
    pub fn insert_file(&self, i: FileHandle, file: File) -> Option<FileHandle> {
        let mut files = self.files.lock();
        if i.into() < super::CONTEXT_MAX_FILES {
            while i.into() >= files.len() {
                files.push(None);
            }
            if files[i.into()].is_none() {
                files[i.into()] = Some(file);
                Some(i)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Remove a file
    // TODO: adjust files vector to smaller size if possible
    pub fn remove_file(&self, i: FileHandle) -> Option<File> {
        let mut files = self.files.lock();
        if i.into() < files.len() {
            files[i.into()].take()
        } else {
            None
        }
    }
}
<commit_msg>Allow for more complicated directory paths<commit_after>use alloc::arc::Arc;
use alloc::boxed::Box;
use collections::{BTreeMap, Vec, VecDeque};
use spin::Mutex;

use arch;
use context::file::File;
use context::memory::{Grant, Memory, SharedMemory, Tls};
use scheme::{SchemeNamespace, FileHandle};
use syscall::data::Event;
use sync::{WaitMap, WaitQueue};

/// Unique identifier for a context (i.e. `pid`).
use ::core::sync::atomic::AtomicUsize;
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);

/// The status of a context - used for scheduling
/// See syscall::process::waitpid and the sync module for examples of usage
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Status {
    Runnable,
    Blocked,
    Exited(usize)
}

/// A context, which identifies either a process or a thread
#[derive(Debug)]
pub struct Context {
    /// The ID of this context
    pub id: ContextId,
    /// The ID of the parent context
    pub ppid: ContextId,
    /// The real user id
    pub ruid: u32,
    /// The real group id
    pub rgid: u32,
    /// The real namespace id
    pub rns: SchemeNamespace,
    /// The effective user id
    pub euid: u32,
    /// The effective group id
    pub egid: u32,
    /// The effective namespace id
    pub ens: SchemeNamespace,
    /// Status of context
    pub status: Status,
    /// Context running or not
    pub running: bool,
    /// CPU ID, if locked
    pub cpu_id: Option<usize>,
    /// Context is halting parent
    pub vfork: bool,
    /// Context is being waited on
    pub waitpid: Arc<WaitMap<ContextId, usize>>,
    /// Context should handle pending signals
    pub pending: VecDeque<u8>,
    /// Context should wake up at specified time
    pub wake: Option<(u64, u64)>,
    /// The architecture specific context
    pub arch: arch::context::Context,
    /// Kernel FX - used to store SIMD and FPU registers on context switch
    pub kfx: Option<Box<[u8]>>,
    /// Kernel stack
    pub kstack: Option<Box<[u8]>>,
    /// Executable image
    pub image: Vec<SharedMemory>,
    /// User heap
    pub heap: Option<SharedMemory>,
    /// User stack
    pub stack: Option<Memory>,
    /// User Thread local storage
    pub tls: Option<Tls>,
    /// User grants
    pub grants: Arc<Mutex<Vec<Grant>>>,
    /// The name of the context
    pub name: Arc<Mutex<Vec<u8>>>,
    /// The current working directory
    pub cwd: Arc<Mutex<Vec<u8>>>,
    /// Kernel events
    pub events: Arc<WaitQueue<Event>>,
    /// The process environment
    pub env: Arc<Mutex<BTreeMap<Box<[u8]>, Arc<Mutex<Vec<u8>>>>>>,
    /// The open files in the scheme
    pub files: Arc<Mutex<Vec<Option<File>>>>
}

impl Context {
    pub fn new(id: ContextId) -> Context {
        Context {
            id: id,
            ppid: ContextId::from(0),
            ruid: 0,
            rgid: 0,
            rns: SchemeNamespace::from(0),
            euid: 0,
            egid: 0,
            ens: SchemeNamespace::from(0),
            status: Status::Blocked,
            running: false,
            cpu_id: None,
            vfork: false,
            waitpid: Arc::new(WaitMap::new()),
            pending: VecDeque::new(),
            wake: None,
            arch: arch::context::Context::new(),
            kfx: None,
            kstack: None,
            image: Vec::new(),
            heap: None,
            stack: None,
            tls: None,
            grants: Arc::new(Mutex::new(Vec::new())),
            name: Arc::new(Mutex::new(Vec::new())),
            cwd: Arc::new(Mutex::new(Vec::new())),
            events: Arc::new(WaitQueue::new()),
            env: Arc::new(Mutex::new(BTreeMap::new())),
            files: Arc::new(Mutex::new(Vec::new()))
        }
    }

    /// Make a relative path absolute
    /// Given a cwd of "scheme:/path"
    /// This function will turn "foo" into "scheme:/path/foo"
    /// "/foo" will turn into "scheme:/foo"
    /// "bar:/foo" will be used directly, as it is already absolute
    pub fn canonicalize(&self, path: &[u8]) -> Vec<u8> {
        if path.iter().position(|&b| b == b':').is_none() {
            let cwd = self.cwd.lock();
            if path == b"." {
                cwd.clone()
            } else if path == b".." {
                cwd[..cwd[..cwd.len() - 1]
                                   .iter().rposition(|&b| b == b'/' || b == b':')
                                   .map_or(cwd.len(), |i| i + 1)]
                   .to_vec()
            } else if path.starts_with(b"/") {
                let mut canon = cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec();
                canon.extend_from_slice(&path);
                canon
            } else {
                let mut canon = cwd.clone();
                if ! canon.ends_with(b"/") {
                    canon.push(b'/');
                }
                canon.extend_from_slice(&path);
                // NOTE: assumes the scheme does not include anything like "../" or "./"
                let rparts = canon.split(|&c| c == b'/')
                    .filter(|&part| part != b".")
                    .rev()
                    .scan(0, |nskip, part| {
                        if part == b".." {
                            *nskip += 1;
                            Some(None)
                        } else {
                            if *nskip > 0 {
                                *nskip -= 1;
                                Some(None)
                            } else {
                                Some(Some(part))
                            }
                        }
                    })
                    .filter_map(|x| x)
                    .collect::<Vec<_>>();
                let mut result = rparts
                    .iter()
                    .rev()
                    .fold(Vec::new(), |mut vec, &part| {
                        vec.extend_from_slice(part);
                        vec.push(b'/');
                        vec
                    });
                result.pop(); // remove extra '/'
                result
        } else {
            path.to_vec()
        }
    }

    /// Block the context, and return true if it was runnable before being blocked
    pub fn block(&mut self) -> bool {
        if self.status == Status::Runnable {
            self.status = Status::Blocked;
            true
        } else {
            false
        }
    }

    /// Unblock context, and return true if it was blocked before being marked runnable
    pub fn unblock(&mut self) -> bool {
        if self.status == Status::Blocked {
            self.status = Status::Runnable;
            if let Some(cpu_id) = self.cpu_id {
                if cpu_id != ::cpu_id() {
                    // Send IPI if not on current CPU
                    // TODO: Make this more architecture independent
                    unsafe { arch::device::local_apic::LOCAL_APIC.ipi(cpu_id) };
                }
            }
            true
        } else {
            false
        }
    }

    /// Add a file to the lowest available slot.
    /// Return the file descriptor number or None if no slot was found
    pub fn add_file(&self, file: File) -> Option<FileHandle> {
        let mut files = self.files.lock();
        for (i, mut file_option) in files.iter_mut().enumerate() {
            if file_option.is_none() {
                *file_option = Some(file);
                return Some(FileHandle::from(i));
            }
        }
        let len = files.len();
        if len < super::CONTEXT_MAX_FILES {
            files.push(Some(file));
            Some(FileHandle::from(len))
        } else {
            None
        }
    }

    /// Get a file
    pub fn get_file(&self, i: FileHandle) -> Option<File> {
        let files = self.files.lock();
        if i.into() < files.len() {
            files[i.into()]
        } else {
            None
        }
    }

    /// Insert a file with a specific handle number. This is used by dup2
    /// Return the file descriptor number or None if the slot was not empty, or i was invalid
    pub fn insert_file(&self, i: FileHandle, file: File) -> Option<FileHandle> {
        let mut files = self.files.lock();
        if i.into() < super::CONTEXT_MAX_FILES {
            while i.into() >= files.len() {
                files.push(None);
            }
            if files[i.into()].is_none() {
                files[i.into()] = Some(file);
                Some(i)
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Remove a file
    // TODO: adjust files vector to smaller size if possible
    pub fn remove_file(&self, i: FileHandle) -> Option<File> {
        let mut files = self.files.lock();
        if i.into() < files.len() {
            files[i.into()].take()
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use syn;
use options::{OptionsBuilder, OptionsBuilderMode, parse_lit_as_string, parse_lit_as_bool, parse_lit_as_path, FieldMode, StructOptions};
use derive_builder_core::{DeprecationNotes, Bindings};

#[derive(Debug, Clone)]
pub struct StructMode {
    build_fn_name: Option<String>,
    build_fn_enabled: Option<bool>,
    build_target_name: String,
    build_target_generics: syn::Generics,
    build_target_vis: syn::Visibility,
    builder_name: Option<String>,
    builder_vis: Option<syn::Visibility>,
    deprecation_notes: DeprecationNotes,
    validator_fn: Option<syn::Path>,
    struct_size_hint: usize,
}

impl OptionsBuilder<StructMode> {
    pub fn parse(ast: &syn::MacroInput) -> Self {
        trace!("Parsing struct `{}`.", ast.ident.as_ref());

        // Note: Set `build_target_name` _before_ parsing attributes, for better diagnostics!
        let mut builder = Self::from(StructMode {
            build_fn_name: None,
            build_fn_enabled: true,
            build_target_name: ast.ident.as_ref().to_string(),
            build_target_generics: ast.generics.clone(),
            build_target_vis: ast.vis.clone(),
            builder_name: None,
            builder_vis: None,
            deprecation_notes: Default::default(),
            validator_fn: None,
            struct_size_hint: 0,
        });

        builder.parse_attributes(&ast.attrs);

        builder
    }
}

impl StructMode {
    impl_setter!{
        ident: builder_name,
        desc: "builder name",
        map: |x: String| { x },
    }

    impl_setter!{
        ident: build_fn_name,
        desc: "build function name",
        map: |x: String| { x },
    }

    impl_setter!{
        ident: build_fn_enabled,
        desc: "build function enabled",
        map: |x: bool| { x },
    }

    impl_setter!{
        ident: validator_fn,
        desc: "validator function path",
        map: |x: syn::Path| { x },
    }

    #[allow(non_snake_case)]
    fn parse_build_fn_options_metaItem(&mut self, meta_item: &syn::MetaItem) {
        trace!("Build Method Options - Parsing MetaItem `{:?}`.", meta_item);
        match *meta_item {
            syn::MetaItem::Word(ref ident) => {
                self.parse_build_fn_options_word(ident)
            },
            syn::MetaItem::NameValue(ref ident, ref lit) => {
                self.parse_build_fn_options_nameValue(ident, lit)
            },
            syn::MetaItem::List(ref ident, ref nested_attrs) => {
                self.parse_build_fn_options_list(ident, nested_attrs)
            }
        }
    }

    #[allow(non_snake_case)]
    fn parse_build_fn_options_nameValue(&mut self, ident: &syn::Ident, lit: &syn::Lit) {
        trace!("Build fn Options - Parsing named value `{}` = `{:?}`", ident.as_ref(), lit);
        match ident.as_ref() {
            "name" => {
                self.parse_build_fn_name(lit)
            },
            "skip" => {
                self.parse_build_fn_skip(lit)
            },
            "validator" => {
                self.parse_build_fn_validator(lit)
            },
            _ => {
                panic!("Unknown build_fn option `{}` {}.", ident.as_ref(), self.where_diagnostics())
            }
        }
    }

    /// e.g `private` in `#[builder(build_fn(private))]`
    fn parse_build_fn_options_word(&mut self, ident: &syn::Ident) {
        trace!("Setter Options - Parsing word `{}`", ident.as_ref());
        match ident.as_ref() {
            "skip" => {
                self.build_fn_enabled(false);
            }
            _ => {
                panic!("Unknown build_fn option `{}` {}.", ident.as_ref(), self.where_diagnostics())
            }
        };
    }

    #[allow(non_snake_case)]
    fn parse_build_fn_options_list(
        &mut self,
        ident: &syn::Ident,
        nested: &[syn::NestedMetaItem]
    ) {
        trace!("Build fn Options - Parsing list `{}({:?})`", ident.as_ref(), nested);
        match ident.as_ref() {
            _ => {
                panic!("Unknown option `{}` {}.", ident.as_ref(), self.where_diagnostics())
            }
        }
    }

    fn parse_build_fn_name(&mut self, lit: &syn::Lit) {
        trace!("Parsing build function name `{:?}`", lit);
        let value = parse_lit_as_string(lit).unwrap();
        self.build_fn_name(value.clone())
    }

    #[allow(dead_code,unused_variables)]
    fn parse_build_fn_skip(&mut self, skip: &syn::Lit) {
        self.build_fn_enabled(!parse_lit_as_bool(skip).unwrap());
    }

    fn parse_build_fn_validator(&mut self, lit: &syn::Lit) {
        trace!("Parsing build function validator path `{:?}`", lit);
        let value = parse_lit_as_path(lit).unwrap();
        self.validator_fn(value);
    }
}

impl OptionsBuilderMode for StructMode {
    fn parse_builder_name(&mut self, name: &syn::Lit) {
        trace!("Parsing builder name `{:?}`", name);
        let value = parse_lit_as_string(name).unwrap();
        self.builder_name(value.clone());
    }

    fn parse_build_fn_options(&mut self, nested: &[syn::NestedMetaItem]) {
        for x in nested {
            match *x {
                syn::NestedMetaItem::MetaItem(ref meta_item) => {
                    self.parse_build_fn_options_metaItem(meta_item);
                },
                syn::NestedMetaItem::Literal(ref lit) => {
                    error!("Expected NestedMetaItem::MetaItem, found `{:?}`.", x);
                    panic!("Could not parse builder option `{:?}` {}.",
                           lit,
                           self.where_diagnostics());
                }
            }
        }
    }

    fn push_deprecation_note<T: Into<String>>(&mut self, x: T) -> &mut Self {
        self.deprecation_notes.push(x.into());
        self
    }

    /// Provide a diagnostic _where_-clause for panics.
    fn where_diagnostics(&self) -> String {
        format!("on struct `{}`", self.build_target_name)
    }

    fn struct_mode(&self) -> bool {
        true
    }
}

impl From<OptionsBuilder<StructMode>> for (StructOptions, OptionsBuilder<FieldMode>) {
    fn from(b: OptionsBuilder<StructMode>) -> (StructOptions, OptionsBuilder<FieldMode>) {
        #[cfg(feature = "struct_default")]
        let (field_default_expression, struct_default_expression) = (None, b.default_expression);
        #[cfg(not(feature = "struct_default"))]
        let (field_default_expression, struct_default_expression) = (b.default_expression, None);

        let field_defaults = OptionsBuilder::<FieldMode> {
            setter_enabled: b.setter_enabled,
            builder_pattern: b.builder_pattern,
            setter_name: None,
            setter_prefix: b.setter_prefix,
            setter_vis: b.setter_vis,
            setter_into: b.setter_into,
            try_setter: b.try_setter,
            default_expression: field_default_expression,
            no_std: b.no_std,
            mode: {
                let mut mode = FieldMode::default();
                mode.use_default_struct = struct_default_expression.is_some();
                mode
            },
        };

        let m = b.mode;

        let struct_options = StructOptions {
            build_fn_enabled: m.build_fn_enabled.unwrap_or(true),
            build_fn_name: syn::Ident::new(
                m.build_fn_name.unwrap_or("build".to_string())
            ),
            builder_ident: syn::Ident::new(
                m.builder_name.unwrap_or(format!("{}Builder", m.build_target_name))
            ),
            builder_visibility: m.builder_vis.unwrap_or(m.build_target_vis),
            builder_pattern: b.builder_pattern.unwrap_or_default(),
            build_target_ident: syn::Ident::new(m.build_target_name),
            deprecation_notes: m.deprecation_notes,
            generics: m.build_target_generics,
            struct_size_hint: m.struct_size_hint,
            bindings: Bindings {
                no_std: b.no_std.unwrap_or(false),
            },
            default_expression: struct_default_expression,
            validation_fn: m.validator_fn,
        };

        (struct_options, field_defaults)
    }
}
<commit_msg>Resolve merge hiccup with build_fn<commit_after>use syn;
use options::{OptionsBuilder, OptionsBuilderMode, parse_lit_as_string, parse_lit_as_bool, parse_lit_as_path, FieldMode, StructOptions};
use derive_builder_core::{DeprecationNotes, Bindings};

#[derive(Debug, Clone)]
pub struct StructMode {
    build_fn_name: Option<String>,
    build_fn_enabled: Option<bool>,
    build_target_name: String,
    build_target_generics: syn::Generics,
    build_target_vis: syn::Visibility,
    builder_name: Option<String>,
    builder_vis: Option<syn::Visibility>,
    deprecation_notes: DeprecationNotes,
    validator_fn: Option<syn::Path>,
    struct_size_hint: usize,
}

impl OptionsBuilder<StructMode> {
    pub fn parse(ast: &syn::MacroInput) -> Self {
        trace!("Parsing struct `{}`.", ast.ident.as_ref());

        // Note: Set `build_target_name` _before_ parsing attributes, for better diagnostics!
        let mut builder = Self::from(StructMode {
            build_fn_name: None,
            build_fn_enabled: None,
            build_target_name: ast.ident.as_ref().to_string(),
            build_target_generics: ast.generics.clone(),
            build_target_vis: ast.vis.clone(),
            builder_name: None,
            builder_vis: None,
            deprecation_notes: Default::default(),
            validator_fn: None,
            struct_size_hint: 0,
        });

        builder.parse_attributes(&ast.attrs);

        builder
    }
}

impl StructMode {
    impl_setter!{
        ident: builder_name,
        desc: "builder name",
        map: |x: String| { x },
    }

    impl_setter!{
        ident: build_fn_name,
        desc: "build function name",
        map: |x: String| { x },
    }

    impl_setter!{
        ident: build_fn_enabled,
        desc: "build function enabled",
        map: |x: bool| { x },
    }

    impl_setter!{
        ident: validator_fn,
        desc: "validator function path",
        map: |x: syn::Path| { x },
    }

    #[allow(non_snake_case)]
    fn parse_build_fn_options_metaItem(&mut self, meta_item: &syn::MetaItem) {
        trace!("Build Method Options - Parsing MetaItem `{:?}`.", meta_item);
        match *meta_item {
            syn::MetaItem::Word(ref ident) => {
                self.parse_build_fn_options_word(ident)
            },
            syn::MetaItem::NameValue(ref ident, ref lit) => {
                self.parse_build_fn_options_nameValue(ident, lit)
            },
            syn::MetaItem::List(ref ident, ref nested_attrs) => {
                self.parse_build_fn_options_list(ident, nested_attrs)
            }
        }
    }

    #[allow(non_snake_case)]
    fn parse_build_fn_options_nameValue(&mut self, ident: &syn::Ident, lit: &syn::Lit) {
        trace!("Build fn Options - Parsing named value `{}` = `{:?}`", ident.as_ref(), lit);
        match ident.as_ref() {
            "name" => {
                self.parse_build_fn_name(lit)
            },
            "skip" => {
                self.parse_build_fn_skip(lit)
            },
            "validator" => {
                self.parse_build_fn_validator(lit)
            },
            _ => {
                panic!("Unknown build_fn option `{}` {}.", ident.as_ref(), self.where_diagnostics())
            }
        }
    }

    /// e.g `private` in `#[builder(build_fn(private))]`
    fn parse_build_fn_options_word(&mut self, ident: &syn::Ident) {
        trace!("Setter Options - Parsing word `{}`", ident.as_ref());
        match ident.as_ref() {
            "skip" => {
                self.build_fn_enabled(false);
            }
            _ => {
                panic!("Unknown build_fn option `{}` {}.", ident.as_ref(), self.where_diagnostics())
            }
        };
    }

    #[allow(non_snake_case)]
    fn parse_build_fn_options_list(
        &mut self,
        ident: &syn::Ident,
        nested: &[syn::NestedMetaItem]
    ) {
        trace!("Build fn Options - Parsing list `{}({:?})`", ident.as_ref(), nested);
        match ident.as_ref() {
            _ => {
                panic!("Unknown option `{}` {}.", ident.as_ref(), self.where_diagnostics())
            }
        }
    }

    fn parse_build_fn_name(&mut self, lit: &syn::Lit) {
        trace!("Parsing build function name `{:?}`", lit);
        let value = parse_lit_as_string(lit).unwrap();
        self.build_fn_name(value.clone())
    }

    #[allow(dead_code,unused_variables)]
    fn parse_build_fn_skip(&mut self, skip: &syn::Lit) {
        self.build_fn_enabled(!parse_lit_as_bool(skip).unwrap());
    }

    fn parse_build_fn_validator(&mut self, lit: &syn::Lit) {
        trace!("Parsing build function validator path `{:?}`", lit);
        let value = parse_lit_as_path(lit).unwrap();
        self.validator_fn(value);
    }
}

impl OptionsBuilderMode for StructMode {
    fn parse_builder_name(&mut self, name: &syn::Lit) {
        trace!("Parsing builder name `{:?}`", name);
        let value = parse_lit_as_string(name).unwrap();
        self.builder_name(value.clone());
    }

    fn parse_build_fn_options(&mut self, nested: &[syn::NestedMetaItem]) {
        for x in nested {
            match *x {
                syn::NestedMetaItem::MetaItem(ref meta_item) => {
                    self.parse_build_fn_options_metaItem(meta_item);
                },
                syn::NestedMetaItem::Literal(ref lit) => {
                    error!("Expected NestedMetaItem::MetaItem, found `{:?}`.", x);
                    panic!("Could not parse builder option `{:?}` {}.",
                           lit,
                           self.where_diagnostics());
                }
            }
        }
    }

    fn push_deprecation_note<T: Into<String>>(&mut self, x: T) -> &mut Self {
        self.deprecation_notes.push(x.into());
        self
    }

    /// Provide a diagnostic _where_-clause for panics.
    fn where_diagnostics(&self) -> String {
        format!("on struct `{}`", self.build_target_name)
    }

    fn struct_mode(&self) -> bool {
        true
    }
}

impl From<OptionsBuilder<StructMode>> for (StructOptions, OptionsBuilder<FieldMode>) {
    fn from(b: OptionsBuilder<StructMode>) -> (StructOptions, OptionsBuilder<FieldMode>) {
        #[cfg(feature = "struct_default")]
        let (field_default_expression, struct_default_expression) = (None, b.default_expression);
        #[cfg(not(feature = "struct_default"))]
        let (field_default_expression, struct_default_expression) = (b.default_expression, None);

        let field_defaults = OptionsBuilder::<FieldMode> {
            setter_enabled: b.setter_enabled,
            builder_pattern: b.builder_pattern,
            setter_name: None,
            setter_prefix: b.setter_prefix,
            setter_vis: b.setter_vis,
            setter_into: b.setter_into,
            try_setter: b.try_setter,
            default_expression: field_default_expression,
            no_std: b.no_std,
            mode: {
                let mut mode = FieldMode::default();
                mode.use_default_struct = struct_default_expression.is_some();
                mode
            },
        };

        let m = b.mode;

        let struct_options = StructOptions {
            build_fn_enabled: m.build_fn_enabled.unwrap_or(true),
            build_fn_name: syn::Ident::new(
                m.build_fn_name.unwrap_or("build".to_string())
            ),
            builder_ident: syn::Ident::new(
                m.builder_name.unwrap_or(format!("{}Builder", m.build_target_name))
            ),
            builder_visibility: m.builder_vis.unwrap_or(m.build_target_vis),
            builder_pattern: b.builder_pattern.unwrap_or_default(),
            build_target_ident: syn::Ident::new(m.build_target_name),
            deprecation_notes: m.deprecation_notes,
            generics: m.build_target_generics,
            struct_size_hint: m.struct_size_hint,
            bindings: Bindings {
                no_std: b.no_std.unwrap_or(false),
            },
            default_expression: struct_default_expression,
            validation_fn: m.validator_fn,
        };

        (struct_options, field_defaults)
    }
}
<|endoftext|>


<commit_before>use super::{GossipError, GossipResult};
use std::collections::HashMap;
use uuid::Uuid;
use bincode::{serialize, deserialize, Infinite};
use std::cmp::{PartialOrd, Ordering};
use std::net::Ipv4Addr;
use super::gossip::Message;

#[derive(Debug, PartialEq, Serialize, Deserialize, Hash, Eq, PartialOrd)]
enum ApplicationState {
    Status,
    Load,
    Schema,
    Datacenter,
    Rack,
    Version,
    InternalIp,
    HostId,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct VersionedValue {
    version: i64,
    value: String,
}

impl PartialOrd for VersionedValue {
    fn partial_cmp(&self, other: &VersionedValue) -> Option<Ordering> {
        self.version.partial_cmp(&other.version)
    }

}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct NodeState {
    is_up: bool,
    id: Uuid,
    address: Ipv4Addr,
    port: usize,
    state: HashMap<ApplicationState, VersionedValue>,
}

impl NodeState {
    fn new(ip: Ipv4Addr, port: usize) -> NodeState {
        let id = Uuid::new_v4();

        NodeState{is_up: false,
            id: id,
            address: ip,
            port: port,
            state: HashMap::new()
            }
    }
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct ClusterState {
    nodes: Vec<NodeState>,
}

impl ClusterState {
    pub fn new() -> ClusterState {
        ClusterState{nodes:Vec::new()}
    }

    pub fn handle(&mut self, message: Message) -> Message {
        match message {
            Message::Join(uuid, addr, port) => {
                self.handle_join(uuid, addr, port);
                Message::ReceivedOK
            },
            _ => Message::ReceivedOK
        }
    }

    pub fn handle_join(&mut self, uuid: Uuid, addr: String, port: usize) -> Message {
        let node = NodeState::new(addr.parse().unwrap(), port);
        self.nodes.push(node);
        Message::ReceivedOK
    }

    fn update(&mut self, node: Uuid, state: NodeState) -> GossipResult<()> {
        Err(GossipError::OldState)
    }

    pub fn node_count(&self) -> usize {
        self.nodes.len()
    }

}<commit_msg>working on handle_join<commit_after>use super::{GossipError, GossipResult};
use std::collections::HashMap;
use uuid::Uuid;
use bincode::{serialize, deserialize, Infinite};
use std::cmp::{PartialOrd, Ordering};
use std::net::Ipv4Addr;
use super::gossip::Message;

#[derive(Debug, PartialEq, Serialize, Deserialize, Hash, Eq, PartialOrd)]
enum ApplicationState {
    Status,
    Load,
    Schema,
    Datacenter,
    Rack,
    Version,
    InternalIp,
    HostId,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct VersionedValue {
    version: i64,
    value: String,
}

impl PartialOrd for VersionedValue {
    fn partial_cmp(&self, other: &VersionedValue) -> Option<Ordering> {
        self.version.partial_cmp(&other.version)
    }

}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct NodeState {
    is_up: bool,
    id: Uuid,
    address: Ipv4Addr,
    port: usize,
    state: HashMap<ApplicationState, VersionedValue>,
}

impl NodeState {
    fn new(ip: Ipv4Addr, port: usize) -> NodeState {
        let id = Uuid::new_v4();

        NodeState{is_up: false,
            id: id,
            address: ip,
            port: port,
            state: HashMap::new()
            }
    }
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct ClusterState {
    nodes: Vec<NodeState>,
}

impl ClusterState {
    pub fn new() -> ClusterState {
        ClusterState{nodes:Vec::new()}
    }

    pub fn handle(&mut self, message: Message) -> Message {
        match message {
            Message::Join(uuid, addr, port) => {
                self.handle_join(uuid, addr, port)
            },
            _ => Message::ReceivedOK
        }
    }

    pub fn handle_join(&mut self, uuid: Uuid, addr: String, port: usize) -> Message {
        let node = NodeState::new(addr.parse().unwrap(), port);
        self.nodes.push(node);
        Message::ReceivedOK
    }

    fn update(&mut self, node: Uuid, state: NodeState) -> GossipResult<()> {
        Err(GossipError::OldState)
    }

    pub fn node_count(&self) -> usize {
        self.nodes.len()
    }

}<|endoftext|>


<commit_before>use helpers::HelperDef;
use registry::Registry;
use context::{Context, JsonTruthy};
use render::{Renderable, RenderContext, RenderError, Helper};

#[derive(Clone, Copy)]
pub struct IfHelper {
    positive: bool,
}

impl HelperDef for IfHelper {
    fn call(&self,
            c: &Context,
            h: &Helper,
            r: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let param = try!(h.param(0)
                          .ok_or_else(|| RenderError::new("Param not found for helper \"if\"")));

        let mut value = param.value().is_truthy();

        if !self.positive {
            value = !value;
        }

        let tmpl = if value {
            h.template()
        } else {
            h.inverse()
        };
        match tmpl {
            Some(ref t) => t.render(c, r, rc),
            None => Ok(()),
        }
    }
}

pub static IF_HELPER: IfHelper = IfHelper { positive: true };
pub static UNLESS_HELPER: IfHelper = IfHelper { positive: false };

#[cfg(test)]
mod test {
    use template::Template;
    use registry::Registry;
    #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
    use serialize::json::Json;
    use helpers::WITH_HELPER;

    #[test]
    fn test_if() {
        let t0 = Template::compile("{{#if this}}hello{{/if}}".to_string()).ok().unwrap();
        let t1 = Template::compile("{{#unless this}}hello{{else}}world{{/unless}}".to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);

        let r0 = handlebars.render("t0", &true);
        assert_eq!(r0.ok().unwrap(), "hello".to_string());

        let r1 = handlebars.render("t1", &true);
        assert_eq!(r1.ok().unwrap(), "world".to_string());

        let r2 = handlebars.render("t0", &false);
        assert_eq!(r2.ok().unwrap(), "".to_string());
    }

    #[test]
    #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
    fn test_if_context() {
        let json_str = r#"{"a":{"b":99,"c":{"d": true}}}"#;
        let data = Json::from_str(json_str).unwrap();

        let t0 = Template::compile("{{#if a.c.d}}hello {{a.b}}{{/if}}".to_string())
                     .ok()
                     .unwrap();
        let t1 = Template::compile("{{#with a}}{{#if c.d}}hello {{../a.b}}{{/if}}{{/with}}"
                                       .to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_helper("with", Box::new(WITH_HELPER));
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);

        let r0 = handlebars.render("t0", &data);
        assert_eq!(r0.ok().unwrap(), "hello 99".to_string());

        let r1 = handlebars.render("t1", &data);
        assert_eq!(r1.ok().unwrap(), "hello 99".to_string());
    }
}
<commit_msg>(chore) remove unused imports<commit_after>use helpers::HelperDef;
use registry::Registry;
use context::{Context, JsonTruthy};
use render::{Renderable, RenderContext, RenderError, Helper};

#[derive(Clone, Copy)]
pub struct IfHelper {
    positive: bool,
}

impl HelperDef for IfHelper {
    fn call(&self,
            c: &Context,
            h: &Helper,
            r: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let param = try!(h.param(0)
                          .ok_or_else(|| RenderError::new("Param not found for helper \"if\"")));

        let mut value = param.value().is_truthy();

        if !self.positive {
            value = !value;
        }

        let tmpl = if value {
            h.template()
        } else {
            h.inverse()
        };
        match tmpl {
            Some(ref t) => t.render(c, r, rc),
            None => Ok(()),
        }
    }
}

pub static IF_HELPER: IfHelper = IfHelper { positive: true };
pub static UNLESS_HELPER: IfHelper = IfHelper { positive: false };

#[cfg(test)]
mod test {
    use template::Template;
    use registry::Registry;
    #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
    use serialize::json::Json;

    #[test]
    fn test_if() {
        let t0 = Template::compile("{{#if this}}hello{{/if}}".to_string()).ok().unwrap();
        let t1 = Template::compile("{{#unless this}}hello{{else}}world{{/unless}}".to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);

        let r0 = handlebars.render("t0", &true);
        assert_eq!(r0.ok().unwrap(), "hello".to_string());

        let r1 = handlebars.render("t1", &true);
        assert_eq!(r1.ok().unwrap(), "world".to_string());

        let r2 = handlebars.render("t0", &false);
        assert_eq!(r2.ok().unwrap(), "".to_string());
    }

    #[test]
    #[cfg(all(feature = "rustc_ser_type", not(feature = "serde_type")))]
    fn test_if_context() {
        let json_str = r#"{"a":{"b":99,"c":{"d": true}}}"#;
        let data = Json::from_str(json_str).unwrap();

        let t0 = Template::compile("{{#if a.c.d}}hello {{a.b}}{{/if}}".to_string())
                     .ok()
                     .unwrap();
        let t1 = Template::compile("{{#with a}}{{#if c.d}}hello {{../a.b}}{{/if}}{{/with}}"
                                       .to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_helper("with", Box::new(WITH_HELPER));
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);

        let r0 = handlebars.render("t0", &data);
        assert_eq!(r0.ok().unwrap(), "hello 99".to_string());

        let r1 = handlebars.render("t1", &data);
        assert_eq!(r1.ok().unwrap(), "hello 99".to_string());
    }
}
<|endoftext|>


<commit_before>use std::convert::{From, Into};
use std::error::Error;
use std::str::FromStr;
use std::hash::Hash;

#[derive(Debug)]
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Eq)]
// #[derive(Display)]
#[derive(Hash)]
pub enum FileIDType {
    UUID,
}

pub enum FileIDTypeParseError {
    UnknownType
}

impl FromStr for FileIDType {
    type Err = FileIDTypeParseError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "UUID" => Ok(FileIDType::UUID),
            _ => Err(FileIDTypeParseError::UnknownType)
        }
    }
}

impl Into<String> for FileIDType {

    fn into(self) -> String {
        match self {
            FileIDType::UUID    => String::from("UUID"),
        }
    }
}

<commit_msg>Add docs to FileIDType<commit_after>use std::convert::{From, Into};
use std::error::Error;
use std::str::FromStr;
use std::hash::Hash;

#[derive(Debug)]
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Eq)]
// #[derive(Display)]
#[derive(Hash)]
/**
 * File ID type
 *
 * Currently only UUID is available. Maybe this will be the only type available at all.
 */
pub enum FileIDType {
    UUID,
}

pub enum FileIDTypeParseError {
    UnknownType
}

impl FromStr for FileIDType {
    type Err = FileIDTypeParseError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "UUID" => Ok(FileIDType::UUID),
            _ => Err(FileIDTypeParseError::UnknownType)
        }
    }
}

impl Into<String> for FileIDType {

    fn into(self) -> String {
        match self {
            FileIDType::UUID    => String::from("UUID"),
        }
    }
}

<|endoftext|>


<commit_before>// -*- rust -*-

use std;
import std::io;
import std::str;

fn test_simple(str tmpfilebase) {
  let str tmpfile = tmpfilebase + ".tmp";
  log tmpfile;
  let str frood = "A hoopy frood who really knows where his towel is.";
  log frood;

  {
    let io::writer out = io::file_writer(tmpfile, [io::create]);
    out.write_str(frood);
  }

  let io::reader inp = io::file_reader(tmpfile);
  let str frood2 = inp.read_c_str();
  log frood2;
  assert (str::eq(frood, frood2));
}

fn main(vec[str] argv) {
  test_simple(argv.(0));
}
<commit_msg>Re-xfail lib-io test. Seems to only work on Linux<commit_after>// xfail-stage0
// xfail-stage1
// xfail-stage2
// -*- rust -*-

use std;
import std::io;
import std::str;

fn test_simple(str tmpfilebase) {
  let str tmpfile = tmpfilebase + ".tmp";
  log tmpfile;
  let str frood = "A hoopy frood who really knows where his towel is.";
  log frood;

  {
    let io::writer out = io::file_writer(tmpfile, [io::create]);
    out.write_str(frood);
  }

  let io::reader inp = io::file_reader(tmpfile);
  let str frood2 = inp.read_c_str();
  log frood2;
  assert (str::eq(frood, frood2));
}

fn main(vec[str] argv) {
  test_simple(argv.(0));
}
<|endoftext|>


<commit_before>use std;
import std::treemap::*;
import std::option::some;
import std::option::none;
import std::str;

#[test]
fn init_treemap() { let m = init::<int, int>(); }

#[test]
fn insert_one() { let m = init(); insert(m, 1, 2); }

#[test]
fn insert_two() { let m = init(); insert(m, 1, 2); insert(m, 3, 4); }

#[test]
fn insert_find() {
    let m = init();
    insert(m, 1, 2);
    assert (find(m, 1) == some(2));
}

#[test]
fn find_empty() { let m = init::<int, int>(); assert (find(m, 1) == none); }

#[test]
fn find_not_found() {
    let m = init();
    insert(m, 1, 2);
    assert (find(m, 2) == none);
}

#[test]
fn traverse_in_order() {
    let m = init();
    insert(m, 3, ());
    insert(m, 0, ());
    insert(m, 4, ());
    insert(m, 2, ());
    insert(m, 1, ());

    let n = 0;
    fn t(&n: int, k: int, v: ()) { assert (n == k); n += 1; }
    traverse(m, bind t(n, _, _));
}

#[test]
fn u8_map() {
    let m = init();

    let k1 = str::bytes("foo");
    let k2 = str::bytes("bar");

    insert(m, k1, "foo");
    insert(m, k2, "bar");

    assert (find(m, k2) == some("bar"));
    assert (find(m, k1) == some("foo"));
}
<commit_msg>Hide unused variable warnings in stdtest::treemap<commit_after>use std;
import std::treemap::*;
import std::option::some;
import std::option::none;
import std::str;

#[test]
fn init_treemap() { let _m = init::<int, int>(); }

#[test]
fn insert_one() { let m = init(); insert(m, 1, 2); }

#[test]
fn insert_two() { let m = init(); insert(m, 1, 2); insert(m, 3, 4); }

#[test]
fn insert_find() {
    let m = init();
    insert(m, 1, 2);
    assert (find(m, 1) == some(2));
}

#[test]
fn find_empty() { let m = init::<int, int>(); assert (find(m, 1) == none); }

#[test]
fn find_not_found() {
    let m = init();
    insert(m, 1, 2);
    assert (find(m, 2) == none);
}

#[test]
fn traverse_in_order() {
    let m = init();
    insert(m, 3, ());
    insert(m, 0, ());
    insert(m, 4, ());
    insert(m, 2, ());
    insert(m, 1, ());

    let n = 0;
    fn t(&n: int, k: int, _v: ()) { assert (n == k); n += 1; }
    traverse(m, bind t(n, _, _));
}

#[test]
fn u8_map() {
    let m = init();

    let k1 = str::bytes("foo");
    let k2 = str::bytes("bar");

    insert(m, k1, "foo");
    insert(m, k2, "bar");

    assert (find(m, k2) == some("bar"));
    assert (find(m, k1) == some("foo"));
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use libimagstore::store::Entry;
use libimagstore::storeid::StoreId;

pub trait IsInDiary {

    fn is_in_diary(&self, name: &str) -> bool;

}

impl IsInDiary for Entry {

    fn is_in_diary(&self, name: &str) -> bool {
        self.get_location().clone().is_in_diary(name)
    }

}

impl IsInDiary for StoreId {

    fn is_in_diary(&self, name: &str) -> bool {
        self.local().starts_with(format!("diary/{}", name))
    }

}

<commit_msg>Add another small helper<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use libimagstore::store::Entry;
use libimagstore::storeid::StoreId;

pub trait IsInDiary {

    fn is_in_diary(&self, name: &str) -> bool;

    fn is_a_diary_entry(&self) -> bool;

}

impl IsInDiary for Entry {

    fn is_in_diary(&self, name: &str) -> bool {
        self.get_location().clone().is_in_diary(name)
    }

    fn is_a_diary_entry(&self) -> bool {
        self.get_location().clone().is_a_diary_entry()
    }

}

impl IsInDiary for StoreId {

    fn is_in_diary(&self, name: &str) -> bool {
        self.local().starts_with(format!("diary/{}", name))
    }

    fn is_a_diary_entry(&self) -> bool {
        self.local().starts_with("diary")
    }

}

<|endoftext|>