<commit_before>use core::ops::{Div, Rem};
pub trait DivRemEuclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
    /// Calculates Euclidean division, the matching method for `rem_euclid`.
    ///
    /// This computes the integer `n` such that
    /// `self = n * rhs + self.rem_euclid(rhs)`.
    /// In other words, the result is `self / rhs` rounded to the integer `n`
    /// such that `self >= n * rhs`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::DivRemEuclid;
    ///
    /// let a: i32 = 7;
    /// let b: i32 = 4;
    /// assert_eq!(DivRemEuclid::div_euclid(&a,&b), 1); // 7 > 4 * 1
    /// assert_eq!(DivRemEuclid::div_euclid(&-a,&b), -2); // -7 >= 4 * -2
    /// assert_eq!(DivRemEuclid::div_euclid(&a,&-b), -1); // 7 >= -4 * -1
    /// assert_eq!(DivRemEuclid::div_euclid(&-a,&-b), 2); // -7 >= -4 * 2
    /// ```
    fn div_euclid(&self, v: &Self) -> Self;

    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
    ///
    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
    /// most cases. However, due to a floating point round-off error it can
    /// result in `r == rhs.abs()`, violating the mathematical definition, if
    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
    /// This result is not an element of the function's codomain, but it is the
    /// closest floating point number in the real numbers and thus fulfills the
    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
    /// approximatively.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::DivRemEuclid;
    ///
    /// let a: i32 = 7;
    /// let b: i32 = 4;
    /// assert_eq!(DivRemEuclid::rem_euclid(&a,&b), 3);
    /// assert_eq!(DivRemEuclid::rem_euclid(&-a,&b), 1);
    /// assert_eq!(DivRemEuclid::rem_euclid(&a,&-b), 3);
    /// assert_eq!(DivRemEuclid::rem_euclid(&-a,&-b), 1);
    /// ```
    fn rem_euclid(&self, v: &Self) -> Self;
}
macro_rules! div_rem_euclid_impl {
    ($trait_name:ident for $($t:ty)*) => {$(
        impl $trait_name for $t {
            #[inline]
            fn div_euclid(&self, v: &$t) -> Self {
                <$t>::div_euclid(*self, *v)
            }

            #[inline]
            fn rem_euclid(&self, v: &$t) -> Self {
                <$t>::rem_euclid(*self, *v)
            }

        }
    )*}
}
div_rem_euclid_impl!(DivRemEuclid for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
#[cfg(has_i128)]
div_rem_euclid_impl!(DivRemEuclid for i128 u128);

#[cfg(any(feature = "std", feature = "libm"))]
impl DivRemEuclid for f32 {
    fn div_euclid(&self, rhs: &f32) -> f32 {
        let q = <f32 as ::Float>::trunc(self / rhs);
        if self % rhs < 0.0 {
            return if *rhs > 0.0 { q - 1.0 } else { q + 1.0 };
        }
        q
    }

    fn rem_euclid(&self, rhs: &f32) -> f32 {
        let r = self % rhs;
        if r < 0.0 {
            r + <f32 as ::Float>::abs(*rhs)
        } else {
            r
        }
    }
}

#[cfg(any(feature = "std", feature = "libm"))]
impl DivRemEuclid for f64 {
    fn div_euclid(&self, rhs: &f64) -> f64 {
        let q = <f64 as ::Float>::trunc(self / rhs);
        if self % rhs < 0.0 {
            return if *rhs > 0.0 { q - 1.0 } else { q + 1.0 };
        }
        q
    }

    fn rem_euclid(&self, rhs: &f64) -> f64 {
        let r = self % rhs;
        if r < 0.0 {
            r + <f64 as ::Float>::abs(*rhs)
        } else {
            r
        }
    }
}

pub trait CheckedDivRemEuclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
    /// Performs euclid division that returns `None` instead of panicking on division by zero
    /// and instead of wrapping around on underflow and overflow.
    fn checked_div_euclid(&self, v: &Self) -> Option<Self>;

    /// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and
    /// division by zero. If any of that happens, `None` is returned.
    fn checked_rem_euclid(&self, v: &Self) -> Option<Self>;
}

macro_rules! checked_div_rem_euclid_impl {
    ($trait_name:ident for $($t:ty)*) => {$(
        impl $trait_name for $t {
            #[inline]
            fn checked_div_euclid(&self, v: &$t) -> Option<$t> {
                <$t>::checked_div_euclid(*self, *v)
            }

            #[inline]
            fn checked_rem_euclid(&self, v: &$t) -> Option<$t> {
                <$t>::checked_rem_euclid(*self, *v)
            }
        }
    )*}
}
checked_div_rem_euclid_impl!(CheckedDivRemEuclid for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
#[cfg(has_i128)]
checked_div_rem_euclid_impl!(CheckedDivRemEuclid for i128 u128);

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

    #[test]
    fn euclid_unsigned() {
        macro_rules! test_euclid {
            ($($t:ident)+) => {
                $(
                    {
                        let x: $t = 10;
                        let y: $t = 3;
                        assert_eq!(DivRemEuclid::div_euclid(&x,&y),3);
                        assert_eq!(DivRemEuclid::rem_euclid(&x,&y),1);
                    }
                )+
            };
        }

        test_euclid!(usize u8 u16 u32 u64 isize);
    }

    #[test]
    fn euclid_signed() {
        macro_rules! test_euclid {
            ($($t:ident)+) => {
                $(
                    {
                        let x: $t = 10;
                        let y: $t = -3;
                        assert_eq!(DivRemEuclid::div_euclid(&x,&y),-3);
                        assert_eq!(DivRemEuclid::div_euclid(&-x,&y),4);
                        assert_eq!(DivRemEuclid::rem_euclid(&x,&y),1);
                        assert_eq!(DivRemEuclid::rem_euclid(&-x,&y),2);
                        let x: $t = $t::MIN+1;
                        let y: $t = -1;
                        assert_eq!(DivRemEuclid::div_euclid(&x,&y),$t::MAX);
                    }
                )+
            };
        }

        test_euclid!(i8 i16 i32 i64);
    }

    #[test]
    #[cfg(any(feature = "std", feature = "libm"))]
    fn euclid_float() {
        macro_rules! test_euclid {
            ($($t:ident)+) => {
                $(
                    {
                        let x: $t = 12.1;
                        let y: $t = 3.2;
                        assert!(DivRemEuclid::div_euclid(&x,&y)*y+DivRemEuclid::rem_euclid(&x,&y)-x
                        <=46.4 * $t::EPSILON);
                        assert!(DivRemEuclid::div_euclid(&x,&-y)*-y+DivRemEuclid::rem_euclid(&x,&-y)-x
                        <= 46.4 * $t::EPSILON);
                        assert!(DivRemEuclid::div_euclid(&-x,&y)*y+DivRemEuclid::rem_euclid(&-x,&y)-(-x)
                        <= 46.4 * $t::EPSILON);
                        assert!(DivRemEuclid::div_euclid(&-x,&-y)*-y+DivRemEuclid::rem_euclid(&-x,&-y)-(-x)
                        <= 46.4 * $t::EPSILON);
                    }
                )+
            };
        }

        test_euclid!(f32 f64);
    }

    #[test]
    fn euclid_checked() {
        macro_rules! test_euclid_checked {
            ($($t:ident)+) => {
                $(
                    {
                        assert_eq!(CheckedDivRemEuclid::checked_div_euclid(&$t::MIN,&-1),None);
                        assert_eq!(CheckedDivRemEuclid::checked_rem_euclid(&$t::MIN,&-1),None);
                        assert_eq!(CheckedDivRemEuclid::checked_div_euclid(&1,&0),None);
                        assert_eq!(CheckedDivRemEuclid::checked_rem_euclid(&1,&0),None);
                    }
                )+
            };
        }

        test_euclid_checked!(i8 i16 i32 i64);
    }
}
<commit_msg>fixes method impl<commit_after>use core::ops::{Div, Rem};
pub trait DivRemEuclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
    /// Calculates Euclidean division, the matching method for `rem_euclid`.
    ///
    /// This computes the integer `n` such that
    /// `self = n * rhs + self.rem_euclid(rhs)`.
    /// In other words, the result is `self / rhs` rounded to the integer `n`
    /// such that `self >= n * rhs`.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::DivRemEuclid;
    ///
    /// let a: i32 = 7;
    /// let b: i32 = 4;
    /// assert_eq!(DivRemEuclid::div_euclid(&a,&b), 1); // 7 > 4 * 1
    /// assert_eq!(DivRemEuclid::div_euclid(&-a,&b), -2); // -7 >= 4 * -2
    /// assert_eq!(DivRemEuclid::div_euclid(&a,&-b), -1); // 7 >= -4 * -1
    /// assert_eq!(DivRemEuclid::div_euclid(&-a,&-b), 2); // -7 >= -4 * 2
    /// ```
    fn div_euclid(&self, v: &Self) -> Self;

    /// Calculates the least nonnegative remainder of `self (mod rhs)`.
    ///
    /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
    /// most cases. However, due to a floating point round-off error it can
    /// result in `r == rhs.abs()`, violating the mathematical definition, if
    /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
    /// This result is not an element of the function's codomain, but it is the
    /// closest floating point number in the real numbers and thus fulfills the
    /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
    /// approximatively.
    ///
    /// # Examples
    ///
    /// ```
    /// use num_traits::DivRemEuclid;
    ///
    /// let a: i32 = 7;
    /// let b: i32 = 4;
    /// assert_eq!(DivRemEuclid::rem_euclid(&a,&b), 3);
    /// assert_eq!(DivRemEuclid::rem_euclid(&-a,&b), 1);
    /// assert_eq!(DivRemEuclid::rem_euclid(&a,&-b), 3);
    /// assert_eq!(DivRemEuclid::rem_euclid(&-a,&-b), 1);
    /// ```
    fn rem_euclid(&self, v: &Self) -> Self;
}
macro_rules! div_rem_euclid_impl {
    ($trait_name:ident,$method:ident,$method_2:ident for $($t:ty)*) => {$(
        impl $trait_name for $t {
            #[inline]
            fn $method(&self, v: &$t) -> Self {
                <$t>::$method(*self, *v)
            }

            #[inline]
            fn $method_2(&self, v: &$t) -> Self {
                <$t>::$method_2(*self, *v)
            }

        }
    )*}
}
div_rem_euclid_impl!(DivRemEuclid,div_euclid,rem_euclid for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
#[cfg(has_i128)]
div_rem_euclid_impl!(DivRemEuclid,div_euclid,rem_euclid for i128 u128);

#[cfg(any(feature = "std", feature = "libm"))]
impl DivRemEuclid for f32 {
    fn div_euclid(&self, rhs: &f32) -> f32 {
        let q = <f32 as ::Float>::trunc(self / rhs);
        if self % rhs < 0.0 {
            return if *rhs > 0.0 { q - 1.0 } else { q + 1.0 };
        }
        q
    }

    fn rem_euclid(&self, rhs: &f32) -> f32 {
        let r = self % rhs;
        if r < 0.0 {
            r + <f32 as ::Float>::abs(*rhs)
        } else {
            r
        }
    }
}

#[cfg(any(feature = "std", feature = "libm"))]
impl DivRemEuclid for f64 {
    fn div_euclid(&self, rhs: &f64) -> f64 {
        let q = <f64 as ::Float>::trunc(self / rhs);
        if self % rhs < 0.0 {
            return if *rhs > 0.0 { q - 1.0 } else { q + 1.0 };
        }
        q
    }

    fn rem_euclid(&self, rhs: &f64) -> f64 {
        let r = self % rhs;
        if r < 0.0 {
            r + <f64 as ::Float>::abs(*rhs)
        } else {
            r
        }
    }
}

pub trait CheckedDivRemEuclid: Sized + Div<Self, Output = Self> + Rem<Self, Output = Self> {
    /// Performs euclid division that returns `None` instead of panicking on division by zero
    /// and instead of wrapping around on underflow and overflow.
    fn checked_div_euclid(&self, v: &Self) -> Option<Self>;

    /// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and
    /// division by zero. If any of that happens, `None` is returned.
    fn checked_rem_euclid(&self, v: &Self) -> Option<Self>;
}

macro_rules! checked_div_rem_euclid_impl {
    ($trait_name:ident,$method:ident,$method_2:ident for $($t:ty)*) => {$(
        impl $trait_name for $t {
            #[inline]
            fn $method(&self, v: &$t) -> Option<$t> {
                <$t>::$method(*self, *v)
            }

            #[inline]
            fn $method_2(&self, v: &$t) -> Option<$t> {
                <$t>::$method_2(*self, *v)
            }
        }
    )*}
}
checked_div_rem_euclid_impl!(CheckedDivRemEuclid,checked_div_euclid,checked_rem_euclid for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
#[cfg(has_i128)]
checked_div_rem_euclid_impl!(CheckedDivRemEuclid,checked_div_euclid,checked_rem_euclid for i128 u128);

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

    #[test]
    fn euclid_unsigned() {
        macro_rules! test_euclid {
            ($($t:ident)+) => {
                $(
                    {
                        let x: $t = 10;
                        let y: $t = 3;
                        assert_eq!(DivRemEuclid::div_euclid(&x,&y),3);
                        assert_eq!(DivRemEuclid::rem_euclid(&x,&y),1);
                    }
                )+
            };
        }

        test_euclid!(usize u8 u16 u32 u64 isize);
    }

    #[test]
    fn euclid_signed() {
        macro_rules! test_euclid {
            ($($t:ident)+) => {
                $(
                    {
                        let x: $t = 10;
                        let y: $t = -3;
                        assert_eq!(DivRemEuclid::div_euclid(&x,&y),-3);
                        assert_eq!(DivRemEuclid::div_euclid(&-x,&y),4);
                        assert_eq!(DivRemEuclid::rem_euclid(&x,&y),1);
                        assert_eq!(DivRemEuclid::rem_euclid(&-x,&y),2);
                        let x: $t = $t::MIN+1;
                        let y: $t = -1;
                        assert_eq!(DivRemEuclid::div_euclid(&x,&y),$t::MAX);
                    }
                )+
            };
        }

        test_euclid!(i8 i16 i32 i64);
    }

    #[test]
    #[cfg(any(feature = "std", feature = "libm"))]
    fn euclid_float() {
        macro_rules! test_euclid {
            ($($t:ident)+) => {
                $(
                    {
                        let x: $t = 12.1;
                        let y: $t = 3.2;
                        assert!(DivRemEuclid::div_euclid(&x,&y)*y+DivRemEuclid::rem_euclid(&x,&y)-x
                        <=46.4 * $t::EPSILON);
                        assert!(DivRemEuclid::div_euclid(&x,&-y)*-y+DivRemEuclid::rem_euclid(&x,&-y)-x
                        <= 46.4 * $t::EPSILON);
                        assert!(DivRemEuclid::div_euclid(&-x,&y)*y+DivRemEuclid::rem_euclid(&-x,&y)-(-x)
                        <= 46.4 * $t::EPSILON);
                        assert!(DivRemEuclid::div_euclid(&-x,&-y)*-y+DivRemEuclid::rem_euclid(&-x,&-y)-(-x)
                        <= 46.4 * $t::EPSILON);
                    }
                )+
            };
        }

        test_euclid!(f32 f64);
    }

    #[test]
    fn euclid_checked() {
        macro_rules! test_euclid_checked {
            ($($t:ident)+) => {
                $(
                    {
                        assert_eq!(CheckedDivRemEuclid::checked_div_euclid(&$t::MIN,&-1),None);
                        assert_eq!(CheckedDivRemEuclid::checked_rem_euclid(&$t::MIN,&-1),None);
                        assert_eq!(CheckedDivRemEuclid::checked_div_euclid(&1,&0),None);
                        assert_eq!(CheckedDivRemEuclid::checked_rem_euclid(&1,&0),None);
                    }
                )+
            };
        }

        test_euclid_checked!(i8 i16 i32 i64);
    }
}
<|endoftext|>


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

use std::any::Any;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::fmt;
use std::marker::PhantomData;
use std::net::SocketAddr;

use bytes::Bytes;
use prometheus::{Error as MetricsError, Registry};

use crate::cluster::Endpoint;
use crate::config::{UpstreamEndpoints, ValidationError};
use crate::extensions::filters::ConvertProtoConfigError;
use std::sync::Arc;

/// DynamicMetadata contains shared state between filters during processing for a single packet.
type DynamicMetadata = HashMap<Arc<String>, Box<dyn Any + Send>>;

/// Contains the input arguments to [read](crate::extensions::filter_registry::Filter::read)
pub struct ReadContext {
    /// The upstream endpoints that the packet will be forwarded to.
    pub endpoints: UpstreamEndpoints,
    /// The source of the received packet.
    pub from: SocketAddr,
    /// Contents of the received packet.
    pub contents: Vec<u8>,
    /// Arbitrary values that can be passed from one filter to another
    pub metadata: DynamicMetadata,
    // Enforce using constructor to create this struct.
    phantom: PhantomData<()>,
}

/// Contains the output of [read](crate::extensions::filter_registry::Filter::read)
///
/// New instances are created from a [`ReadContext`]
///
/// ```rust
/// # use quilkin::extensions::{ReadContext, ReadResponse};
///   fn read(ctx: ReadContext) -> Option<ReadResponse> {
///       Some(ctx.into())
///   }
/// ```
pub struct ReadResponse {
    /// The upstream endpoints that the packet should be forwarded to.
    pub endpoints: UpstreamEndpoints,
    /// Contents of the packet to be forwarded.
    pub contents: Vec<u8>,
    /// Arbitrary values that can be passed from one filter to another
    pub metadata: DynamicMetadata,
    // Enforce using constructor to create this struct.
    phantom: PhantomData<()>,
}

/// Contains the input arguments to [write](crate::extensions::filter_registry::Filter::write)
pub struct WriteContext<'a> {
    /// The upstream endpoint that we're expecting packets from.
    pub endpoint: &'a Endpoint,
    /// The source of the received packet.
    pub from: SocketAddr,
    /// The destination of the received packet.
    pub to: SocketAddr,
    /// Contents of the received packet.
    pub contents: Vec<u8>,
    /// Arbitrary values that can be passed from one filter to another
    pub metadata: HashMap<String, Box<dyn Any + Send>>,
    // Enforce using constructor to create this struct.
    phantom: PhantomData<()>,
}

/// Contains the output of [write](crate::extensions::filter_registry::Filter::write)
///
/// New instances are created from an [`WriteContext`]
///
/// ```rust
/// # use quilkin::extensions::{WriteContext, WriteResponse};
///   fn write(ctx: WriteContext) -> Option<WriteResponse> {
///       Some(ctx.into())
///   }
/// ```
pub struct WriteResponse {
    /// Contents of the packet to be sent back to the original sender.
    pub contents: Vec<u8>,
    /// Arbitrary values that can be passed from one filter to another
    pub metadata: HashMap<String, Box<dyn Any + Send>>,
    // Enforce using constructor to create this struct.
    phantom: PhantomData<()>,
}

impl ReadContext {
    /// Creates a new [`ReadContext`]
    pub fn new(endpoints: UpstreamEndpoints, from: SocketAddr, contents: Vec<u8>) -> Self {
        Self {
            endpoints,
            from,
            contents,
            metadata: HashMap::new(),
            phantom: PhantomData,
        }
    }

    /// Creates a new [`ReadContext`] from a [`ReadResponse`]
    pub fn with_response(from: SocketAddr, response: ReadResponse) -> Self {
        Self {
            endpoints: response.endpoints,
            from,
            contents: response.contents,
            metadata: response.metadata,
            phantom: PhantomData,
        }
    }
}

impl From<ReadContext> for ReadResponse {
    fn from(ctx: ReadContext) -> Self {
        Self {
            endpoints: ctx.endpoints,
            contents: ctx.contents,
            metadata: ctx.metadata,
            phantom: ctx.phantom,
        }
    }
}

impl WriteContext<'_> {
    /// Creates a new [`WriteContext`]
    pub fn new(
        endpoint: &Endpoint,
        from: SocketAddr,
        to: SocketAddr,
        contents: Vec<u8>,
    ) -> WriteContext {
        WriteContext {
            endpoint,
            from,
            to,
            contents,
            metadata: HashMap::new(),
            phantom: PhantomData,
        }
    }

    /// Creates a new [`WriteContext`] from a [`WriteResponse`]
    pub fn with_response(
        endpoint: &Endpoint,
        from: SocketAddr,
        to: SocketAddr,
        response: WriteResponse,
    ) -> WriteContext {
        WriteContext {
            endpoint,
            from,
            to,
            contents: response.contents,
            metadata: response.metadata,
            phantom: PhantomData,
        }
    }
}

impl From<WriteContext<'_>> for WriteResponse {
    fn from(ctx: WriteContext) -> Self {
        Self {
            contents: ctx.contents,
            phantom: ctx.phantom,
            metadata: ctx.metadata,
        }
    }
}

/// Filter is a trait for routing and manipulating packets.
pub trait Filter: Send + Sync {
    /// Read is invoked when the proxy receives data from a downstream connection on the
    /// listening port.
    /// This function should return a [`ReadResponse`] containing the array of
    /// endpoints that the packet should be sent to and the packet that should be
    /// sent (which may be manipulated) as well.
    /// If the packet should be rejected, return None.
    /// By default, passes the context through unchanged
    fn read(&self, ctx: ReadContext) -> Option<ReadResponse> {
        Some(ctx.into())
    }

    /// Write is invoked when the proxy is about to send data to a downstream connection
    /// via the listening port after receiving it via one of the upstream Endpoints.
    /// This function should return an [`WriteResponse`] containing the packet to
    /// be sent (which may be manipulated).
    /// If the packet should be rejected, return None.
    /// By default, passes the context through unchanged
    fn write(&self, ctx: WriteContext) -> Option<WriteResponse> {
        Some(ctx.into())
    }
}

#[derive(Debug, PartialEq)]
/// Error is an error when attempting to create a Filter from_config() from a FilterFactory
pub enum Error {
    NotFound(String),
    MissingConfig(String),
    FieldInvalid { field: String, reason: String },
    DeserializeFailed(String),
    InitializeMetricsFailed(String),
    ConvertProtoConfig(ConvertProtoConfigError),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::NotFound(key) => write!(f, "filter {} is not found", key),
            Error::MissingConfig(filter_name) => {
                write!(f, "filter `{}` requires a configuration", filter_name)
            }
            Error::FieldInvalid { field, reason } => {
                write!(f, "field {} is invalid: {}", field, reason)
            }
            Error::DeserializeFailed(reason) => write!(f, "Deserialization failed: {}", reason),
            Error::InitializeMetricsFailed(reason) => {
                write!(f, "failed to initialize metrics: {}", reason)
            }
            Error::ConvertProtoConfig(inner) => write!(f, "{}", inner),
        }
    }
}

impl From<Error> for ValidationError {
    fn from(error: Error) -> Self {
        Self::FilterInvalid(error)
    }
}

impl From<MetricsError> for Error {
    fn from(error: MetricsError) -> Self {
        Error::InitializeMetricsFailed(error.to_string())
    }
}

pub enum ConfigType<'a> {
    Static(&'a serde_yaml::Value),
    Dynamic(prost_types::Any),
}

impl ConfigType<'_> {
    /// Deserializes a config based on the input type.
    pub fn deserialize<T, P>(self, filter_name: &str) -> Result<T, Error>
    where
        P: prost::Message + Default,
        T: for<'de> serde::Deserialize<'de> + TryFrom<P, Error = ConvertProtoConfigError>,
    {
        match self {
            ConfigType::Static(config) => serde_yaml::to_string(config)
                .and_then(|raw_config| serde_yaml::from_str(raw_config.as_str()))
                .map_err(|err| Error::DeserializeFailed(err.to_string())),
            ConfigType::Dynamic(config) => prost::Message::decode(Bytes::from(config.value))
                .map_err(|err| {
                    Error::DeserializeFailed(format!(
                        "filter `{}`: config decode error: {}",
                        filter_name,
                        err.to_string()
                    ))
                })
                .and_then(|config| T::try_from(config).map_err(Error::ConvertProtoConfig)),
        }
    }
}

/// Arguments needed to create a new filter.
pub struct CreateFilterArgs<'a> {
    /// Configuration for the filter.
    pub config: Option<ConfigType<'a>>,
    /// metrics_registry is used to register filter metrics collectors.
    pub metrics_registry: Registry,
}

impl CreateFilterArgs<'_> {
    pub fn fixed(
        metrics_registry: Registry,
        config: Option<&serde_yaml::Value>,
    ) -> CreateFilterArgs {
        CreateFilterArgs {
            config: config.map(|config| ConfigType::Static(config)),
            metrics_registry,
        }
    }

    pub fn dynamic(
        metrics_registry: Registry,
        config: Option<prost_types::Any>,
    ) -> CreateFilterArgs<'static> {
        CreateFilterArgs {
            config: config.map(ConfigType::Dynamic),
            metrics_registry,
        }
    }

    pub fn with_metrics_registry(self, metrics_registry: Registry) -> Self {
        CreateFilterArgs {
            metrics_registry,
            ..self
        }
    }
}

/// FilterFactory provides the name and creation function for a given Filter.
pub trait FilterFactory: Sync + Send {
    /// name returns the configuration name for the Filter
    /// The returned string identifies the filter item's path with the following format:
    ///     `quilkin.extensions.filters.<module>.<version>.<item-name>`
    /// where:
    ///     <module>: The rust module name containing the filter item
    ///     <version>: The filter's version.
    ///     <item-name>: The name of the rust item (e.g enum, struct) implementing the filter.
    /// For example the `v1alpha1` version of the debug filter has the name:
    ///     `quilkin.extensions.filters.debug_filter.v1alpha1.Debug`
    fn name(&self) -> String;

    /// Returns a filter based on the provided arguments.
    fn create_filter(&self, args: CreateFilterArgs) -> Result<Box<dyn Filter>, Error>;

    /// Returns the [`ConfigType`] from the provided Option, otherwise it returns
    /// Error::MissingConfig if the Option is None.
    fn require_config<'a, 'b>(
        &'a self,
        config: Option<ConfigType<'b>>,
    ) -> Result<ConfigType<'b>, Error> {
        config.ok_or_else(|| Error::MissingConfig(self.name()))
    }
}

/// FilterRegistry is the registry of all Filters that can be applied in the system.
#[derive(Default)]
pub struct FilterRegistry {
    registry: HashMap<String, Box<dyn FilterFactory>>,
}

impl FilterRegistry {
    /// insert adds a [`FilterFactory`] to this filter registry.
    pub fn insert<T: 'static>(&mut self, factory: T)
    where
        T: FilterFactory,
    {
        self.registry.insert(factory.name(), Box::new(factory));
    }

    /// insert_all adds the provided [`FilterFactory`]s to this filter registry.
    pub fn insert_all(&mut self, factories: Vec<Box<dyn FilterFactory>>) {
        for factory in factories {
            self.registry.insert(factory.name(), factory);
        }
    }

    /// get returns an instance of a filter for a given Key. Returns Error if not found,
    /// or if there is a configuration issue.
    pub fn get(&self, key: &str, args: CreateFilterArgs) -> Result<Box<dyn Filter>, Error> {
        match self.registry.get(key).map(|p| p.create_filter(args)) {
            None => Err(Error::NotFound(key.into())),
            Some(filter) => filter,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::net::{IpAddr, Ipv4Addr, SocketAddr};

    use crate::test_utils::TestFilterFactory;

    use super::*;
    use crate::cluster::Endpoint;
    use crate::config::Endpoints;

    struct TestFilter {}

    impl Filter for TestFilter {
        fn read(&self, _: ReadContext) -> Option<ReadResponse> {
            None
        }

        fn write(&self, _: WriteContext) -> Option<WriteResponse> {
            None
        }
    }

    #[test]
    fn insert_and_get() {
        let mut reg = FilterRegistry::default();
        reg.insert(TestFilterFactory {});

        match reg.get(
            &String::from("not.found"),
            CreateFilterArgs::fixed(Registry::default(), None),
        ) {
            Ok(_) => unreachable!("should not be filter"),
            Err(err) => assert_eq!(Error::NotFound("not.found".to_string()), err),
        };

        assert!(reg
            .get(
                &String::from("TestFilter"),
                CreateFilterArgs::fixed(Registry::default(), None)
            )
            .is_ok());

        let filter = reg
            .get(
                &String::from("TestFilter"),
                CreateFilterArgs::fixed(Registry::default(), None),
            )
            .unwrap();

        let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
        let endpoint = Endpoint::from_address(addr);

        assert!(filter
            .read(ReadContext::new(
                Endpoints::new(vec![Endpoint::from_address(
                    "127.0.0.1:8080".parse().unwrap(),
                )])
                .unwrap()
                .into(),
                addr,
                vec![]
            ))
            .is_some());
        assert!(filter
            .write(WriteContext::new(&endpoint, addr, addr, vec![],))
            .is_some());
    }
}
<commit_msg>Fix links in rustdoc documentation (#260)<commit_after>/*
 * Copyright 2020 Google LLC All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use std::any::Any;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::fmt;
use std::marker::PhantomData;
use std::net::SocketAddr;

use bytes::Bytes;
use prometheus::{Error as MetricsError, Registry};

use crate::cluster::Endpoint;
use crate::config::{UpstreamEndpoints, ValidationError};
use crate::extensions::filters::ConvertProtoConfigError;
use std::sync::Arc;

/// DynamicMetadata contains shared state between filters during processing for a single packet.
type DynamicMetadata = HashMap<Arc<String>, Box<dyn Any + Send>>;

/// Contains the input arguments to [`Filter::read`].
pub struct ReadContext {
    /// The upstream endpoints that the packet will be forwarded to.
    pub endpoints: UpstreamEndpoints,
    /// The source of the received packet.
    pub from: SocketAddr,
    /// Contents of the received packet.
    pub contents: Vec<u8>,
    /// Arbitrary values that can be passed from one filter to another
    pub metadata: DynamicMetadata,
    // Enforce using constructor to create this struct.
    phantom: PhantomData<()>,
}

/// Contains the output of [`Filter::read`].
///
/// New instances are created from a [`ReadContext`]
///
/// ```rust
/// # use quilkin::extensions::{ReadContext, ReadResponse};
///   fn read(ctx: ReadContext) -> Option<ReadResponse> {
///       Some(ctx.into())
///   }
/// ```
pub struct ReadResponse {
    /// The upstream endpoints that the packet should be forwarded to.
    pub endpoints: UpstreamEndpoints,
    /// Contents of the packet to be forwarded.
    pub contents: Vec<u8>,
    /// Arbitrary values that can be passed from one filter to another
    pub metadata: DynamicMetadata,
    // Enforce using constructor to create this struct.
    phantom: PhantomData<()>,
}

/// Contains the input arguments to [`Filter::write`].
pub struct WriteContext<'a> {
    /// The upstream endpoint that we're expecting packets from.
    pub endpoint: &'a Endpoint,
    /// The source of the received packet.
    pub from: SocketAddr,
    /// The destination of the received packet.
    pub to: SocketAddr,
    /// Contents of the received packet.
    pub contents: Vec<u8>,
    /// Arbitrary values that can be passed from one filter to another
    pub metadata: HashMap<String, Box<dyn Any + Send>>,
    // Enforce using constructor to create this struct.
    phantom: PhantomData<()>,
}

/// Contains the output of [`Filter::write`].
///
/// New instances are created from an [`WriteContext`]
///
/// ```rust
/// # use quilkin::extensions::{WriteContext, WriteResponse};
///   fn write(ctx: WriteContext) -> Option<WriteResponse> {
///       Some(ctx.into())
///   }
/// ```
pub struct WriteResponse {
    /// Contents of the packet to be sent back to the original sender.
    pub contents: Vec<u8>,
    /// Arbitrary values that can be passed from one filter to another
    pub metadata: HashMap<String, Box<dyn Any + Send>>,
    // Enforce using constructor to create this struct.
    phantom: PhantomData<()>,
}

impl ReadContext {
    /// Creates a new [`ReadContext`]
    pub fn new(endpoints: UpstreamEndpoints, from: SocketAddr, contents: Vec<u8>) -> Self {
        Self {
            endpoints,
            from,
            contents,
            metadata: HashMap::new(),
            phantom: PhantomData,
        }
    }

    /// Creates a new [`ReadContext`] from a [`ReadResponse`]
    pub fn with_response(from: SocketAddr, response: ReadResponse) -> Self {
        Self {
            endpoints: response.endpoints,
            from,
            contents: response.contents,
            metadata: response.metadata,
            phantom: PhantomData,
        }
    }
}

impl From<ReadContext> for ReadResponse {
    fn from(ctx: ReadContext) -> Self {
        Self {
            endpoints: ctx.endpoints,
            contents: ctx.contents,
            metadata: ctx.metadata,
            phantom: ctx.phantom,
        }
    }
}

impl WriteContext<'_> {
    /// Creates a new [`WriteContext`]
    pub fn new(
        endpoint: &Endpoint,
        from: SocketAddr,
        to: SocketAddr,
        contents: Vec<u8>,
    ) -> WriteContext {
        WriteContext {
            endpoint,
            from,
            to,
            contents,
            metadata: HashMap::new(),
            phantom: PhantomData,
        }
    }

    /// Creates a new [`WriteContext`] from a [`WriteResponse`]
    pub fn with_response(
        endpoint: &Endpoint,
        from: SocketAddr,
        to: SocketAddr,
        response: WriteResponse,
    ) -> WriteContext {
        WriteContext {
            endpoint,
            from,
            to,
            contents: response.contents,
            metadata: response.metadata,
            phantom: PhantomData,
        }
    }
}

impl From<WriteContext<'_>> for WriteResponse {
    fn from(ctx: WriteContext) -> Self {
        Self {
            contents: ctx.contents,
            phantom: ctx.phantom,
            metadata: ctx.metadata,
        }
    }
}

/// Filter is a trait for routing and manipulating packets.
pub trait Filter: Send + Sync {
    /// Read is invoked when the proxy receives data from a downstream connection on the
    /// listening port.
    /// This function should return a [`ReadResponse`] containing the array of
    /// endpoints that the packet should be sent to and the packet that should be
    /// sent (which may be manipulated) as well.
    /// If the packet should be rejected, return None.
    /// By default, passes the context through unchanged
    fn read(&self, ctx: ReadContext) -> Option<ReadResponse> {
        Some(ctx.into())
    }

    /// Write is invoked when the proxy is about to send data to a downstream connection
    /// via the listening port after receiving it via one of the upstream Endpoints.
    /// This function should return an [`WriteResponse`] containing the packet to
    /// be sent (which may be manipulated).
    /// If the packet should be rejected, return None.
    /// By default, passes the context through unchanged
    fn write(&self, ctx: WriteContext) -> Option<WriteResponse> {
        Some(ctx.into())
    }
}

#[derive(Debug, PartialEq)]
/// Error is an error when attempting to create a Filter from_config() from a FilterFactory
pub enum Error {
    NotFound(String),
    MissingConfig(String),
    FieldInvalid { field: String, reason: String },
    DeserializeFailed(String),
    InitializeMetricsFailed(String),
    ConvertProtoConfig(ConvertProtoConfigError),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::NotFound(key) => write!(f, "filter {} is not found", key),
            Error::MissingConfig(filter_name) => {
                write!(f, "filter `{}` requires a configuration", filter_name)
            }
            Error::FieldInvalid { field, reason } => {
                write!(f, "field {} is invalid: {}", field, reason)
            }
            Error::DeserializeFailed(reason) => write!(f, "Deserialization failed: {}", reason),
            Error::InitializeMetricsFailed(reason) => {
                write!(f, "failed to initialize metrics: {}", reason)
            }
            Error::ConvertProtoConfig(inner) => write!(f, "{}", inner),
        }
    }
}

impl From<Error> for ValidationError {
    fn from(error: Error) -> Self {
        Self::FilterInvalid(error)
    }
}

impl From<MetricsError> for Error {
    fn from(error: MetricsError) -> Self {
        Error::InitializeMetricsFailed(error.to_string())
    }
}

pub enum ConfigType<'a> {
    Static(&'a serde_yaml::Value),
    Dynamic(prost_types::Any),
}

impl ConfigType<'_> {
    /// Deserializes a config based on the input type.
    pub fn deserialize<T, P>(self, filter_name: &str) -> Result<T, Error>
    where
        P: prost::Message + Default,
        T: for<'de> serde::Deserialize<'de> + TryFrom<P, Error = ConvertProtoConfigError>,
    {
        match self {
            ConfigType::Static(config) => serde_yaml::to_string(config)
                .and_then(|raw_config| serde_yaml::from_str(raw_config.as_str()))
                .map_err(|err| Error::DeserializeFailed(err.to_string())),
            ConfigType::Dynamic(config) => prost::Message::decode(Bytes::from(config.value))
                .map_err(|err| {
                    Error::DeserializeFailed(format!(
                        "filter `{}`: config decode error: {}",
                        filter_name,
                        err.to_string()
                    ))
                })
                .and_then(|config| T::try_from(config).map_err(Error::ConvertProtoConfig)),
        }
    }
}

/// Arguments needed to create a new filter.
pub struct CreateFilterArgs<'a> {
    /// Configuration for the filter.
    pub config: Option<ConfigType<'a>>,
    /// metrics_registry is used to register filter metrics collectors.
    pub metrics_registry: Registry,
}

impl CreateFilterArgs<'_> {
    pub fn fixed(
        metrics_registry: Registry,
        config: Option<&serde_yaml::Value>,
    ) -> CreateFilterArgs {
        CreateFilterArgs {
            config: config.map(|config| ConfigType::Static(config)),
            metrics_registry,
        }
    }

    pub fn dynamic(
        metrics_registry: Registry,
        config: Option<prost_types::Any>,
    ) -> CreateFilterArgs<'static> {
        CreateFilterArgs {
            config: config.map(ConfigType::Dynamic),
            metrics_registry,
        }
    }

    pub fn with_metrics_registry(self, metrics_registry: Registry) -> Self {
        CreateFilterArgs {
            metrics_registry,
            ..self
        }
    }
}

/// FilterFactory provides the name and creation function for a given Filter.
pub trait FilterFactory: Sync + Send {
    /// name returns the configuration name for the Filter
    /// The returned string identifies the filter item's path with the following format:
    ///     `quilkin.extensions.filters.<module>.<version>.<item-name>`
    /// where:
    ///     <module>: The rust module name containing the filter item
    ///     <version>: The filter's version.
    ///     <item-name>: The name of the rust item (e.g enum, struct) implementing the filter.
    /// For example the `v1alpha1` version of the debug filter has the name:
    ///     `quilkin.extensions.filters.debug_filter.v1alpha1.Debug`
    fn name(&self) -> String;

    /// Returns a filter based on the provided arguments.
    fn create_filter(&self, args: CreateFilterArgs) -> Result<Box<dyn Filter>, Error>;

    /// Returns the [`ConfigType`] from the provided Option, otherwise it returns
    /// Error::MissingConfig if the Option is None.
    fn require_config<'a, 'b>(
        &'a self,
        config: Option<ConfigType<'b>>,
    ) -> Result<ConfigType<'b>, Error> {
        config.ok_or_else(|| Error::MissingConfig(self.name()))
    }
}

/// FilterRegistry is the registry of all Filters that can be applied in the system.
#[derive(Default)]
pub struct FilterRegistry {
    registry: HashMap<String, Box<dyn FilterFactory>>,
}

impl FilterRegistry {
    /// insert adds a [`FilterFactory`] to this filter registry.
    pub fn insert<T: 'static>(&mut self, factory: T)
    where
        T: FilterFactory,
    {
        self.registry.insert(factory.name(), Box::new(factory));
    }

    /// insert_all adds the provided [`FilterFactory`]s to this filter registry.
    pub fn insert_all(&mut self, factories: Vec<Box<dyn FilterFactory>>) {
        for factory in factories {
            self.registry.insert(factory.name(), factory);
        }
    }

    /// get returns an instance of a filter for a given Key. Returns Error if not found,
    /// or if there is a configuration issue.
    pub fn get(&self, key: &str, args: CreateFilterArgs) -> Result<Box<dyn Filter>, Error> {
        match self.registry.get(key).map(|p| p.create_filter(args)) {
            None => Err(Error::NotFound(key.into())),
            Some(filter) => filter,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::net::{IpAddr, Ipv4Addr, SocketAddr};

    use crate::test_utils::TestFilterFactory;

    use super::*;
    use crate::cluster::Endpoint;
    use crate::config::Endpoints;

    struct TestFilter {}

    impl Filter for TestFilter {
        fn read(&self, _: ReadContext) -> Option<ReadResponse> {
            None
        }

        fn write(&self, _: WriteContext) -> Option<WriteResponse> {
            None
        }
    }

    #[test]
    fn insert_and_get() {
        let mut reg = FilterRegistry::default();
        reg.insert(TestFilterFactory {});

        match reg.get(
            &String::from("not.found"),
            CreateFilterArgs::fixed(Registry::default(), None),
        ) {
            Ok(_) => unreachable!("should not be filter"),
            Err(err) => assert_eq!(Error::NotFound("not.found".to_string()), err),
        };

        assert!(reg
            .get(
                &String::from("TestFilter"),
                CreateFilterArgs::fixed(Registry::default(), None)
            )
            .is_ok());

        let filter = reg
            .get(
                &String::from("TestFilter"),
                CreateFilterArgs::fixed(Registry::default(), None),
            )
            .unwrap();

        let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
        let endpoint = Endpoint::from_address(addr);

        assert!(filter
            .read(ReadContext::new(
                Endpoints::new(vec![Endpoint::from_address(
                    "127.0.0.1:8080".parse().unwrap(),
                )])
                .unwrap()
                .into(),
                addr,
                vec![]
            ))
            .is_some());
        assert!(filter
            .write(WriteContext::new(&endpoint, addr, addr, vec![],))
            .is_some());
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use linked_hash_map::LinkedHashMap;
pub use parser::store::*;
pub use parser::loc::Loc;

#[derive(Debug, Default)]
pub struct Template {
    pub children: Vec<Loc<NodeType, (usize, usize)>>,
}

impl Template {
    pub fn new(children: Vec<Loc<NodeType, (usize, usize)>>) -> Template {
        Template { children: children }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum NodeType {
    UseStmtNode(UseStmtType),
    ComponentDefinitionNode(ComponentDefinitionType),
    StoreNode(Vec<DefaultScopeNodeType>),
    ContentNode(ContentNodeType),
}

#[derive(Debug, Clone, PartialEq)]
pub enum ContentNodeType {
    ElementNode(ElementType),
    ExpressionValueNode(ExprValue, String),
    ForNode(Option<String>, ExprValue, Option<Vec<ContentNodeType>>),
}

/// Operators
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ExprOp {
    Add,
    Sub,
    Mul,
    Div,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ExprApplyOp {
    JoinString(Option<String>),
    Sum
}

#[derive(Debug, Clone, PartialEq)]
pub enum PrimitiveVarType {
    StringVar,
    Number,
    Expr,
}

#[derive(Debug, Clone, PartialEq)]
pub enum VarType {
    ArrayVar(Option<Box<VarType>>),
    Primitive(PrimitiveVarType),
}

#[derive(Debug, Clone, PartialEq)]
pub enum SymbolReferenceType {
    UnresolvedReference(String),
    Binding(BindingType),
    ResolvedReference(String, ResolvedSymbolType, Option<String>),
}

#[derive(Debug, Clone, PartialEq)]
pub enum KeyReferenceType {
    ReducerKey(String),
    FuncParam(i32),
    FuncParamObjectProp(i32, String),
    UnboundFormalParam,
    BlockMapIndex,
    BlockMapObjectProp,
    ComponentProp(String),
    InvocationProp(Option<Box<ExprValue>>),
    CurrentElementProp(String),
    CurrentReducerActionParam(String),
    CurrentReducerActionState,
    UnboundReducerActionParam(String)
}

#[derive(Debug, Clone, PartialEq)]
pub enum ResolvedSymbolType {
    ReferenceToKeyInScope(KeyReferenceType, Option<String>),

    ReducerKeyReference(String),
    ParameterReference(String),
    LocalVarReference(String),
    GlobalVarReference(String),
    ActionStateReference(Option<VarType>),
    ActionParamReference(String),
    LoopVarReference(String),
    LoopIndexReference(String, String),
    BlockParamReference(String),
    PropReference(String),
    LensPropReference(String, Box<LensExprType>),
    ForLensElementReference(String),
    ElementValueReference(String),
}

#[derive(Debug, Clone, PartialEq)]
pub struct Symbol(SymbolReferenceType, Option<VarType>, Option<Box<ExprValue>>);
pub type SymbolMap = LinkedHashMap<String, Symbol>;
pub type ValueMap = LinkedHashMap<String, ExprValue>;

impl Symbol {
    pub fn unresolved(key: &str) -> Symbol {
        Symbol(SymbolReferenceType::UnresolvedReference(key.to_owned()),
               None,
               None)
    }

    pub fn binding(binding: &BindingType) -> Symbol {
        Symbol(SymbolReferenceType::Binding(binding.to_owned()), None, None)
    }

    pub fn ref_key_in_scope(key: &str, key_ref: KeyReferenceType, scope_id: Option<&str>) -> Symbol {
        let resolved = ResolvedSymbolType::ReferenceToKeyInScope(key_ref, scope_id.map(|s| s.to_owned()));
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               None,
               None)
    }

    pub fn ref_prop_in_scope(key: &str, prop_key: &str, scope_id: Option<&str>) -> Symbol {
        let key_ref = KeyReferenceType::ComponentProp(prop_key.to_owned());
        let resolved = ResolvedSymbolType::ReferenceToKeyInScope(key_ref, scope_id.map(|s| s.to_owned()));
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               None,
               None)
    }

    pub fn element_prop(key: &str, prop_key: &str, scope_id: Option<&str>) -> Symbol {
        let key_ref = KeyReferenceType::CurrentElementProp(prop_key.to_owned());
        Self::ref_key_in_scope(key, key_ref, scope_id)
    }

    pub fn component_prop(key: &str, prop_key: &str, scope_id: Option<&str>) -> Symbol {
        let key_ref = KeyReferenceType::ComponentProp(prop_key.to_owned());
        Self::ref_key_in_scope(key, key_ref, scope_id)
    }

    /// Defines a value for a given formal parameter on the current component invocation scope.
    pub fn invocation_prop(key: &str, expr: Option<&ExprValue>) -> Symbol {
        let key_ref = KeyReferenceType::InvocationProp(expr.map(|e| Box::new(e.to_owned())));
        Self::ref_key_in_scope(key, key_ref, None)
    }

    /// Defines an unbound formal parameter on the current component definition.
    ///
    /// Retains the current scope id.
    pub fn unbound_formal_param(key: &str, scope_id: Option<&str>) -> Symbol {
        let key_ref = KeyReferenceType::UnboundFormalParam;
        Self::ref_key_in_scope(key, key_ref, scope_id)
    }

    // /// Creates a reference to an unbound formal parameter the given scope.
    // ///
    // /// Typically will be used to reference an unbound formal parameter in the currently
    // /// defined component and refers to the closest enclosing component definition.
    // pub fn unbound_formal_param_ref(key: &str, scope_id: &str) -> Symbol {
    //     // let key_ref = KeyReferenceType::UnboundFormalParamRef(key.to_owned());
    //     let key_ref = KeyReferenceType::UnboundFormalParam;
    //     Self::ref_key_in_scope(key, key_ref, Some(scope_id))
    // }

    pub fn reducer_key(key: &str) -> Symbol {
        let resolved = ResolvedSymbolType::ReducerKeyReference(key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               None,
               None)
    }

    pub fn reducer_key_with_ty(key: &str, ty: Option<&VarType>) -> Symbol {
        let resolved = ResolvedSymbolType::ReducerKeyReference(key.to_owned());
        let ty = ty.map(|ty| ty.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               ty,
               None)
    }

    pub fn reducer_key_with_value(key: &str, value: &ExprValue) -> Symbol {
        let resolved = ResolvedSymbolType::ReducerKeyReference(key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               None,
               Some(Box::new(value.clone())))
    }

    pub fn reducer_key_with(key: &str, ty: Option<&VarType>, value: Option<&ExprValue>) -> Symbol {
        let resolved = ResolvedSymbolType::ReducerKeyReference(key.to_owned());
        let value = value.map(|value| Box::new(value.clone()));
        let ty = ty.map(|ty| ty.clone());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               ty,
               value)
    }

    pub fn action_param(key: &str, _scope_id: &str) -> Symbol {
        Symbol::binding(&BindingType::ActionParamBinding(key.to_owned()))
        // let resolved = ResolvedSymbolType::ActionParamReference(key.to_owned());
        // Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, Some(scope_id.to_owned())),
        //        None,
        //        None)
    }

    pub fn loop_idx(key: &str, block_id: &str, scope_id: &str) -> Symbol {
        let var_key = format!("__{}_{}", key, block_id);
        let resolved = ResolvedSymbolType::LoopIndexReference(key.to_owned(), block_id.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(var_key.clone(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    pub fn loop_var(key: &str, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::LoopVarReference(key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    pub fn param(key: &str, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::ParameterReference(key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    pub fn block_param(key: &str, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::BlockParamReference(key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    // pub fn loop_var_with_value(key: &str, value: &ExprValue) -> Symbol {
    //     let resolved = ResolvedSymbolType::ReducerKeyReference(key.to_owned());
    //     let value = Some(Box::new(value.clone()));
    //     Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved),
    //            None,
    //            value)
    // }

    pub fn prop(prop_name: &str, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::PropReference(prop_name.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(prop_name.to_owned(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    // pub fn prop_with_value(prop_name: &str, value: &ExprValue) -> Symbol {
    //     let resolved = ResolvedSymbolType::PropReference(prop_name.to_owned());
    //     let value = Some(Box::new(value.clone()));
    //     // TODO: peek type
    //     Symbol(SymbolReferenceType::ResolvedReference(prop_name.to_owned(), resolved),
    //            None,
    //            value)
    // }

    pub fn action_state(ty: Option<&VarType>, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::ActionStateReference(ty.map(|ty| ty.to_owned()));
        Symbol(SymbolReferenceType::ResolvedReference("state".to_owned(), resolved, Some(scope_id.to_owned())),
               ty.map(|ty| ty.to_owned()),
               None)
    }

    pub fn for_lens_element_key(key: &str, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::ForLensElementReference(key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    pub fn element_value_binding(key: &str, element_key: &str, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::ElementValueReference(element_key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    /// References used within reducers and actions

    pub fn unbound_action_param(key: &str, scope_id: Option<&str>) -> Symbol {
        // Symbol::binding(&BindingType::UnboundActionParam(key.to_owned()))
        let key_ref = KeyReferenceType::UnboundReducerActionParam(key.to_owned());
        Self::ref_key_in_scope(key, key_ref, scope_id)
    }

    /// Accessors

    pub fn sym_ref(&self) -> &SymbolReferenceType {
        &self.0
    }

    pub fn ty(&self) -> Option<&VarType> {
        self.1.as_ref()
    }

    pub fn value(&self) -> Option<&ExprValue> {
        self.2.as_ref().map(|b| b.as_ref())
    }
}

/// Bindings
#[derive(Debug, Clone, PartialEq)]
pub enum BindingType {
    ExpressionBinding(Box<ExprValue>),
    KeyInSymbolsBinding(String, String),
    ReducerPathBinding(String, Option<Vec<String>>),
    LoopIndexBinding,
    ActionStateBinding,
    ActionParamBinding(String)
}

pub type BindingMap = LinkedHashMap<String, BindingType>;

/// Simple expression (parameter value)
#[derive(Debug, Clone, PartialEq)]
pub enum ExprValue {
    LiteralNumber(i32),
    LiteralString(String),
    LiteralArray(Option<Vec<ExprValue>>),
    DefaultVariableReference,
    SymbolReference(Symbol),
    SymbolPathReference(Vec<Symbol>),
    Binding(BindingType),

    Expr(ExprOp, Box<ExprValue>, Box<ExprValue>),
    Apply(ExprApplyOp, Option<Vec<Box<ExprValue>>>),
    ContentNode(Box<ContentNodeType>),
    DefaultAction(Option<Vec<String>>, Option<Vec<ActionOpNode>>),
    Action(String, Option<Vec<String>>, Option<Vec<ActionOpNode>>),
    Undefined,
}

impl ExprValue {
    #[inline]
    pub fn is_literal(&self) -> bool {
        match self {
            &ExprValue::LiteralArray(..) |
            &ExprValue::LiteralString(..) |
            &ExprValue::LiteralNumber(..) => true,
            _ => false,
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum ElementExpr {
    Element(String, Option<String>, Option<Vec<Box<ExprValue>>>),
    Value(ExprValue),
}

#[derive(Debug, Clone, PartialEq)]
pub enum LensExprType {
    ForLens(Option<String>, Symbol),
    GetLens(Symbol),
}

#[derive(Debug, Clone, PartialEq)]
pub enum ActionOpNode {
    DispatchAction(String, Option<PropVec>),
}

#[derive(Debug, Clone, PartialEq)]
pub struct UseStmtType {
    pub package: String,
}

#[derive(Debug, Clone, PartialEq)]
pub struct ComponentDefinitionType {
    pub name: String,
    pub inputs: Option<Vec<String>>,
    pub children: Option<Vec<NodeType>>,
}

pub type EventHandler = (Option<String>, Option<EventHandlerParams>, Option<EventHandlerActionOps>);
pub type EventHandlerParams = Vec<String>;
pub type EventHandlerActionOps = Vec<ActionOpNode>;
pub type EventHandlersVec = Vec<EventHandler>;
pub type EventsItem = (String,
                       Option<String>,
                       Option<EventHandlerParams>,
                       Option<EventHandlerActionOps>,
                       Option<String>,
                       Option<String>);
pub type EventsVec = Vec<EventsItem>;
pub type PropVec = Vec<Prop>;

pub type ElementEventBinding = (Option<String>, Option<Vec<String>>, Option<Vec<ActionOpNode>>);
pub type ElementValueBinding = Option<String>;
pub type ElementBindings = (ElementValueBinding, Option<Vec<ElementEventBinding>>);

#[derive(Debug, Clone, PartialEq)]
pub enum ElementBindingNodeType {
    ElementEventBindingNode(ElementEventBinding),
    ElementValueBindingNode(String),
}
pub type ElementBindingNodeVec = Vec<ElementBindingNodeType>;

pub type PropKey = String;
pub type PropList = Vec<PropKey>;
pub type Prop = (String, Option<ExprValue>);

#[derive(Debug, Clone, PartialEq)]
pub struct ElementType {
    pub element_ty: String,
    pub element_key: String,
    pub attrs: Option<PropVec>,
    pub lens: Option<LensExprType>,
    pub children: Option<Vec<ContentNodeType>>,
    pub bindings: Option<Vec<ElementBindingNodeType>>,
}
<commit_msg>Remove unused variables and helpers in `ast.rs`<commit_after>// #![allow(dead_code)]

use linked_hash_map::LinkedHashMap;
pub use parser::store::*;
pub use parser::loc::Loc;

#[derive(Debug, Default)]
pub struct Template {
    pub children: Vec<Loc<NodeType, (usize, usize)>>,
}

impl Template {
    #[allow(dead_code)]
    pub fn new(children: Vec<Loc<NodeType, (usize, usize)>>) -> Template {
        Template { children: children }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum NodeType {
    UseStmtNode(UseStmtType),
    ComponentDefinitionNode(ComponentDefinitionType),
    StoreNode(Vec<DefaultScopeNodeType>),
    ContentNode(ContentNodeType),
}

#[derive(Debug, Clone, PartialEq)]
pub enum ContentNodeType {
    ElementNode(ElementType),
    ExpressionValueNode(ExprValue, String),
    ForNode(Option<String>, ExprValue, Option<Vec<ContentNodeType>>),
}

/// Operators
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ExprOp {
    Add,
    Sub,
    Mul,
    Div,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ExprApplyOp {
    JoinString(Option<String>),
    // Sum
}

#[derive(Debug, Clone, PartialEq)]
pub enum PrimitiveVarType {
    StringVar,
    Number,
    // Expr,
}

#[derive(Debug, Clone, PartialEq)]
pub enum VarType {
    ArrayVar(Option<Box<VarType>>),
    Primitive(PrimitiveVarType),
}

#[derive(Debug, Clone, PartialEq)]
pub enum SymbolReferenceType {
    UnresolvedReference(String),
    Binding(BindingType),
    ResolvedReference(String, ResolvedSymbolType, Option<String>),
}

#[derive(Debug, Clone, PartialEq)]
pub enum KeyReferenceType {
    UnboundFormalParam,
    ComponentProp(String),
    InvocationProp(Option<Box<ExprValue>>),
    CurrentElementProp(String),
    UnboundReducerActionParam(String)
}

#[derive(Debug, Clone, PartialEq)]
pub enum ResolvedSymbolType {
    ReferenceToKeyInScope(KeyReferenceType, Option<String>),
    ReducerKeyReference(String),
    ParameterReference(String),
    PropReference(String),
}

#[derive(Debug, Clone, PartialEq)]
pub struct Symbol(SymbolReferenceType, Option<VarType>, Option<Box<ExprValue>>);
pub type SymbolMap = LinkedHashMap<String, Symbol>;
// pub type ValueMap = LinkedHashMap<String, ExprValue>;

impl Symbol {
    pub fn unresolved(key: &str) -> Symbol {
        Symbol(SymbolReferenceType::UnresolvedReference(key.to_owned()),
               None,
               None)
    }

    pub fn binding(binding: &BindingType) -> Symbol {
        Symbol(SymbolReferenceType::Binding(binding.to_owned()), None, None)
    }

    pub fn ref_key_in_scope(key: &str, key_ref: KeyReferenceType, scope_id: Option<&str>) -> Symbol {
        let resolved = ResolvedSymbolType::ReferenceToKeyInScope(key_ref, scope_id.map(|s| s.to_owned()));
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               None,
               None)
    }

    pub fn element_prop(key: &str, prop_key: &str, scope_id: Option<&str>) -> Symbol {
        let key_ref = KeyReferenceType::CurrentElementProp(prop_key.to_owned());
        Self::ref_key_in_scope(key, key_ref, scope_id)
    }

    pub fn component_prop(key: &str, prop_key: &str, scope_id: Option<&str>) -> Symbol {
        let key_ref = KeyReferenceType::ComponentProp(prop_key.to_owned());
        Self::ref_key_in_scope(key, key_ref, scope_id)
    }

    /// Defines a value for a given formal parameter on the current component invocation scope.
    pub fn invocation_prop(key: &str, expr: Option<&ExprValue>) -> Symbol {
        let key_ref = KeyReferenceType::InvocationProp(expr.map(|e| Box::new(e.to_owned())));
        Self::ref_key_in_scope(key, key_ref, None)
    }

    /// Defines an unbound formal parameter on the current component definition.
    ///
    /// Retains the current scope id.
    pub fn unbound_formal_param(key: &str, scope_id: Option<&str>) -> Symbol {
        let key_ref = KeyReferenceType::UnboundFormalParam;
        Self::ref_key_in_scope(key, key_ref, scope_id)
    }

    pub fn reducer_key(key: &str) -> Symbol {
        let resolved = ResolvedSymbolType::ReducerKeyReference(key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               None,
               None)
    }

    pub fn reducer_key_with(key: &str, ty: Option<&VarType>, value: Option<&ExprValue>) -> Symbol {
        let resolved = ResolvedSymbolType::ReducerKeyReference(key.to_owned());
        let value = value.map(|value| Box::new(value.clone()));
        let ty = ty.map(|ty| ty.clone());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, None),
               ty,
               value)
    }

    pub fn action_param(key: &str, _scope_id: &str) -> Symbol {
        Symbol::binding(&BindingType::ActionParamBinding(key.to_owned()))
    }

    pub fn param(key: &str, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::ParameterReference(key.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(key.to_owned(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    pub fn prop(prop_name: &str, scope_id: &str) -> Symbol {
        let resolved = ResolvedSymbolType::PropReference(prop_name.to_owned());
        Symbol(SymbolReferenceType::ResolvedReference(prop_name.to_owned(), resolved, Some(scope_id.to_owned())),
               None,
               None)
    }

    /// References used within reducers and actions

    pub fn unbound_action_param(key: &str, scope_id: Option<&str>) -> Symbol {
        // Symbol::binding(&BindingType::UnboundActionParam(key.to_owned()))
        let key_ref = KeyReferenceType::UnboundReducerActionParam(key.to_owned());
        Self::ref_key_in_scope(key, key_ref, scope_id)
    }

    /// Accessors

    pub fn sym_ref(&self) -> &SymbolReferenceType {
        &self.0
    }

    pub fn ty(&self) -> Option<&VarType> {
        self.1.as_ref()
    }

    #[allow(dead_code)]
    pub fn value(&self) -> Option<&ExprValue> {
        self.2.as_ref().map(|b| b.as_ref())
    }
}

/// Bindings
#[derive(Debug, Clone, PartialEq)]
pub enum BindingType {
    ExpressionBinding(Box<ExprValue>),
    KeyInSymbolsBinding(String, String),
    ReducerPathBinding(String, Option<Vec<String>>),
    // LoopIndexBinding,
    ActionStateBinding,
    ActionParamBinding(String)
}

pub type BindingMap = LinkedHashMap<String, BindingType>;

/// Simple expression (parameter value)
#[derive(Debug, Clone, PartialEq)]
pub enum ExprValue {
    LiteralNumber(i32),
    LiteralString(String),
    LiteralArray(Option<Vec<ExprValue>>),
    DefaultVariableReference,
    SymbolReference(Symbol),
    SymbolPathReference(Vec<Symbol>),
    Binding(BindingType),

    Expr(ExprOp, Box<ExprValue>, Box<ExprValue>),
    Apply(ExprApplyOp, Option<Vec<Box<ExprValue>>>),
    ContentNode(Box<ContentNodeType>),
    // DefaultAction(Option<Vec<String>>, Option<Vec<ActionOpNode>>),
    // Action(String, Option<Vec<String>>, Option<Vec<ActionOpNode>>),
    Undefined,
}

impl ExprValue {
    #[inline]
    pub fn is_literal(&self) -> bool {
        match self {
            &ExprValue::LiteralArray(..) |
            &ExprValue::LiteralString(..) |
            &ExprValue::LiteralNumber(..) => true,
            _ => false,
        }
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub enum ElementExpr {
    Element(String, Option<String>, Option<Vec<Box<ExprValue>>>),
    Value(ExprValue),
}

#[derive(Debug, Clone, PartialEq)]
pub enum LensExprType {
    ForLens(Option<String>, Symbol),
    GetLens(Symbol),
}

#[derive(Debug, Clone, PartialEq)]
pub enum ActionOpNode {
    DispatchAction(String, Option<PropVec>),
}

#[derive(Debug, Clone, PartialEq)]
pub struct UseStmtType {
    pub package: String,
}

#[derive(Debug, Clone, PartialEq)]
pub struct ComponentDefinitionType {
    pub name: String,
    pub inputs: Option<Vec<String>>,
    pub children: Option<Vec<NodeType>>,
}

pub type EventHandler = (Option<String>, Option<EventHandlerParams>, Option<EventHandlerActionOps>);
pub type EventHandlerParams = Vec<String>;
pub type EventHandlerActionOps = Vec<ActionOpNode>;
pub type EventHandlersVec = Vec<EventHandler>;
pub type EventsItem = (String,
                       Option<String>,
                       Option<EventHandlerParams>,
                       Option<EventHandlerActionOps>,
                       Option<String>,
                       Option<String>);
pub type EventsVec = Vec<EventsItem>;
pub type PropVec = Vec<Prop>;

pub type ElementEventBinding = (Option<String>, Option<Vec<String>>, Option<Vec<ActionOpNode>>);
pub type ElementValueBinding = Option<String>;

#[derive(Debug, Clone, PartialEq)]
pub enum ElementBindingNodeType {
    ElementEventBindingNode(ElementEventBinding),
    ElementValueBindingNode(String),
}

pub type PropKey = String;
pub type Prop = (String, Option<ExprValue>);

#[derive(Debug, Clone, PartialEq)]
pub struct ElementType {
    pub element_ty: String,
    pub element_key: String,
    pub attrs: Option<PropVec>,
    pub lens: Option<LensExprType>,
    pub children: Option<Vec<ContentNodeType>>,
    pub bindings: Option<Vec<ElementBindingNodeType>>,
}
<|endoftext|>


<commit_before>#![feature(unboxed_closures)]

extern crate regex;

pub mod parsers;

#[macro_use]
pub mod macros;

mod tests;

mod peruse {
    pub use parsers;
}

<commit_msg>Allow unstable<commit_after>#![feature(unboxed_closures)]
#![allow(unstable)]

extern crate regex;

pub mod parsers;

#[macro_use]
pub mod macros;

mod tests;

mod peruse {
    pub use parsers;
}

<|endoftext|>


<commit_before>use super::mode;
use super::util;
use std::collections::DList;
use std::collections::Deque;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Group(Box<Doc>),
    Nest(uint, Box<Doc>),
    Newline,
    Text(String),
}

pub type Doc = DOC;

fn fitting(mut cmds: DList<(uint,mode::Mode,Doc)>, mut rem:int) -> bool {
    let mut fits = true;

    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match cmds.pop_front() {
            None => {
                break;
            },
            Some((ind, mode, ref doc)) => match doc.clone() {
                Nil => {},
                Append(box lhs, box rhs) => {
                    let mut prefix = DList::new();
                    prefix.push((ind, mode, lhs));
                    prefix.push((ind, mode, rhs));
                    cmds.prepend(prefix);
                },
                Group(box doc) => {
                    let mut prefix = DList::new();
                    prefix.push((ind, mode, doc));
                    cmds.prepend(prefix);
                },
                Nest(off, box doc) => {
                    let mut prefix = DList::new();
                    prefix.push((ind + off, mode, doc));
                    cmds.prepend(prefix);
                },
                Newline => {
                    fits = true;
                },
                Text(str) => {
                    rem -= str.len() as int;
                },
            }
        }
    }

    fits
}

impl Doc {

    fn best(self:Doc, width:uint, mut buf:DList<String>) -> DList<String> {
        let mut pos: uint = 0;
        let mut cmds: DList<(uint,mode::Mode,Doc)> = DList::new();

        cmds.push((0, mode::Break, self));

        loop {
            match cmds.pop_front() {
                None => {
                    break;
                },
                Some((ind, mode, ref doc)) => match doc.clone() {
                    Nil => {},
                    Append(box lhs, box rhs) => {
                        let mut prefix = DList::new();
                        prefix.push((ind, mode, lhs));
                        prefix.push((ind, mode, rhs));
                        cmds.prepend(prefix);
                    },
                    Group(box doc) => match mode {
                        mode::Flat => {
                            let mut prefix = DList::new();
                            prefix.push((ind, mode::Flat, doc));
                            cmds.prepend(prefix);
                        },
                        mode::Break => {
                            let mut cmds_dup = cmds.clone();
                            let mut flat_prefix = DList::new();
                            flat_prefix.push((ind, mode::Flat, doc.clone()));
                            cmds_dup.prepend(flat_prefix);
                            if fitting(cmds_dup, width as int - pos as int) {
                                let mut prefix = DList::new();
                                prefix.push((ind, mode::Flat, doc));
                                cmds.prepend(prefix);
                            } else {
                                let mut prefix = DList::new();
                                prefix.push((ind, mode::Break, doc));
                                cmds.prepend(prefix);
                            }
                        }
                    },
                    Nest(off, box doc) => {
                        let mut prefix = DList::new();
                        prefix.push((ind + off, mode, doc));
                        cmds.prepend(prefix);
                    },
                    Newline => {
                        let mut prefix = DList::new();
                        prefix.push(util::string::nl_spaces(ind));
                        buf.prepend(prefix);
                        pos = ind;
                    },
                    Text(str) => {
                        let mut prefix = DList::new();
                        prefix.push(str.clone());
                        buf.prepend(prefix);
                        pos += str.len();
                    },
                }
            }
        }

        buf
    }

    #[inline]
    pub fn nil() -> Doc {
        Nil
    }

    #[inline]
    pub fn append(self, that:Doc) -> Doc {
        match self {
            Nil => that,
            lhs => match that {
                Nil => lhs,
                rhs => Append(box lhs, box rhs)
            }
        }
    }

    #[inline]
    pub fn as_string<T:ToString>(t:T) -> Doc {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    #[inline]
    pub fn group(self) -> Doc {
        Group(box self)
    }

    #[inline]
    pub fn nest(self, off:uint) -> Doc {
        Nest(off, box self)
    }

    #[inline]
    pub fn newline() -> Doc {
        Newline
    }

    #[inline]
    pub fn render(self, width:uint) -> String {
        let mut result = String::new();
        for str in self.best(width, DList::new()).iter().rev() {
            result.push_str(str.as_slice());
        }
        result
    }

    #[inline]
    pub fn text<S:Str>(str:S) -> Doc {
        Text(String::from_str(str.as_slice()))
    }

}
<commit_msg>Optimizations; another 5x faster<commit_after>use super::mode;
use super::util;
use std::collections::DList;
use std::collections::Deque;

#[deriving(Clone)]
#[deriving(Show)]
enum DOC {
    Nil,
    Append(Box<Doc>, Box<Doc>),
    Group(Box<Doc>),
    Nest(uint, Box<Doc>),
    Newline,
    Text(String),
}

pub type Doc = DOC;
type Cmd<'a> = (uint,mode::Mode,&'a Doc);

fn fitting(mut cmds:DList<Cmd>, mut rem:int) -> bool {
    let mut fits = true;

    loop {
        if rem < 0 {
            fits = false;
            break;
        }
        match cmds.pop_front() {
            None => {
                break;
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(box ref ldoc, box ref rdoc) => {
                    cmds.push_front((ind, mode, rdoc));
                    cmds.push_front((ind, mode, ldoc));
                },
                &Group(box ref doc) => {
                    cmds.push_front((ind, mode, doc));
                },
                &Nest(off, box ref doc) => {
                    cmds.push_front((ind + off, mode, doc));
                },
                &Newline => {
                    fits = true;
                },
                &Text(ref str) => {
                    rem -= str.len() as int;
                },
            }
        }
    }

    fits
}

impl Doc {

    fn best(&self, width:uint) -> DList<String> {
        let mut pos: uint = 0;
        let mut cmds: DList<Cmd> = DList::new();
        let mut result:DList<String> = DList::new();

        cmds.push((0, mode::Break, self));

        loop {
            match cmds.pop_front() {
                None => {
                    break;
                },
                Some((ind, mode, doc)) => match doc {
                    &Nil => {
                    },
                    &Append(box ref ldoc, box ref rdoc) => {
                        cmds.push_front((ind, mode, rdoc));
                        cmds.push_front((ind, mode, ldoc));
                    },
                    &Group(box ref doc) => match mode {
                        mode::Flat => {
                            cmds.push_front((ind, mode::Flat, doc));
                        },
                        mode::Break => {
                            // FIXME: fitting() modifies cmds so we must either
                            // take a clone and pass it or rewrite fitting()
                            // to modify a separate cmd stack and only observe
                            // this one.
                            let mut cmds_dup = cmds.clone();
                            let next = (ind, mode::Flat, doc);
                            cmds_dup.push_front(next);
                            if fitting(cmds_dup, width as int - pos as int) {
                                cmds.push_front(next);
                            } else {
                                cmds.push_front((ind, mode::Break, doc));
                            }
                        }
                    },
                    &Nest(off, box ref doc) => {
                        cmds.push_front((ind + off, mode, doc));
                    },
                    &Newline => {
                        result.push(util::string::nl_spaces(ind));
                        pos = ind;
                    },
                    &Text(ref str) => {
                        // FIXME: we have to clone here otherwise result would
                        // have to contain String and &String. We cannot make
                        // Newline case return &String because the region is
                        // limited to the scope of its arm; it does not live
                        // long enough (the strings in Text will outlast).
                        result.push(str.clone());
                        pos += str.len();
                    },
                }
            }
        }

        result
    }

    #[inline]
    pub fn nil() -> Doc {
        Nil
    }

    #[inline]
    pub fn append(self, that:Doc) -> Doc {
        match self {
            Nil => {
                that
            },
            ldoc => match that {
                Nil => {
                    ldoc
                },
                rdoc => {
                    Append(box ldoc, box rdoc)
                },
            }
        }
    }

    #[inline]
    pub fn as_string<T:ToString>(t:T) -> Doc {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat(ds:&[Doc]) -> Doc {
        ds.iter().fold(Nil, |a, b| a.append(b.clone()))
    }

    #[inline]
    pub fn group(self) -> Doc {
        Group(box self)
    }

    #[inline]
    pub fn nest(self, off:uint) -> Doc {
        Nest(off, box self)
    }

    #[inline]
    pub fn newline() -> Doc {
        Newline
    }

    #[inline]
    pub fn render(&self, width:uint) -> String {
        let mut result = String::new();
        for str in self.best(width).iter() {
            result.push_str(str.as_slice());
        }
        result
    }

    #[inline]
    pub fn text<T:Str>(str:T) -> Doc {
        Text(String::from_str(str.as_slice()))
    }

}
<|endoftext|>


<commit_before>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate chrono;
extern crate futures;
extern crate log;
extern crate tokio_core;
extern crate trust_dns;
extern crate trust_dns_proto;
extern crate trust_dns_server;

#[cfg(feature = "tls")]
extern crate trust_dns_openssl;

mod server_harness;

use std::net::*;
use std::str::FromStr;

use tokio_core::reactor::Core;

use trust_dns::client::*;
use trust_dns::op::ResponseCode;
use trust_dns::rr::*;
use trust_dns::tcp::TcpClientStream;
use trust_dns::udp::UdpClientStream;

// TODO: Needed for when TLS tests are added back
// #[cfg(feature = "tls")]
// use trust_dns_openssl::TlsClientStreamBuilder;

use server_harness::{named_test_harness, query_a};

#[test]
fn test_example_toml_startup() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);

        // just tests that multiple queries work
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);
    })
}

#[test]
fn test_ipv4_only_toml_startup() {
    named_test_harness("ipv4_only.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should fail
        let message = io_loop.run(client.query(
            Name::from_str("www.example.com").unwrap(),
            DNSClass::IN,
            RecordType::AAAA,
        ));
        assert!(message.is_err());
    })
}

// TODO: this is commented out b/c at least on macOS, ipv4 will route properly to ipv6 only
//  listeners over the [::ffff:127.0.0.1] interface
//
// #[ignore]
// #[test]
// fn test_ipv6_only_toml_startup() {
//   named_test_harness("ipv6_only.toml", |port, _| {
//     let mut io_loop = Core::new().unwrap();
//     let addr: SocketAddr = ("127.0.0.1", port).to_socket_addrs().unwrap().next().unwrap();
//     let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
//     let client = ClientFuture::new(stream, sender, &io_loop.handle(), None);
//
//     // ipv4 should fail
//     assert!(!query(&mut io_loop, client));
//
//     let addr: SocketAddr = ("::1", port).to_socket_addrs().unwrap().next().unwrap();
//     let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
//     let client = ClientFuture::new(stream, sender, &io_loop.handle(), None);
//
//     // ipv6 should succeed
//     assert!(query(&mut io_loop, client));
//
//     assert!(true);
//   })
// }

#[ignore]
#[test]
fn test_ipv4_and_ipv6_toml_startup() {
    named_test_harness("ipv4_and_ipv6.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should succeed
        query_a(&mut io_loop, &mut client);

        assert!(true);
    })
}

#[test]
fn test_nodata_where_name_exists() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        let msg = io_loop
            .run(client.query(
                Name::from_str("www.example.com.").unwrap(),
                DNSClass::IN,
                RecordType::SRV,
            ))
            .unwrap();
        assert_eq!(msg.response_code(), ResponseCode::NoError);
        assert!(msg.answers().is_empty());
        assert!(true);
    })
}

#[test]
fn test_nxdomain_where_no_name_exists() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        let msg = io_loop
            .run(client.query(
                Name::from_str("nxdomain.example.com.").unwrap(),
                DNSClass::IN,
                RecordType::SRV,
            ))
            .unwrap();
        assert_eq!(msg.response_code(), ResponseCode::NXDomain);
        assert!(msg.answers().is_empty());
        assert!(true);
    })
}

#[cfg(feature = "tls")]
#[test]
fn test_example_tls_toml_startup() {
    use std::env;
    use std::fs::File;
    use std::io::*;
    use trust_dns_openssl::TlsClientStreamBuilder;

    named_test_harness("dns_over_tls.toml", move |_, tls_port| {
        let mut cert_der = vec![];
        let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or_else(|_| ".".to_owned());
        println!("using server src path: {}", server_path);

        File::open(&format!(
            "{}/tests/named_test_configs/sec/example.cert",
            server_path
        )).expect("failed to open cert")
            .read_to_end(&mut cert_der)
            .expect("failed to read cert");

        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), tls_port);
        let mut tls_conn_builder = TlsClientStreamBuilder::new();
        tls_conn_builder.add_ca_der(&cert_der).unwrap();
        let (stream, sender) =
            tls_conn_builder.build(addr, "ns.example.com".to_string(), &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), tls_port);
        let mut tls_conn_builder = TlsClientStreamBuilder::new();
        tls_conn_builder.add_ca_der(&cert_der).unwrap();
        let (stream, sender) =
            tls_conn_builder.build(addr, "ns.example.com".to_string(), &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should succeed
        query_a(&mut io_loop, &mut client);

        assert!(true);
    })
}

#[test]
fn test_server_continues_on_bad_data() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = UdpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);

        // Send a bad packet, this should get rejected by the server
        let raw_socket = UdpSocket::bind(SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0))
            .expect("couldn't bind raw");

        raw_socket
            .send_to(b"0xDEADBEEF", addr)
            .expect("raw send failed");

        // just tests that multiple queries work
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = UdpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);
    })
}
<commit_msg>remove test from master<commit_after>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate chrono;
extern crate futures;
extern crate log;
extern crate tokio_core;
extern crate trust_dns;
extern crate trust_dns_proto;
extern crate trust_dns_server;

#[cfg(feature = "tls")]
extern crate trust_dns_openssl;

mod server_harness;

use std::net::*;
use std::str::FromStr;

use tokio_core::reactor::Core;

use trust_dns::client::*;
use trust_dns::op::ResponseCode;
use trust_dns::rr::*;
use trust_dns::tcp::TcpClientStream;
use trust_dns::udp::UdpClientStream;

// TODO: Needed for when TLS tests are added back
// #[cfg(feature = "tls")]
// use trust_dns_openssl::TlsClientStreamBuilder;

use server_harness::{named_test_harness, query_a};

#[test]
fn test_example_toml_startup() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);

        // just tests that multiple queries work
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        query_a(&mut io_loop, &mut client);
    })
}

#[test]
fn test_ipv4_only_toml_startup() {
    named_test_harness("ipv4_only.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should fail
        let message = io_loop.run(client.query(
            Name::from_str("www.example.com").unwrap(),
            DNSClass::IN,
            RecordType::AAAA,
        ));
        assert!(message.is_err());
    })
}

// TODO: this is commented out b/c at least on macOS, ipv4 will route properly to ipv6 only
//  listeners over the [::ffff:127.0.0.1] interface
//
// #[ignore]
// #[test]
// fn test_ipv6_only_toml_startup() {
//   named_test_harness("ipv6_only.toml", |port, _| {
//     let mut io_loop = Core::new().unwrap();
//     let addr: SocketAddr = ("127.0.0.1", port).to_socket_addrs().unwrap().next().unwrap();
//     let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
//     let client = ClientFuture::new(stream, sender, &io_loop.handle(), None);
//
//     // ipv4 should fail
//     assert!(!query(&mut io_loop, client));
//
//     let addr: SocketAddr = ("::1", port).to_socket_addrs().unwrap().next().unwrap();
//     let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
//     let client = ClientFuture::new(stream, sender, &io_loop.handle(), None);
//
//     // ipv6 should succeed
//     assert!(query(&mut io_loop, client));
//
//     assert!(true);
//   })
// }

#[ignore]
#[test]
fn test_ipv4_and_ipv6_toml_startup() {
    named_test_harness("ipv4_and_ipv6.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should succeed
        query_a(&mut io_loop, &mut client);

        assert!(true);
    })
}

#[test]
fn test_nodata_where_name_exists() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        let msg = io_loop
            .run(client.query(
                Name::from_str("www.example.com.").unwrap(),
                DNSClass::IN,
                RecordType::SRV,
            ))
            .unwrap();
        assert_eq!(msg.response_code(), ResponseCode::NoError);
        assert!(msg.answers().is_empty());
        assert!(true);
    })
}

#[test]
fn test_nxdomain_where_no_name_exists() {
    named_test_harness("example.toml", |port, _| {
        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
        let (stream, sender) = TcpClientStream::new(addr, &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        let msg = io_loop
            .run(client.query(
                Name::from_str("nxdomain.example.com.").unwrap(),
                DNSClass::IN,
                RecordType::SRV,
            ))
            .unwrap();
        assert_eq!(msg.response_code(), ResponseCode::NXDomain);
        assert!(msg.answers().is_empty());
        assert!(true);
    })
}

#[cfg(feature = "tls")]
#[test]
fn test_example_tls_toml_startup() {
    use std::env;
    use std::fs::File;
    use std::io::*;
    use trust_dns_openssl::TlsClientStreamBuilder;

    named_test_harness("dns_over_tls.toml", move |_, tls_port| {
        let mut cert_der = vec![];
        let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or_else(|_| ".".to_owned());
        println!("using server src path: {}", server_path);

        File::open(&format!(
            "{}/tests/named_test_configs/sec/example.cert",
            server_path
        )).expect("failed to open cert")
            .read_to_end(&mut cert_der)
            .expect("failed to read cert");

        let mut io_loop = Core::new().unwrap();
        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), tls_port);
        let mut tls_conn_builder = TlsClientStreamBuilder::new();
        tls_conn_builder.add_ca_der(&cert_der).unwrap();
        let (stream, sender) =
            tls_conn_builder.build(addr, "ns.example.com".to_string(), &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv4 should succeed
        query_a(&mut io_loop, &mut client);

        let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), tls_port);
        let mut tls_conn_builder = TlsClientStreamBuilder::new();
        tls_conn_builder.add_ca_der(&cert_der).unwrap();
        let (stream, sender) =
            tls_conn_builder.build(addr, "ns.example.com".to_string(), &io_loop.handle());
        let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

        // ipv6 should succeed
        query_a(&mut io_loop, &mut client);

        assert!(true);
    })
}

// #[test]
// fn test_server_continues_on_bad_data() {
//     named_test_harness("example.toml", |port, _| {
//         let mut io_loop = Core::new().unwrap();
//         let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
//         let (stream, sender) = UdpClientStream::new(addr, &io_loop.handle());
//         let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

//         query_a(&mut io_loop, &mut client);

//         // Send a bad packet, this should get rejected by the server
//         let raw_socket = UdpSocket::bind(SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 0))
//             .expect("couldn't bind raw");

//         raw_socket
//             .send_to(b"0xDEADBEEF", addr)
//             .expect("raw send failed");

//         // just tests that multiple queries work
//         let addr: SocketAddr = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), port);
//         let (stream, sender) = UdpClientStream::new(addr, &io_loop.handle());
//         let mut client = ClientFuture::new(stream, sender, &io_loop.handle(), None);

//         query_a(&mut io_loop, &mut client);
//     })
// }
<|endoftext|>