<commit_before>use base::math::*;
use std::f32::consts;

#[derive(Clone, Copy)]
pub struct Camera {
    pub position: Point3f, // PRP
    // VUV will be calculated on the fly
    // used to calculate the look_at_point
    pub theta: f32,
    pub phi: f32,
}

// Initinal values
impl Default for Camera {
    fn default() -> Camera {
        Camera {
            position: Point3::new(0.0, 0.0, 60.0),
            phi: -0.27,
            theta: 2.6,
        }
    }
}

impl Camera {
    /// Returns the projection matrix
    pub fn proj_matrix(&self) -> Matrix4<f32> {
        perspective(deg(60.0), 16.0 / 9.0, 0.1, 3_000.0)
    }

    /// Returns view matrix
    pub fn view_matrix(&self) -> Matrix4<f32> {
        Matrix4::look_at(self.position, self.get_look_at_point(), Vector3::unit_z())
    }

    /// Calculates the look_at_point by adding the current position to the
    /// look_at_vector
    pub fn get_look_at_point(&self) -> Point3f {
        self.position + self.get_look_at_vector()
    }

    /// Calculates the look_at_vector by using theta and phi on the unit sphere
    pub fn get_look_at_vector(&self) -> Vector3f {
        Vector3f::new(self.theta.sin() * self.phi.cos(),
                      self.theta.sin() * self.phi.sin(),
                      self.theta.cos())
    }

    /// Internal function to move the position of the camera

    /// Will be called by the other functions (move_forwars etc)
    pub fn move_by(&mut self, pos_diff: Vector3f) {
        self.position += pos_diff;
    }

    /// Method to call when **forward movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for foward movement
    pub fn move_forward(&mut self, factor: f32) {
        let mut lookatvector = self.get_look_at_vector();
        lookatvector.z = 0.0;
        lookatvector = lookatvector.normalize();
        lookatvector *= factor;
        self.move_by(lookatvector);
    }

    /// Method to call when **backward movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for backward movement
    pub fn move_backward(&mut self, factor: f32) {
        let mut lookatvector = self.get_look_at_vector();
        lookatvector.z = 0.0;
        lookatvector = lookatvector.normalize();
        lookatvector *= -factor;
        self.move_by(lookatvector);
    }

    /// Method to call when **left movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for left movement
    pub fn move_left(&mut self, factor: f32) {
        let mut lookatvector = self.get_look_at_vector();
        lookatvector.z = 0.0;
        lookatvector = lookatvector.normalize();
        // Get the orthogonal 2d-vector, which is 90 degrees to the left
        let mut move_dir = Vector3f::new(-lookatvector.y, lookatvector.x, 0.0);
        move_dir *= factor;
        self.move_by(move_dir);
    }

    /// Method to call when **right movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for right movement
    pub fn move_right(&mut self, factor: f32) {
        let mut lookatvector = self.get_look_at_vector();
        lookatvector.z = 0.0;
        lookatvector = lookatvector.normalize();
        // Get the orthogonal 2d-vector, which is 90 degrees to the left
        let mut move_dir = Vector3f::new(lookatvector.y, -lookatvector.x, 0.0);
        move_dir *= factor;
        self.move_by(move_dir);
    }

    /// Method to call when **upward movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for upward movement
    pub fn move_up(&mut self, factor: f32) {
        self.move_by(Vector3f::new(0.0, 0.0, factor));
    }

    /// Method to call when **downward movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for downward movement
    pub fn move_down(&mut self, factor: f32) {
        self.move_by(Vector3f::new(0.0, 0.0, -factor));
    }

    /// Changes `theta` and `phi` to essentially change the direction the
    /// camera looks
    pub fn change_dir(&mut self, theta_diff: f32, phi_diff: f32) {
        if self.theta < 0.1 {
            if theta_diff > 0.0 {
                // all the way UP, theta will not go any lower
                self.theta += theta_diff;
            }
        } else if self.theta > consts::PI - 0.1 {
            if theta_diff < 0.0 {
                // all the way DOWN, theta will not go any higher
                self.theta += theta_diff;
            }
        } else {
            self.theta += theta_diff;
        }
        self.phi += phi_diff;
    }
}
<commit_msg>add new_from_vector function to camera for the "shadow-group"<commit_after>use base::math::*;
use std::f32::consts;

#[derive(Clone, Copy)]
pub struct Camera {
    pub position: Point3f, // PRP
    // VUV will be calculated on the fly
    // used to calculate the look_at_point
    pub theta: f32,
    pub phi: f32,
}

// Initinal values
impl Default for Camera {
    fn default() -> Camera {
        Camera {
            position: Point3::new(0.0, 0.0, 60.0),
            phi: -0.27,
            theta: 2.6,
        }
    }
}

impl Camera {
    /// returns a camera based on a vector to look at
    pub fn new_from_vector(pos: Point3f, look: Vector3f) -> Self {

        let mut look_phi = ((look.x) / ((look.x * look.x + look.y * look.y).sqrt())).acos();
        if look.y < 0.0 {
            look_phi = 2.0 * consts::PI - look_phi;
        }

        let look_theta = (consts::PI / 2.0) -
                         ((look.z) / ((look.x * look.x + look.y * look.y).sqrt())).atan();

        Camera {
            position: pos,
            phi: look_phi,
            theta: look_theta,
        }

    }

    /// Returns the projection matrix
    pub fn proj_matrix(&self) -> Matrix4<f32> {
        perspective(deg(60.0), 16.0 / 9.0, 0.1, 3_000.0)
    }

    /// Returns view matrix
    pub fn view_matrix(&self) -> Matrix4<f32> {
        Matrix4::look_at(self.position, self.get_look_at_point(), Vector3::unit_z())
    }

    /// Calculates the look_at_point by adding the current position to the
    /// look_at_vector
    pub fn get_look_at_point(&self) -> Point3f {
        self.position + self.get_look_at_vector()
    }

    /// Calculates the look_at_vector by using theta and phi on the unit sphere
    pub fn get_look_at_vector(&self) -> Vector3f {
        Vector3f::new(self.theta.sin() * self.phi.cos(),
                      self.theta.sin() * self.phi.sin(),
                      self.theta.cos())
    }

    /// Internal function to move the position of the camera

    /// Will be called by the other functions (move_forwars etc)
    pub fn move_by(&mut self, pos_diff: Vector3f) {
        self.position += pos_diff;
    }

    /// Method to call when **forward movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for foward movement
    pub fn move_forward(&mut self, factor: f32) {
        let mut lookatvector = self.get_look_at_vector();
        lookatvector.z = 0.0;
        lookatvector = lookatvector.normalize();
        lookatvector *= factor;
        self.move_by(lookatvector);
    }

    /// Method to call when **backward movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for backward movement
    pub fn move_backward(&mut self, factor: f32) {
        let mut lookatvector = self.get_look_at_vector();
        lookatvector.z = 0.0;
        lookatvector = lookatvector.normalize();
        lookatvector *= -factor;
        self.move_by(lookatvector);
    }

    /// Method to call when **left movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for left movement
    pub fn move_left(&mut self, factor: f32) {
        let mut lookatvector = self.get_look_at_vector();
        lookatvector.z = 0.0;
        lookatvector = lookatvector.normalize();
        // Get the orthogonal 2d-vector, which is 90 degrees to the left
        let mut move_dir = Vector3f::new(-lookatvector.y, lookatvector.x, 0.0);
        move_dir *= factor;
        self.move_by(move_dir);
    }

    /// Method to call when **right movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for right movement
    pub fn move_right(&mut self, factor: f32) {
        let mut lookatvector = self.get_look_at_vector();
        lookatvector.z = 0.0;
        lookatvector = lookatvector.normalize();
        // Get the orthogonal 2d-vector, which is 90 degrees to the left
        let mut move_dir = Vector3f::new(lookatvector.y, -lookatvector.x, 0.0);
        move_dir *= factor;
        self.move_by(move_dir);
    }

    /// Method to call when **upward movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for upward movement
    pub fn move_up(&mut self, factor: f32) {
        self.move_by(Vector3f::new(0.0, 0.0, factor));
    }

    /// Method to call when **downward movement** is needed

    /// `factor` is a factor to scale the movement speed

    /// `factor` has to be positive for downward movement
    pub fn move_down(&mut self, factor: f32) {
        self.move_by(Vector3f::new(0.0, 0.0, -factor));
    }

    /// Changes `theta` and `phi` to essentially change the direction the
    /// camera looks
    pub fn change_dir(&mut self, theta_diff: f32, phi_diff: f32) {
        if self.theta < 0.1 {
            if theta_diff > 0.0 {
                // all the way UP, theta will not go any lower
                self.theta += theta_diff;
            }
        } else if self.theta > consts::PI - 0.1 {
            if theta_diff < 0.0 {
                // all the way DOWN, theta will not go any higher
                self.theta += theta_diff;
            }
        } else {
            self.theta += theta_diff;
        }
        self.phi += phi_diff;
    }
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::ops::{self, DocOptions};

pub fn cli() -> App {
    subcommand("doc")
        // subcommand aliases are handled in aliased_command()
        // .alias("d")
        .about("Build a package's documentation")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(opt(
            "open",
            "Opens the docs in a browser after the operation",
        ))
        .arg_package_spec(
            "Package to document",
            "Document all packages in the workspace",
            "Exclude packages from the build",
        )
        .arg(opt("no-deps", "Don't build documentation for dependencies"))
        .arg(opt("document-private-items", "Document private items"))
        .arg_jobs()
        .arg_targets_lib_bin(
            "Document only this package's library",
            "Document only the specified binary",
            "Document all binaries",
        )
        .arg_release("Build artifacts in release mode, with optimizations")
        .arg_profile("Build artifacts with the specified profile")
        .arg_features()
        .arg_target_triple("Build for the target triple")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .arg_ignore_rust_version()
        .arg_unit_graph()
        .after_help("Run `cargo help doc` for more detailed information.\n")
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;
    let mode = CompileMode::Doc {
        deps: !args.is_present("no-deps"),
    };
    let mut compile_opts =
        args.compile_options(config, mode, Some(&ws), ProfileChecking::Custom)?;
    compile_opts.rustdoc_document_private_items = args.is_present("document-private-items");

    let doc_opts = DocOptions {
        open_result: args.is_present("open"),
        compile_opts,
    };
    ops::doc(&ws, &doc_opts)?;
    Ok(())
}
<commit_msg>Add cargo doc --examples subcommand<commit_after>use crate::command_prelude::*;

use cargo::ops::{self, DocOptions};

pub fn cli() -> App {
    subcommand("doc")
        // subcommand aliases are handled in aliased_command()
        // .alias("d")
        .about("Build a package's documentation")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(opt(
            "open",
            "Opens the docs in a browser after the operation",
        ))
		.arg(opt(
            "examples",
            "Document all examples",
        ))
        .arg_package_spec(
            "Package to document",
            "Document all packages in the workspace",
            "Exclude packages from the build",
        )
        .arg(opt("no-deps", "Don't build documentation for dependencies"))
        .arg(opt("document-private-items", "Document private items"))
        .arg_jobs()
        .arg_targets_lib_bin(
            "Document only this package's library",
            "Document only the specified binary",
            "Document all binaries",
        )
        .arg_release("Build artifacts in release mode, with optimizations")
        .arg_profile("Build artifacts with the specified profile")
        .arg_features()
        .arg_target_triple("Build for the target triple")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .arg_ignore_rust_version()
        .arg_unit_graph()
        .after_help("Run `cargo help doc` for more detailed information.\n")
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;
    let mode = CompileMode::Doc {
        deps: !args.is_present("no-deps"),
    };
    let mut compile_opts =
        args.compile_options(config, mode, Some(&ws), ProfileChecking::Custom)?;
    compile_opts.rustdoc_document_private_items = args.is_present("document-private-items");

    let doc_opts = DocOptions {
        open_result: args.is_present("open"),
        compile_opts,
    };
    ops::doc(&ws, &doc_opts)?;
    Ok(())
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use serde_json::{json, Value};

use crate::internal::prelude::*;
use crate::model::prelude::*;

/// A builder for creating a new [`GuildChannel`] in a [`Guild`].
///
/// Except [`Self::name`], all fields are optional.
///
/// [`GuildChannel`]: crate::model::channel::GuildChannel
/// [`Guild`]: crate::model::guild::Guild
#[derive(Debug, Clone)]
pub struct CreateChannel(pub HashMap<&'static str, Value>);

impl CreateChannel {
    /// Specify how to call this new channel.
    ///
    /// **Note**: Must be between 2 and 100 characters long.
    pub fn name<D: ToString>(&mut self, name: D) -> &mut Self {
        self.0.insert("name", Value::String(name.to_string()));

        self
    }
    /// Specify what type the channel is, whether it's a text, voice, category or news channel.
    pub fn kind(&mut self, kind: ChannelType) -> &mut Self {
        self.0.insert("type", Value::Number(Number::from(kind as u8)));

        self
    }

    /// Specifiy the category, the "parent" of this channel.
    pub fn category<I: Into<ChannelId>>(&mut self, id: I) -> &mut Self {
        self.0.insert("parent_id", Value::Number(Number::from(id.into().0)));

        self
    }

    /// Set an interesting topic.
    ///
    /// **Note**: Must be between 0 and 1000 characters long.
    pub fn topic<D: ToString>(&mut self, topic: D) -> &mut Self {
        self.0.insert("topic", Value::String(topic.to_string()));

        self
    }

    /// Specify if this channel will be inappropriate to browse while at work.
    pub fn nsfw(&mut self, b: bool) -> &mut Self {
        self.0.insert("nsfw", Value::Bool(b));

        self
    }

    /// [Voice-only] Specify the bitrate at which sound plays in the voice channel.
    pub fn bitrate(&mut self, rate: u32) -> &mut Self {
        self.0.insert("bitrate", Value::Number(Number::from(rate)));

        self
    }

    /// [Voice-only] Set how many users may occupy this voice channel.
    pub fn user_limit(&mut self, limit: u32) -> &mut Self {
        self.0.insert("user_limit", Value::Number(Number::from(limit)));

        self
    }

    /// How many seconds must a user wait before sending another message.
    ///
    /// Bots, or users with the [`MANAGE_MESSAGES`] and/or [`MANAGE_CHANNELS`] permissions are exempt
    /// from this restriction.
    ///
    /// **Note**: Must be between 0 and 21600 seconds (360 minutes or 6 hours).
    ///
    /// [`MANAGE_MESSAGES`]: crate::model::permissions::Permissions::MANAGE_MESSAGES
    /// [`MANAGE_CHANNELS`]: crate::model::permissions::Permissions::MANAGE_CHANNELS
    pub fn rate_limit(&mut self, limit: u64) -> &mut Self {
        self.0.insert("rate_limit_per_user", Value::Number(Number::from(limit)));

        self
    }

    /// Specify where the channel should be located.
    pub fn position(&mut self, pos: u32) -> &mut Self {
        self.0.insert("position", Value::Number(Number::from(pos)));

        self
    }

    /// A set of overwrites defining what a user or a user carrying a certain role can
    /// and cannot do.
    ///
    /// # Example
    ///
    /// Inheriting permissions from an exisiting channel:
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// # use std::sync::Arc;
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Arc::new(Http::default());
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::model::channel::{PermissionOverwrite, PermissionOverwriteType};
    /// use serenity::model::id::UserId;
    /// use serenity::model::permissions::Permissions;
    ///
    /// // Assuming a guild has already been bound.
    /// let permissions = vec![PermissionOverwrite {
    ///     allow: Permissions::READ_MESSAGES,
    ///     deny: Permissions::SEND_TTS_MESSAGES,
    ///     kind: PermissionOverwriteType::Member(UserId(1234)),
    /// }];
    ///
    /// guild.create_channel(http, |c| {
    ///     c.name("my_new_cool_channel")
    ///     .permissions(permissions)
    /// })
    /// .await?;
    /// #    Ok(())
    /// # }
    /// ```
    pub fn permissions<I>(&mut self, perms: I) -> &mut Self
    where
        I: IntoIterator<Item = PermissionOverwrite>,
    {
        let overwrites = perms
            .into_iter()
            .map(|perm| {
                let (id, kind) = match perm.kind {
                    PermissionOverwriteType::Member(id) => (id.0, "member"),
                    PermissionOverwriteType::Role(id) => (id.0, "role"),
                };

                json!({
                    "allow": perm.allow.bits(),
                    "deny": perm.deny.bits(),
                    "id": id,
                    "type": kind,
                })
            })
            .collect();

        self.0.insert("permission_overwrites", Value::Array(overwrites));

        self
    }
}

impl Default for CreateChannel {
    /// Creates a builder with default values, setting [`Self::kind`] to [`ChannelType::Text`].
    ///
    /// # Examples
    ///
    /// Create a default [`CreateChannel`] builder:
    ///
    /// ```rust
    /// use serenity::builder::CreateChannel;
    ///
    /// let channel_builder = CreateChannel::default();
    /// ```
    fn default() -> Self {
        let mut builder = CreateChannel(HashMap::new());
        builder.kind(ChannelType::Text);

        builder
    }
}
<commit_msg>Fix permission overwrites by sending Discord the correct overwrite types (#1546)<commit_after>use std::collections::HashMap;

use serde_json::{json, Value};

use crate::internal::prelude::*;
use crate::model::prelude::*;

/// A builder for creating a new [`GuildChannel`] in a [`Guild`].
///
/// Except [`Self::name`], all fields are optional.
///
/// [`GuildChannel`]: crate::model::channel::GuildChannel
/// [`Guild`]: crate::model::guild::Guild
#[derive(Debug, Clone)]
pub struct CreateChannel(pub HashMap<&'static str, Value>);

impl CreateChannel {
    /// Specify how to call this new channel.
    ///
    /// **Note**: Must be between 2 and 100 characters long.
    pub fn name<D: ToString>(&mut self, name: D) -> &mut Self {
        self.0.insert("name", Value::String(name.to_string()));

        self
    }
    /// Specify what type the channel is, whether it's a text, voice, category or news channel.
    pub fn kind(&mut self, kind: ChannelType) -> &mut Self {
        self.0.insert("type", Value::Number(Number::from(kind as u8)));

        self
    }

    /// Specifiy the category, the "parent" of this channel.
    pub fn category<I: Into<ChannelId>>(&mut self, id: I) -> &mut Self {
        self.0.insert("parent_id", Value::Number(Number::from(id.into().0)));

        self
    }

    /// Set an interesting topic.
    ///
    /// **Note**: Must be between 0 and 1000 characters long.
    pub fn topic<D: ToString>(&mut self, topic: D) -> &mut Self {
        self.0.insert("topic", Value::String(topic.to_string()));

        self
    }

    /// Specify if this channel will be inappropriate to browse while at work.
    pub fn nsfw(&mut self, b: bool) -> &mut Self {
        self.0.insert("nsfw", Value::Bool(b));

        self
    }

    /// [Voice-only] Specify the bitrate at which sound plays in the voice channel.
    pub fn bitrate(&mut self, rate: u32) -> &mut Self {
        self.0.insert("bitrate", Value::Number(Number::from(rate)));

        self
    }

    /// [Voice-only] Set how many users may occupy this voice channel.
    pub fn user_limit(&mut self, limit: u32) -> &mut Self {
        self.0.insert("user_limit", Value::Number(Number::from(limit)));

        self
    }

    /// How many seconds must a user wait before sending another message.
    ///
    /// Bots, or users with the [`MANAGE_MESSAGES`] and/or [`MANAGE_CHANNELS`] permissions are exempt
    /// from this restriction.
    ///
    /// **Note**: Must be between 0 and 21600 seconds (360 minutes or 6 hours).
    ///
    /// [`MANAGE_MESSAGES`]: crate::model::permissions::Permissions::MANAGE_MESSAGES
    /// [`MANAGE_CHANNELS`]: crate::model::permissions::Permissions::MANAGE_CHANNELS
    pub fn rate_limit(&mut self, limit: u64) -> &mut Self {
        self.0.insert("rate_limit_per_user", Value::Number(Number::from(limit)));

        self
    }

    /// Specify where the channel should be located.
    pub fn position(&mut self, pos: u32) -> &mut Self {
        self.0.insert("position", Value::Number(Number::from(pos)));

        self
    }

    /// A set of overwrites defining what a user or a user carrying a certain role can
    /// and cannot do.
    ///
    /// # Example
    ///
    /// Inheriting permissions from an exisiting channel:
    ///
    /// ```rust,no_run
    /// # use serenity::{http::Http, model::id::GuildId};
    /// # use std::sync::Arc;
    /// #
    /// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
    /// #     let http = Arc::new(Http::default());
    /// #     let mut guild = GuildId(0).to_partial_guild(&http).await?;
    /// use serenity::model::channel::{PermissionOverwrite, PermissionOverwriteType};
    /// use serenity::model::id::UserId;
    /// use serenity::model::permissions::Permissions;
    ///
    /// // Assuming a guild has already been bound.
    /// let permissions = vec![PermissionOverwrite {
    ///     allow: Permissions::READ_MESSAGES,
    ///     deny: Permissions::SEND_TTS_MESSAGES,
    ///     kind: PermissionOverwriteType::Member(UserId(1234)),
    /// }];
    ///
    /// guild.create_channel(http, |c| {
    ///     c.name("my_new_cool_channel")
    ///     .permissions(permissions)
    /// })
    /// .await?;
    /// #    Ok(())
    /// # }
    /// ```
    pub fn permissions<I>(&mut self, perms: I) -> &mut Self
    where
        I: IntoIterator<Item = PermissionOverwrite>,
    {
        let overwrites = perms
            .into_iter()
            .map(|perm| {
                let (id, kind) = match perm.kind {
                    PermissionOverwriteType::Role(id) => (id.0, 0),
                    PermissionOverwriteType::Member(id) => (id.0, 1),
                };

                json!({
                    "allow": perm.allow.bits(),
                    "deny": perm.deny.bits(),
                    "id": id,
                    "type": kind,
                })
            })
            .collect();

        self.0.insert("permission_overwrites", Value::Array(overwrites));

        self
    }
}

impl Default for CreateChannel {
    /// Creates a builder with default values, setting [`Self::kind`] to [`ChannelType::Text`].
    ///
    /// # Examples
    ///
    /// Create a default [`CreateChannel`] builder:
    ///
    /// ```rust
    /// use serenity::builder::CreateChannel;
    ///
    /// let channel_builder = CreateChannel::default();
    /// ```
    fn default() -> Self {
        let mut builder = CreateChannel(HashMap::new());
        builder.kind(ChannelType::Text);

        builder
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use crate::data::frame::ArcFrame;
use crate::data::packet::Packet;

pub use crate::common::CodecList;
use crate::error::*;

/// Used to interact with a decoder.
pub trait Decoder: Send {
    // TODO support codec configuration using set_option
    // fn open(&mut self) -> Result<()>;
    /// Saves the extra data contained in a codec.
    fn set_extradata(&mut self, extra: &[u8]);
    /// Sends to the decoder a packet to be decoded.
    fn send_packet(&mut self, pkt: &Packet) -> Result<()>;
    /// Returns a decoded frame.
    fn receive_frame(&mut self) -> Result<ArcFrame>;
    /// Configures the decoder.
    fn configure(&mut self) -> Result<()>;
    /// Tells decoder to clear its internal state.
    fn flush(&mut self) -> Result<()>;
}

/// Codec descriptor.
///
/// Contains information on a codec and its own decoder.
#[derive(Debug)]
pub struct Descr {
    /// The codec name.
    pub codec: &'static str,
    /// The extended codec name.
    pub name: &'static str,
    /// The codec description.
    pub desc: &'static str,
    /// The codec MIME.
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

/// Auxiliary structure to encapsulate a decoder object and
/// its additional data.
pub struct Context {
    dec: Box<dyn Decoder>,
    // TODO: Queue up packets/frames
}

impl Context {
    // TODO: More constructors
    /// Retrieves a codec descriptor from a codec list through its name,
    /// creates the relative decoder, and encapsulates it into a new `Context`.
    pub fn by_name(codecs: &Codecs, name: &str) -> Option<Context> {
        if let Some(builder) = codecs.by_name(name) {
            let dec = builder.create();
            Some(Context { dec })
        } else {
            None
        }
    }
    /// Saves the extra data contained in a codec.
    pub fn set_extradata(&mut self, extra: &[u8]) {
        self.dec.set_extradata(extra);
    }

    /// Sends to the decoder a packet to be decoded.
    pub fn send_packet(&mut self, pkt: &Packet) -> Result<()> {
        self.dec.send_packet(pkt)
    }
    /// Returns a decoded frame.
    pub fn receive_frame(&mut self) -> Result<ArcFrame> {
        self.dec.receive_frame()
    }
    /// Configures the decoder.
    pub fn configure(&mut self) -> Result<()> {
        self.dec.configure()
    }

    /// Tells decoder to clear its internal state.
    pub fn flush(&mut self) -> Result<()> {
        self.dec.flush()
    }
}

/// Used to get the descriptor of a codec and create its own decoder.
pub trait Descriptor {
    /// Creates a new decoder for the requested codec.
    fn create(&self) -> Box<dyn Decoder>;
    /// Returns the codec descriptor.
    fn describe(&self) -> &Descr;
}

/// A list of codec descriptors.
pub struct Codecs {
    list: HashMap<&'static str, Vec<&'static dyn Descriptor>>,
}

impl CodecList for Codecs {
    type D = dyn Descriptor;

    fn new() -> Codecs {
        Codecs {
            list: HashMap::new(),
        }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        self.list.get(name).map(|descs| descs[0])
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list
            .entry(codec_name)
            .or_insert_with(Vec::new)
            .push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use crate::data::pixel::Formaton;
        use std::sync::Arc;

        struct Dec {
            state: usize,
            format: Option<Arc<Formaton>>,
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            fn create(&self) -> Box<dyn Decoder> {
                Box::new(Dec {
                    state: 0,
                    format: None,
                })
            }
            fn describe<'a>(&'a self) -> &'a Descr {
                &self.descr
            }
        }

        impl Decoder for Dec {
            fn configure(&mut self) -> Result<()> {
                Ok(())
            }
            fn set_extradata(&mut self, extra: &[u8]) {
                if extra.len() > 4 {
                    self.state = 42;
                } else {
                    self.state = 12;
                }
            }
            fn send_packet(&mut self, _packet: &Packet) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_frame(&mut self) -> Result<ArcFrame> {
                unimplemented!()
            }
            fn flush(&mut self) -> Result<()> {
                Ok(())
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy decoder",
                mime: "x-application/dummy",
            },
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _dec = codecs.by_name("dummy").unwrap();
    }
}
<commit_msg>codec: Add Sync trait to Decoder trait<commit_after>use std::collections::HashMap;

use crate::data::frame::ArcFrame;
use crate::data::packet::Packet;

pub use crate::common::CodecList;
use crate::error::*;

/// Used to interact with a decoder.
pub trait Decoder: Send + Sync {
    // TODO support codec configuration using set_option
    // fn open(&mut self) -> Result<()>;
    /// Saves the extra data contained in a codec.
    fn set_extradata(&mut self, extra: &[u8]);
    /// Sends to the decoder a packet to be decoded.
    fn send_packet(&mut self, pkt: &Packet) -> Result<()>;
    /// Returns a decoded frame.
    fn receive_frame(&mut self) -> Result<ArcFrame>;
    /// Configures the decoder.
    fn configure(&mut self) -> Result<()>;
    /// Tells decoder to clear its internal state.
    fn flush(&mut self) -> Result<()>;
}

/// Codec descriptor.
///
/// Contains information on a codec and its own decoder.
#[derive(Debug)]
pub struct Descr {
    /// The codec name.
    pub codec: &'static str,
    /// The extended codec name.
    pub name: &'static str,
    /// The codec description.
    pub desc: &'static str,
    /// The codec MIME.
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

/// Auxiliary structure to encapsulate a decoder object and
/// its additional data.
pub struct Context {
    dec: Box<dyn Decoder>,
    // TODO: Queue up packets/frames
}

impl Context {
    // TODO: More constructors
    /// Retrieves a codec descriptor from a codec list through its name,
    /// creates the relative decoder, and encapsulates it into a new `Context`.
    pub fn by_name(codecs: &Codecs, name: &str) -> Option<Context> {
        if let Some(builder) = codecs.by_name(name) {
            let dec = builder.create();
            Some(Context { dec })
        } else {
            None
        }
    }
    /// Saves the extra data contained in a codec.
    pub fn set_extradata(&mut self, extra: &[u8]) {
        self.dec.set_extradata(extra);
    }

    /// Sends to the decoder a packet to be decoded.
    pub fn send_packet(&mut self, pkt: &Packet) -> Result<()> {
        self.dec.send_packet(pkt)
    }
    /// Returns a decoded frame.
    pub fn receive_frame(&mut self) -> Result<ArcFrame> {
        self.dec.receive_frame()
    }
    /// Configures the decoder.
    pub fn configure(&mut self) -> Result<()> {
        self.dec.configure()
    }

    /// Tells decoder to clear its internal state.
    pub fn flush(&mut self) -> Result<()> {
        self.dec.flush()
    }
}

/// Used to get the descriptor of a codec and create its own decoder.
pub trait Descriptor {
    /// Creates a new decoder for the requested codec.
    fn create(&self) -> Box<dyn Decoder>;
    /// Returns the codec descriptor.
    fn describe(&self) -> &Descr;
}

/// A list of codec descriptors.
pub struct Codecs {
    list: HashMap<&'static str, Vec<&'static dyn Descriptor>>,
}

impl CodecList for Codecs {
    type D = dyn Descriptor;

    fn new() -> Codecs {
        Codecs {
            list: HashMap::new(),
        }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        self.list.get(name).map(|descs| descs[0])
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list
            .entry(codec_name)
            .or_insert_with(Vec::new)
            .push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use crate::data::pixel::Formaton;
        use std::sync::Arc;

        struct Dec {
            state: usize,
            format: Option<Arc<Formaton>>,
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            fn create(&self) -> Box<dyn Decoder> {
                Box::new(Dec {
                    state: 0,
                    format: None,
                })
            }
            fn describe<'a>(&'a self) -> &'a Descr {
                &self.descr
            }
        }

        impl Decoder for Dec {
            fn configure(&mut self) -> Result<()> {
                Ok(())
            }
            fn set_extradata(&mut self, extra: &[u8]) {
                if extra.len() > 4 {
                    self.state = 42;
                } else {
                    self.state = 12;
                }
            }
            fn send_packet(&mut self, _packet: &Packet) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_frame(&mut self) -> Result<ArcFrame> {
                unimplemented!()
            }
            fn flush(&mut self) -> Result<()> {
                Ok(())
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy decoder",
                mime: "x-application/dummy",
            },
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _dec = codecs.by_name("dummy").unwrap();
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use openssl::x509::X509;
use openssl::hash::MessageDigest;

use sozu::messages::{CertFingerprint,CertificateAndKey,Order,HttpFront,TlsFront,Instance};

pub type AppId = String;

#[derive(Debug,Clone,PartialEq,Eq, Serialize, Deserialize)]
pub struct HttpProxy {
  ip_address: String,
  port:       u16,
  fronts:     HashMap<AppId, Vec<HttpFront>>,
  instances:  HashMap<AppId, Vec<Instance>>,
}

#[derive(Debug,Clone,PartialEq,Eq,Serialize, Deserialize)]
pub struct TlsProxy {
  ip_address:   String,
  port:         u16,
  certificates: HashMap<CertFingerprint, CertificateAndKey>,
  fronts:       HashMap<AppId, Vec<TlsFront>>,
  instances:    HashMap<AppId, Vec<Instance>>,
}

#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
pub enum ConfigState {
  Http(HttpProxy),
  Tls(TlsProxy),
  Tcp
}

impl ConfigState {
  pub fn handle_order(&mut self, order: &Order) {
    match *self {
      ConfigState::Http(ref mut state) => state.handle_order(order),
      ConfigState::Tls(ref mut state)  => state.handle_order(order),
      ConfigState::Tcp                 => {},
    }
  }

  pub fn generate_orders(&self) -> Vec<Order> {
    match *self {
      ConfigState::Http(ref state) => state.generate_orders(),
      ConfigState::Tls(ref state)  => state.generate_orders(),
      ConfigState::Tcp             => vec!(),
    }
  }
}

impl HttpProxy {
  pub fn new(ip: String, port: u16) -> HttpProxy {
    HttpProxy {
      ip_address: ip,
      port:       port,
      fronts:     HashMap::new(),
      instances:  HashMap::new(),
    }
  }

  pub fn handle_order(&mut self, order: &Order) {
    match order {
      &Order::AddHttpFront(ref front) => {
        let f = HttpFront {
          app_id:     front.app_id.clone(),
          hostname:   front.hostname.clone(),
          path_begin: front.path_begin.clone(),
        };
        if self.fronts.contains_key(&front.app_id) {
          self.fronts.get_mut(&front.app_id).map(|front| {
            if !front.contains(&f) {
              front.push(f);
            }
          });
        } else {
          self.fronts.insert(front.app_id.clone(), vec!(f));
        }
      },
      &Order::RemoveHttpFront(ref front) => {
        if let Some(front_list) = self.fronts.get_mut(&front.app_id) {
          front_list.retain(|el| el.hostname != front.hostname || el.path_begin != front.path_begin);
        }
      },
      &Order::AddInstance(ref instance)  => {
        if self.instances.contains_key(&instance.app_id) {
          self.instances.get_mut(&instance.app_id).map(|instance_vec| {
            if !instance_vec.contains(&instance) {
              instance_vec.push(instance.clone());
            }
          });
        } else {
          self.instances.insert(instance.app_id.clone(), vec!(instance.clone()));
        }
      },
      &Order::RemoveInstance(ref instance) => {
        if let Some(instance_list) = self.instances.get_mut(&instance.app_id) {
          instance_list.retain(|el| el.ip_address != instance.ip_address || el.port != instance.port);
          /*let mut v = Vec::new();
          for el in front.instances.iter() {
            if el.ip_address != instance.ip_address || el.port != instance.port {
              v.push(el.clone());
            }
          }
          front.instances = v;
          */
        }
      }
      _ => {}
    }
  }

  pub fn generate_orders(&self) -> Vec<Order> {
    let mut v = Vec::new();
    for (app_id, front_list) in self.fronts.iter() {
      for front in front_list {
        v.push(Order::AddHttpFront(HttpFront {
          app_id:     app_id.clone(),
          hostname:   front.hostname.clone(),
          path_begin: front.path_begin.clone(),
        }));
      }
    }

    for instance_list in self.instances.values() {
      for instance in instance_list {
        v.push(Order::AddInstance(instance.clone()));
      }
    }

    v
  }
}

impl TlsProxy {
  pub fn new(ip: String, port: u16) -> TlsProxy {
    TlsProxy {
      ip_address:   ip,
      port:         port,
      certificates: HashMap::new(),
      fronts:       HashMap::new(),
      instances:    HashMap::new(),
    }
  }

  pub fn handle_order(&mut self, order: &Order) {
    match order {
      &Order::AddCertificate(ref certificate_and_key) => {
        let f = CertificateAndKey {
          certificate:       certificate_and_key.certificate.clone(),
          certificate_chain: certificate_and_key.certificate_chain.clone(),
          key:               certificate_and_key.key.clone(),
        };
        let fingerprint = match X509::from_pem(&certificate_and_key.certificate.as_bytes()[..]).and_then(|cert|
                                  cert.fingerprint(MessageDigest::sha256())) {
          Ok(f)  => f,
          Err(e) => {
            error!("cannot obtain the certificate's fingerprint: {:?}", e);
            return;
          }
        };

        if !self.certificates.contains_key(&fingerprint) {
          self.certificates.insert(fingerprint.clone(), f);
        }
      },
      &Order::RemoveCertificate(ref fingerprint) => {
        self.certificates.remove(fingerprint);
      },
      &Order::AddTlsFront(ref front) => {
        let f = TlsFront {
          app_id:      front.app_id.clone(),
          hostname:    front.hostname.clone(),
          path_begin:  front.path_begin.clone(),
          fingerprint: front.fingerprint.clone(),
        };
        if self.fronts.contains_key(&front.app_id) {
          self.fronts.get_mut(&front.app_id).map(|front| {
            if !front.contains(&f) {
              front.push(f);
            }
          });
        } else {
          self.fronts.insert(front.app_id.clone(), vec!(f));
        }
      },
      &Order::RemoveTlsFront(ref front) => {
        self.fronts.remove(&front.app_id);
      },
      &Order::AddInstance(ref instance)  => {
        let inst = Instance {
          app_id:     instance.app_id.clone(),
          ip_address: instance.ip_address.clone(),
          port:       instance.port,
        };
        if self.instances.contains_key(&instance.app_id) {
          self.instances.get_mut(&instance.app_id).map(|instance| {
            if !instance.contains(&inst) {
              instance.push(inst);
            }
          });
        } else {
          self.instances.insert(instance.app_id.clone(), vec!(inst));
        }
      },
      &Order::RemoveInstance(ref instance) => {
        if let Some(instance_list) = self.instances.get_mut(&instance.app_id) {
          instance_list.retain(|el| el.ip_address != instance.ip_address || el.port != instance.port);
          /*let mut v = Vec::new();
          for el in instance_list.iter() {
            if el.ip_address != instance.ip_address || el.port != instance.port {
              v.push(el.clone());
            }
          }
          front.instances = v;*/
        }
      }
      _ => {}
    }
  }

  pub fn generate_orders(&self) -> Vec<Order> {
    let mut v = Vec::new();
    for certificate_and_key in (&self.certificates).values() {
      v.push(Order::AddCertificate(certificate_and_key.clone()));
    }
    for (app_id, front_list) in &self.fronts {
      for front in front_list {
        v.push(Order::AddTlsFront(TlsFront {
          app_id:      app_id.clone(),
          hostname:    front.hostname.clone(),
          path_begin:  front.path_begin.clone(),
          fingerprint: front.fingerprint.clone(),
        }));
      }
    }
    for (app_id, instance_list) in &self.instances {
      for instance in instance_list {
        v.push(Order::AddInstance(Instance {
          app_id:     app_id.clone(),
          ip_address: instance.ip_address.clone(),
          port:       instance.port.clone(),
        }));
      }
    }

    v
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use sozu::messages::{Order,HttpFront,Instance};

  #[test]
  fn serialize() {
    let mut state = HttpProxy::new(String::from("127.0.0.1"), 80);
    state.handle_order(&Order::AddHttpFront(HttpFront { app_id: String::from("app_1"), hostname: String::from("lolcatho.st:8080"), path_begin: String::from("/") }));
    state.handle_order(&Order::AddHttpFront(HttpFront { app_id: String::from("app_2"), hostname: String::from("test.local"), path_begin: String::from("/abc") }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.1"), port: 1026 }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.2"), port: 1027 }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_2"), ip_address: String::from("192.167.1.2"), port: 1026 }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("192.168.1.3"), port: 1027 }));
    state.handle_order(&Order::RemoveInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("192.168.1.3"), port: 1027 }));

    /*
    let encoded = state.encode();
    println!("serialized:\n{}", encoded);

    let new_state: Option<HttpProxy> = decode_str(&encoded);
    println!("deserialized:\n{:?}", new_state);
    assert_eq!(new_state, Some(state));
    */
    //assert!(false);
  }
}
<commit_msg>implement state diffs<commit_after>use std::collections::{HashMap,HashSet};
use std::iter::FromIterator;
use openssl::x509::X509;
use openssl::hash::MessageDigest;

use sozu::messages::{CertFingerprint,CertificateAndKey,Order,HttpFront,TlsFront,Instance};

pub type AppId = String;

#[derive(Debug,Clone,PartialEq,Eq, Serialize, Deserialize)]
pub struct HttpProxy {
  ip_address: String,
  port:       u16,
  fronts:     HashMap<AppId, Vec<HttpFront>>,
  instances:  HashMap<AppId, Vec<Instance>>,
}

#[derive(Debug,Clone,PartialEq,Eq,Serialize, Deserialize)]
pub struct TlsProxy {
  ip_address:   String,
  port:         u16,
  certificates: HashMap<CertFingerprint, CertificateAndKey>,
  fronts:       HashMap<AppId, Vec<TlsFront>>,
  instances:    HashMap<AppId, Vec<Instance>>,
}

#[derive(Debug,Clone,PartialEq,Eq,Serialize,Deserialize)]
pub enum ConfigState {
  Http(HttpProxy),
  Tls(TlsProxy),
  Tcp
}

impl ConfigState {
  pub fn handle_order(&mut self, order: &Order) {
    match *self {
      ConfigState::Http(ref mut state) => state.handle_order(order),
      ConfigState::Tls(ref mut state)  => state.handle_order(order),
      ConfigState::Tcp                 => {},
    }
  }

  pub fn generate_orders(&self) -> Vec<Order> {
    match *self {
      ConfigState::Http(ref state) => state.generate_orders(),
      ConfigState::Tls(ref state)  => state.generate_orders(),
      ConfigState::Tcp             => vec!(),
    }
  }

  pub fn diff(&self, other:&ConfigState) -> Vec<Order> {
    match (self, other) {
      (&ConfigState::Http(ref state), &ConfigState::Http(ref other_state)) => state.diff(other_state),
      (&ConfigState::Tls(ref state),  &ConfigState::Tls(ref other_state))  => state.diff(other_state),
      _                                                                  => vec!(),
    }
  }
}

impl HttpProxy {
  pub fn new(ip: String, port: u16) -> HttpProxy {
    HttpProxy {
      ip_address: ip,
      port:       port,
      fronts:     HashMap::new(),
      instances:  HashMap::new(),
    }
  }

  pub fn handle_order(&mut self, order: &Order) {
    match order {
      &Order::AddHttpFront(ref front) => {
        let f = HttpFront {
          app_id:     front.app_id.clone(),
          hostname:   front.hostname.clone(),
          path_begin: front.path_begin.clone(),
        };
        if self.fronts.contains_key(&front.app_id) {
          self.fronts.get_mut(&front.app_id).map(|front| {
            if !front.contains(&f) {
              front.push(f);
            }
          });
        } else {
          self.fronts.insert(front.app_id.clone(), vec!(f));
        }
      },
      &Order::RemoveHttpFront(ref front) => {
        if let Some(front_list) = self.fronts.get_mut(&front.app_id) {
          front_list.retain(|el| el.hostname != front.hostname || el.path_begin != front.path_begin);
        }
      },
      &Order::AddInstance(ref instance)  => {
        if self.instances.contains_key(&instance.app_id) {
          self.instances.get_mut(&instance.app_id).map(|instance_vec| {
            if !instance_vec.contains(&instance) {
              instance_vec.push(instance.clone());
            }
          });
        } else {
          self.instances.insert(instance.app_id.clone(), vec!(instance.clone()));
        }
      },
      &Order::RemoveInstance(ref instance) => {
        if let Some(instance_list) = self.instances.get_mut(&instance.app_id) {
          instance_list.retain(|el| el.ip_address != instance.ip_address || el.port != instance.port);
          /*let mut v = Vec::new();
          for el in front.instances.iter() {
            if el.ip_address != instance.ip_address || el.port != instance.port {
              v.push(el.clone());
            }
          }
          front.instances = v;
          */
        }
      }
      _ => {}
    }
  }

  pub fn generate_orders(&self) -> Vec<Order> {
    let mut v = Vec::new();
    for (app_id, front_list) in self.fronts.iter() {
      for front in front_list {
        v.push(Order::AddHttpFront(HttpFront {
          app_id:     app_id.clone(),
          hostname:   front.hostname.clone(),
          path_begin: front.path_begin.clone(),
        }));
      }
    }

    for instance_list in self.instances.values() {
      for instance in instance_list {
        v.push(Order::AddInstance(instance.clone()));
      }
    }

    v
  }

  pub fn diff(&self, other:&HttpProxy) -> Vec<Order> {
    let mut my_fronts: HashSet<(&AppId, &HttpFront)> = HashSet::new();
    for (ref app_id, ref front_list) in self.fronts.iter() {
      for ref front in front_list.iter() {
        my_fronts.insert((&app_id, &front));
      }
    }
    let mut their_fronts: HashSet<(&AppId, &HttpFront)> = HashSet::new();
    for (ref app_id, ref front_list) in other.fronts.iter() {
      for ref front in front_list.iter() {
        their_fronts.insert((&app_id, &front));
      }
    }

    let removed_fronts = my_fronts.difference(&their_fronts);
    let added_fronts   = their_fronts.difference(&my_fronts);

    let mut my_instances: HashSet<(&AppId, &Instance)> = HashSet::new();
    for (ref app_id, ref instance_list) in self.instances.iter() {
      for ref instance in instance_list.iter() {
        my_instances.insert((&app_id, &instance));
      }
    }
    let mut their_instances: HashSet<(&AppId, &Instance)> = HashSet::new();
    for (ref app_id, ref instance_list) in other.instances.iter() {
      for ref instance in instance_list.iter() {
        their_instances.insert((&app_id, &instance));
      }
    }

    let removed_instances = my_instances.difference(&their_instances);
    let added_instances   = their_instances.difference(&my_instances);

    let mut v = vec!();

    for &(app_id, front) in removed_fronts {
     v.push(Order::RemoveHttpFront(HttpFront {
       app_id:     app_id.clone(),
       hostname:   front.hostname.clone(),
       path_begin: front.path_begin.clone(),
      }));
    }

    for &(_, instance) in added_instances {
      v.push(Order::AddInstance(instance.clone()));
    }

    for &(_, instance) in removed_instances {
      v.push(Order::RemoveInstance(instance.clone()));
    }

    for &(app_id, front) in added_fronts {
      v.push(Order::AddHttpFront(HttpFront {
        app_id:     app_id.clone(),
        hostname:   front.hostname.clone(),
        path_begin: front.path_begin.clone(),
      }));
    }

    v
  }
}

impl TlsProxy {
  pub fn new(ip: String, port: u16) -> TlsProxy {
    TlsProxy {
      ip_address:   ip,
      port:         port,
      certificates: HashMap::new(),
      fronts:       HashMap::new(),
      instances:    HashMap::new(),
    }
  }

  pub fn handle_order(&mut self, order: &Order) {
    match order {
      &Order::AddCertificate(ref certificate_and_key) => {
        let f = CertificateAndKey {
          certificate:       certificate_and_key.certificate.clone(),
          certificate_chain: certificate_and_key.certificate_chain.clone(),
          key:               certificate_and_key.key.clone(),
        };
        let fingerprint = match X509::from_pem(&certificate_and_key.certificate.as_bytes()[..]).and_then(|cert|
                                  cert.fingerprint(MessageDigest::sha256())) {
          Ok(f)  => f,
          Err(e) => {
            error!("cannot obtain the certificate's fingerprint: {:?}", e);
            return;
          }
        };

        if !self.certificates.contains_key(&fingerprint) {
          self.certificates.insert(fingerprint.clone(), f);
        }
      },
      &Order::RemoveCertificate(ref fingerprint) => {
        self.certificates.remove(fingerprint);
      },
      &Order::AddTlsFront(ref front) => {
        let f = TlsFront {
          app_id:      front.app_id.clone(),
          hostname:    front.hostname.clone(),
          path_begin:  front.path_begin.clone(),
          fingerprint: front.fingerprint.clone(),
        };
        if self.fronts.contains_key(&front.app_id) {
          self.fronts.get_mut(&front.app_id).map(|front| {
            if !front.contains(&f) {
              front.push(f);
            }
          });
        } else {
          self.fronts.insert(front.app_id.clone(), vec!(f));
        }
      },
      &Order::RemoveTlsFront(ref front) => {
        self.fronts.remove(&front.app_id);
      },
      &Order::AddInstance(ref instance)  => {
        let inst = Instance {
          app_id:     instance.app_id.clone(),
          ip_address: instance.ip_address.clone(),
          port:       instance.port,
        };
        if self.instances.contains_key(&instance.app_id) {
          self.instances.get_mut(&instance.app_id).map(|instance| {
            if !instance.contains(&inst) {
              instance.push(inst);
            }
          });
        } else {
          self.instances.insert(instance.app_id.clone(), vec!(inst));
        }
      },
      &Order::RemoveInstance(ref instance) => {
        if let Some(instance_list) = self.instances.get_mut(&instance.app_id) {
          instance_list.retain(|el| el.ip_address != instance.ip_address || el.port != instance.port);
          /*let mut v = Vec::new();
          for el in instance_list.iter() {
            if el.ip_address != instance.ip_address || el.port != instance.port {
              v.push(el.clone());
            }
          }
          front.instances = v;*/
        }
      }
      _ => {}
    }
  }

  pub fn generate_orders(&self) -> Vec<Order> {
    let mut v = Vec::new();
    for certificate_and_key in (&self.certificates).values() {
      v.push(Order::AddCertificate(certificate_and_key.clone()));
    }
    for (app_id, front_list) in &self.fronts {
      for front in front_list {
        v.push(Order::AddTlsFront(TlsFront {
          app_id:      app_id.clone(),
          hostname:    front.hostname.clone(),
          path_begin:  front.path_begin.clone(),
          fingerprint: front.fingerprint.clone(),
        }));
      }
    }
    for (app_id, instance_list) in &self.instances {
      for instance in instance_list {
        v.push(Order::AddInstance(Instance {
          app_id:     app_id.clone(),
          ip_address: instance.ip_address.clone(),
          port:       instance.port.clone(),
        }));
      }
    }

    v
  }

  pub fn diff(&self, other:&TlsProxy) -> Vec<Order> {
    let mut my_fronts: HashSet<(&AppId, &TlsFront)> = HashSet::new();
    for (ref app_id, ref front_list) in self.fronts.iter() {
      for ref front in front_list.iter() {
        my_fronts.insert((&app_id, &front));
      }
    }
    let mut their_fronts: HashSet<(&AppId, &TlsFront)> = HashSet::new();
    for (ref app_id, ref front_list) in other.fronts.iter() {
      for ref front in front_list.iter() {
        their_fronts.insert((&app_id, &front));
      }
    }

    let removed_fronts = my_fronts.difference(&their_fronts);
    let added_fronts   = their_fronts.difference(&my_fronts);

    let mut my_instances: HashSet<(&AppId, &Instance)> = HashSet::new();
    for (ref app_id, ref instance_list) in self.instances.iter() {
      for ref instance in instance_list.iter() {
        my_instances.insert((&app_id, &instance));
      }
    }
    let mut their_instances: HashSet<(&AppId, &Instance)> = HashSet::new();
    for (ref app_id, ref instance_list) in other.instances.iter() {
      for ref instance in instance_list.iter() {
        their_instances.insert((&app_id, &instance));
      }
    }

    let removed_instances = my_instances.difference(&their_instances);
    let added_instances   = their_instances.difference(&my_instances);

    let my_certificates:    HashSet<(&CertFingerprint, &CertificateAndKey)> = HashSet::from_iter(self.certificates.iter());
    let their_certificates: HashSet<(&CertFingerprint, &CertificateAndKey)> = HashSet::from_iter(other.certificates.iter());

    let removed_certificates = my_certificates.difference(&their_certificates);
    let added_certificates   = their_certificates.difference(&my_certificates);

    let mut v = vec!();

    for &(_, certificate_and_key) in added_certificates {
      v.push(Order::AddCertificate(certificate_and_key.clone()));
    }

    for &(app_id, front) in removed_fronts {
     v.push(Order::RemoveTlsFront(TlsFront {
       app_id:      app_id.clone(),
       hostname:    front.hostname.clone(),
       path_begin:  front.path_begin.clone(),
       fingerprint: front.fingerprint.clone(),
      }));
    }

    for &(_, instance) in added_instances {
      v.push(Order::AddInstance(instance.clone()));
    }

    for &(_, instance) in removed_instances {
      v.push(Order::RemoveInstance(instance.clone()));
    }

    for &(app_id, front) in added_fronts {
      v.push(Order::AddTlsFront(TlsFront {
        app_id:      app_id.clone(),
        hostname:    front.hostname.clone(),
        path_begin:  front.path_begin.clone(),
        fingerprint: front.fingerprint.clone(),
      }));
    }

    for  &(fingerprint, _) in removed_certificates {
      v.push(Order::RemoveCertificate(fingerprint.clone()));
    }

    v
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use sozu::messages::{Order,HttpFront,Instance};

  #[test]
  fn serialize() {
    let mut state = HttpProxy::new(String::from("127.0.0.1"), 80);
    state.handle_order(&Order::AddHttpFront(HttpFront { app_id: String::from("app_1"), hostname: String::from("lolcatho.st:8080"), path_begin: String::from("/") }));
    state.handle_order(&Order::AddHttpFront(HttpFront { app_id: String::from("app_2"), hostname: String::from("test.local"), path_begin: String::from("/abc") }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.1"), port: 1026 }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.2"), port: 1027 }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_2"), ip_address: String::from("192.167.1.2"), port: 1026 }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("192.168.1.3"), port: 1027 }));
    state.handle_order(&Order::RemoveInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("192.168.1.3"), port: 1027 }));

    /*
    let encoded = state.encode();
    println!("serialized:\n{}", encoded);

    let new_state: Option<HttpProxy> = decode_str(&encoded);
    println!("deserialized:\n{:?}", new_state);
    assert_eq!(new_state, Some(state));
    */
    //assert!(false);
  }

  #[test]
  fn diff() {
    let mut state = HttpProxy::new(String::from("127.0.0.1"), 80);
    state.handle_order(&Order::AddHttpFront(HttpFront { app_id: String::from("app_1"), hostname: String::from("lolcatho.st:8080"), path_begin: String::from("/") }));
    state.handle_order(&Order::AddHttpFront(HttpFront { app_id: String::from("app_2"), hostname: String::from("test.local"), path_begin: String::from("/abc") }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.1"), port: 1026 }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.2"), port: 1027 }));
    state.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_2"), ip_address: String::from("192.167.1.2"), port: 1026 }));

    let mut state2 = HttpProxy::new(String::from("127.0.0.1"), 80);
    state2.handle_order(&Order::AddHttpFront(HttpFront { app_id: String::from("app_1"), hostname: String::from("lolcatho.st:8080"), path_begin: String::from("/") }));
    state2.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.1"), port: 1026 }));
    state2.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.2"), port: 1027 }));
    state2.handle_order(&Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.2"), port: 1028 }));

   let e = vec!(
     Order::RemoveHttpFront(HttpFront { app_id: String::from("app_2"), hostname: String::from("test.local"), path_begin: String::from("/abc") }),
     Order::RemoveInstance(Instance { app_id: String::from("app_2"), ip_address: String::from("192.167.1.2"), port: 1026 }),
     Order::AddInstance(Instance { app_id: String::from("app_1"), ip_address: String::from("127.0.0.2"), port: 1028 }),
   );
   let expected_diff:HashSet<&Order> = HashSet::from_iter(e.iter());

   let d = state.diff(&state2);
   let diff = HashSet::from_iter(d.iter());
   println!("diff orders:\n{:?}\n", diff);
   println!("expected diff orders:\n{:?}\n", expected_diff);

   assert_eq!(diff, expected_diff);
  }
}
<|endoftext|>


<commit_before>extern crate xswag_syntax_java as syntax;
extern crate xswag_base as base;

use base::diag;

// FIXME: import is currently wrong
const SRC: &'static str = "\
package yolo.swag;

import AlgoTools.IO;
import java.lang-*;

public private class Cheese {
	private public % yolo;
}

";

fn main() {
    let file = base::code::FileMap::new("<test>", SRC);
    let (res, errors) = syntax::parse_compilation_unit(&file);

    println!("{:#?}", res);
    for e in &errors {
    	diag::print(&e, &file, diag::PrintOptions::default());
    }
    // println!("{:#?}", errors);
}
<commit_msg>Improve error printing in example<commit_after>extern crate xswag_syntax_java as syntax;
extern crate xswag_base as base;

use base::diag;

// FIXME: import is currently wrong
const SRC: &'static str = "\
package yolo.swag;

import AlgoTools.IO;
import java.lang-*;

public private class Cheese {
	private public % yolo;
};

;
class Bread {}

";

fn main() {
    let file = base::code::FileMap::new("<test>", SRC);
    let (res, errors) = syntax::parse_compilation_unit(&file);

	match res {
		Ok(ast) => print!("{:#?}", ast),
		Err(e) => {
			// println!("{:#?}", e);
			diag::print(&e, &file, diag::PrintOptions::default());
		}
	}
    for e in &errors {
    	diag::print(&e, &file, diag::PrintOptions::default());
    }
    // println!("{:#?}", res);
    // println!("{:#?}", errors);
}
<|endoftext|>


<commit_before>//! Modules for events in the `m.room` namespace.
//!
//! This module also contains types shared by events in its child namespaces.

use std::collections::BTreeMap;

use js_int::UInt;
use serde::{Deserialize, Serialize};

use crate::{
    serde::{base64::UrlSafe, Base64},
    MxcUri,
};

pub mod aliases;
pub mod avatar;
pub mod canonical_alias;
pub mod create;
pub mod encrypted;
pub mod encryption;
pub mod guest_access;
pub mod history_visibility;
pub mod join_rules;
pub mod member;
pub mod message;
pub mod name;
pub mod pinned_events;
pub mod power_levels;
pub mod redaction;
pub mod server_acl;
pub mod third_party_invite;
mod thumbnail_source_serde;
pub mod tombstone;
pub mod topic;

/// The source of a media file.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_enums)]
pub enum MediaSource {
    /// The MXC URI to the unencrypted media file.
    #[serde(rename = "url")]
    Plain(Box<MxcUri>),

    /// The encryption info of the encrypted media file.
    #[serde(rename = "file")]
    Encrypted(Box<EncryptedFile>),
}

/// Metadata about an image.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ImageInfo {
    /// The height of the image in pixels.
    #[serde(rename = "h", skip_serializing_if = "Option::is_none")]
    pub height: Option<UInt>,

    /// The width of the image in pixels.
    #[serde(rename = "w", skip_serializing_if = "Option::is_none")]
    pub width: Option<UInt>,

    /// The MIME type of the image, e.g. "image/png."
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mimetype: Option<String>,

    /// The file size of the image in bytes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub size: Option<UInt>,

    /// Metadata about the image referred to in `thumbnail_source`.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub thumbnail_info: Option<Box<ThumbnailInfo>>,

    /// The source of the thumbnail of the image.
    #[serde(flatten, with = "thumbnail_source_serde", skip_serializing_if = "Option::is_none")]
    pub thumbnail_source: Option<MediaSource>,

    /// The [BlurHash](https://blurha.sh) for this image.
    ///
    /// This uses the unstable prefix in
    /// [MSC2448](https://github.com/matrix-org/matrix-spec-proposals/pull/2448).
    #[cfg(feature = "unstable-msc2448")]
    #[serde(
        rename = "xyz.amorgan.blurhash",
        alias = "blurhash",
        skip_serializing_if = "Option::is_none"
    )]
    pub blurhash: Option<String>,
}

impl ImageInfo {
    /// Creates an empty `ImageInfo`.
    pub fn new() -> Self {
        Self::default()
    }
}

/// Metadata about a thumbnail.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ThumbnailInfo {
    /// The height of the thumbnail in pixels.
    #[serde(rename = "h", skip_serializing_if = "Option::is_none")]
    pub height: Option<UInt>,

    /// The width of the thumbnail in pixels.
    #[serde(rename = "w", skip_serializing_if = "Option::is_none")]
    pub width: Option<UInt>,

    /// The MIME type of the thumbnail, e.g. "image/png."
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mimetype: Option<String>,

    /// The file size of the thumbnail in bytes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub size: Option<UInt>,
}

impl ThumbnailInfo {
    /// Creates an empty `ThumbnailInfo`.
    pub fn new() -> Self {
        Self::default()
    }
}

/// A file sent to a room with end-to-end encryption enabled.
///
/// To create an instance of this type, first create a `EncryptedFileInit` and convert it via
/// `EncryptedFile::from` / `.into()`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct EncryptedFile {
    /// The URL to the file.
    pub url: Box<MxcUri>,

    /// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
    pub key: JsonWebKey,

    /// The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64.
    pub iv: Base64,

    /// A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64.
    ///
    /// Clients should support the SHA-256 hash, which uses the key sha256.
    pub hashes: BTreeMap<String, Base64>,

    /// Version of the encrypted attachments protocol.
    ///
    /// Must be `v2`.
    pub v: String,
}

/// Initial set of fields of `EncryptedFile`.
///
/// This struct will not be updated even if additional fields are added to `EncryptedFile` in a new
/// (non-breaking) release of the Matrix specification.
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct EncryptedFileInit {
    /// The URL to the file.
    pub url: Box<MxcUri>,

    /// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
    pub key: JsonWebKey,

    /// The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64.
    pub iv: Base64,

    /// A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64.
    ///
    /// Clients should support the SHA-256 hash, which uses the key sha256.
    pub hashes: BTreeMap<String, Base64>,

    /// Version of the encrypted attachments protocol.
    ///
    /// Must be `v2`.
    pub v: String,
}

impl From<EncryptedFileInit> for EncryptedFile {
    fn from(init: EncryptedFileInit) -> Self {
        let EncryptedFileInit { url, key, iv, hashes, v } = init;
        Self { url, key, iv, hashes, v }
    }
}

/// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
///
/// To create an instance of this type, first create a `JsonWebKeyInit` and convert it via
/// `JsonWebKey::from` / `.into()`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct JsonWebKey {
    /// Key type.
    ///
    /// Must be `oct`.
    pub kty: String,

    /// Key operations.
    ///
    /// Must at least contain `encrypt` and `decrypt`.
    pub key_ops: Vec<String>,

    /// Algorithm.
    ///
    /// Must be `A256CTR`.
    pub alg: String,

    /// The key, encoded as url-safe unpadded base64.
    pub k: Base64<UrlSafe>,

    /// Extractable.
    ///
    /// Must be `true`. This is a
    /// [W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk).
    pub ext: bool,
}

/// Initial set of fields of `JsonWebKey`.
///
/// This struct will not be updated even if additional fields are added to `JsonWebKey` in a new
/// (non-breaking) release of the Matrix specification.
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct JsonWebKeyInit {
    /// Key type.
    ///
    /// Must be `oct`.
    pub kty: String,

    /// Key operations.
    ///
    /// Must at least contain `encrypt` and `decrypt`.
    pub key_ops: Vec<String>,

    /// Algorithm.
    ///
    /// Must be `A256CTR`.
    pub alg: String,

    /// The key, encoded as url-safe unpadded base64.
    pub k: Base64<UrlSafe>,

    /// Extractable.
    ///
    /// Must be `true`. This is a
    /// [W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk).
    pub ext: bool,
}

impl From<JsonWebKeyInit> for JsonWebKey {
    fn from(init: JsonWebKeyInit) -> Self {
        let JsonWebKeyInit { kty, key_ops, alg, k, ext } = init;
        Self { kty, key_ops, alg, k, ext }
    }
}
<commit_msg>events: Add a test for encrypted media sources being preferred<commit_after>//! Modules for events in the `m.room` namespace.
//!
//! This module also contains types shared by events in its child namespaces.

use std::collections::BTreeMap;

use js_int::UInt;
use serde::{Deserialize, Serialize};

use crate::{
    serde::{base64::UrlSafe, Base64},
    MxcUri,
};

pub mod aliases;
pub mod avatar;
pub mod canonical_alias;
pub mod create;
pub mod encrypted;
pub mod encryption;
pub mod guest_access;
pub mod history_visibility;
pub mod join_rules;
pub mod member;
pub mod message;
pub mod name;
pub mod pinned_events;
pub mod power_levels;
pub mod redaction;
pub mod server_acl;
pub mod third_party_invite;
mod thumbnail_source_serde;
pub mod tombstone;
pub mod topic;

/// The source of a media file.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_enums)]
pub enum MediaSource {
    /// The MXC URI to the unencrypted media file.
    #[serde(rename = "url")]
    Plain(Box<MxcUri>),

    /// The encryption info of the encrypted media file.
    #[serde(rename = "file")]
    Encrypted(Box<EncryptedFile>),
}

/// Metadata about an image.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ImageInfo {
    /// The height of the image in pixels.
    #[serde(rename = "h", skip_serializing_if = "Option::is_none")]
    pub height: Option<UInt>,

    /// The width of the image in pixels.
    #[serde(rename = "w", skip_serializing_if = "Option::is_none")]
    pub width: Option<UInt>,

    /// The MIME type of the image, e.g. "image/png."
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mimetype: Option<String>,

    /// The file size of the image in bytes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub size: Option<UInt>,

    /// Metadata about the image referred to in `thumbnail_source`.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub thumbnail_info: Option<Box<ThumbnailInfo>>,

    /// The source of the thumbnail of the image.
    #[serde(flatten, with = "thumbnail_source_serde", skip_serializing_if = "Option::is_none")]
    pub thumbnail_source: Option<MediaSource>,

    /// The [BlurHash](https://blurha.sh) for this image.
    ///
    /// This uses the unstable prefix in
    /// [MSC2448](https://github.com/matrix-org/matrix-spec-proposals/pull/2448).
    #[cfg(feature = "unstable-msc2448")]
    #[serde(
        rename = "xyz.amorgan.blurhash",
        alias = "blurhash",
        skip_serializing_if = "Option::is_none"
    )]
    pub blurhash: Option<String>,
}

impl ImageInfo {
    /// Creates an empty `ImageInfo`.
    pub fn new() -> Self {
        Self::default()
    }
}

/// Metadata about a thumbnail.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ThumbnailInfo {
    /// The height of the thumbnail in pixels.
    #[serde(rename = "h", skip_serializing_if = "Option::is_none")]
    pub height: Option<UInt>,

    /// The width of the thumbnail in pixels.
    #[serde(rename = "w", skip_serializing_if = "Option::is_none")]
    pub width: Option<UInt>,

    /// The MIME type of the thumbnail, e.g. "image/png."
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mimetype: Option<String>,

    /// The file size of the thumbnail in bytes.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub size: Option<UInt>,
}

impl ThumbnailInfo {
    /// Creates an empty `ThumbnailInfo`.
    pub fn new() -> Self {
        Self::default()
    }
}

/// A file sent to a room with end-to-end encryption enabled.
///
/// To create an instance of this type, first create a `EncryptedFileInit` and convert it via
/// `EncryptedFile::from` / `.into()`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct EncryptedFile {
    /// The URL to the file.
    pub url: Box<MxcUri>,

    /// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
    pub key: JsonWebKey,

    /// The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64.
    pub iv: Base64,

    /// A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64.
    ///
    /// Clients should support the SHA-256 hash, which uses the key sha256.
    pub hashes: BTreeMap<String, Base64>,

    /// Version of the encrypted attachments protocol.
    ///
    /// Must be `v2`.
    pub v: String,
}

/// Initial set of fields of `EncryptedFile`.
///
/// This struct will not be updated even if additional fields are added to `EncryptedFile` in a new
/// (non-breaking) release of the Matrix specification.
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct EncryptedFileInit {
    /// The URL to the file.
    pub url: Box<MxcUri>,

    /// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
    pub key: JsonWebKey,

    /// The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64.
    pub iv: Base64,

    /// A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64.
    ///
    /// Clients should support the SHA-256 hash, which uses the key sha256.
    pub hashes: BTreeMap<String, Base64>,

    /// Version of the encrypted attachments protocol.
    ///
    /// Must be `v2`.
    pub v: String,
}

impl From<EncryptedFileInit> for EncryptedFile {
    fn from(init: EncryptedFileInit) -> Self {
        let EncryptedFileInit { url, key, iv, hashes, v } = init;
        Self { url, key, iv, hashes, v }
    }
}

/// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
///
/// To create an instance of this type, first create a `JsonWebKeyInit` and convert it via
/// `JsonWebKey::from` / `.into()`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct JsonWebKey {
    /// Key type.
    ///
    /// Must be `oct`.
    pub kty: String,

    /// Key operations.
    ///
    /// Must at least contain `encrypt` and `decrypt`.
    pub key_ops: Vec<String>,

    /// Algorithm.
    ///
    /// Must be `A256CTR`.
    pub alg: String,

    /// The key, encoded as url-safe unpadded base64.
    pub k: Base64<UrlSafe>,

    /// Extractable.
    ///
    /// Must be `true`. This is a
    /// [W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk).
    pub ext: bool,
}

/// Initial set of fields of `JsonWebKey`.
///
/// This struct will not be updated even if additional fields are added to `JsonWebKey` in a new
/// (non-breaking) release of the Matrix specification.
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct JsonWebKeyInit {
    /// Key type.
    ///
    /// Must be `oct`.
    pub kty: String,

    /// Key operations.
    ///
    /// Must at least contain `encrypt` and `decrypt`.
    pub key_ops: Vec<String>,

    /// Algorithm.
    ///
    /// Must be `A256CTR`.
    pub alg: String,

    /// The key, encoded as url-safe unpadded base64.
    pub k: Base64<UrlSafe>,

    /// Extractable.
    ///
    /// Must be `true`. This is a
    /// [W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk).
    pub ext: bool,
}

impl From<JsonWebKeyInit> for JsonWebKey {
    fn from(init: JsonWebKeyInit) -> Self {
        let JsonWebKeyInit { kty, key_ops, alg, k, ext } = init;
        Self { kty, key_ops, alg, k, ext }
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;

    use matches::assert_matches;
    use serde::Deserialize;
    use serde_json::{from_value as from_json_value, json};

    use crate::serde::Base64;

    use super::{EncryptedFile, JsonWebKey, MediaSource};

    #[derive(Deserialize)]
    struct MsgWithAttachment {
        #[allow(dead_code)]
        body: String,
        #[serde(flatten)]
        source: MediaSource,
    }

    fn dummy_jwt() -> JsonWebKey {
        JsonWebKey {
            kty: "oct".to_owned(),
            key_ops: vec!["encrypt".to_owned(), "decrypt".to_owned()],
            alg: "A256CTR".to_owned(),
            k: Base64::new(vec![0; 64]),
            ext: true,
        }
    }

    fn encrypted_file() -> EncryptedFile {
        EncryptedFile {
            url: "mxc://localhost/encrypted_file".into(),
            key: dummy_jwt(),
            iv: Base64::new(vec![0; 64]),
            hashes: BTreeMap::new(),
            v: "v2".to_owned(),
        }
    }

    #[test]
    fn prefer_encrypted_attachment_over_plain() {
        let msg: MsgWithAttachment = from_json_value(json!({
            "body": "",
            "url": "mxc://localhost/file",
            "file": encrypted_file(),
        }))
        .unwrap();

        assert_matches!(msg.source, MediaSource::Encrypted(_));

        // As above, but with the file field before the url field
        let msg: MsgWithAttachment = from_json_value(json!({
            "body": "",
            "file": encrypted_file(),
            "url": "mxc://localhost/file",
        }))
        .unwrap();

        assert_matches!(msg.source, MediaSource::Encrypted(_));
    }
}
<|endoftext|>


<commit_before>fn main() {
    let some_vec = vec![1, 2, 3];
    let some_vec_iter = some_vec.iter();

    for val in some_vec_iter {
        println!("Value: {}", val);
    }

    let some_other_vec: Vec<_> = some_vec.iter().map(|x| x + 1).collect();
    println!("{:?}", some_other_vec);
}
<commit_msg>Example of filter<commit_after>fn main() {
    let some_vec = vec![1, 2, 3];
    let some_vec_iter = some_vec.iter();

    for val in some_vec_iter {
        println!("Value: {}", val);
    }

    let some_other_vec: Vec<_> = some_vec.iter().map(|x| x + 1).collect();
    println!("{:?}", some_other_vec);

    let shoes = vec![
        Shoe { size: 40, style: String::from("sandal") },
        Shoe { size: 42, style: String::from("sneaker") }
    ];

    let in_my_size = shoes_in_my_size(shoes, 42);

    for val in in_my_size {
        println!("In my size! {:?}", val);
    }
}

#[derive(PartialEq, Debug)]
struct Shoe {
    size: i32,
    style: String
}

fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: i32) -> Vec<Shoe> {
    shoes.into_iter()
        .filter(|s| s.size == shoe_size)
        .collect()
}
<|endoftext|>


<commit_before>// Kevin Lang
// Cole Garner
//
// Concurrent Patricia trie with managed memory instead of
// garbage collection. Based off of the following paper:
// http://www.temple.edu/cis/icdcs2013/data/5000a216.pdf
// by Niloufar Shafiei

use std::sync::Arc;

// The CPT simply is a root to the tree
pub struct CPT {
    root: Arc<Internal>
}

enum Node {
    Leaf(Leaf),
    Internal(Internal),
}

// In order for Leaf to be both 'type of Node' and a distinct type
// we need to have the actual fields stored in its own struct
// Thus, we have enum value Node::Leaf and the distinct type Leaf
struct Leaf {
    label:  String,
    info:   Info,
}

// See Leaf struct for details as to why we need a struct and
// an enum type.
struct Internal {
    label:  String,
    info:   Info,
    child:  [Option<Arc<Node>>; 2],
}

// Flags are used to mark nodes that will be changed, instead of
// needing to use locks.
enum Info {
    Flag {
        flag:   Vec<Arc<Internal>>, // nodes to be flagged [0,4]
        oldI:   Vec<Arc<Info>>,     // expected CAS value for flagging
        unflag: Vec<Arc<Internal>>, // nodes to unflag [0,2]
        par:    Vec<Arc<Internal>>, // nodes whose child changed [0,2]
        old:    Vec<Arc<Node>>,     // expected children
        new:    Vec<Arc<Node>>,     // new children
        mvLeaf: Option<Arc<Leaf>>,  // leaf that may be flagged [0,1]
        flagDone: bool,
    },

    Unflag,
}

impl CPT {
    fn new() -> CPT {
        CPT {
            root: Arc::new(
                Internal{ label: String::new(),
                          info:  Info::Unflag,
                          child: [None, None], }
                          ),
        }
    }
}

fn main() {

}
<commit_msg>changed to arrays since algorithm utilized array indices in search<commit_after>// Kevin Lang
// Cole Garner
//
// Concurrent Patricia trie with managed memory instead of
// garbage collection. Based off of the following paper:
// http://www.temple.edu/cis/icdcs2013/data/5000a216.pdf
// by Niloufar Shafiei

use std::sync::Arc;

// The CPT simply is a root to the tree
pub struct CPT {
    root: Arc<Internal>
}

enum Node {
    Leaf(Leaf),
    Internal(Internal),
}

// In order for Leaf to be both 'type of Node' and a distinct type
// we need to have the actual fields stored in its own struct
// Thus, we have enum value Node::Leaf and the distinct type Leaf
struct Leaf {
    label:  String,
    info:   Info,
}

// See Leaf struct for details as to why we need a struct and
// an enum type.
struct Internal {
    label:  String,
    info:   Info,
    child:  [Option<Arc<Node>>; 2],
}

// Flags are used to mark nodes that will be changed, instead of
// needing to use locks.
enum Info {
    Flag(Flag),
    Unflag,
}

struct Flag {
    flag:   [Option<Arc<Internal>>; 4],// nodes to be flagged
    oldI:   [Option<Arc<Info>>; 4],     // expected CAS value for flagging
    unflag: [Option<Arc<Internal>>; 2], // nodes to unflag
    par:    [Option<Arc<Internal>>; 2], // nodes whose child changed
    old:    [Option<Arc<Node>>; 2],     // expected children
    new:    [Option<Arc<Node>>; 2],     // new children
    mvLeaf: Option<Arc<Leaf>>,          // leaf that may be flagged
    flagDone: bool,
}

impl CPT {
    fn new() -> CPT {
        CPT {
            root: Arc::new(
                Internal{ label: String::new(),
                          info:  Info::Unflag,
                          child: [None, None], }
                          ),
        }
    }
}

fn main() {

}
<|endoftext|>