<commit_before>//! A module to handle `Event` enumerator

pub mod attributes;

use std::borrow::Cow;
use std::str::from_utf8;
use std::ops::Deref;
use encoding_rs::Encoding;
use std::io::BufRead;

use escape::unescape;
use self::attributes::{Attributes, Attribute};
use errors::Result;
use reader::Reader;

/// A struct to manage `Event::Start` events
///
/// Provides in particular an iterator over attributes
#[derive(Clone, Debug)]
pub struct BytesStart<'a> {
    /// content of the element, before any utf8 conversion
    buf: Cow<'a, [u8]>,
    /// end of the element name, the name starts at that the start of `buf`
    name_len: usize,
}

impl<'a> BytesStart<'a> {
    /// Creates a new `BytesStart` from the given name.
    #[inline]
    pub fn borrowed(content: &'a [u8], name_len: usize) -> BytesStart<'a> {
        BytesStart {
            buf: Cow::Borrowed(content),
            name_len: name_len,
        }
    }

    /// Creates a new `BytesStart` from the given name. Owns its content
    #[inline]
    pub fn owned(content: Vec<u8>, name_len: usize) -> BytesStart<'static> {
        BytesStart {
            buf: Cow::Owned(content),
            name_len: name_len,
        }
    }

    /// Converts the event into an Owned event
    pub fn into_owned(self) -> BytesStart<'static> {
        BytesStart {
            buf: Cow::Owned(self.buf.into_owned()),
            name_len: self.name_len,
        }
    }

    /// Consumes self and adds attributes to this element from an iterator
    /// over (key, value) tuples.
    /// Key and value can be anything that implements the AsRef<[u8]> trait,
    /// like byte slices and strings.
    pub fn with_attributes<'b, I>(mut self, attributes: I) -> Self
        where I: IntoIterator,
              I::Item: Into<Attribute<'b>>
    {
        self.extend_attributes(attributes);
        self
    }

    /// name as &[u8] (without eventual attributes)
    pub fn name(&self) -> &[u8] {
        &self.buf[..self.name_len]
    }

    /// local name (excluding namespace) as &[u8] (without eventual attributes)
    /// returns the name() with any leading namespace removed (all content up to
    /// and including the first ':' character)
    #[inline]
    pub fn local_name(&self) -> &[u8] {
        if let Some(i) = self.name().iter().position(|b| *b == b':') {
            &self.name()[i + 1..]
        } else {
            self.name()
        }
    }

    /// gets unescaped content
    ///
    /// Searches for '&' into content and try to escape the coded character if possible
    /// returns Malformed error with index within element if '&' is not followed by ';'
    pub fn unescaped(&self) -> Result<Cow<[u8]>> {
        unescape(&*self.buf)
    }

    /// gets attributes iterator
    pub fn attributes(&self) -> Attributes {
        Attributes::new(self, self.name_len)
    }

    /// extend the attributes of this element from an iterator over (key, value) tuples.
    /// Key and value can be anything that implements the AsRef<[u8]> trait,
    /// like byte slices and strings.
    pub fn extend_attributes<'b, I>(&mut self, attributes: I) -> &mut BytesStart<'a>
        where I: IntoIterator,
              I::Item: Into<Attribute<'b>>
    {
        for attr in attributes {
            self.push_attribute(attr);
        }
        self
    }

    /// helper method to unescape then decode self using the reader encoding
    ///
    /// for performance reasons (could avoid allocating a `String`),
    /// it might be wiser to manually use
    /// 1. BytesStart::unescaped()
    /// 2. Reader::decode(...)
    pub fn unescape_and_decode<B: BufRead>(&self, reader: &Reader<B>) -> Result<String> {
        self.unescaped().map(|e| reader.decode(&*e).into_owned())
    }

    /// Adds an attribute to this element from the given key and value.
    /// Key and value can be anything that implements the AsRef<[u8]> trait,
    /// like byte slices and strings.
    pub fn push_attribute<'b, A: Into<Attribute<'b>>>(&mut self, attr: A) {
        let a = attr.into();
        let bytes = self.buf.to_mut();
        bytes.push(b' ');
        bytes.extend_from_slice(a.key);
        bytes.extend_from_slice(b"=\"");
        bytes.extend_from_slice(a.value);
        bytes.push(b'"');
    }
}

/// Wrapper around `BytesElement` to parse/write `XmlDecl`
///
/// Postpone element parsing only when needed.
///
/// [W3C XML 1.1 Prolog and Document Type Delcaration](http://w3.org/TR/xml11/#sec-prolog-dtd)
#[derive(Clone, Debug)]
pub struct BytesDecl<'a> {
    element: BytesStart<'a>,
}

impl<'a> BytesDecl<'a> {
    /// Creates a `BytesDecl` from a `BytesStart`
    pub fn from_start(start: BytesStart<'a>) -> BytesDecl<'a> {
        BytesDecl { element: start }
    }

    /// Gets xml version, including quotes (' or ")
    pub fn version(&self) -> Result<&[u8]> {
        match self.element.attributes().next() {
            Some(Err(e)) => Err(e),
            Some(Ok(Attribute {
                        key: b"version",
                        value: v,
                    })) => Ok(v),
            Some(Ok(a)) => {
                Err(format!("XmlDecl must start with 'version' attribute, found {:?}",
                            from_utf8(a.key))
                        .into())
            }
            None => Err("XmlDecl must start with 'version' attribute, found none".into()),
        }
    }

    /// Gets xml encoding, including quotes (' or ")
    pub fn encoding(&self) -> Option<Result<&[u8]>> {
        for a in self.element.attributes() {
            match a {
                Err(e) => return Some(Err(e)),
                Ok(Attribute {
                       key: b"encoding",
                       value: v,
                   }) => return Some(Ok(v)),
                _ => (),
            }
        }
        None
    }

    /// Gets xml standalone, including quotes (' or ")
    pub fn standalone(&self) -> Option<Result<&[u8]>> {
        for a in self.element.attributes() {
            match a {
                Err(e) => return Some(Err(e)),
                Ok(Attribute {
                       key: b"standalone",
                       value: v,
                   }) => return Some(Ok(v)),
                _ => (),
            }
        }
        None
    }

    /// Constructs a new `XmlDecl` from the (mandatory) _version_ (should be `1.0` or `1.1`),
    /// the optional _encoding_ (e.g., `UTF-8`) and the optional _standalone_ (`yes` or `no`)
    /// attribute.
    ///
    /// Does not escape any of its inputs. Always uses double quotes to wrap the attribute values.
    /// The caller is responsible for escaping attribute values. Shouldn't usually be relevant since
    /// the double quote character is not allowed in any of the attribute values.
    pub fn new(version: &[u8],
               encoding: Option<&[u8]>,
               standalone: Option<&[u8]>)
               -> BytesDecl<'static> {
        // Compute length of the buffer based on supplied attributes
        // ' encoding=""'   => 12
        let encoding_attr_len = if let Some(xs) = encoding {
            12 + xs.len()
        } else {
            0
        };
        // ' standalone=""' => 14
        let standalone_attr_len = if let Some(xs) = standalone {
            14 + xs.len()
        } else {
            0
        };
        // 'xml version=""' => 14
        let mut buf = Vec::with_capacity(14 + encoding_attr_len + standalone_attr_len);

        buf.extend_from_slice(b"xml version=\"");
        buf.extend_from_slice(version);

        if let Some(encoding_val) = encoding {
            buf.extend_from_slice(b"\" encoding=\"");
            buf.extend_from_slice(encoding_val);
        }

        if let Some(standalone_val) = standalone {
            buf.extend_from_slice(b"\" standalone=\"");
            buf.extend_from_slice(standalone_val);
        }
        buf.push(b'"');

        BytesDecl { element: BytesStart::owned(buf, 3) }
    }

    /// Gets the decoder struct
    pub fn encoder(&self) -> Option<&'static Encoding> {
        self.encoding()
            .and_then(|e| e.ok())
            .and_then(|e| Encoding::for_label(e))
    }
}

/// A struct to manage `Event::End` events
#[derive(Clone, Debug)]
pub struct BytesEnd<'a> {
    name: Cow<'a, [u8]>,
}

impl<'a> BytesEnd<'a> {
    /// Creates a new `BytesEnd` borrowing a slice
    #[inline]
    pub fn borrowed(name: &'a [u8]) -> BytesEnd<'a> {
        BytesEnd { name: Cow::Borrowed(name) }
    }

    /// Creates a new `BytesEnd` owning its name
    #[inline]
    pub fn owned(name: Vec<u8>) -> BytesEnd<'static> {
        BytesEnd { name: Cow::Owned(name) }
    }

    /// Gets `BytesEnd` event name
    #[inline]
    pub fn name(&self) -> &[u8] {
        &*self.name
    }

    /// local name (excluding namespace) as &[u8] (without eventual attributes)
    /// returns the name() with any leading namespace removed (all content up to
    /// and including the first ':' character)
    #[inline]
    pub fn local_name(&self) -> &[u8] {
        if let Some(i) = self.name().iter().position(|b| *b == b':') {
            &self.name()[i + 1..]
        } else {
            self.name()
        }
    }
}

/// A struct to manage `Event::End` events
#[derive(Clone, Debug)]
pub struct BytesText<'a> {
    content: Cow<'a, [u8]>,
}

impl<'a> BytesText<'a> {
    /// Creates a new `BytesEnd` borrowing a slice
    #[inline]
    pub fn borrowed(content: &'a [u8]) -> BytesText<'a> {
        BytesText { content: Cow::Borrowed(content) }
    }

    /// Creates a new `BytesEnd` owning its name
    #[inline]
    pub fn owned(content: Vec<u8>) -> BytesText<'static> {
        BytesText { content: Cow::Owned(content) }
    }

    /// gets escaped content
    ///
    /// Searches for '&' into content and try to escape the coded character if possible
    /// returns Malformed error with index within element if '&' is not followed by ';'
    pub fn unescaped(&self) -> Result<Cow<[u8]>> {
        unescape(self)
    }

    /// helper method to unescape then decode self using the reader encoding
    ///
    /// for performance reasons (could avoid allocating a `String`),
    /// it might be wiser to manually use
    /// 1. BytesText::unescaped()
    /// 2. Reader::decode(...)
    pub fn unescape_and_decode<B: BufRead>(&self, reader: &Reader<B>) -> Result<String> {
        self.unescaped().map(|e| reader.decode(&*e).into_owned())
    }
}

/// Event to interprete node as they are parsed
#[derive(Clone, Debug)]
pub enum Event<'a> {
    /// Start tag (with attributes) <...>
    Start(BytesStart<'a>),
    /// End tag </...>
    End(BytesEnd<'a>),
    /// Empty element tag (with attributes) <.../>
    Empty(BytesStart<'a>),
    /// Data between Start and End element
    Text(BytesText<'a>),
    /// Comment <!-- ... -->
    Comment(BytesText<'a>),
    /// CData <![CDATA[...]]>
    CData(BytesText<'a>),
    /// Xml declaration <?xml ...?>
    Decl(BytesDecl<'a>),
    /// Processing instruction <?...?>
    PI(BytesText<'a>),
    /// Doctype <!DOCTYPE...>
    DocType(BytesText<'a>),
    /// Eof of file event
    Eof,
}

impl<'a> Deref for BytesStart<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &*self.buf
    }
}

impl<'a> Deref for BytesDecl<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &*self.element
    }
}

impl<'a> Deref for BytesEnd<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &*self.name
    }
}

impl<'a> Deref for BytesText<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &*self.content
    }
}

impl<'a> Deref for Event<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        match *self {
            Event::Start(ref e) |
            Event::Empty(ref e) => &*e,
            Event::End(ref e) => &*e,
            Event::Text(ref e) => &*e,
            Event::Decl(ref e) => &*e,
            Event::PI(ref e) => &*e,
            Event::CData(ref e) => &*e,
            Event::Comment(ref e) => &*e,
            Event::DocType(ref e) => &*e,
            Event::Eof => &[],
        }
    }
}

#[cfg(test)]
#[test]
fn local_name() {
    use std::str::from_utf8;
    let xml = r#"
        <foo:bus attr='bar'>foobusbar</foo:bus>
        <foo: attr='bar'>foobusbar</foo:>
        <:foo attr='bar'>foobusbar</:foo>
        <foo:bus:baz attr='bar'>foobusbar</foo:bus:baz>
        "#;
    let mut rdr = Reader::from_str(xml);
    let mut buf = Vec::new();
    let mut parsed_local_names = Vec::new();
    loop {
        match rdr.read_event(&mut buf).expect("unable to read xml event") {
            Event::Start(ref e) => {
                parsed_local_names.push(from_utf8(e.local_name())
                                            .expect("unable to build str from local_name")
                                            .to_string())
            }
            Event::End(ref e) => {
                parsed_local_names.push(from_utf8(e.local_name())
                                            .expect("unable to build str from local_name")
                                            .to_string())
            }
            Event::Eof => break,
            _ => {}
        }
    }
    assert_eq!(parsed_local_names[0], "bus".to_string());
    assert_eq!(parsed_local_names[1], "bus".to_string());
    assert_eq!(parsed_local_names[2], "".to_string());
    assert_eq!(parsed_local_names[3], "".to_string());
    assert_eq!(parsed_local_names[4], "foo".to_string());
    assert_eq!(parsed_local_names[5], "foo".to_string());
    assert_eq!(parsed_local_names[6], "bus:baz".to_string());
    assert_eq!(parsed_local_names[7], "bus:baz".to_string());
}
<commit_msg>make Event: AsRef<Event><commit_after>//! A module to handle `Event` enumerator

pub mod attributes;

use std::borrow::Cow;
use std::str::from_utf8;
use std::ops::Deref;
use encoding_rs::Encoding;
use std::io::BufRead;

use escape::unescape;
use self::attributes::{Attributes, Attribute};
use errors::Result;
use reader::Reader;

/// A struct to manage `Event::Start` events
///
/// Provides in particular an iterator over attributes
#[derive(Clone, Debug)]
pub struct BytesStart<'a> {
    /// content of the element, before any utf8 conversion
    buf: Cow<'a, [u8]>,
    /// end of the element name, the name starts at that the start of `buf`
    name_len: usize,
}

impl<'a> BytesStart<'a> {
    /// Creates a new `BytesStart` from the given name.
    #[inline]
    pub fn borrowed(content: &'a [u8], name_len: usize) -> BytesStart<'a> {
        BytesStart {
            buf: Cow::Borrowed(content),
            name_len: name_len,
        }
    }

    /// Creates a new `BytesStart` from the given name. Owns its content
    #[inline]
    pub fn owned(content: Vec<u8>, name_len: usize) -> BytesStart<'static> {
        BytesStart {
            buf: Cow::Owned(content),
            name_len: name_len,
        }
    }

    /// Converts the event into an Owned event
    pub fn into_owned(self) -> BytesStart<'static> {
        BytesStart {
            buf: Cow::Owned(self.buf.into_owned()),
            name_len: self.name_len,
        }
    }

    /// Consumes self and adds attributes to this element from an iterator
    /// over (key, value) tuples.
    /// Key and value can be anything that implements the AsRef<[u8]> trait,
    /// like byte slices and strings.
    pub fn with_attributes<'b, I>(mut self, attributes: I) -> Self
        where I: IntoIterator,
              I::Item: Into<Attribute<'b>>
    {
        self.extend_attributes(attributes);
        self
    }

    /// name as &[u8] (without eventual attributes)
    pub fn name(&self) -> &[u8] {
        &self.buf[..self.name_len]
    }

    /// local name (excluding namespace) as &[u8] (without eventual attributes)
    /// returns the name() with any leading namespace removed (all content up to
    /// and including the first ':' character)
    #[inline]
    pub fn local_name(&self) -> &[u8] {
        if let Some(i) = self.name().iter().position(|b| *b == b':') {
            &self.name()[i + 1..]
        } else {
            self.name()
        }
    }

    /// gets unescaped content
    ///
    /// Searches for '&' into content and try to escape the coded character if possible
    /// returns Malformed error with index within element if '&' is not followed by ';'
    pub fn unescaped(&self) -> Result<Cow<[u8]>> {
        unescape(&*self.buf)
    }

    /// gets attributes iterator
    pub fn attributes(&self) -> Attributes {
        Attributes::new(self, self.name_len)
    }

    /// extend the attributes of this element from an iterator over (key, value) tuples.
    /// Key and value can be anything that implements the AsRef<[u8]> trait,
    /// like byte slices and strings.
    pub fn extend_attributes<'b, I>(&mut self, attributes: I) -> &mut BytesStart<'a>
        where I: IntoIterator,
              I::Item: Into<Attribute<'b>>
    {
        for attr in attributes {
            self.push_attribute(attr);
        }
        self
    }

    /// helper method to unescape then decode self using the reader encoding
    ///
    /// for performance reasons (could avoid allocating a `String`),
    /// it might be wiser to manually use
    /// 1. BytesStart::unescaped()
    /// 2. Reader::decode(...)
    pub fn unescape_and_decode<B: BufRead>(&self, reader: &Reader<B>) -> Result<String> {
        self.unescaped().map(|e| reader.decode(&*e).into_owned())
    }

    /// Adds an attribute to this element from the given key and value.
    /// Key and value can be anything that implements the AsRef<[u8]> trait,
    /// like byte slices and strings.
    pub fn push_attribute<'b, A: Into<Attribute<'b>>>(&mut self, attr: A) {
        let a = attr.into();
        let bytes = self.buf.to_mut();
        bytes.push(b' ');
        bytes.extend_from_slice(a.key);
        bytes.extend_from_slice(b"=\"");
        bytes.extend_from_slice(a.value);
        bytes.push(b'"');
    }
}

/// Wrapper around `BytesElement` to parse/write `XmlDecl`
///
/// Postpone element parsing only when needed.
///
/// [W3C XML 1.1 Prolog and Document Type Delcaration](http://w3.org/TR/xml11/#sec-prolog-dtd)
#[derive(Clone, Debug)]
pub struct BytesDecl<'a> {
    element: BytesStart<'a>,
}

impl<'a> BytesDecl<'a> {
    /// Creates a `BytesDecl` from a `BytesStart`
    pub fn from_start(start: BytesStart<'a>) -> BytesDecl<'a> {
        BytesDecl { element: start }
    }

    /// Gets xml version, including quotes (' or ")
    pub fn version(&self) -> Result<&[u8]> {
        match self.element.attributes().next() {
            Some(Err(e)) => Err(e),
            Some(Ok(Attribute {
                        key: b"version",
                        value: v,
                    })) => Ok(v),
            Some(Ok(a)) => {
                Err(format!("XmlDecl must start with 'version' attribute, found {:?}",
                            from_utf8(a.key))
                        .into())
            }
            None => Err("XmlDecl must start with 'version' attribute, found none".into()),
        }
    }

    /// Gets xml encoding, including quotes (' or ")
    pub fn encoding(&self) -> Option<Result<&[u8]>> {
        for a in self.element.attributes() {
            match a {
                Err(e) => return Some(Err(e)),
                Ok(Attribute {
                       key: b"encoding",
                       value: v,
                   }) => return Some(Ok(v)),
                _ => (),
            }
        }
        None
    }

    /// Gets xml standalone, including quotes (' or ")
    pub fn standalone(&self) -> Option<Result<&[u8]>> {
        for a in self.element.attributes() {
            match a {
                Err(e) => return Some(Err(e)),
                Ok(Attribute {
                       key: b"standalone",
                       value: v,
                   }) => return Some(Ok(v)),
                _ => (),
            }
        }
        None
    }

    /// Constructs a new `XmlDecl` from the (mandatory) _version_ (should be `1.0` or `1.1`),
    /// the optional _encoding_ (e.g., `UTF-8`) and the optional _standalone_ (`yes` or `no`)
    /// attribute.
    ///
    /// Does not escape any of its inputs. Always uses double quotes to wrap the attribute values.
    /// The caller is responsible for escaping attribute values. Shouldn't usually be relevant since
    /// the double quote character is not allowed in any of the attribute values.
    pub fn new(version: &[u8],
               encoding: Option<&[u8]>,
               standalone: Option<&[u8]>)
               -> BytesDecl<'static> {
        // Compute length of the buffer based on supplied attributes
        // ' encoding=""'   => 12
        let encoding_attr_len = if let Some(xs) = encoding {
            12 + xs.len()
        } else {
            0
        };
        // ' standalone=""' => 14
        let standalone_attr_len = if let Some(xs) = standalone {
            14 + xs.len()
        } else {
            0
        };
        // 'xml version=""' => 14
        let mut buf = Vec::with_capacity(14 + encoding_attr_len + standalone_attr_len);

        buf.extend_from_slice(b"xml version=\"");
        buf.extend_from_slice(version);

        if let Some(encoding_val) = encoding {
            buf.extend_from_slice(b"\" encoding=\"");
            buf.extend_from_slice(encoding_val);
        }

        if let Some(standalone_val) = standalone {
            buf.extend_from_slice(b"\" standalone=\"");
            buf.extend_from_slice(standalone_val);
        }
        buf.push(b'"');

        BytesDecl { element: BytesStart::owned(buf, 3) }
    }

    /// Gets the decoder struct
    pub fn encoder(&self) -> Option<&'static Encoding> {
        self.encoding()
            .and_then(|e| e.ok())
            .and_then(|e| Encoding::for_label(e))
    }
}

/// A struct to manage `Event::End` events
#[derive(Clone, Debug)]
pub struct BytesEnd<'a> {
    name: Cow<'a, [u8]>,
}

impl<'a> BytesEnd<'a> {
    /// Creates a new `BytesEnd` borrowing a slice
    #[inline]
    pub fn borrowed(name: &'a [u8]) -> BytesEnd<'a> {
        BytesEnd { name: Cow::Borrowed(name) }
    }

    /// Creates a new `BytesEnd` owning its name
    #[inline]
    pub fn owned(name: Vec<u8>) -> BytesEnd<'static> {
        BytesEnd { name: Cow::Owned(name) }
    }

    /// Gets `BytesEnd` event name
    #[inline]
    pub fn name(&self) -> &[u8] {
        &*self.name
    }

    /// local name (excluding namespace) as &[u8] (without eventual attributes)
    /// returns the name() with any leading namespace removed (all content up to
    /// and including the first ':' character)
    #[inline]
    pub fn local_name(&self) -> &[u8] {
        if let Some(i) = self.name().iter().position(|b| *b == b':') {
            &self.name()[i + 1..]
        } else {
            self.name()
        }
    }
}

/// A struct to manage `Event::End` events
#[derive(Clone, Debug)]
pub struct BytesText<'a> {
    content: Cow<'a, [u8]>,
}

impl<'a> BytesText<'a> {
    /// Creates a new `BytesEnd` borrowing a slice
    #[inline]
    pub fn borrowed(content: &'a [u8]) -> BytesText<'a> {
        BytesText { content: Cow::Borrowed(content) }
    }

    /// Creates a new `BytesEnd` owning its name
    #[inline]
    pub fn owned(content: Vec<u8>) -> BytesText<'static> {
        BytesText { content: Cow::Owned(content) }
    }

    /// gets escaped content
    ///
    /// Searches for '&' into content and try to escape the coded character if possible
    /// returns Malformed error with index within element if '&' is not followed by ';'
    pub fn unescaped(&self) -> Result<Cow<[u8]>> {
        unescape(self)
    }

    /// helper method to unescape then decode self using the reader encoding
    ///
    /// for performance reasons (could avoid allocating a `String`),
    /// it might be wiser to manually use
    /// 1. BytesText::unescaped()
    /// 2. Reader::decode(...)
    pub fn unescape_and_decode<B: BufRead>(&self, reader: &Reader<B>) -> Result<String> {
        self.unescaped().map(|e| reader.decode(&*e).into_owned())
    }
}

/// Event to interprete node as they are parsed
#[derive(Clone, Debug)]
pub enum Event<'a> {
    /// Start tag (with attributes) <...>
    Start(BytesStart<'a>),
    /// End tag </...>
    End(BytesEnd<'a>),
    /// Empty element tag (with attributes) <.../>
    Empty(BytesStart<'a>),
    /// Data between Start and End element
    Text(BytesText<'a>),
    /// Comment <!-- ... -->
    Comment(BytesText<'a>),
    /// CData <![CDATA[...]]>
    CData(BytesText<'a>),
    /// Xml declaration <?xml ...?>
    Decl(BytesDecl<'a>),
    /// Processing instruction <?...?>
    PI(BytesText<'a>),
    /// Doctype <!DOCTYPE...>
    DocType(BytesText<'a>),
    /// Eof of file event
    Eof,
}

impl<'a> Deref for BytesStart<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &*self.buf
    }
}

impl<'a> Deref for BytesDecl<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &*self.element
    }
}

impl<'a> Deref for BytesEnd<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &*self.name
    }
}

impl<'a> Deref for BytesText<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        &*self.content
    }
}

impl<'a> Deref for Event<'a> {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        match *self {
            Event::Start(ref e) |
            Event::Empty(ref e) => &*e,
            Event::End(ref e) => &*e,
            Event::Text(ref e) => &*e,
            Event::Decl(ref e) => &*e,
            Event::PI(ref e) => &*e,
            Event::CData(ref e) => &*e,
            Event::Comment(ref e) => &*e,
            Event::DocType(ref e) => &*e,
            Event::Eof => &[],
        }
    }
}

impl<'a> AsRef<Event<'a>> for Event<'a> {
    fn as_ref(&self) -> &Event<'a> {
        self
    }
}

#[cfg(test)]
#[test]
fn local_name() {
    use std::str::from_utf8;
    let xml = r#"
        <foo:bus attr='bar'>foobusbar</foo:bus>
        <foo: attr='bar'>foobusbar</foo:>
        <:foo attr='bar'>foobusbar</:foo>
        <foo:bus:baz attr='bar'>foobusbar</foo:bus:baz>
        "#;
    let mut rdr = Reader::from_str(xml);
    let mut buf = Vec::new();
    let mut parsed_local_names = Vec::new();
    loop {
        match rdr.read_event(&mut buf).expect("unable to read xml event") {
            Event::Start(ref e) => {
                parsed_local_names.push(from_utf8(e.local_name())
                                            .expect("unable to build str from local_name")
                                            .to_string())
            }
            Event::End(ref e) => {
                parsed_local_names.push(from_utf8(e.local_name())
                                            .expect("unable to build str from local_name")
                                            .to_string())
            }
            Event::Eof => break,
            _ => {}
        }
    }
    assert_eq!(parsed_local_names[0], "bus".to_string());
    assert_eq!(parsed_local_names[1], "bus".to_string());
    assert_eq!(parsed_local_names[2], "".to_string());
    assert_eq!(parsed_local_names[3], "".to_string());
    assert_eq!(parsed_local_names[4], "foo".to_string());
    assert_eq!(parsed_local_names[5], "foo".to_string());
    assert_eq!(parsed_local_names[6], "bus:baz".to_string());
    assert_eq!(parsed_local_names[7], "bus:baz".to_string());
}
<|endoftext|>


<commit_before>// Copyright 2018 The Exonum Team
//
// 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 serde::{de::Error, ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::{from_value, Error as SerdeJsonError, Value};

use super::{
    super::{BinaryForm, UniqueHash},
    hash_one, hash_pair,
    key::ProofListKey,
};
use exonum_crypto::Hash;

#[derive(Debug, PartialEq, Eq)]
/// Encapsulates proof of absence for `ProofListIndex`.
///
/// Proof of absence for element with specified `index`consists of
/// `merkle_root` of `ProofListIndex` and `length` of the list.
///
/// Element with `index` is absent in the list with provided `length`
/// and `merkle_root` when two conditions are met:
/// ```text
/// 1. list_hash == sha256( HashTag::List || length || merkle_root )
/// 2. index > length
/// ```
///
/// For range proof this rules applies for whole range.
pub struct ProofOfAbsence {
    length: u64,
    merkle_root: Hash,
}

impl ProofOfAbsence {
    /// New `ProofOfAbsence` for specified list `length` and `merkle_root`.
    pub fn new(length: u64, merkle_root: Hash) -> Self {
        Self { length, merkle_root }
    }

    pub fn length(&self) -> u64 {
        self.length
    }

    pub fn merkle_root(&self) -> Hash {
        self.merkle_root
    }
}

/// An enum that represents a proof of existence for a proof list elements.
#[derive(Debug, PartialEq, Eq)]
pub enum ListProof<V> {
    /// A branch of proof in which both children contain requested elements.
    Full(Box<ListProof<V>>, Box<ListProof<V>>),
    /// A branch of proof in which only the left child contains requested elements.
    Left(Box<ListProof<V>>, Option<Hash>),
    /// A branch of proof in which only the right child contains requested elements.
    Right(Hash, Box<ListProof<V>>),
    /// A leaf of proof with requested element.
    Leaf(V),
    /// Proof of absence of element with specified index.
    Absent(ProofOfAbsence),
}

/// An error that is returned when the list proof is invalid.
#[derive(Debug)]
pub enum ListProofError {
    /// The proof is too short and does not correspond to the height of the tree.
    UnexpectedLeaf,
    /// The proof is too long and does not correspond to the height of the tree.
    UnexpectedBranch,
    /// The hash of the proof is not equal to the trusted root hash.
    UnmatchedRootHash,
}

impl<V> ListProof<V>
where
    V: BinaryForm + UniqueHash,
{
    fn collect<'a>(
        &'a self,
        key: ProofListKey,
        vec: &mut Vec<(u64, &'a V)>,
    ) -> Result<Hash, ListProofError> {
        if key.height() == 0 {
            return Err(ListProofError::UnexpectedBranch);
        }
        let hash = match *self {
            ListProof::Full(ref left, ref right) => HashTag::hash_node(
                &left.collect(key.left(), vec)?,
                &right.collect(key.right(), vec)?,
            ),
            ListProof::Left(ref left, Some(ref right)) => {
                HashTag::hash_node(&left.collect(key.left(), vec)?, right)
            }
            ListProof::Left(ref left, None) => {
                HashTag::hash_single_node(&left.collect(key.left(), vec)?)
            }
            ListProof::Right(ref left, ref right) => {
                HashTag::hash_node(left, &right.collect(key.right(), vec)?)
            }
            ListProof::Leaf(ref value) => {
                if key.height() > 1 {
                    return Err(ListProofError::UnexpectedLeaf);
                }
                vec.push((key.index(), value));
                HashTag::hash_leaf(value.clone())
            }
            ListProof::Absent(ref proof) => HashTag::hash_list_node(proof.length, proof.merkle_root),
        };
        Ok(hash)
    }

    /// Verifies the correctness of the proof by the trusted list hash and the number of
    /// elements in the tree.
    ///
    /// To validate proof one need to provide `expected_list_hash` calculated as follows:
    /// ```text
    /// h = sha-256( HashTag::List || len as u64 || merkle_root )
    /// ```
    /// and `length` of the `ProofListIndex`.
    ///
    /// If the proof is valid, a vector with indices and references to elements is returned.
    /// Otherwise, `Err` is returned.
    ///
    /// If proof is the proof of absence then empty vector will be returned.
    pub fn validate(
        &self,
        expected_list_hash: Hash,
        len: u64,
    ) -> Result<Vec<(u64, &V)>, ListProofError> {
        let mut vec = Vec::new();
        let height = len.next_power_of_two().trailing_zeros() as u8 + 1;
        let root_hash = self.collect(ProofListKey::new(height, 0), &mut vec)?;

        match *self {
            ListProof::Absent(ref _proof) => {
                if expected_list_hash != root_hash {
                    return Err(ListProofError::UnmatchedRootHash);
                }
            }
            _ => {
                if HashTag::hash_list_node(len, root_hash) != expected_list_hash {
                    return Err(ListProofError::UnmatchedRootHash);
                }
            }
        }
        Ok(vec)
    }
}

impl<V: Serialize> Serialize for ListProof<V> {
    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        use self::ListProof::*;
        let mut state;
        match *self {
            Full(ref left_proof, ref right_proof) => {
                state = ser.serialize_struct("Full", 2)?;
                state.serialize_field("left", left_proof)?;
                state.serialize_field("right", right_proof)?;
            }
            Left(ref left_proof, ref option_hash) => {
                if let Some(ref hash) = *option_hash {
                    state = ser.serialize_struct("Left", 2)?;
                    state.serialize_field("left", left_proof)?;
                    state.serialize_field("right", &hash)?;
                } else {
                    state = ser.serialize_struct("Left", 1)?;
                    state.serialize_field("left", left_proof)?;
                }
            }
            Right(ref hash, ref right_proof) => {
                state = ser.serialize_struct("Right", 2)?;
                state.serialize_field("left", &hash)?;
                state.serialize_field("right", right_proof)?;
            }
            Leaf(ref val) => {
                state = ser.serialize_struct("Leaf", 1)?;
                state.serialize_field("val", val)?;
            }
            ListProof::Absent(ref proof) => {
                state = ser.serialize_struct("Absent", 2)?;
                state.serialize_field("length", &proof.length)?;
                state.serialize_field("hash", &proof.merkle_root)?;
            }
        }
        state.end()
    }
}
impl<'a, V> Deserialize<'a> for ListProof<V>
where
    for<'de> V: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'a>,
    {
        fn format_err_string(type_str: &str, value: &Value, err: &SerdeJsonError) -> String {
            format!(
                "Couldn't deserialize {} from serde_json::Value: {}, error: {}",
                type_str, value, err
            )
        }

        let json: Value = <Value as Deserialize>::deserialize(deserializer)?;
        if !json.is_object() {
            return Err(D::Error::custom(format!(
                "Invalid json: it is expected to be json \
                 Object. json: {:?}",
                json
            )));
        }
        let map_key_value = json.as_object().unwrap();
        let res: Self = match map_key_value.len() {
            2 => {
                let left_value: &Value = match map_key_value.get("left") {
                    None => {
                        return Err(D::Error::custom(format!(
                            "Invalid json: Key {} not found. \
                             Value: {:?}",
                            "left", json
                        )))
                    }
                    Some(left) => left,
                };
                let right_value: &Value = match map_key_value.get("right") {
                    None => {
                        return Err(D::Error::custom(format!(
                            "Invalid json: Key {} not found. \
                             Value: {:?}",
                            "right", json
                        )))
                    }
                    Some(right) => right,
                };
                if right_value.is_string() {
                    let left_proof: Self = from_value(left_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", left_value, &err))
                    })?;
                    let right_hash: Hash = from_value(right_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("Hash", right_value, &err))
                    })?;
                    ListProof::Left(Box::new(left_proof), Some(right_hash))
                } else if left_value.is_string() {
                    let right_proof: Self = from_value(right_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", right_value, &err))
                    })?;
                    let left_hash: Hash = from_value(left_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("Hash", left_value, &err))
                    })?;
                    ListProof::Right(left_hash, Box::new(right_proof))
                } else {
                    let left_proof = from_value(left_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", left_value, &err))
                    })?;
                    let right_proof = from_value(right_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", right_value, &err))
                    })?;
                    ListProof::Full(Box::new(left_proof), Box::new(right_proof))
                }
            }
            1 => {
                if map_key_value.get("val").is_none() && map_key_value.get("left").is_none() {
                    return Err(D::Error::custom(format!(
                        "Invalid json: unknown key met. \
                         Expected: {} or {}. json: {:?}",
                        "val", "left", json
                    )));
                }
                if let Some(leaf_value) = map_key_value.get("val") {
                    let val: V = from_value(leaf_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("V", leaf_value, &err))
                    })?;
                    ListProof::Leaf(val)
                } else {
                    // "left" is present
                    let left_value = map_key_value.get("left").unwrap();
                    let left_proof: Self = from_value(left_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", left_value, &err))
                    })?;
                    ListProof::Left(Box::new(left_proof), None)
                }
            }
            _ => {
                return Err(D::Error::custom(format!(
                    "Invalid json: Number of keys should be \
                     either 1 or 2. json: {:?}",
                    json
                )))
            }
        };
        Ok(res)
    }
}
<commit_msg>Fix build.<commit_after>// Copyright 2018 The Exonum Team
//
// 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 serde::{de::Error, ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::{from_value, Error as SerdeJsonError, Value};

use super::{
    super::{BinaryForm, UniqueHash},
    hash_one, hash_pair,
    key::ProofListKey,
};
use exonum_crypto::Hash;

#[derive(Debug, PartialEq, Eq)]
/// Encapsulates proof of absence for `ProofListIndex`.
///
/// Proof of absence for element with specified `index`consists of
/// `merkle_root` of `ProofListIndex` and `length` of the list.
///
/// Element with `index` is absent in the list with provided `length`
/// and `merkle_root` when two conditions are met:
/// ```text
/// 1. list_hash == sha256( HashTag::List || length || merkle_root )
/// 2. index > length
/// ```
///
/// For range proof this rules applies for whole range.
pub struct ProofOfAbsence {
    length: u64,
    merkle_root: Hash,
}

impl ProofOfAbsence {
    /// New `ProofOfAbsence` for specified list `length` and `merkle_root`.
    pub fn new(length: u64, merkle_root: Hash) -> Self {
        Self {
            length,
            merkle_root,
        }
    }

    pub fn length(&self) -> u64 {
        self.length
    }

    pub fn merkle_root(&self) -> Hash {
        self.merkle_root
    }
}

/// An enum that represents a proof of existence for a proof list elements.
#[derive(Debug, PartialEq, Eq)]
pub enum ListProof<V> {
    /// A branch of proof in which both children contain requested elements.
    Full(Box<ListProof<V>>, Box<ListProof<V>>),
    /// A branch of proof in which only the left child contains requested elements.
    Left(Box<ListProof<V>>, Option<Hash>),
    /// A branch of proof in which only the right child contains requested elements.
    Right(Hash, Box<ListProof<V>>),
    /// A leaf of proof with requested element.
    Leaf(V),
    /// Proof of absence of element with specified index.
    Absent(ProofOfAbsence),
}

/// An error that is returned when the list proof is invalid.
#[derive(Debug)]
pub enum ListProofError {
    /// The proof is too short and does not correspond to the height of the tree.
    UnexpectedLeaf,
    /// The proof is too long and does not correspond to the height of the tree.
    UnexpectedBranch,
    /// The hash of the proof is not equal to the trusted root hash.
    UnmatchedRootHash,
}

impl<V> ListProof<V>
where
    V: BinaryForm + UniqueHash,
{
    fn collect<'a>(
        &'a self,
        key: ProofListKey,
        vec: &mut Vec<(u64, &'a V)>,
    ) -> Result<Hash, ListProofError> {
        if key.height() == 0 {
            return Err(ListProofError::UnexpectedBranch);
        }
        let hash = match *self {
            ListProof::Full(ref left, ref right) => HashTag::hash_node(
                &left.collect(key.left(), vec)?,
                &right.collect(key.right(), vec)?,
            ),
            ListProof::Left(ref left, Some(ref right)) => {
                HashTag::hash_node(&left.collect(key.left(), vec)?, right)
            }
            ListProof::Left(ref left, None) => {
                HashTag::hash_single_node(&left.collect(key.left(), vec)?)
            }
            ListProof::Right(ref left, ref right) => {
                HashTag::hash_node(left, &right.collect(key.right(), vec)?)
            }
            ListProof::Leaf(ref value) => {
                if key.height() > 1 {
                    return Err(ListProofError::UnexpectedLeaf);
                }
                vec.push((key.index(), value));
                HashTag::hash_leaf(value.clone())
            }
            ListProof::Absent(ref proof) => {
                HashTag::hash_list_node(proof.length, proof.merkle_root)
            }
        };
        Ok(hash)
    }

    /// Verifies the correctness of the proof by the trusted list hash and the number of
    /// elements in the tree.
    ///
    /// To validate proof one need to provide `expected_list_hash` calculated as follows:
    /// ```text
    /// h = sha-256( HashTag::List || len as u64 || merkle_root )
    /// ```
    /// and `length` of the `ProofListIndex`.
    ///
    /// If the proof is valid, a vector with indices and references to elements is returned.
    /// Otherwise, `Err` is returned.
    ///
    /// If proof is the proof of absence then empty vector will be returned.
    pub fn validate(
        &self,
        expected_list_hash: Hash,
        len: u64,
    ) -> Result<Vec<(u64, &V)>, ListProofError> {
        let mut vec = Vec::new();
        let height = len.next_power_of_two().trailing_zeros() as u8 + 1;
        let root_hash = self.collect(ProofListKey::new(height, 0), &mut vec)?;

        match *self {
            ListProof::Absent(ref _proof) => {
                if expected_list_hash != root_hash {
                    return Err(ListProofError::UnmatchedRootHash);
                }
            }
            _ => {
                if HashTag::hash_list_node(len, root_hash) != expected_list_hash {
                    return Err(ListProofError::UnmatchedRootHash);
                }
            }
        }
        Ok(vec)
    }
}

impl<V: Serialize> Serialize for ListProof<V> {
    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        use self::ListProof::*;
        let mut state;
        match *self {
            Full(ref left_proof, ref right_proof) => {
                state = ser.serialize_struct("Full", 2)?;
                state.serialize_field("left", left_proof)?;
                state.serialize_field("right", right_proof)?;
            }
            Left(ref left_proof, ref option_hash) => {
                if let Some(ref hash) = *option_hash {
                    state = ser.serialize_struct("Left", 2)?;
                    state.serialize_field("left", left_proof)?;
                    state.serialize_field("right", &hash)?;
                } else {
                    state = ser.serialize_struct("Left", 1)?;
                    state.serialize_field("left", left_proof)?;
                }
            }
            Right(ref hash, ref right_proof) => {
                state = ser.serialize_struct("Right", 2)?;
                state.serialize_field("left", &hash)?;
                state.serialize_field("right", right_proof)?;
            }
            Leaf(ref val) => {
                state = ser.serialize_struct("Leaf", 1)?;
                state.serialize_field("val", val)?;
            }
            ListProof::Absent(ref proof) => {
                state = ser.serialize_struct("Absent", 2)?;
                state.serialize_field("length", &proof.length)?;
                state.serialize_field("hash", &proof.merkle_root)?;
            }
        }
        state.end()
    }
}
impl<'a, V> Deserialize<'a> for ListProof<V>
where
    for<'de> V: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'a>,
    {
        fn format_err_string(type_str: &str, value: &Value, err: &SerdeJsonError) -> String {
            format!(
                "Couldn't deserialize {} from serde_json::Value: {}, error: {}",
                type_str, value, err
            )
        }

        let json: Value = <Value as Deserialize>::deserialize(deserializer)?;
        if !json.is_object() {
            return Err(D::Error::custom(format!(
                "Invalid json: it is expected to be json \
                 Object. json: {:?}",
                json
            )));
        }
        let map_key_value = json.as_object().unwrap();
        let res: Self = match map_key_value.len() {
            2 => {
                let left_value: &Value = match map_key_value.get("left") {
                    None => {
                        return Err(D::Error::custom(format!(
                            "Invalid json: Key {} not found. \
                             Value: {:?}",
                            "left", json
                        )))
                    }
                    Some(left) => left,
                };
                let right_value: &Value = match map_key_value.get("right") {
                    None => {
                        return Err(D::Error::custom(format!(
                            "Invalid json: Key {} not found. \
                             Value: {:?}",
                            "right", json
                        )))
                    }
                    Some(right) => right,
                };
                if right_value.is_string() {
                    let left_proof: Self = from_value(left_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", left_value, &err))
                    })?;
                    let right_hash: Hash = from_value(right_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("Hash", right_value, &err))
                    })?;
                    ListProof::Left(Box::new(left_proof), Some(right_hash))
                } else if left_value.is_string() {
                    let right_proof: Self = from_value(right_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", right_value, &err))
                    })?;
                    let left_hash: Hash = from_value(left_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("Hash", left_value, &err))
                    })?;
                    ListProof::Right(left_hash, Box::new(right_proof))
                } else {
                    let left_proof = from_value(left_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", left_value, &err))
                    })?;
                    let right_proof = from_value(right_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", right_value, &err))
                    })?;
                    ListProof::Full(Box::new(left_proof), Box::new(right_proof))
                }
            }
            1 => {
                if map_key_value.get("val").is_none() && map_key_value.get("left").is_none() {
                    return Err(D::Error::custom(format!(
                        "Invalid json: unknown key met. \
                         Expected: {} or {}. json: {:?}",
                        "val", "left", json
                    )));
                }
                if let Some(leaf_value) = map_key_value.get("val") {
                    let val: V = from_value(leaf_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("V", leaf_value, &err))
                    })?;
                    ListProof::Leaf(val)
                } else {
                    // "left" is present
                    let left_value = map_key_value.get("left").unwrap();
                    let left_proof: Self = from_value(left_value.clone()).map_err(|err| {
                        D::Error::custom(format_err_string("ListProof", left_value, &err))
                    })?;
                    ListProof::Left(Box::new(left_proof), None)
                }
            }
            _ => {
                return Err(D::Error::custom(format!(
                    "Invalid json: Number of keys should be \
                     either 1 or 2. json: {:?}",
                    json
                )))
            }
        };
        Ok(res)
    }
}
<|endoftext|>


<commit_before>use std::net::IpAddr;

use hyper::header::ContentType;
use hyper::server::{Request, Response};
use serde_json::to_string_pretty;

use makeresponse::MakeResponse;

#[derive(Serialize)]
pub struct Origin {
    ip: IpAddr,
    port: u16,
    ipv4: bool,
    ipv6: bool,
}

impl MakeResponse for Origin {
    fn content_type(&self) -> ContentType {
        ContentType::json()
    }

    fn make_response(&self, mut response: Response) {
        *response.status_mut() = self.status();
        response.headers_mut().set(self.content_type());
        let body = to_string_pretty(self).unwrap_or_else(|_| String::new());
        response.send(body.as_bytes()).unwrap();
    }
}

pub fn origin(request: &Request) -> Origin {
    Origin {
        ip: request.remote_addr.ip(),
        port: request.remote_addr.port(),
        ipv4: request.remote_addr.is_ipv4(),
        ipv6: request.remote_addr.is_ipv6(),
    }
}
<commit_msg>Idiomatic conversion<commit_after>use std::net::IpAddr;

use hyper::header::ContentType;
use hyper::server::{Request, Response};
use serde_json::to_string_pretty;

use makeresponse::MakeResponse;

#[derive(Serialize)]
pub struct Origin {
    ip: IpAddr,
    port: u16,
    ipv4: bool,
    ipv6: bool,
}

impl Origin {
    pub fn from(request: &Request) -> Self {
        Origin {
            ip: request.remote_addr.ip(),
            port: request.remote_addr.port(),
            ipv4: request.remote_addr.is_ipv4(),
            ipv6: request.remote_addr.is_ipv6(),
        }
    }
}

impl MakeResponse for Origin {
    fn content_type(&self) -> ContentType {
        ContentType::json()
    }

    fn make_response(&self, mut response: Response) {
        *response.status_mut() = self.status();
        response.headers_mut().set(self.content_type());
        let body = to_string_pretty(self).unwrap_or_else(|_| String::new());
        response.send(body.as_bytes()).unwrap();
    }
}

pub fn origin(request: &Request) -> Origin {
    Origin::from(request)
}
<|endoftext|>


<commit_before>//! Utilities for creating zero-cost wakers that don't do anything.
use futures_core::task::{RawWaker, RawWakerVTable, Waker};
use core::ptr::null;
#[cfg(feature = "std")]
use core::cell::UnsafeCell;

unsafe fn noop_clone(_data: *const ()) -> RawWaker {
    noop_raw_waker()
}

unsafe fn noop(_data: *const ()) {}

const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);

fn noop_raw_waker() -> RawWaker {
    RawWaker::new(null(), &NOOP_WAKER_VTABLE)
}

/// Create a new [`Waker`](futures_core::task::Waker) which does
/// nothing when `wake()` is called on it. The [`Waker`](futures_core::task::Waker) can be converted
/// into a [`Waker`](futures_core::task::Waker) which will behave the same way.
///
/// # Examples
///
/// ```
/// use futures::task::noop_waker;
/// let waker = noop_waker();
/// waker.wake();
/// ```
#[inline]
pub fn noop_waker() -> Waker {
    unsafe {
        Waker::from_raw(noop_raw_waker())
    }
}

/// Get a thread local reference to a
/// [`Waker`](futures_core::task::Waker) referencing a singleton
/// instance of a [`Waker`](futures_core::task::Waker) which panics when woken.
///
/// # Examples
///
/// ```
/// use futures::task::noop_waker_ref;
/// let waker = noop_waker_ref();
/// waker.wake_by_ref();
/// ```
#[inline]
#[cfg(feature = "std")]
pub fn noop_waker_ref() -> &'static Waker {
    thread_local! {
        static NOOP_WAKER_INSTANCE: UnsafeCell<Waker> =
            UnsafeCell::new(noop_waker());
    }
    NOOP_WAKER_INSTANCE.with(|l| unsafe { &*l.get() })
}
<commit_msg>Remove mention of panic from noop_waker docs<commit_after>//! Utilities for creating zero-cost wakers that don't do anything.
use futures_core::task::{RawWaker, RawWakerVTable, Waker};
use core::ptr::null;
#[cfg(feature = "std")]
use core::cell::UnsafeCell;

unsafe fn noop_clone(_data: *const ()) -> RawWaker {
    noop_raw_waker()
}

unsafe fn noop(_data: *const ()) {}

const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);

fn noop_raw_waker() -> RawWaker {
    RawWaker::new(null(), &NOOP_WAKER_VTABLE)
}

/// Create a new [`Waker`](futures_core::task::Waker) which does
/// nothing when `wake()` is called on it.
///
/// # Examples
///
/// ```
/// use futures::task::noop_waker;
/// let waker = noop_waker();
/// waker.wake();
/// ```
#[inline]
pub fn noop_waker() -> Waker {
    unsafe {
        Waker::from_raw(noop_raw_waker())
    }
}

/// Get a static reference to a [`Waker`](futures_core::task::Waker) which
/// does nothing when `wake()` is called on it.
///
/// # Examples
///
/// ```
/// use futures::task::noop_waker_ref;
/// let waker = noop_waker_ref();
/// waker.wake_by_ref();
/// ```
#[inline]
#[cfg(feature = "std")]
pub fn noop_waker_ref() -> &'static Waker {
    thread_local! {
        static NOOP_WAKER_INSTANCE: UnsafeCell<Waker> =
            UnsafeCell::new(noop_waker());
    }
    NOOP_WAKER_INSTANCE.with(|l| unsafe { &*l.get() })
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
use test::Bencher;

extern crate polylabel;
use polylabel::polylabel;

extern crate geo;
use self::geo::{Point, LineString, Polygon};

#[bench]
fn bench_threads(b: &mut Bencher) {
    // an L shape
    let coords = vec![(0.0, 0.0), (4.0, 0.0), (4.0, 1.0), (1.0, 1.0), (1.0, 4.0), (0.0, 4.0),
                      (0.0, 0.0)];
    let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
    let poly = Polygon::new(ls, vec![]);
    b.iter(|| { polylabel(&poly, &10.0); });
}

#[bench]
fn large_polygon(b: &mut Bencher) {
    let points = include!("../data/norway_main.rs");
    let points_ls: Vec<_> = points.iter().map(|e| Point::new(e[0], e[1])).collect();
    let poly = Polygon::new(points_ls.into(), vec![]);
    b.iter(|| { polylabel(&poly, &10.0); });
}
<commit_msg>Benchmark update<commit_after>#![feature(test)]

extern crate test;
use test::Bencher;

extern crate polylabel;
use polylabel::polylabel;

extern crate geo;
use self::geo::{Point, LineString, Polygon};

#[bench]
fn bench_threads(b: &mut Bencher) {
    // an L shape
    let coords = vec![(0.0, 0.0), (4.0, 0.0), (4.0, 1.0), (1.0, 1.0), (1.0, 4.0), (0.0, 4.0),
                      (0.0, 0.0)];
    let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
    let poly = Polygon::new(ls, vec![]);
    b.iter(|| { polylabel(&poly, &10.0); });
}

#[bench]
fn large_polygon(b: &mut Bencher) {
    let points = include!("../data/norway_main.rs");
    let points_ls: Vec<_> = points.iter().map(|e| Point::new(e[0], e[1])).collect();
    let poly = Polygon::new(points_ls.into(), vec![]);
    b.iter(|| { polylabel(&poly, &1.0); });
}
<|endoftext|>


<commit_before>use dioxus::prelude::*;
use dioxus_router::use_route;
use fermi::use_read;
use homectl_types::group::GroupId;
use itertools::Itertools;

use crate::{app_state::GROUPS_ATOM, util::tw};

#[derive(PartialEq, Props)]
pub struct HeaderProps {}

#[allow(non_snake_case)]
pub fn Header(cx: Scope<HeaderProps>) -> Element {
    let window = web_sys::window().unwrap();
    let history = window.history().unwrap();

    let groups = use_read(&cx, GROUPS_ATOM);

    let route = use_route(&cx);
    let mut segments = vec![];

    let mut n = 0;
    while let Some(segment) = route.nth_segment(n) {
        if !segment.is_empty() {
            segments.push(segment);
        }
        n += 1;
    }

    // Vec<String> -> &[&str]
    let segments = segments.iter().map(|s| &**s).collect_vec();
    let segments = segments.as_slice();

    let title = match segments {
        [] => "homectl dashboard".to_string(),
        ["scenes"] => "Scenes".to_string(),
        ["groups"] => "Groups".to_string(),
        ["groups", group_id] => {
            let group = groups.get(&GroupId::new(group_id.to_string()));

            match group {
                Some(group) => format!("{} devices", group.name),
                None => "Unknown group devices".to_string(),
            }
        }
        ["devices"] => "Devices".to_string(),
        _ => "Unknown".to_string(),
    };

    let disable_back_button = segments.is_empty();

    let cursor = if disable_back_button {
        tw("cursor-default")
    } else {
        tw("cursor-pointer")
    };

    let back_button_opacity = if disable_back_button {
        tw("opacity-0")
    } else {
        tw("opacity-100")
    };

    cx.render(rsx! {
        div {
            class: "sticky top-0 h-14 bg-stone-100 shadow-md flex flex-row items-center gap-4 px-2",

            button {
                class: "w-8 h-8 text-2xl leading-4 {cursor} {back_button_opacity} hover:text-slate-500",
                disabled: "{disable_back_button}",
                onclick: move |_| { history.back().unwrap() },

                "<"
            }
            h2 { "{title}" }
        }
    })
}
<commit_msg>Back button navigates up in stack<commit_after>use dioxus::prelude::*;
use dioxus_router::{use_route, Link};
use fermi::use_read;
use homectl_types::group::GroupId;
use itertools::Itertools;

use crate::{app_state::GROUPS_ATOM, util::tw};

#[derive(PartialEq, Props)]
pub struct HeaderProps {}

#[allow(non_snake_case)]
pub fn Header(cx: Scope<HeaderProps>) -> Element {
    let groups = use_read(&cx, GROUPS_ATOM);

    let route = use_route(&cx);
    let mut segments = vec![];

    let mut n = 0;
    while let Some(segment) = route.nth_segment(n) {
        if !segment.is_empty() {
            segments.push(segment);
        }
        n += 1;
    }

    // Vec<String> -> &[&str]
    let segments = segments.iter().map(|s| &**s).collect_vec();
    let segments = segments.as_slice();

    let title = match segments {
        [] => "homectl dashboard".to_string(),
        ["scenes"] => "Scenes".to_string(),
        ["groups"] => "Groups".to_string(),
        ["groups", group_id] => {
            let group = groups.get(&GroupId::new(group_id.to_string()));

            match group {
                Some(group) => format!("{} devices", group.name),
                None => "Unknown group devices".to_string(),
            }
        }
        ["devices"] => "Devices".to_string(),
        _ => "Unknown".to_string(),
    };

    let disable_back_button = segments.is_empty();

    let cursor = if disable_back_button {
        tw("cursor-default")
    } else {
        tw("cursor-pointer")
    };

    let back_button_opacity = if disable_back_button {
        tw("opacity-0")
    } else {
        tw("opacity-100")
    };

    let back_href = if segments.is_empty() {
        String::from("/")
    } else {
        String::from("/") + &segments[0..segments.len() - 1].join("/")
    };

    cx.render(rsx! {
        div {
            class: "sticky top-0 h-14 bg-stone-100 shadow-md flex flex-row items-center gap-4 px-2",

            (!disable_back_button).then(|| rsx! {
                Link {
                    to: "{back_href}",
                    span {
                        class: "w-12 h-12 flex justify-center items-center text-2xl leading-4 {cursor} {back_button_opacity} hover:text-slate-500",

                        "<"
                    }
                }
            })

            h2 { "{title}" }
        }
    })
}
<|endoftext|>


<commit_before>/*!
 * Hello World server in Rust
 * Binds REP socket to tcp://*:5555
 * Expects "Hello" from client, replies with "World"
 */

extern mod zmq;

use std::rt;

fn main() {
#[fixed_stack_segment];

    let context = zmq::Context::new();
    let responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new();
    loop {
        responder.recv(&mut msg, 0);
        do msg.with_str |s| {
            printfln!("Received %s", s);
        }
        responder.send_str("World", 0);
        let timer = ~rt::io::Timer::new();
        do timer.map_move |mut t| { t.sleep(1) };
    }
}
<commit_msg>sleep time is in ms<commit_after>/*!
 * Hello World server in Rust
 * Binds REP socket to tcp://*:5555
 * Expects "Hello" from client, replies with "World"
 */

extern mod zmq;

use std::rt;

fn main() {
#[fixed_stack_segment];

    let context = zmq::Context::new();
    let responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new();
    loop {
        responder.recv(&mut msg, 0);
        do msg.with_str |s| {
            printfln!("Received %s", s);
        }
        responder.send_str("World", 0);
        let timer = ~rt::io::Timer::new();
        do timer.map_move |mut t| { t.sleep(1000) };
    }
}
<|endoftext|>


<commit_before>//! The module contains the implementation of HTTP/2 frames.

/// A helper macro that unpacks a sequence of 4 bytes found in the buffer with
/// the given identifier, starting at the given offset, into the given integer
/// type. Obviously, the integer type should be able to support at least 4
/// bytes.
///
/// # Examples
///
/// ```rust
/// let buf: [u8; 4] = [0, 0, 0, 1];
/// assert_eq!(1u32, unpack_octets_4!(buf, 0, u32));
/// ```
macro_rules! unpack_octets_4 {
    ($buf:ident, $offset:expr, $tip:ty) => (
        (($buf[$offset + 0] as $tip) << 24) |
        (($buf[$offset + 1] as $tip) << 16) |
        (($buf[$offset + 2] as $tip) <<  8) |
        (($buf[$offset + 3] as $tip) <<  0)
    );
}

/// An alias for the 9-byte buffer that each HTTP/2 frame header must be stored
/// in.
type FrameHeaderBuffer = [u8; 9];
/// An alias for the 4-tuple representing the components of each HTTP/2 frame
/// header.
type FrameHeader = (u32, u8, u8, u32);

/// Deconstructs a `FrameHeader` into its corresponding 4 components,
/// represented as a 4-tuple: `(length, frame_type, flags, stream_id)`.
///
/// The frame `type` and `flags` components are returned as their original
/// octet representation, rather than reinterpreted.
fn unpack_header(header: &FrameHeaderBuffer) -> FrameHeader {
    let length: u32 = (
        ((header[0] as u32) << 16) |
        ((header[1] as u32) <<  8) |
        ((header[2] as u32) <<  0));
    let frame_type = header[3];
    let flags = header[4];
    let stream_id: u32 = unpack_octets_4!(header, 5, u32);

    (length, frame_type, flags, stream_id)
}

/// Constructs a buffer of 9 bytes that represents the given `FrameHeader`.
fn pack_header(header: &FrameHeader) -> FrameHeaderBuffer {
    let &(length, frame_type, flags, stream_id) = header;

    [
        (((length >> 16) & 0x000000FF) as u8),
        (((length >>  8) & 0x000000FF) as u8),
        (((length >>  0) & 0x000000FF) as u8),
        frame_type,
        flags,
        (((stream_id >> 24) & 0x000000FF) as u8),
        (((stream_id >> 16) & 0x000000FF) as u8),
        (((stream_id >>  8) & 0x000000FF) as u8),
        (((stream_id >>  0) & 0x000000FF) as u8),
    ]
}

#[cfg(test)]
mod tests {
    use super::{
        unpack_header,
        pack_header
    };

    /// Tests that the `unpack_header` function correctly returns the
    /// components of HTTP/2 frame headers.
    #[test]
    fn test_unpack_header() {
        {
            let header = [0; 9];
            assert_eq!((0, 0, 0, 0), unpack_header(&header));
        }
        {
            let header = [0, 0, 1, 2, 3, 0, 0, 0, 4];
            assert_eq!((1, 2, 3, 4), unpack_header(&header));
        }
        {
            let header = [0, 0, 1, 200, 100, 0, 0, 0, 4];
            assert_eq!((1, 200, 100, 4), unpack_header(&header));
        }
        {
            let header = [0, 0, 1, 0, 0, 0, 0, 0, 0];
            assert_eq!((1, 0, 0, 0), unpack_header(&header));
        }
        {
            let header = [0, 1, 0, 0, 0, 0, 0, 0, 0];
            assert_eq!((256, 0, 0, 0), unpack_header(&header));
        }
        {
            let header = [1, 0, 0, 0, 0, 0, 0, 0, 0];
            assert_eq!((256 * 256, 0, 0, 0), unpack_header(&header));
        }
        {
            let header = [0, 0, 0, 0, 0, 0, 0, 0, 1];
            assert_eq!((0, 0, 0, 1), unpack_header(&header));
        }
        {
            let header = [0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 1];
            assert_eq!(((1 << 24) - 1, 0, 0, 1), unpack_header(&header));
        }
        {
            let header = [0xFF, 0xFF, 0xFF, 0, 0, 1, 1, 1, 1];
            assert_eq!(
                ((1 << 24) - 1, 0, 0, 1 + (1 << 8) + (1 << 16) + (1 << 24)),
                unpack_header(&header));
        }
    }

    /// Tests that the `pack_header` function correctly returns the buffer
    /// corresponding to components of HTTP/2 frame headers.
    #[test]
    fn test_pack_header() {
        {
            let header = [0; 9];
            assert_eq!(pack_header(&(0, 0, 0, 0)), header);
        }
        {
            let header = [0, 0, 1, 2, 3, 0, 0, 0, 4];
            assert_eq!(pack_header(&(1, 2, 3, 4)), header);
        }
        {
            let header = [0, 0, 1, 200, 100, 0, 0, 0, 4];
            assert_eq!(pack_header(&(1, 200, 100, 4)), header);
        }
        {
            let header = [0, 0, 1, 0, 0, 0, 0, 0, 0];
            assert_eq!(pack_header(&(1, 0, 0, 0)), header);
        }
        {
            let header = [0, 1, 0, 0, 0, 0, 0, 0, 0];
            assert_eq!(pack_header(&(256, 0, 0, 0)), header);
        }
        {
            let header = [1, 0, 0, 0, 0, 0, 0, 0, 0];
            assert_eq!(pack_header(&(256 * 256, 0, 0, 0)), header);
        }
        {
            let header = [0, 0, 0, 0, 0, 0, 0, 0, 1];
            assert_eq!(pack_header(&(0, 0, 0, 1)), header);
        }
        {
            let header = [0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 1];
            assert_eq!(pack_header(&((1 << 24) - 1, 0, 0, 1)), header);
        }
        {
            let header = [0xFF, 0xFF, 0xFF, 0, 0, 1, 1, 1, 1];
            let header_components = (
                (1 << 24) - 1, 0, 0, 1 + (1 << 8) + (1 << 16) + (1 << 24)
            );
            assert_eq!(pack_header(&header_components), header);
        }
    }
}
<commit_msg>Add an enum representing HTTP/2 settings<commit_after>//! The module contains the implementation of HTTP/2 frames.

/// A helper macro that unpacks a sequence of 4 bytes found in the buffer with
/// the given identifier, starting at the given offset, into the given integer
/// type. Obviously, the integer type should be able to support at least 4
/// bytes.
///
/// # Examples
///
/// ```rust
/// let buf: [u8; 4] = [0, 0, 0, 1];
/// assert_eq!(1u32, unpack_octets_4!(buf, 0, u32));
/// ```
macro_rules! unpack_octets_4 {
    ($buf:ident, $offset:expr, $tip:ty) => (
        (($buf[$offset + 0] as $tip) << 24) |
        (($buf[$offset + 1] as $tip) << 16) |
        (($buf[$offset + 2] as $tip) <<  8) |
        (($buf[$offset + 3] as $tip) <<  0)
    );
}

/// An alias for the 9-byte buffer that each HTTP/2 frame header must be stored
/// in.
type FrameHeaderBuffer = [u8; 9];
/// An alias for the 4-tuple representing the components of each HTTP/2 frame
/// header.
type FrameHeader = (u32, u8, u8, u32);

/// Deconstructs a `FrameHeader` into its corresponding 4 components,
/// represented as a 4-tuple: `(length, frame_type, flags, stream_id)`.
///
/// The frame `type` and `flags` components are returned as their original
/// octet representation, rather than reinterpreted.
fn unpack_header(header: &FrameHeaderBuffer) -> FrameHeader {
    let length: u32 = (
        ((header[0] as u32) << 16) |
        ((header[1] as u32) <<  8) |
        ((header[2] as u32) <<  0));
    let frame_type = header[3];
    let flags = header[4];
    let stream_id: u32 = unpack_octets_4!(header, 5, u32);

    (length, frame_type, flags, stream_id)
}

/// Constructs a buffer of 9 bytes that represents the given `FrameHeader`.
fn pack_header(header: &FrameHeader) -> FrameHeaderBuffer {
    let &(length, frame_type, flags, stream_id) = header;

    [
        (((length >> 16) & 0x000000FF) as u8),
        (((length >>  8) & 0x000000FF) as u8),
        (((length >>  0) & 0x000000FF) as u8),
        frame_type,
        flags,
        (((stream_id >> 24) & 0x000000FF) as u8),
        (((stream_id >> 16) & 0x000000FF) as u8),
        (((stream_id >>  8) & 0x000000FF) as u8),
        (((stream_id >>  0) & 0x000000FF) as u8),
    ]
}

/// An enum that lists all valid settings that can be sent in a SETTINGS
/// frame.
///
/// Each setting has a value that is a 32 bit unsigned integer (6.5.1.).
#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
#[derive(Copy)]
pub enum HttpSetting {
    HeaderTableSize(u32),
    EnablePush(u32),
    MaxConcurrentStreams(u32),
    InitialWindowSize(u32),
    MaxFrameSize(u32),
    MaxHeaderListSize(u32),
}

#[cfg(test)]
mod tests {
    use super::{
        unpack_header,
        pack_header,
    };

    /// Tests that the `unpack_header` function correctly returns the
    /// components of HTTP/2 frame headers.
    #[test]
    fn test_unpack_header() {
        {
            let header = [0; 9];
            assert_eq!((0, 0, 0, 0), unpack_header(&header));
        }
        {
            let header = [0, 0, 1, 2, 3, 0, 0, 0, 4];
            assert_eq!((1, 2, 3, 4), unpack_header(&header));
        }
        {
            let header = [0, 0, 1, 200, 100, 0, 0, 0, 4];
            assert_eq!((1, 200, 100, 4), unpack_header(&header));
        }
        {
            let header = [0, 0, 1, 0, 0, 0, 0, 0, 0];
            assert_eq!((1, 0, 0, 0), unpack_header(&header));
        }
        {
            let header = [0, 1, 0, 0, 0, 0, 0, 0, 0];
            assert_eq!((256, 0, 0, 0), unpack_header(&header));
        }
        {
            let header = [1, 0, 0, 0, 0, 0, 0, 0, 0];
            assert_eq!((256 * 256, 0, 0, 0), unpack_header(&header));
        }
        {
            let header = [0, 0, 0, 0, 0, 0, 0, 0, 1];
            assert_eq!((0, 0, 0, 1), unpack_header(&header));
        }
        {
            let header = [0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 1];
            assert_eq!(((1 << 24) - 1, 0, 0, 1), unpack_header(&header));
        }
        {
            let header = [0xFF, 0xFF, 0xFF, 0, 0, 1, 1, 1, 1];
            assert_eq!(
                ((1 << 24) - 1, 0, 0, 1 + (1 << 8) + (1 << 16) + (1 << 24)),
                unpack_header(&header));
        }
    }

    /// Tests that the `pack_header` function correctly returns the buffer
    /// corresponding to components of HTTP/2 frame headers.
    #[test]
    fn test_pack_header() {
        {
            let header = [0; 9];
            assert_eq!(pack_header(&(0, 0, 0, 0)), header);
        }
        {
            let header = [0, 0, 1, 2, 3, 0, 0, 0, 4];
            assert_eq!(pack_header(&(1, 2, 3, 4)), header);
        }
        {
            let header = [0, 0, 1, 200, 100, 0, 0, 0, 4];
            assert_eq!(pack_header(&(1, 200, 100, 4)), header);
        }
        {
            let header = [0, 0, 1, 0, 0, 0, 0, 0, 0];
            assert_eq!(pack_header(&(1, 0, 0, 0)), header);
        }
        {
            let header = [0, 1, 0, 0, 0, 0, 0, 0, 0];
            assert_eq!(pack_header(&(256, 0, 0, 0)), header);
        }
        {
            let header = [1, 0, 0, 0, 0, 0, 0, 0, 0];
            assert_eq!(pack_header(&(256 * 256, 0, 0, 0)), header);
        }
        {
            let header = [0, 0, 0, 0, 0, 0, 0, 0, 1];
            assert_eq!(pack_header(&(0, 0, 0, 1)), header);
        }
        {
            let header = [0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 1];
            assert_eq!(pack_header(&((1 << 24) - 1, 0, 0, 1)), header);
        }
        {
            let header = [0xFF, 0xFF, 0xFF, 0, 0, 1, 1, 1, 1];
            let header_components = (
                (1 << 24) - 1, 0, 0, 1 + (1 << 8) + (1 << 16) + (1 << 24)
            );
            assert_eq!(pack_header(&header_components), header);
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};
use std::result::Result;

pub fn walk_dir<P: AsRef<Path>>(path: P) -> BTreeSet<String> {
    fn walk_dir(path: PathBuf) -> Vec<OsString> {
        let paths = match fs::read_dir(path) {
            Ok(rd)   => rd,
            Err(why) => panic!("{:?}", why),
        };
        paths
            .filter_map(Result::ok)
            .flat_map(|de| {
                let path = de.path();
                if is_hidden(&path) {
                    Vec::new()
                } else if path.is_file() {
                    vec![path.into_os_string()]
                } else {
                    walk_dir(path)
                }
            })
            .collect::<Vec<OsString>>()
    }

    walk_dir(path.as_ref().to_path_buf()).iter()
        .map(|f| f.clone().into_string())
        .filter_map(Result::ok)
        .collect::<BTreeSet<String>>()
}

fn is_hidden(path: &PathBuf) -> bool {
    let file_name = path.file_name().and_then(|f| f.to_str());
    file_name.map_or(false, |f| f.starts_with(".") && f.len() > 1 && f != "..")
}
<commit_msg>Use into_iter()<commit_after>use std::collections::BTreeSet;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};
use std::result::Result;

pub fn walk_dir<P: AsRef<Path>>(path: P) -> BTreeSet<String> {
    fn walk_dir(path: PathBuf) -> Vec<OsString> {
        let paths = match fs::read_dir(path) {
            Ok(rd)   => rd,
            Err(why) => panic!("{:?}", why),
        };
        paths
            .filter_map(Result::ok)
            .flat_map(|de| {
                let path = de.path();
                if is_hidden(&path) {
                    Vec::new()
                } else if path.is_file() {
                    vec![path.into_os_string()]
                } else {
                    walk_dir(path)
                }
            })
            .collect::<Vec<OsString>>()
    }

    walk_dir(path.as_ref().to_path_buf()).into_iter()
        .map(|f| f.into_string())
        .filter_map(Result::ok)
        .collect::<BTreeSet<String>>()
}

fn is_hidden(path: &PathBuf) -> bool {
    let file_name = path.file_name().and_then(|f| f.to_str());
    file_name.map_or(false, |f| f.starts_with(".") && f.len() > 1 && f != "..")
}
<|endoftext|>


<commit_before>extern crate rustfft;
use ndarray::{arr1, s, Array, Array1};
use rustfft::num_complex::Complex;
use rustfft::num_traits::Zero;
use rustfft::FFTplanner;

// Until https://github.com/rust-ndarray/ndarray/issues/446 is solved
pub const TEMPLATES_MAJMIN: [f64; 12 * 24] = [
    1., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0.,
    0., 1., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0.,
    0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1.,
    0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 1., 1., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0.,
    1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0.,
    0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 1., 0.,
    0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 1.,
    1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0.,
    0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0.,
    0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0.,
    0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0.,
    0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1.,
];

pub fn mean<T: Clone + Into<f32>>(input: &[T]) -> f32 {
    input.iter().map(|x| x.clone().into() as f32).sum::<f32>() / input.len() as f32
}

pub trait Normalize {
    const MAX_VALUE: f32;
    const MIN_VALUE: f32;

    fn normalize(&self, value: f32) -> f32 {
        2. * (value - Self::MIN_VALUE) / (Self::MAX_VALUE - Self::MIN_VALUE) - 1.
    }
}

// Essentia algorithm
// https://github.com/MTG/essentia/blob/master/src/algorithms/temporal/zerocrossingrate.cpp
pub fn number_crossings(input: &[f32]) -> u32 {
    let mut crossings = 0;
    let mut val = input[0];

    if val.abs() < 0. {
        val = 0.
    };
    let mut was_positive = val > 0.;
    let mut is_positive: bool;

    for sample in input {
        val = *sample;
        if val.abs() <= 0.0 {
            val = 0.0
        };
        is_positive = val > 0.;
        if was_positive != is_positive {
            crossings += 1;
            was_positive = is_positive;
        }
    }

    crossings
}

pub fn geometric_mean(input: &[f32]) -> f32 {
    let mut mean = 0.0;
    for &sample in input {
        if sample == 0.0 {
            return 0.0;
        }
        mean += sample.ln();
    }
    mean /= input.len() as f32;
    mean.exp()
}

pub fn hz_to_octs(frequencies: &Array1<f64>, tuning: f64, bins_per_octave: u32) -> Array1<f64> {
    let a440 = 440.0 * (2_f64.powf(tuning / f64::from(bins_per_octave)) as f64);

    (frequencies / (a440 / 16.)).mapv(f64::log2)
}

pub fn hz_to_octs_inplace(
    frequencies: &mut Array1<f64>,
    tuning: f64,
    bins_per_octave: u32,
) -> &mut Array1<f64> {
    let a440 = 440.0 * (2_f64.powf(tuning / f64::from(bins_per_octave)) as f64);

    *frequencies /= a440 / 16.;
    frequencies.mapv_inplace(f64::log2);
    frequencies
}

pub fn convolve(input: &Array1<f64>, kernel: &Array1<f64>) -> Array1<f64> {
    let common_length = input.len() + kernel.len() - 1;
    let input = input.mapv(|x| Complex::new(x, 0.));
    let kernel = kernel.mapv(|x| Complex::new(x, 0.));
    let mut padded_input = Array::from_elem(common_length, Complex::new(0., 0.));
    padded_input.slice_mut(s![..input.len()]).assign(&input);
    let mut padded_kernel = Array::zeros(common_length);
    padded_kernel.slice_mut(s![..kernel.len()]).assign(&kernel);

    let mut input_fft: Vec<Complex<f64>> = vec![Complex::zero(); common_length];
    let mut kernel_fft: Vec<Complex<f64>> = vec![Complex::zero(); common_length];

    let mut planner = FFTplanner::new(false);
    let fft = planner.plan_fft(common_length);
    fft.process(&mut padded_input.to_vec(), &mut input_fft);
    fft.process(&mut padded_kernel.to_vec(), &mut kernel_fft);

    let mut multiplication = input_fft
        .iter()
        .zip(kernel_fft)
        .map(|(x, y)| x * y)
        .collect::<Vec<Complex<f64>>>();

    let mut planner = FFTplanner::new(true);
    let mut output: Vec<Complex<f64>> = vec![Complex::zero(); common_length];
    let fft = planner.plan_fft(common_length);
    fft.process(&mut multiplication, &mut output);

    let output = arr1(
        &output
            .iter()
            .map(|x| x.re / output.len() as f64)
            .collect::<Vec<f64>>(),
    );
    output.slice_move(s![
        (common_length - input.len()) / 2..(common_length - input.len()) / 2 + input.len()
    ])
}

#[cfg(test)]
mod tests {
    use super::*;
    use ndarray::{arr1, Array};
    use ndarray_npy::ReadNpyExt;
    use std::fs::File;

    #[test]
    fn test_convolve() {
        let file = File::open("data/convolve.npy").unwrap();
        let expected_convolve = Array1::<f64>::read_npy(file).unwrap();
        let input: Array1<f64> = Array::range(0., 1000., 0.5);
        let kernel: Array1<f64> = Array::ones(100);

        let output = convolve(&input, &kernel);

        for (expected, actual) in expected_convolve.iter().zip(output.iter()) {
            assert!(0.0000001 > (expected - actual).abs());
        }
    }

    #[test]
    fn test_mean() {
        let numbers = vec![0.0, 1.0, 2.0, 3.0, 4.0];
        assert_eq!(2.0, mean(&numbers));
    }

    #[test]
    fn test_geometric_mean() {
        let numbers = vec![0.0, 1.0, 2.0, 3.0, 4.0];
        assert_eq!(0.0, geometric_mean(&numbers));

        let numbers = vec![4.0, 1.0, 0.03125];
        assert_eq!(0.5, geometric_mean(&numbers));
    }

    #[test]
    fn test_hz_to_octs() {
        let frequencies = arr1(&[32., 64., 128., 256.]);
        let expected = arr1(&[0.16864029, 1.16864029, 2.16864029, 3.16864029]);

        let octs = hz_to_octs(&frequencies, 0.5, 10);
        octs.iter()
            .zip(expected.iter())
            .for_each(|(x, y)| assert!(0.0001 > (x - y).abs()));
    }

    #[test]
    fn test_hz_to_octs_inplace() {
        let mut frequencies = arr1(&[32., 64., 128., 256.]);
        let expected = arr1(&[0.16864029, 1.16864029, 2.16864029, 3.16864029]);

        hz_to_octs_inplace(&mut frequencies, 0.5, 10)
            .iter()
            .zip(expected.iter())
            .for_each(|(x, y)| assert!(0.0001 > (x - y).abs()));
    }
}
<commit_msg>Clear convolve code<commit_after>extern crate rustfft;
use ndarray::{s, Array, Array1};
use rustfft::num_complex::Complex;
use rustfft::num_traits::Zero;
use rustfft::FFTplanner;

// Until https://github.com/rust-ndarray/ndarray/issues/446 is solved
pub const TEMPLATES_MAJMIN: [f64; 12 * 24] = [
    1., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0.,
    0., 1., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0.,
    0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1.,
    0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 1., 1., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0.,
    1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0.,
    0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 1., 0.,
    0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0., 1.,
    1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 0.,
    0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0.,
    0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0., 0.,
    0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1., 0.,
    0., 0., 0., 0., 1., 0., 0., 1., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 1., 0., 0., 1.,
];

pub fn mean<T: Clone + Into<f32>>(input: &[T]) -> f32 {
    input.iter().map(|x| x.clone().into() as f32).sum::<f32>() / input.len() as f32
}

pub trait Normalize {
    const MAX_VALUE: f32;
    const MIN_VALUE: f32;

    fn normalize(&self, value: f32) -> f32 {
        2. * (value - Self::MIN_VALUE) / (Self::MAX_VALUE - Self::MIN_VALUE) - 1.
    }
}

// Essentia algorithm
// https://github.com/MTG/essentia/blob/master/src/algorithms/temporal/zerocrossingrate.cpp
pub fn number_crossings(input: &[f32]) -> u32 {
    let mut crossings = 0;
    let mut val = input[0];

    if val.abs() < 0. {
        val = 0.
    };
    let mut was_positive = val > 0.;
    let mut is_positive: bool;

    for sample in input {
        val = *sample;
        if val.abs() <= 0.0 {
            val = 0.0
        };
        is_positive = val > 0.;
        if was_positive != is_positive {
            crossings += 1;
            was_positive = is_positive;
        }
    }

    crossings
}

pub fn geometric_mean(input: &[f32]) -> f32 {
    let mut mean = 0.0;
    for &sample in input {
        if sample == 0.0 {
            return 0.0;
        }
        mean += sample.ln();
    }
    mean /= input.len() as f32;
    mean.exp()
}

pub fn hz_to_octs(frequencies: &Array1<f64>, tuning: f64, bins_per_octave: u32) -> Array1<f64> {
    let a440 = 440.0 * (2_f64.powf(tuning / f64::from(bins_per_octave)) as f64);

    (frequencies / (a440 / 16.)).mapv(f64::log2)
}

pub fn hz_to_octs_inplace(
    frequencies: &mut Array1<f64>,
    tuning: f64,
    bins_per_octave: u32,
) -> &mut Array1<f64> {
    let a440 = 440.0 * (2_f64.powf(tuning / f64::from(bins_per_octave)) as f64);

    *frequencies /= a440 / 16.;
    frequencies.mapv_inplace(f64::log2);
    frequencies
}

// TODO try to make this FFT real only
// TODO have less buffers - technically, we probably only need two
pub fn convolve(input: &Array1<f64>, kernel: &Array1<f64>) -> Array1<f64> {
    let common_length = input.len() + kernel.len() - 1;
    let input = input.mapv(|x| Complex::new(x, 0.));
    let kernel = kernel.mapv(|x| Complex::new(x, 0.));
    let mut padded_input = Array::from_elem(common_length, Complex::new(0., 0.));
    padded_input.slice_mut(s![..input.len()]).assign(&input);
    let mut padded_kernel = Array::zeros(common_length);
    padded_kernel.slice_mut(s![..kernel.len()]).assign(&kernel);

    let mut input_fft = Array::from_elem(common_length, Complex::zero());
    let mut kernel_fft = Array::from_elem(common_length, Complex::zero());

    let mut planner = FFTplanner::new(false);
    let fft = planner.plan_fft(common_length);
    fft.process(padded_input.as_slice_mut().unwrap(), input_fft.as_slice_mut().unwrap());
    fft.process(padded_kernel.as_slice_mut().unwrap(), kernel_fft.as_slice_mut().unwrap());

    let mut multiplication = input_fft * kernel_fft;

    let mut planner = FFTplanner::new(true);
    let mut output = Array::from_elem(common_length, Complex::zero());
    let fft = planner.plan_fft(common_length);
    fft.process(multiplication.as_slice_mut().unwrap(), output.as_slice_mut().unwrap());

    let output_length = output.len() as f64;
    let output = output.slice_move(s![
        (common_length - input.len()) / 2..(common_length - input.len()) / 2 + input.len()
    ]);
    output.mapv(|x| x.re / output_length)
}

#[cfg(test)]
mod tests {
    use super::*;
    use ndarray::{arr1, Array};
    use ndarray_npy::ReadNpyExt;
    use std::fs::File;

    #[test]
    fn test_convolve() {
        let file = File::open("data/convolve.npy").unwrap();
        let expected_convolve = Array1::<f64>::read_npy(file).unwrap();
        let input: Array1<f64> = Array::range(0., 1000., 0.5);
        let kernel: Array1<f64> = Array::ones(100);

        let output = convolve(&input, &kernel);

        for (expected, actual) in expected_convolve.iter().zip(output.iter()) {
            assert!(0.0000001 > (expected - actual).abs());
        }
    }

    #[test]
    fn test_mean() {
        let numbers = vec![0.0, 1.0, 2.0, 3.0, 4.0];
        assert_eq!(2.0, mean(&numbers));
    }

    #[test]
    fn test_geometric_mean() {
        let numbers = vec![0.0, 1.0, 2.0, 3.0, 4.0];
        assert_eq!(0.0, geometric_mean(&numbers));

        let numbers = vec![4.0, 1.0, 0.03125];
        assert_eq!(0.5, geometric_mean(&numbers));
    }

    #[test]
    fn test_hz_to_octs() {
        let frequencies = arr1(&[32., 64., 128., 256.]);
        let expected = arr1(&[0.16864029, 1.16864029, 2.16864029, 3.16864029]);

        let octs = hz_to_octs(&frequencies, 0.5, 10);
        octs.iter()
            .zip(expected.iter())
            .for_each(|(x, y)| assert!(0.0001 > (x - y).abs()));
    }

    #[test]
    fn test_hz_to_octs_inplace() {
        let mut frequencies = arr1(&[32., 64., 128., 256.]);
        let expected = arr1(&[0.16864029, 1.16864029, 2.16864029, 3.16864029]);

        hz_to_octs_inplace(&mut frequencies, 0.5, 10)
            .iter()
            .zip(expected.iter())
            .for_each(|(x, y)| assert!(0.0001 > (x - y).abs()));
    }
}
<|endoftext|>


<commit_before><commit_msg>refactor(Request): Refactor towards clients<commit_after><|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    local_client::LocalClient,
    persistent_storage::PersistentStorage,
    remote_service::RemoteService,
    serializer::{SerializerClient, SerializerService},
    thread::ThreadService,
    InMemoryStorage, OnDiskStorage, SafetyRules, TSafetyRules,
};
use consensus_types::common::Payload;
use libra_config::config::{NodeConfig, SafetyRulesBackend, SafetyRulesService};
use libra_types::crypto_proxies::ValidatorSigner;
use std::sync::{Arc, RwLock};

enum SafetyRulesWrapper<T> {
    Local(Arc<RwLock<SafetyRules<T>>>),
    Serializer(Arc<RwLock<SerializerService<T>>>),
    Thread(ThreadService<T>),
}

pub struct SafetyRulesManager<T> {
    internal_safety_rules: SafetyRulesWrapper<T>,
}

impl<T: Payload> SafetyRulesManager<T> {
    pub fn new(config: &mut NodeConfig) -> Self {
        let private_key = config
            .test
            .as_mut()
            .expect("Missing test config")
            .consensus_keypair
            .as_mut()
            .expect("Missing consensus keypair in test config")
            .take_private()
            .expect("Failed to take Consensus private key, key absent or already read");

        let author = config
            .validator_network
            .as_ref()
            .expect("Missing validator network")
            .peer_id;

        let validator_signer = ValidatorSigner::new(author, private_key);

        let sr_config = &config.consensus.safety_rules;
        let storage = match &sr_config.backend {
            SafetyRulesBackend::InMemoryStorage => InMemoryStorage::default_storage(),
            SafetyRulesBackend::OnDiskStorage(config) => {
                if config.default {
                    OnDiskStorage::default_storage(config.path())
                        .expect("Unable to allocate SafetyRules storage")
                } else {
                    OnDiskStorage::new_storage(config.path())
                        .expect("Unable to instantiate SafetyRules storage")
                }
            }
        };

        match sr_config.service {
            SafetyRulesService::Local => Self::new_local(storage, validator_signer),
            SafetyRulesService::Serializer => Self::new_serializer(storage, validator_signer),
            SafetyRulesService::Thread => Self::new_thread(storage, validator_signer),
            _ => panic!("Unimplemented SafetyRulesService: {:?}", sr_config.service),
        }
    }

    pub fn new_local(
        storage: Box<dyn PersistentStorage>,
        validator_signer: ValidatorSigner,
    ) -> Self {
        let safety_rules = SafetyRules::new(storage, Arc::new(validator_signer));

        Self {
            internal_safety_rules: SafetyRulesWrapper::Local(Arc::new(RwLock::new(safety_rules))),
        }
    }

    pub fn new_serializer(
        storage: Box<dyn PersistentStorage>,
        validator_signer: ValidatorSigner,
    ) -> Self {
        let safety_rules = SafetyRules::new(storage, Arc::new(validator_signer));
        let serializer_service = SerializerService::new(safety_rules);

        Self {
            internal_safety_rules: SafetyRulesWrapper::Serializer(Arc::new(RwLock::new(
                serializer_service,
            ))),
        }
    }

    pub fn new_thread(
        storage: Box<dyn PersistentStorage>,
        validator_signer: ValidatorSigner,
    ) -> Self {
        let thread = ThreadService::<T>::new(storage, validator_signer);

        Self {
            internal_safety_rules: SafetyRulesWrapper::Thread(thread),
        }
    }

    pub fn client(&self) -> Box<dyn TSafetyRules<T> + Send + Sync> {
        match &self.internal_safety_rules {
            SafetyRulesWrapper::Local(safety_rules) => {
                Box::new(LocalClient::new(safety_rules.clone()))
            }
            SafetyRulesWrapper::Serializer(serializer_service) => {
                Box::new(SerializerClient::new(serializer_service.clone()))
            }
            SafetyRulesWrapper::Thread(thread) => Box::new(thread.client()),
        }
    }
}
<commit_msg>[consensus] refactor SafetyRulesManager<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    local_client::LocalClient,
    persistent_storage::PersistentStorage,
    remote_service::RemoteService,
    serializer::{SerializerClient, SerializerService},
    thread::ThreadService,
    InMemoryStorage, OnDiskStorage, SafetyRules, TSafetyRules,
};
use consensus_types::common::Payload;
use libra_config::config::{NodeConfig, SafetyRulesBackend, SafetyRulesService};
use libra_types::crypto_proxies::ValidatorSigner;
use std::sync::{Arc, RwLock};

pub fn extract_service_inputs(
    config: &mut NodeConfig,
) -> (ValidatorSigner, Box<dyn PersistentStorage>) {
    let private_key = config
        .test
        .as_mut()
        .expect("Missing test config")
        .consensus_keypair
        .as_mut()
        .expect("Missing consensus keypair in test config")
        .take_private()
        .expect("Failed to take Consensus private key, key absent or already read");

    let author = config
        .validator_network
        .as_ref()
        .expect("Missing validator network")
        .peer_id;

    let validator_signer = ValidatorSigner::new(author, private_key);

    let storage = match &config.consensus.safety_rules.backend {
        SafetyRulesBackend::InMemoryStorage => InMemoryStorage::default_storage(),
        SafetyRulesBackend::OnDiskStorage(config) => {
            if config.default {
                OnDiskStorage::default_storage(config.path())
                    .expect("Unable to allocate SafetyRules storage")
            } else {
                OnDiskStorage::new_storage(config.path())
                    .expect("Unable to instantiate SafetyRules storage")
            }
        }
    };

    (validator_signer, storage)
}

enum SafetyRulesWrapper<T> {
    Local(Arc<RwLock<SafetyRules<T>>>),
    Serializer(Arc<RwLock<SerializerService<T>>>),
    Thread(ThreadService<T>),
}

pub struct SafetyRulesManager<T> {
    internal_safety_rules: SafetyRulesWrapper<T>,
}

impl<T: Payload> SafetyRulesManager<T> {
    pub fn new(config: &mut NodeConfig) -> Self {
        let (validator_signer, storage) = extract_service_inputs(config);
        let sr_config = &config.consensus.safety_rules;
        match sr_config.service {
            SafetyRulesService::Local => Self::new_local(storage, validator_signer),
            SafetyRulesService::Serializer => Self::new_serializer(storage, validator_signer),
            SafetyRulesService::Thread => Self::new_thread(storage, validator_signer),
            _ => panic!("Unimplemented SafetyRulesService: {:?}", sr_config.service),
        }
    }

    pub fn new_local(
        storage: Box<dyn PersistentStorage>,
        validator_signer: ValidatorSigner,
    ) -> Self {
        let safety_rules = SafetyRules::new(storage, Arc::new(validator_signer));

        Self {
            internal_safety_rules: SafetyRulesWrapper::Local(Arc::new(RwLock::new(safety_rules))),
        }
    }

    pub fn new_serializer(
        storage: Box<dyn PersistentStorage>,
        validator_signer: ValidatorSigner,
    ) -> Self {
        let safety_rules = SafetyRules::new(storage, Arc::new(validator_signer));
        let serializer_service = SerializerService::new(safety_rules);

        Self {
            internal_safety_rules: SafetyRulesWrapper::Serializer(Arc::new(RwLock::new(
                serializer_service,
            ))),
        }
    }

    pub fn new_thread(
        storage: Box<dyn PersistentStorage>,
        validator_signer: ValidatorSigner,
    ) -> Self {
        let thread = ThreadService::<T>::new(storage, validator_signer);

        Self {
            internal_safety_rules: SafetyRulesWrapper::Thread(thread),
        }
    }

    pub fn client(&self) -> Box<dyn TSafetyRules<T> + Send + Sync> {
        match &self.internal_safety_rules {
            SafetyRulesWrapper::Local(safety_rules) => {
                Box::new(LocalClient::new(safety_rules.clone()))
            }
            SafetyRulesWrapper::Serializer(serializer_service) => {
                Box::new(SerializerClient::new(serializer_service.clone()))
            }
            SafetyRulesWrapper::Thread(thread) => Box::new(thread.client()),
            _ => panic!("Unable to retrieve client for this service"),
        }
    }
}
<|endoftext|>