<commit_before>//! A flash simulator
//!
//! This module is capable of simulating the type of NOR flash commonly used in microcontrollers.
//! These generally can be written as individual bytes, but must be erased in larger units.

use std::fs::File;
use std::io::Write;
use std::iter::Enumerate;
use std::path::Path;
use std::slice;
use pdump::HexDump;

error_chain! {
    errors {
        OutOfBounds(t: String) {
            description("Offset is out of bounds")
            display("Offset out of bounds: {}", t)
        }
        Write(t: String) {
            description("Invalid write")
            display("Invalid write: {}", t)
        }
    }
}

fn ebounds<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::OutOfBounds(message.as_ref().to_owned())
}

fn ewrite<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::Write(message.as_ref().to_owned())
}

/// An emulated flash device.  It is represented as a block of bytes, and a list of the sector
/// mapings.
#[derive(Clone)]
pub struct Flash {
    data: Vec<u8>,
    sectors: Vec<usize>,
    // Alignment required for writes.
    align: usize,
}

impl Flash {
    /// Given a sector size map, construct a flash device for that.
    pub fn new(sectors: Vec<usize>, align: usize) -> Flash {
        // Verify that the alignment is a positive power of two.
        assert!(align > 0);
        assert!(align & (align - 1) == 0);

        let total = sectors.iter().sum();
        Flash {
            data: vec![0xffu8; total],
            sectors: sectors,
            align: align,
        }
    }

    /// The flash drivers tend to erase beyond the bounds of the given range.  Instead, we'll be
    /// strict, and make sure that the passed arguments are exactly at a sector boundary, otherwise
    /// return an error.
    pub fn erase(&mut self, offset: usize, len: usize) -> Result<()> {
        let (_start, slen) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
        let (end, elen) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;

        if slen != 0 {
            bail!(ebounds("offset not at start of sector"));
        }
        if elen != self.sectors[end] - 1 {
            bail!(ebounds("end not at start of sector"));
        }

        for x in &mut self.data[offset .. offset + len] {
            *x = 0xff;
        }

        Ok(())
    }

    /// Writes are fairly unconstrained, but we restrict to only allowing writes of values that
    /// are entirely written as 0xFF.
    pub fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()> {
        if offset + payload.len() > self.data.len() {
            panic!("Write outside of device");
        }

        // Verify the alignment (which must be a power of two).
        if offset & (self.align - 1) != 0 {
            panic!("Misaligned write address");
        }

        if payload.len() & (self.align - 1) != 0 {
            panic!("Write length not multiple of alignment");
        }

        let mut sub = &mut self.data[offset .. offset + payload.len()];
        for (i, x) in sub.iter().enumerate() {
            if *x != 0xFF {
                bail!(ewrite(format!("Write to non-FF location at 0x{:x}", offset + i)));
            }
        }

        sub.copy_from_slice(payload);
        Ok(())
    }

    /// Read is simple.
    pub fn read(&self, offset: usize, data: &mut [u8]) -> Result<()> {
        if offset + data.len() > self.data.len() {
            bail!(ebounds("Read outside of device"));
        }

        let sub = &self.data[offset .. offset + data.len()];
        data.copy_from_slice(sub);
        Ok(())
    }

    // Scan the sector map, and return the base and offset within a sector for this given byte.
    // Returns None if the value is outside of the device.
    fn get_sector(&self, offset: usize) -> Option<(usize, usize)> {
        let mut offset = offset;
        for (sector, &size) in self.sectors.iter().enumerate() {
            if offset < size {
                return Some((sector, offset));
            }
            offset -= size;
        }
        return None;
    }

    /// An iterator over each sector in the device.
    pub fn sector_iter(&self) -> SectorIter {
        SectorIter {
            iter: self.sectors.iter().enumerate(),
            base: 0,
        }
    }

    pub fn device_size(&self) -> usize {
        self.data.len()
    }

    pub fn dump(&self) {
        self.data.dump();
    }

    /// Dump this image to the given file.
    pub fn write_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
        let mut fd = File::create(path).chain_err(|| "Unable to write image file")?;
        fd.write_all(&self.data).chain_err(|| "Unable to write to image file")?;
        Ok(())
    }
}

/// It is possible to iterate over the sectors in the device, each element returning this.
#[derive(Debug)]
pub struct Sector {
    /// Which sector is this, starting from 0.
    pub num: usize,
    /// The offset, in bytes, of the start of this sector.
    pub base: usize,
    /// The length, in bytes, of this sector.
    pub size: usize,
}

pub struct SectorIter<'a> {
    iter: Enumerate<slice::Iter<'a, usize>>,
    base: usize,
}

impl<'a> Iterator for SectorIter<'a> {
    type Item = Sector;

    fn next(&mut self) -> Option<Sector> {
        match self.iter.next() {
            None => None,
            Some((num, &size)) => {
                let base = self.base;
                self.base += size;
                Some(Sector {
                    num: num,
                    base: base,
                    size: size,
                })
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Flash, Error, ErrorKind, Result, Sector};

    #[test]
    fn test_flash() {
        // NXP-style, uniform sectors.
        let mut f1 = Flash::new(vec![4096usize; 256]);
        test_device(&mut f1);

        // STM style, non-uniform sectors
        let mut f2 = Flash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
                                128 * 1024, 128 * 1024, 128 * 1024]);
        test_device(&mut f2);
    }

    fn test_device(flash: &mut Flash) {
        let sectors: Vec<Sector> = flash.sector_iter().collect();

        flash.erase(0, sectors[0].size).unwrap();
        let flash_size = flash.device_size();
        flash.erase(0, flash_size).unwrap();
        assert!(flash.erase(0, sectors[0].size - 1).is_bounds());

        // Verify that write and erase do something.
        flash.write(0, &[0]).unwrap();
        let mut buf = [0; 4];
        flash.read(0, &mut buf).unwrap();
        assert_eq!(buf, [0, 0xff, 0xff, 0xff]);

        flash.erase(0, sectors[0].size).unwrap();
        flash.read(0, &mut buf).unwrap();
        assert_eq!(buf, [0xff; 4]);

        // Program the first and last byte of each sector, verify that has been done, and then
        // erase to verify the erase boundaries.
        for sector in &sectors {
            let byte = [(sector.num & 127) as u8];
            flash.write(sector.base, &byte).unwrap();
            flash.write(sector.base + sector.size - 1, &byte).unwrap();
        }

        // Verify the above
        let mut buf = Vec::new();
        for sector in &sectors {
            let byte = (sector.num & 127) as u8;
            buf.resize(sector.size, 0);
            flash.read(sector.base, &mut buf).unwrap();
            assert_eq!(buf.first(), Some(&byte));
            assert_eq!(buf.last(), Some(&byte));
            assert!(buf[1..buf.len()-1].iter().all(|&x| x == 0xff));
        }
    }

    // Helper checks for the result type.
    trait EChecker {
        fn is_bounds(&self) -> bool;
    }

    impl<T> EChecker for Result<T> {

        fn is_bounds(&self) -> bool {
            match *self {
                Err(Error(ErrorKind::OutOfBounds(_), _)) => true,
                _ => false,
            }
        }
    }
}
<commit_msg>sim: add stricter write checking<commit_after>//! A flash simulator
//!
//! This module is capable of simulating the type of NOR flash commonly used in microcontrollers.
//! These generally can be written as individual bytes, but must be erased in larger units.

use std::fs::File;
use std::io::Write;
use std::iter::Enumerate;
use std::path::Path;
use std::slice;
use pdump::HexDump;

error_chain! {
    errors {
        OutOfBounds(t: String) {
            description("Offset is out of bounds")
            display("Offset out of bounds: {}", t)
        }
        Write(t: String) {
            description("Invalid write")
            display("Invalid write: {}", t)
        }
    }
}

fn ebounds<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::OutOfBounds(message.as_ref().to_owned())
}

fn ewrite<T: AsRef<str>>(message: T) -> ErrorKind {
    ErrorKind::Write(message.as_ref().to_owned())
}

/// An emulated flash device.  It is represented as a block of bytes, and a list of the sector
/// mapings.
#[derive(Clone)]
pub struct Flash {
    data: Vec<u8>,
    write_safe: Vec<bool>,
    sectors: Vec<usize>,
    // Alignment required for writes.
    align: usize,
}

impl Flash {
    /// Given a sector size map, construct a flash device for that.
    pub fn new(sectors: Vec<usize>, align: usize) -> Flash {
        // Verify that the alignment is a positive power of two.
        assert!(align > 0);
        assert!(align & (align - 1) == 0);

        let total = sectors.iter().sum();
        Flash {
            data: vec![0xffu8; total],
            write_safe: vec![true; total],
            sectors: sectors,
            align: align,
        }
    }

    /// The flash drivers tend to erase beyond the bounds of the given range.  Instead, we'll be
    /// strict, and make sure that the passed arguments are exactly at a sector boundary, otherwise
    /// return an error.
    pub fn erase(&mut self, offset: usize, len: usize) -> Result<()> {
        let (_start, slen) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
        let (end, elen) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;

        if slen != 0 {
            bail!(ebounds("offset not at start of sector"));
        }
        if elen != self.sectors[end] - 1 {
            bail!(ebounds("end not at start of sector"));
        }

        for x in &mut self.data[offset .. offset + len] {
            *x = 0xff;
        }

        for x in &mut self.write_safe[offset .. offset + len] {
            *x = true;
        }

        Ok(())
    }

    /// We restrict to only allowing writes of values that are:
    ///
    /// 1. being written to for the first time
    /// 2. being written to after being erased
    ///
    /// This emulates a flash device which starts out erased, with the
    /// added restriction that repeated writes to the same location
    /// are disallowed, even if they would be safe to do.
    pub fn write(&mut self, offset: usize, payload: &[u8]) -> Result<()> {
        if offset + payload.len() > self.data.len() {
            panic!("Write outside of device");
        }

        // Verify the alignment (which must be a power of two).
        if offset & (self.align - 1) != 0 {
            panic!("Misaligned write address");
        }

        if payload.len() & (self.align - 1) != 0 {
            panic!("Write length not multiple of alignment");
        }

        for (i, x) in &mut self.write_safe[offset .. offset + payload.len()].iter_mut().enumerate() {
            if !(*x) {
                bail!(ewrite(format!("Write to unerased location at 0x{:x}", i)));
            }
            *x = false;
        }

        let mut sub = &mut self.data[offset .. offset + payload.len()];
        sub.copy_from_slice(payload);
        Ok(())
    }

    /// Read is simple.
    pub fn read(&self, offset: usize, data: &mut [u8]) -> Result<()> {
        if offset + data.len() > self.data.len() {
            bail!(ebounds("Read outside of device"));
        }

        let sub = &self.data[offset .. offset + data.len()];
        data.copy_from_slice(sub);
        Ok(())
    }

    // Scan the sector map, and return the base and offset within a sector for this given byte.
    // Returns None if the value is outside of the device.
    fn get_sector(&self, offset: usize) -> Option<(usize, usize)> {
        let mut offset = offset;
        for (sector, &size) in self.sectors.iter().enumerate() {
            if offset < size {
                return Some((sector, offset));
            }
            offset -= size;
        }
        return None;
    }

    /// An iterator over each sector in the device.
    pub fn sector_iter(&self) -> SectorIter {
        SectorIter {
            iter: self.sectors.iter().enumerate(),
            base: 0,
        }
    }

    pub fn device_size(&self) -> usize {
        self.data.len()
    }

    pub fn dump(&self) {
        self.data.dump();
    }

    /// Dump this image to the given file.
    pub fn write_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
        let mut fd = File::create(path).chain_err(|| "Unable to write image file")?;
        fd.write_all(&self.data).chain_err(|| "Unable to write to image file")?;
        Ok(())
    }
}

/// It is possible to iterate over the sectors in the device, each element returning this.
#[derive(Debug)]
pub struct Sector {
    /// Which sector is this, starting from 0.
    pub num: usize,
    /// The offset, in bytes, of the start of this sector.
    pub base: usize,
    /// The length, in bytes, of this sector.
    pub size: usize,
}

pub struct SectorIter<'a> {
    iter: Enumerate<slice::Iter<'a, usize>>,
    base: usize,
}

impl<'a> Iterator for SectorIter<'a> {
    type Item = Sector;

    fn next(&mut self) -> Option<Sector> {
        match self.iter.next() {
            None => None,
            Some((num, &size)) => {
                let base = self.base;
                self.base += size;
                Some(Sector {
                    num: num,
                    base: base,
                    size: size,
                })
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{Flash, Error, ErrorKind, Result, Sector};

    #[test]
    fn test_flash() {
        // NXP-style, uniform sectors.
        let mut f1 = Flash::new(vec![4096usize; 256]);
        test_device(&mut f1);

        // STM style, non-uniform sectors
        let mut f2 = Flash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
                                128 * 1024, 128 * 1024, 128 * 1024]);
        test_device(&mut f2);
    }

    fn test_device(flash: &mut Flash) {
        let sectors: Vec<Sector> = flash.sector_iter().collect();

        flash.erase(0, sectors[0].size).unwrap();
        let flash_size = flash.device_size();
        flash.erase(0, flash_size).unwrap();
        assert!(flash.erase(0, sectors[0].size - 1).is_bounds());

        // Verify that write and erase do something.
        flash.write(0, &[0]).unwrap();
        let mut buf = [0; 4];
        flash.read(0, &mut buf).unwrap();
        assert_eq!(buf, [0, 0xff, 0xff, 0xff]);

        flash.erase(0, sectors[0].size).unwrap();
        flash.read(0, &mut buf).unwrap();
        assert_eq!(buf, [0xff; 4]);

        // Program the first and last byte of each sector, verify that has been done, and then
        // erase to verify the erase boundaries.
        for sector in &sectors {
            let byte = [(sector.num & 127) as u8];
            flash.write(sector.base, &byte).unwrap();
            flash.write(sector.base + sector.size - 1, &byte).unwrap();
        }

        // Verify the above
        let mut buf = Vec::new();
        for sector in &sectors {
            let byte = (sector.num & 127) as u8;
            buf.resize(sector.size, 0);
            flash.read(sector.base, &mut buf).unwrap();
            assert_eq!(buf.first(), Some(&byte));
            assert_eq!(buf.last(), Some(&byte));
            assert!(buf[1..buf.len()-1].iter().all(|&x| x == 0xff));
        }
    }

    // Helper checks for the result type.
    trait EChecker {
        fn is_bounds(&self) -> bool;
    }

    impl<T> EChecker for Result<T> {

        fn is_bounds(&self) -> bool {
            match *self {
                Err(Error(ErrorKind::OutOfBounds(_), _)) => true,
                _ => false,
            }
        }
    }
}
<|endoftext|>


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

//! DNS Service Discovery

#![cfg(feature = "mdns")]

use futures::{Async, Future, Poll};
use tokio_core::reactor::Core;

use trust_dns_proto::rr::{IntoName, Name, RecordType};
use trust_dns_proto::xfer::DnsRequestOptions;

use error::*;
use lookup::{InnerLookupFuture, LookupFuture, ReverseLookup, ReverseLookupFuture,
             ReverseLookupIter, TxtLookup, TxtLookupFuture, TxtLookupIter};
use resolver_future::ResolverFuture;

/// An extension for the Resolver to perform DNS Service Discovery
pub trait DnsSdFuture {
    /// List all services available
    ///
    /// https://tools.ietf.org/html/rfc6763#section-4.1
    ///
    /// For registered service types, see: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
    ///
    /// # Arguments
    ///
    /// * `service` - the type of service to be looked up, eg `http`
    /// * `protocol` - the protocol used for these services, eg `tcp`
    /// * `domain` - the domain in which the search will be done, eg `local.`
    fn list_services(&self, service: &str, protocol: &str, domain: &str) -> ListServicesFuture;

    /// Retrieve service information
    ///
    /// https://tools.ietf.org/html/rfc6763#section-6
    fn service_info<N: IntoName>(&self, name: N) -> ServiceInfoFuture;
}

impl DnsSdFuture for ResolverFuture {
    fn list_services(&self, service: &str, protocol: &str, domain: &str) -> ListServicesFuture {
        let name = format!("_{}._{}.{}", service, protocol, domain);
        let options = DnsRequestOptions {
            expects_multiple_responses: true,
            ..Default::default()
        };
        let name: Name = match name.into_name() {
            Ok(name) => name,
            Err(err) => {
                return ListServicesFuture(ReverseLookupFuture::from(InnerLookupFuture::error(
                    self.client_cache.clone(),
                    err,
                )));
            }
        };

        let ptr_future: LookupFuture = self.inner_lookup(name, RecordType::PTR, options);
        let ptr_future: ReverseLookupFuture = ptr_future.into();

        ListServicesFuture(ptr_future)
    }

    fn service_info<N: IntoName>(&self, name: N) -> ServiceInfoFuture {
        let txt_future: TxtLookupFuture = self.txt_lookup(name);
        panic!();
    }
}

/// A DNS Service Discovery future of Services discovered through the list operation
pub struct ListServicesFuture(ReverseLookupFuture);

impl Future for ListServicesFuture {
    type Item = ListServices;
    type Error = ResolveError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0.poll() {
            Ok(Async::Ready(lookup)) => Ok(Async::Ready(ListServices(lookup))),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
    }
}

/// The list of Services discovered
pub struct ListServices(ReverseLookup);

impl ListServices {
    /// Returns an iterator over the list of returned names of services.
    ///
    /// Each name can be queried for additional information. To lookup service entries see `ResolverFuture::srv_lookup`. To get parameters associated with the service, see `DnsSdFuture::service_info`.
    pub fn iter(&self) -> ListServicesIter {
        ListServicesIter(self.0.iter())
    }
}

/// An iterator over the Lookup type
pub struct ListServicesIter<'i>(ReverseLookupIter<'i>);

impl<'i> Iterator for ListServicesIter<'i> {
    type Item = &'i Name;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// A Future that resolves to the TXT information for a service
pub struct ServiceInfoFuture(TxtLookupFuture);

impl Future for ServiceInfoFuture {
    type Item = ServiceInfo;
    type Error = ResolveError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0.poll() {
            Ok(Async::Ready(lookup)) => {
                panic!();

                //Ok(Async::Ready(ServiceInfo(lookup)))
            }
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
    }
}

/// The list of Services discovered
pub struct ServiceInfo(TxtLookup);

impl ServiceInfo {
    /// Returns an iterator over the list of returned names of services.
    ///
    /// Each name can be queried for additional information. To lookup service entries see `ResolverFuture::srv_lookup`. To get parameters associated with the service, see `DnsSdFuture::service_info`.
    pub fn iter(&self) -> ServiceInfoIter {
        ServiceInfoIter(self.0.iter())
    }
}

/// An iterator over the Lookup type
pub struct ServiceInfoIter<'i>(TxtLookupIter<'i>);

impl<'i> Iterator for ServiceInfoIter<'i> {
    type Item = &'i [u8];

    fn next(&mut self) -> Option<Self::Item> {
        panic!()
    }
}

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

    use super::*;

    #[test]
    #[ignore]
    fn test_list_services() {
        let mut io_loop = Core::new().unwrap();
        let resolver = ResolverFuture::new(
            ResolverConfig::default(),
            ResolverOpts {
                ip_strategy: LookupIpStrategy::Ipv6thenIpv4,
                ..ResolverOpts::default()
            },
            &io_loop.handle(),
        );

        let response = io_loop
            .run(resolver.list_services("http", "tcp", "local"))
            .expect("failed to run lookup");

        let mut iter = response.iter();
        for i in iter {
            println!("service: {}", i);
        }
    }
}
<commit_msg>add some local network tests to dns_sd<commit_after>// Copyright 2015-2018 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! DNS Service Discovery

#![cfg(feature = "mdns")]

use futures::{Async, Future, Poll};
use tokio_core::reactor::Core;

use trust_dns_proto::rr::{IntoName, Name, RecordType};
use trust_dns_proto::xfer::DnsRequestOptions;

use error::*;
use lookup::{InnerLookupFuture, LookupFuture, ReverseLookup, ReverseLookupFuture,
             ReverseLookupIter, TxtLookup, TxtLookupFuture, TxtLookupIter};
use resolver_future::ResolverFuture;

/// An extension for the Resolver to perform DNS Service Discovery
pub trait DnsSdFuture {
    /// List all services available
    ///
    /// https://tools.ietf.org/html/rfc6763#section-4.1
    ///
    /// For registered service types, see: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
    ///
    /// # Arguments
    ///
    /// * `service` - the type of service to be looked up, eg `http`
    /// * `protocol` - the protocol used for these services, eg `tcp`
    /// * `domain` - the domain in which the search will be done, eg `local.`
    fn list_services<N: IntoName>(&self, name: N) -> ListServicesFuture;

    /// Retrieve service information
    ///
    /// https://tools.ietf.org/html/rfc6763#section-6
    fn service_info<N: IntoName>(&self, name: N) -> ServiceInfoFuture;
}

impl DnsSdFuture for ResolverFuture {
    fn list_services<N: IntoName>(&self, name: N) -> ListServicesFuture {
        let options = DnsRequestOptions {
            expects_multiple_responses: true,
            ..Default::default()
        };
        let name: Name = match name.into_name() {
            Ok(name) => name,
            Err(err) => {
                return ListServicesFuture(ReverseLookupFuture::from(InnerLookupFuture::error(
                    self.client_cache.clone(),
                    err,
                )));
            }
        };

        let ptr_future: LookupFuture = self.inner_lookup(name, RecordType::PTR, options);
        let ptr_future: ReverseLookupFuture = ptr_future.into();

        ListServicesFuture(ptr_future)
    }

    fn service_info<N: IntoName>(&self, name: N) -> ServiceInfoFuture {
        let txt_future: TxtLookupFuture = self.txt_lookup(name);
        unimplemented!("this feature not yet implemented");
    }
}

/// A DNS Service Discovery future of Services discovered through the list operation
pub struct ListServicesFuture(ReverseLookupFuture);

impl Future for ListServicesFuture {
    type Item = ListServices;
    type Error = ResolveError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0.poll() {
            Ok(Async::Ready(lookup)) => Ok(Async::Ready(ListServices(lookup))),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
    }
}

/// The list of Services discovered
pub struct ListServices(ReverseLookup);

impl ListServices {
    /// Returns an iterator over the list of returned names of services.
    ///
    /// Each name can be queried for additional information. To lookup service entries see `ResolverFuture::srv_lookup`. To get parameters associated with the service, see `DnsSdFuture::service_info`.
    pub fn iter(&self) -> ListServicesIter {
        ListServicesIter(self.0.iter())
    }
}

/// An iterator over the Lookup type
pub struct ListServicesIter<'i>(ReverseLookupIter<'i>);

impl<'i> Iterator for ListServicesIter<'i> {
    type Item = &'i Name;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

/// A Future that resolves to the TXT information for a service
pub struct ServiceInfoFuture(TxtLookupFuture);

impl Future for ServiceInfoFuture {
    type Item = ServiceInfo;
    type Error = ResolveError;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.0.poll() {
            Ok(Async::Ready(lookup)) => {
                panic!();

                //Ok(Async::Ready(ServiceInfo(lookup)))
            }
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
    }
}

/// The list of Services discovered
pub struct ServiceInfo(TxtLookup);

impl ServiceInfo {
    /// Returns an iterator over the list of returned names of services.
    ///
    /// Each name can be queried for additional information. To lookup service entries see `ResolverFuture::srv_lookup`. To get parameters associated with the service, see `DnsSdFuture::service_info`.
    pub fn iter(&self) -> ServiceInfoIter {
        ServiceInfoIter(self.0.iter())
    }
}

/// An iterator over the Lookup type
pub struct ServiceInfoIter<'i>(TxtLookupIter<'i>);

impl<'i> Iterator for ServiceInfoIter<'i> {
    type Item = &'i [u8];

    fn next(&mut self) -> Option<Self::Item> {
        panic!()
    }
}

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

    use super::*;

    #[test]
    #[ignore]
    fn test_list_services() {
        let mut io_loop = Core::new().unwrap();
        let resolver = ResolverFuture::new(
            ResolverConfig::default(),
            ResolverOpts {
                ip_strategy: LookupIpStrategy::Ipv6thenIpv4,
                ..ResolverOpts::default()
            },
            &io_loop.handle(),
        );

        let response = io_loop
            .run(resolver.list_services("_http._tcp.local."))
            .expect("failed to run lookup");

        let mut iter = response.iter();
        for name in iter {
            println!("service: {}", name);
            let srvs = io_loop
                .run(resolver.lookup_srv(name))
                .expect("failed to lookup name");

            for srv in srvs.iter() {
                println!("service: {:#?}", srv);

                let txts = io_loop
                    .run(resolver.txt_lookup(name /*srv.target()*/))
                    .expect("txt lookup failed");

                for txt in txts.iter() {
                    println!("txt: {:#?}", txt);
                }
            }

            for ip in srvs.ip_iter() {
                println!("ip: {}", ip);
            }
        }
    }
}
<|endoftext|>


<commit_before>/// A blinky example for Tessel

// Import the tessel library
extern crate rust_tessel;
// Import the Tessel API
use rust_tessel::Tessel;
// Import sleep from the standard lib
use std::thread::sleep;
// Import durations from the standard lib
use std::time::Duration;

fn main() {
    // Create a new Tessel
    let mut tessel = Tessel::new();

    // Turn on one of the LEDs
    tessel.led[2].on().unwrap();

    println!("I'm blinking! (Press CTRL + C to stop)");

    // Loop forever
    loop {
        // Toggle each LED
        tessel.led[2].toggle().unwrap();
        tessel.led[3].toggle().unwrap();
        // Re-execute the loop after sleeping for 100ms
        sleep(Duration::from_millis(100));
    }
}
<commit_msg>Turn top comment into crate-wide comment<commit_after>//! A blinky example for Tessel

// Import the tessel library
extern crate rust_tessel;
// Import the Tessel API
use rust_tessel::Tessel;
// Import sleep from the standard lib
use std::thread::sleep;
// Import durations from the standard lib
use std::time::Duration;

fn main() {
    // Create a new Tessel
    let mut tessel = Tessel::new();

    // Turn on one of the LEDs
    tessel.led[2].on().unwrap();

    println!("I'm blinking! (Press CTRL + C to stop)");

    // Loop forever
    loop {
        // Toggle each LED
        tessel.led[2].toggle().unwrap();
        tessel.led[3].toggle().unwrap();
        // Re-execute the loop after sleeping for 100ms
        sleep(Duration::from_millis(100));
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy))] // turn warnings into errors

extern crate dtoa;
extern crate linked_hash_map;
extern crate serde;
extern crate yaml_rust;

pub use self::de::{Deserializer, from_iter, from_reader, from_slice, from_str};
pub use self::ser::{Serializer, to_string, to_vec, to_writer};
pub use self::value::{Mapping, Sequence, Value, from_value, to_value};
pub use self::error::{Error, Result};

#[macro_use]
mod forward;

pub mod de;
pub mod ser;
pub mod value;
pub mod error;
<commit_msg>Hide the modules<commit_after>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy))] // turn warnings into errors

extern crate dtoa;
extern crate linked_hash_map;
extern crate serde;
extern crate yaml_rust;

pub use self::de::{Deserializer, from_iter, from_reader, from_slice, from_str};
pub use self::ser::{Serializer, to_string, to_vec, to_writer};
pub use self::value::{Mapping, Sequence, Value, from_value, to_value};
pub use self::error::{Error, Result};

#[macro_use]
mod forward;

mod de;
mod ser;
mod value;
mod error;
<|endoftext|>


<commit_before>//! Crate docs
//!
//! Example:
//!
//! ```no_run
//! // build.rs
//! use std::env;
//! use std::path::PathBuf;
//!
//! fn main() {
//!     // lcm types are in a sibling directory: ../types/
//!     let mut lcm_source_dir : PathBuf = env!("CARGO_MANIFEST_DIR").into();
//!     lcm_source_dir.pop();
//!     lcm_source_dir.push("types");
//!
//!     println!("cargo:rerun-if-changed={}", lcm_source_dir.display());
//!
//!     lcm_gen::LcmGen::new()
//!         .add_directory(lcm_source_dir)
//!         .run();
//! }
//! ```

extern crate glob;

use glob::glob;
use std::path::PathBuf;
use std::env;
use std::process::Command;

/// This struct is used to configure options for, and then run, the `lcm-gen` command.
pub struct LcmGen {
    files: Vec<PathBuf>,
    out_dir: PathBuf,
}

impl LcmGen {
    /// Constructs a new `lcm-gen` command.
    pub fn new() -> Self {
        LcmGen {
            files: Vec::new(),
            out_dir: env::var("OUT_DIR").unwrap().into(),
        }
    }

    /// Sets the output directory. The default is `env::var("OUT_DIR")`.
    pub fn output_directory(&mut self, path: PathBuf) -> &Self {
        self.out_dir = path;
        self
    }

    /// Adds a file to the list of arguments to pass to `lcm-gen`
    pub fn add_file(&mut self, path: PathBuf) -> &Self {
        self.files.push(path);
        self
    }

    /// Recursively adds all the `.lcm` files from a directory.
    pub fn add_directory(&mut self, path: PathBuf) -> &Self {
        let pattern = format!("{}/**/*.lcm", path.display());
        let paths = glob(pattern.as_str())
            .unwrap()
            .filter_map(Result::ok);
        for path in paths {
            self.files.push(path);
        }
        self
    }

    /// Runs `lcm-gen --rust --rast-path={}` on each `.lcm` file that was added.
    pub fn run(&self) {
        let mut cmd = Command::new("lcm-gen");
        for path in &self.files {
            cmd.arg(path);
        }
        cmd.arg("--rust")
            .arg(format!("--rust-path={}", self.out_dir.display()));

        let status = cmd.status().unwrap();
        assert!(status.success());
    }
}
<commit_msg>Output messages so Cargo reruns if .lcm files or the lcm-gen binary change.<commit_after>//! Crate docs
//!
//! Example:
//!
//! ```no_run
//! // build.rs
//! use std::env;
//! use std::path::PathBuf;
//!
//! fn main() {
//!     // lcm types are in a sibling directory: ../types/
//!     let mut lcm_source_dir : PathBuf = env!("CARGO_MANIFEST_DIR").into();
//!     lcm_source_dir.pop();
//!     lcm_source_dir.push("types");
//!
//!     println!("cargo:rerun-if-changed={}", lcm_source_dir.display());
//!
//!     lcm_gen::LcmGen::new()
//!         .add_directory(lcm_source_dir)
//!         .run();
//! }
//! ```

extern crate glob;

use glob::glob;
use std::path::PathBuf;
use std::env;
use std::process::Command;

/// This struct is used to configure options for, and then run, the `lcm-gen` command.
pub struct LcmGen {
    files: Vec<PathBuf>,
    out_dir: PathBuf,
}

impl LcmGen {
    /// Constructs a new `lcm-gen` command.
    pub fn new() -> Self {
        LcmGen {
            files: Vec::new(),
            out_dir: env::var("OUT_DIR").unwrap().into(),
        }
    }

    /// Sets the output directory. The default is `env::var("OUT_DIR")`.
    pub fn output_directory(&mut self, path: &PathBuf) -> &Self {
        self.out_dir = path.clone();
        self
    }

    /// Adds a file to the list of arguments to pass to `lcm-gen`
    pub fn add_file(&mut self, path: PathBuf) -> &Self {
        self.files.push(path);
        self
    }

    /// Recursively adds all the `.lcm` files from a directory.
    pub fn add_directory(&mut self, path: PathBuf) -> &Self {
        let pattern = format!("{}/**/*.lcm", path.display());
        let paths = glob(pattern.as_str())
            .unwrap()
            .filter_map(Result::ok);
        for path in paths {
            self.files.push(path);
        }
        self
    }

    /// Runs `lcm-gen --rust --rust-path={}` on each `.lcm` file that was added.
    pub fn run(&self) {
        // Rerun if the lcm-gen binary changes
        let which_output =
            Command::new("which")
            .arg("lcm-gen")
            .output()
            .expect("failed to find lcm-gen binary");
        assert!(which_output.status.success(), "Failed to find lcm-gen binary");
        println!("cargo:rerun-if-changed={}", String::from_utf8_lossy(&which_output.stdout));

        // Build the lcm-gen command
        let mut cmd = Command::new("lcm-gen");
        cmd.arg("--rust")
            .arg(format!("--rust-path={}", self.out_dir.display()));
        for path in &self.files {
            println!("cargo:rerun-if-changed={}", path.display());
            cmd.arg(path);
        }

        let status = cmd.status().unwrap();
        assert!(status.success(), "lcm-gen failed");

        println!("cargo:include={}", self.out_dir.display());
    }
}
<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate x11;
extern crate libc;

use std::ptr;
use std::ffi;
use std::mem;
use std::str;
use std::slice;
use std::boxed::Box;

use x11::xlib;
use x11::xlib::{ Display, Window };
use libc::{ c_int, c_long, c_uint, c_ulong, c_void };

#[derive(Debug, Copy, Clone)]
pub struct Context {
    display: *mut Display
}

pub fn open_display(name: Option<&str>) -> Option<Context> {
    unsafe{
        let display = match name {
            Some(n) => {
                let s = ffi::CString::new(n).unwrap();
                xlib::XOpenDisplay(s.as_ptr())
            }
            None => { xlib::XOpenDisplay(ptr::null()) }
        };

        if display == ptr::null_mut() {
            None
        }
        else{
            // let b = Some(Box::<Display>::new(*display));
            // xlib::XFree(display as *mut libc::c_void);
            // b
            let c = Context {
                display: display,
            };
            Some(c)
        }
    }
}

pub fn close_display(context: Context) {
    unsafe{
        xlib::XCloseDisplay(context.display);
    }
}

pub fn default_screen(context: Context) -> c_int {
    unsafe{
        xlib::XDefaultScreen(context.display)
    }
}

pub fn root_window(context: Context, screen_num: c_int) -> c_ulong {
    unsafe {
        xlib::XRootWindow(context.display, screen_num)
    }
}

pub fn next_event(context: Context) -> xlib::XEvent {
    unsafe{
        let mut e: xlib::XEvent = mem::zeroed();
        xlib::XNextEvent(context.display, &mut e);
        e
    }
}

pub fn get_atom_name(context: Context, atom: xlib::Atom) -> Option<String> {
    unsafe{
        let name = xlib::XGetAtomName(context.display, atom);
        if name == ptr::null_mut() {
            return None
        }
        let s = ffi::CStr::from_ptr(name);
        let s = s.to_bytes();
        match str::from_utf8(s) {
            Ok(v) => {
                let tmp = Some(v.to_string());
                xlib::XFree(name as *mut libc::c_void);
                tmp
            }
            _ => None
        }
    }
}

pub fn get_atom(context: Context, name: &str) -> xlib::Atom{
    unsafe{
        let cstr = ffi::CString::new(name).unwrap();
        let atom = xlib::XInternAtom(context.display, cstr.as_ptr(), xlib::False);
        atom
    }
}

pub fn get_text_property(context: Context, window: xlib::Window, atom: xlib::Atom) -> Option<String>{
    unsafe{
        let mut prop: xlib::XTextProperty = mem::zeroed();
        let r = xlib::XGetTextProperty(context.display, window, &mut prop, atom);
        if r == 0 || prop.nitems == 0{
            None
        }else{

            // let s = String::from_raw_parts(prop.value, prop.nitems as usize, prop.nitems as usize).clone()
            let s = slice::from_raw_parts(prop.value, prop.nitems as usize).iter().map(|&c| c as u8).collect();
            match String::from_utf8(s) {
                Ok(v) => {
                    xlib::XFree(prop.value as *mut libc::c_void);
                    Some(v)
                }
                _ => None
            }
        }
    }
}

pub fn get_wm_protocols(context: Context, window: Window) -> Vec<xlib::Atom>{
    unsafe{
        let mut atoms: *mut xlib::Atom = ptr::null_mut();
        let mut count = 0;
        let s = xlib::XGetWMProtocols(context.display, window, &mut atoms, &mut count);
        let mut vec: Vec<xlib::Atom> = Vec::new();
        if s > 0 {
            vec = slice::from_raw_parts(atoms, count as usize).iter()
                .map(|&a| a as xlib::Atom).collect();
            xlib::XFree(atoms as *mut c_void);
        }
        vec
    }
}

pub fn get_window_attributes(context: Context, window: Window) -> xlib::XWindowAttributes {
    unsafe{
        let mut attrs: xlib::XWindowAttributes = mem::zeroed();
        xlib::XGetWindowAttributes(context.display, window, &mut attrs);
        attrs
    }
}

pub fn get_transient_for_hint(context: Context, window: Window) -> i32 {
    unsafe{
        let mut window_return: xlib::Window = 0;
        xlib::XGetTransientForHint(context.display, window, &mut window_return)
    }
}

pub fn change_window_attributes(context: Context, window: Window, valuemask: c_ulong, attrs: *mut xlib::XSetWindowAttributes) {
    unsafe{
        xlib::XChangeWindowAttributes(context.display, window, valuemask, attrs);
    }

}

fn get_window_property(context: Context, window: Window, atom: xlib::Atom) {
    unsafe {
        let mut actual_type_return: u64 = 0;
        let mut actual_format_return: i32 = 0;
        let mut nitem_return: libc::c_ulong = 0;
        let mut bytes_after_return: libc::c_ulong = 0;
        let mut prop_return: *mut libc::c_uchar = mem::zeroed();

        let r = xlib::XGetWindowProperty(context.display, window, xlib::XA_WM_NAME,
                                         0, 0xFFFFFFFF, 0, 0,
                                         &mut actual_type_return,
                                         &mut actual_format_return,
                                         &mut nitem_return,
                                         &mut bytes_after_return,
                                         &mut prop_return);

        debug!("result get wp {}", r);
        if r == 0 {

        }else{
            debug!("actual format return {}", actual_format_return);
            if actual_format_return == 0 {

            }
            else {
                // let s = from_raw_parts(prop_return as *const libc::c_ulong, nitems_return as usize).iter()
                //     .map(|&c| c as u64)
                //     .collect();
                let s = String::from_raw_parts(prop_return, nitem_return as usize, nitem_return as usize);
                println!("{}", s);

            }
        }
    }
}

pub fn set_input_focus(context: Context, window: Window) {
    let none = 0;
    let pointer_root = 1;
    let parent = 2;
    unsafe{
        let (old, _) = get_input_focus(context);
        debug!("set focus from {} to {}", old, window);
        xlib::XSetInputFocus(context.display, window, pointer_root, 0);
    }
}

pub fn get_input_focus(context: Context) -> (Window, c_int){
    let mut window: xlib::Window = 0;
    let mut revert_to: libc::c_int = 0;
    unsafe{
        let s = xlib::XGetInputFocus(context.display, &mut window, &mut revert_to);
    }
    (window, revert_to)
}

pub fn unmap_window(context: Context, window: Window) -> c_int{
    unsafe{
        xlib::XUnmapWindow(context.display, window)
    }

}

pub fn configure_window(context: Context, window: Window, mask:c_uint, mut change: xlib::XWindowChanges) {
    unsafe{
        xlib::XConfigureWindow(context.display, window, mask, &mut change);
    }
}
pub fn map_window(context: Context, window: Window) -> c_int{
    unsafe{
        xlib::XMapWindow(context.display, window)
    }
}

pub fn kill_window(context: Context, window: Window) {
    let mut event: xlib::XClientMessageEvent = unsafe {
        mem::zeroed()
    };

    let display = context.display;
    let wm_delete_window = get_atom(context, "WM_DELETE_WINDOW");
    let wm_protocols = get_atom(context, "WM_PROTOCOLS");
    let protocols = get_wm_protocols(context, window);

    if protocols.iter().any(|&p| p == wm_delete_window){
        event.type_ = xlib::ClientMessage;
        event.message_type = wm_protocols;
        event.format = 32;
        event.window = window;
        event.send_event = xlib::True;
        event.display = display;
        event.data.set_long(0, wm_delete_window as libc::c_long);

        let mut e: xlib::XEvent = From::from(event);
        send_event(context, window, xlib::True, xlib::NoEventMask, e);
    }
    else{
        unsafe{
            xlib::XKillClient(display, window);
        }
    }

}

pub fn send_event(context: Context, window: Window,
                  propagate: c_int, event_mask: c_long,
                  mut event: xlib::XEvent) {
    unsafe{
        xlib::XSendEvent(context.display, window, propagate, event_mask, &mut event);
    }
}

pub fn string_to_keysym(s: &str) -> xlib::KeySym {
    let tmp = ffi::CString::new(s).unwrap();
    unsafe{
        xlib::XStringToKeysym(tmp.as_ptr())
    }

}

pub fn select_input(context: Context, window: Window, mask: c_long) {
    unsafe{
        xlib::XSelectInput(context.display, window, mask);
    }
}

pub fn sync(context: Context, discard: c_int) {
    unsafe {
        xlib::XSync(context.display, discard);
    }
}

pub fn display_height(context: Context, screen_num: c_int) -> c_int{
    unsafe{
        xlib::XDisplayHeight(context.display, screen_num)
    }
}

pub fn display_width(context: Context, screen_num: c_int) -> c_int{
    unsafe{
        xlib::XDisplayWidth(context.display, screen_num)
    }
}

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

#[test]
fn test_open(){
    let display = open_display(None);
    assert!(display.is_some());
}

}
<commit_msg>add wrappers for xquerytree<commit_after>#![allow(unstable)]

extern crate x11;
extern crate libc;

use std::ptr;
use std::ffi;
use std::mem;
use std::str;
use std::slice;
use std::boxed::Box;

use x11::xlib;
use x11::xlib::{ Display, Window };
use libc::{ c_int, c_long, c_uint, c_ulong, c_void };

#[derive(Debug, Copy, Clone)]
pub struct Context {
    display: *mut Display
}

pub fn open_display(name: Option<&str>) -> Option<Context> {
    unsafe{
        let display = match name {
            Some(n) => {
                let s = ffi::CString::new(n).unwrap();
                xlib::XOpenDisplay(s.as_ptr())
            }
            None => { xlib::XOpenDisplay(ptr::null()) }
        };

        if display == ptr::null_mut() {
            None
        }
        else{
            // let b = Some(Box::<Display>::new(*display));
            // xlib::XFree(display as *mut libc::c_void);
            // b
            let c = Context {
                display: display,
            };
            Some(c)
        }
    }
}

pub fn close_display(context: Context) {
    unsafe{
        xlib::XCloseDisplay(context.display);
    }
}

pub fn default_screen(context: Context) -> c_int {
    unsafe{
        xlib::XDefaultScreen(context.display)
    }
}

pub fn root_window(context: Context, screen_num: c_int) -> c_ulong {
    unsafe {
        xlib::XRootWindow(context.display, screen_num)
    }
}

pub fn next_event(context: Context) -> xlib::XEvent {
    unsafe{
        let mut e: xlib::XEvent = mem::zeroed();
        xlib::XNextEvent(context.display, &mut e);
        e
    }
}

pub fn get_atom_name(context: Context, atom: xlib::Atom) -> Option<String> {
    unsafe{
        let name = xlib::XGetAtomName(context.display, atom);
        if name == ptr::null_mut() {
            return None
        }
        let s = ffi::CStr::from_ptr(name);
        let s = s.to_bytes();
        match str::from_utf8(s) {
            Ok(v) => {
                let tmp = Some(v.to_string());
                xlib::XFree(name as *mut libc::c_void);
                tmp
            }
            _ => None
        }
    }
}

pub fn get_atom(context: Context, name: &str) -> xlib::Atom{
    unsafe{
        let cstr = ffi::CString::new(name).unwrap();
        let atom = xlib::XInternAtom(context.display, cstr.as_ptr(), xlib::False);
        atom
    }
}

pub fn get_text_property(context: Context, window: xlib::Window, atom: xlib::Atom) -> Option<String>{
    unsafe{
        let mut prop: xlib::XTextProperty = mem::zeroed();
        let r = xlib::XGetTextProperty(context.display, window, &mut prop, atom);
        if r == 0 || prop.nitems == 0{
            None
        }else{

            // let s = String::from_raw_parts(prop.value, prop.nitems as usize, prop.nitems as usize).clone()
            let s = slice::from_raw_parts(prop.value, prop.nitems as usize).iter().map(|&c| c as u8).collect();
            match String::from_utf8(s) {
                Ok(v) => {
                    xlib::XFree(prop.value as *mut libc::c_void);
                    Some(v)
                }
                _ => None
            }
        }
    }
}

pub fn get_wm_protocols(context: Context, window: Window) -> Vec<xlib::Atom>{
    unsafe{
        let mut atoms: *mut xlib::Atom = ptr::null_mut();
        let mut count = 0;
        let s = xlib::XGetWMProtocols(context.display, window, &mut atoms, &mut count);
        let mut vec: Vec<xlib::Atom> = Vec::new();
        if s > 0 {
            vec = slice::from_raw_parts(atoms, count as usize).iter()
                .map(|&a| a as xlib::Atom).collect();
            xlib::XFree(atoms as *mut c_void);
        }
        vec
    }
}

pub fn get_window_attributes(context: Context, window: Window) -> xlib::XWindowAttributes {
    unsafe{
        let mut attrs: xlib::XWindowAttributes = mem::zeroed();
        xlib::XGetWindowAttributes(context.display, window, &mut attrs);
        attrs
    }
}

pub fn get_transient_for_hint(context: Context, window: Window) -> i32 {
    unsafe{
        let mut window_return: xlib::Window = 0;
        xlib::XGetTransientForHint(context.display, window, &mut window_return)
    }
}

pub fn change_window_attributes(context: Context, window: Window, valuemask: c_ulong, attrs: *mut xlib::XSetWindowAttributes) {
    unsafe{
        xlib::XChangeWindowAttributes(context.display, window, valuemask, attrs);
    }

}

fn get_window_property(context: Context, window: Window, atom: xlib::Atom) {
    unsafe {
        let mut actual_type_return: u64 = 0;
        let mut actual_format_return: i32 = 0;
        let mut nitem_return: libc::c_ulong = 0;
        let mut bytes_after_return: libc::c_ulong = 0;
        let mut prop_return: *mut libc::c_uchar = mem::zeroed();

        let r = xlib::XGetWindowProperty(context.display, window, xlib::XA_WM_NAME,
                                         0, 0xFFFFFFFF, 0, 0,
                                         &mut actual_type_return,
                                         &mut actual_format_return,
                                         &mut nitem_return,
                                         &mut bytes_after_return,
                                         &mut prop_return);

        debug!("result get wp {}", r);
        if r == 0 {

        }else{
            debug!("actual format return {}", actual_format_return);
            if actual_format_return == 0 {

            }
            else {
                // let s = from_raw_parts(prop_return as *const libc::c_ulong, nitems_return as usize).iter()
                //     .map(|&c| c as u64)
                //     .collect();
                let s = String::from_raw_parts(prop_return, nitem_return as usize, nitem_return as usize);
                println!("{}", s);

            }
        }
    }
}

pub fn get_top_window(context: Context, window: Window)-> Option<Window>{
    let mut w = window;
    let mut root = window;
    let mut parent = window;
    unsafe{
        while parent != root {
            w = parent;
            unsafe{
                let res = query_tree(context, w);
                match res {
                    Some((r, p, _)) => {
                        parent = p;
                        root = r;
                    }
                    None => {
                        return None
                    }
                }
            }
        }
        Some(w)
    }
}

pub fn get_children(context: Context, window: Window) -> Option<Vec<Window>> {
    let res = query_tree(context, window);
    match res {
        Some((_, _, v)) => {
            Some(v)
        }
        None => { None }
    }
}

pub fn query_tree(context: Context, window: Window) -> Option<(Window, Window, Vec<Window>)> {
    let mut root: Window = 0;
    let mut parent: Window = window;
    let mut children: *mut Window = ptr::null_mut();
    let mut nchildren: libc::c_uint = 0;
    unsafe{
        let s = xlib::XQueryTree(context.display, window, &mut root, &mut parent, &mut children, &mut nchildren);
        if s > 0 {
            let vec = slice::from_raw_parts(children,
                                            nchildren as usize).iter()
                .map(|&a| a as Window).collect();
            xlib::XFree(children as *mut libc::c_void);
            Some((root, parent, vec))
        }
        else{
            None
        }
    }

}
pub fn set_input_focus(context: Context, window: Window) {
    let none = 0;
    let pointer_root = 1;
    let parent = 2;
    unsafe{
        let (old, _) = get_input_focus(context);
        debug!("set focus from {} to {}", old, window);
        xlib::XSetInputFocus(context.display, window, none, 0);
    }
}

pub fn get_input_focus(context: Context) -> (Window, c_int){
    let mut window: xlib::Window = 0;
    let mut revert_to: libc::c_int = 0;
    unsafe{
        let s = xlib::XGetInputFocus(context.display, &mut window, &mut revert_to);
    }
    (window, revert_to)
}

pub fn unmap_window(context: Context, window: Window) -> c_int{
    unsafe{
        xlib::XUnmapWindow(context.display, window)
    }
}

pub fn configure_window(context: Context, window: Window, mask:c_uint, mut change: xlib::XWindowChanges) {
    unsafe{
        xlib::XConfigureWindow(context.display, window, mask, &mut change);
    }
}
pub fn map_window(context: Context, window: Window) -> c_int{
    unsafe{
        xlib::XMapWindow(context.display, window)
    }
}

pub fn kill_window(context: Context, window: Window) {
    let mut event: xlib::XClientMessageEvent = unsafe {
        mem::zeroed()
    };

    let display = context.display;
    let wm_delete_window = get_atom(context, "WM_DELETE_WINDOW");
    let wm_protocols = get_atom(context, "WM_PROTOCOLS");
    let protocols = get_wm_protocols(context, window);

    if protocols.iter().any(|&p| p == wm_delete_window){
        event.type_ = xlib::ClientMessage;
        event.message_type = wm_protocols;
        event.format = 32;
        event.window = window;
        event.send_event = xlib::True;
        event.display = display;
        event.data.set_long(0, wm_delete_window as libc::c_long);

        let mut e: xlib::XEvent = From::from(event);
        send_event(context, window, xlib::True, xlib::NoEventMask, e);
    }
    else{
        unsafe{
            xlib::XKillClient(display, window);
        }
    }

}

pub fn send_event(context: Context, window: Window,
                  propagate: c_int, event_mask: c_long,
                  mut event: xlib::XEvent) {
    unsafe{
        xlib::XSendEvent(context.display, window, propagate, event_mask, &mut event);
    }
}

pub fn string_to_keysym(s: &str) -> xlib::KeySym {
    let tmp = ffi::CString::new(s).unwrap();
    unsafe{
        xlib::XStringToKeysym(tmp.as_ptr())
    }

}

pub fn select_input(context: Context, window: Window, mask: c_long) {
    unsafe{
        xlib::XSelectInput(context.display, window, mask);
    }
}

pub fn sync(context: Context, discard: c_int) {
    unsafe {
        xlib::XSync(context.display, discard);
    }
}

pub fn display_height(context: Context, screen_num: c_int) -> c_int{
    unsafe{
        xlib::XDisplayHeight(context.display, screen_num)
    }
}

pub fn display_width(context: Context, screen_num: c_int) -> c_int{
    unsafe{
        xlib::XDisplayWidth(context.display, screen_num)
    }
}

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

#[test]
fn test_open(){
    let display = open_display(None);
    assert!(display.is_some());
}

}
<|endoftext|>


<commit_before>//! Operations on manifest files.

use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, BufRead};
use std::num::ParseIntError;
use std::path::Path;
use std::str::{self, FromStr};
use std::string::FromUtf8Error;
use std::usize;

use rawpath::RawPath;

/// Manifest file info.
pub struct Manifest {
    hostname: String,
    local_dir: RawPath,
    volumes: Vec<Option<Volume>>,
}

/// Volume info.
pub struct Volume {
    start_path: PathBlock,
    end_path: PathBlock,
    hash_type: String,
    hash: Vec<u8>,
}

/// wip
#[derive(Debug)]
pub enum ParseError {
    /// wip
    Io(io::Error),
    /// wip
    MissingKeyword(String),
    /// wip
    ParseInt(ParseIntError),
    /// wip
    Utf8(FromUtf8Error),
}

struct PathBlock {
    path: RawPath,
    block: Option<usize>,
}

struct ManifestParser<R> {
    input: R,
    buf: Vec<u8>,
}

impl Manifest {
    /// Parses a stream to get a manifest.
    pub fn parse<R: BufRead>(m: &mut R) -> Result<Self, ParseError> {
        let parser = ManifestParser::new(m);
        parser.parse()
    }

    /// wip
    pub fn hostname(&self) -> Option<&str> {
        Some(&self.hostname)
    }

    /// wip
    pub fn local_dir(&self) -> Option<&Path> {
        self.local_dir.as_path()
    }

    /// wip
    pub fn max_vol_num(&self) -> usize {
        self.volumes.len()
    }

    /// wip
    pub fn volume(&self, num: usize) -> Option<&Volume> {
        self.volumes.get(num).and_then(|v| v.as_ref())
    }
}

impl Volume {
    /// wip
    pub fn start_path(&self) -> Option<&Path> {
        self.start_path.path.as_path()
    }

    /// wip
    pub fn end_path(&self) -> Option<&Path> {
        self.end_path.path.as_path()
    }

    /// wip
    pub fn start_path_bytes(&self) -> &[u8] {
        self.start_path.path.as_bytes()
    }

    /// wip
    pub fn end_path_bytes(&self) -> &[u8] {
        self.end_path.path.as_bytes()
    }

    /// wip
    pub fn start_block(&self) -> Option<usize> {
        self.start_path.block
    }

    /// wip
    pub fn end_block(&self) -> Option<usize> {
        self.end_path.block
    }

    /// wip
    pub fn hash_type(&self) -> &str {
        &self.hash_type
    }

    /// wip
    pub fn hash(&self) -> &[u8] {
        &self.hash
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::Io(ref err) => err.description(),
            ParseError::MissingKeyword(_) => "missing keyword in manifest",
            ParseError::ParseInt(ref err) => err.description(),
            ParseError::Utf8(ref err) => err.description(),
        }
    }
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::Io(ref e) => write!(fmt, "{}", e),
            ParseError::MissingKeyword(ref e) => write!(fmt, "missing keyword '{}' in manifest", e),
            ParseError::ParseInt(ref e) => write!(fmt, "{}", e),
            ParseError::Utf8(ref e) => write!(fmt, "{}", e),
        }
    }
}

impl From<io::Error> for ParseError {
    fn from(err: io::Error) -> ParseError {
        ParseError::Io(err)
    }
}

impl From<ParseIntError> for ParseError {
    fn from(err: ParseIntError) -> ParseError {
        ParseError::ParseInt(err)
    }
}

impl From<FromUtf8Error> for ParseError {
    fn from(err: FromUtf8Error) -> ParseError {
        ParseError::Utf8(err)
    }
}

impl<R: BufRead> ManifestParser<R> {
    pub fn new(input: R) -> Self {
        ManifestParser {
            input: input,
            buf: vec![],
        }
    }

    pub fn parse(mut self) -> Result<Manifest, ParseError> {
        let hostname = try!(self.read_param_str("Hostname"));
        let local_dir = RawPath::with_bytes(try!(self.read_param_bytes("Localdir")));

        let mut volumes = Vec::new();
        while let Some((vol, i)) = try!(self.read_volume()) {
            // resize volumes if necessary
            if i >= volumes.len() {
                volumes.reserve(i + 1);
                for _ in volumes.len()..i + 1 {
                    volumes.push(None);
                }
            }
            volumes[i] = Some(vol);
        }

        Ok(Manifest {
            hostname: hostname,
            local_dir: local_dir,
            volumes: volumes,
        })
    }

    fn read_volume(&mut self) -> Result<Option<(Volume, usize)>, ParseError> {
        // volume number
        let mut param = try!(self.read_param_str("Volume"));
        if param.ends_with(":") {
            param.pop();
        }
        let num = try!(usize::from_str(&param));
        let start_path = try!(self.read_path_block("StartingPath"));
        let end_path = try!(self.read_path_block("EndingPath"));
        let (htype, h) = try!(self.read_hash_param());

        let vol = Volume {
            start_path: start_path,
            end_path: end_path,
            hash_type: htype,
            hash: h,
        };
        Ok(Some((vol, num)))
    }

    fn read_path_block(&mut self, key: &str) -> Result<PathBlock, ParseError> {
        try!(self.consume_whitespace());
        if !try!(self.consume_keyword(key)) {
            return Err(ParseError::MissingKeyword(key.to_owned()));
        }
        try!(self.consume_whitespace());
        let path = try!(self.read_param_value());
        try!(self.consume_whitespace());
        let block = if !try!(self.consume_byte(b'\n')) {
            let bytes = try!(self.read_param_value());
            let s = try!(String::from_utf8(bytes));
            let num = try!(usize::from_str(&s));
            Some(num)
        } else {
            None
        };
        Ok(PathBlock {
            path: RawPath::with_bytes(path),
            block: block,
        })
    }

    fn read_hash_param(&mut self) -> Result<(String, Vec<u8>), ParseError> {
        try!(self.consume_whitespace());
        if !try!(self.consume_keyword("Hash")) {
            return Err(ParseError::MissingKeyword("Hash".to_owned()));
        }
        try!(self.consume_whitespace());
        let htype = try!(self.read_param_value_str());
        try!(self.consume_whitespace());
        let mut hash = try!(self.read_param_value());
        for b in &mut hash {
            *b -= b'0'
        }
        try!(self.consume_newline());

        Ok((htype, hash))
    }

    fn read_param_bytes(&mut self, key: &str) -> Result<Vec<u8>, ParseError> {
        try!(self.consume_whitespace());
        if !try!(self.consume_keyword(key)) {
            return Err(ParseError::MissingKeyword(key.to_owned()));
        }
        try!(self.consume_whitespace());
        match self.read_param_value() {
            Ok(res) => {
                try!(self.consume_newline());
                Ok(res)
            }
            Err(e) => Err(From::from(e)),
        }
    }

    fn read_param_str(&mut self, key: &str) -> Result<String, ParseError> {
        let bytes = try!(self.read_param_bytes(key));
        String::from_utf8(bytes).map_err(From::from)
    }

    fn consume_keyword(&mut self, key: &str) -> io::Result<bool> {
        try!(self.input.read_until(b' ', &mut self.buf));
        Ok(match_keyword(&self.buf, key))
    }

    fn consume_newline(&mut self) -> io::Result<()> {
        self.consume_until(|b| {
            match b {
                b' ' | b'\t' | b'\r' | b'\n' => true,
                _ => false,
            }
        })
    }

    fn consume_whitespace(&mut self) -> io::Result<()> {
        self.consume_until(|b| {
            match b {
                b' ' | b'\t' => true,
                _ => false,
            }
        })
    }

    fn consume_until<F>(&mut self, mut f: F) -> io::Result<()>
        where F: FnMut(u8) -> bool
    {
        loop {
            let (pos, end) = {
                let buf = try!(self.input.fill_buf());
                match buf.iter().cloned().position(&mut f) {
                    Some(p) => (p, true),
                    None => (buf.len(), buf.is_empty()),
                }
            };
            self.input.consume(pos);
            if end {
                return Ok(());
            }
        }
    }

    fn read_param_value_str(&mut self) -> Result<String, ParseError> {
        let bytes = try!(self.read_param_value());
        String::from_utf8(bytes).map_err(From::from)
    }

    fn read_param_value(&mut self) -> io::Result<Vec<u8>> {
        if try!(self.consume_byte(b'"')) {
            try!(self.input.read_until(b'"', &mut self.buf));
        } else {
            try!(self.input.read_until(b'\n', &mut self.buf));
        }
        let mut result = Vec::with_capacity(self.buf.len());
        // unescape
        for (i, b) in self.buf.iter().cloned().enumerate() {
            if b != b'\\' {
                result.push(b);
            } else {
                // expects a \xNN where NN is a number string representing the escaped char in hex
                // e.g. \x20 is the space ' '
                if self.buf.len() - i >= 4 && self.buf[i + 1] == b'x' {
                    let num = ((self.buf[i + 2] - b'0') << 4) + self.buf[i + 3] - b'0';
                    result.push(num);
                }
            }
        }
        Ok(result)
    }

    fn consume_byte(&mut self, expected: u8) -> io::Result<bool> {
        let found = {
            let buf = try!(self.input.fill_buf());
            buf.first().map_or(false, |b| *b == expected)
        };
        if found {
            self.input.consume(1);
        }
        Ok(found)
    }
}

#[inline]
fn match_keyword(buf: &[u8], key: &str) -> bool {
    str::from_utf8(&buf).ok().map_or(false, |s| s == key)
}

#[cfg(test)]
mod test {
    use super::*;
    use std::fs::File;
    use std::io::BufReader;

    #[test]
    fn parse_no_err() {
        let file = File::open("tests/manifest/full1.manifest").unwrap();
        let mut bfile = BufReader::new(file);
        Manifest::parse(&mut bfile).unwrap();
    }
}
<commit_msg>Fixed consume_keyword<commit_after>//! Operations on manifest files.

use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, BufRead};
use std::num::ParseIntError;
use std::path::Path;
use std::str::{self, FromStr};
use std::string::FromUtf8Error;
use std::usize;

use rawpath::RawPath;

/// Manifest file info.
pub struct Manifest {
    hostname: String,
    local_dir: RawPath,
    volumes: Vec<Option<Volume>>,
}

/// Volume info.
pub struct Volume {
    start_path: PathBlock,
    end_path: PathBlock,
    hash_type: String,
    hash: Vec<u8>,
}

/// wip
#[derive(Debug)]
pub enum ParseError {
    /// wip
    Io(io::Error),
    /// wip
    MissingKeyword(String),
    /// wip
    ParseInt(ParseIntError),
    /// wip
    Utf8(FromUtf8Error),
}

struct PathBlock {
    path: RawPath,
    block: Option<usize>,
}

struct ManifestParser<R> {
    input: R,
    buf: Vec<u8>,
}

impl Manifest {
    /// Parses a stream to get a manifest.
    pub fn parse<R: BufRead>(m: &mut R) -> Result<Self, ParseError> {
        let parser = ManifestParser::new(m);
        parser.parse()
    }

    /// wip
    pub fn hostname(&self) -> Option<&str> {
        Some(&self.hostname)
    }

    /// wip
    pub fn local_dir(&self) -> Option<&Path> {
        self.local_dir.as_path()
    }

    /// wip
    pub fn max_vol_num(&self) -> usize {
        self.volumes.len()
    }

    /// wip
    pub fn volume(&self, num: usize) -> Option<&Volume> {
        self.volumes.get(num).and_then(|v| v.as_ref())
    }
}

impl Volume {
    /// wip
    pub fn start_path(&self) -> Option<&Path> {
        self.start_path.path.as_path()
    }

    /// wip
    pub fn end_path(&self) -> Option<&Path> {
        self.end_path.path.as_path()
    }

    /// wip
    pub fn start_path_bytes(&self) -> &[u8] {
        self.start_path.path.as_bytes()
    }

    /// wip
    pub fn end_path_bytes(&self) -> &[u8] {
        self.end_path.path.as_bytes()
    }

    /// wip
    pub fn start_block(&self) -> Option<usize> {
        self.start_path.block
    }

    /// wip
    pub fn end_block(&self) -> Option<usize> {
        self.end_path.block
    }

    /// wip
    pub fn hash_type(&self) -> &str {
        &self.hash_type
    }

    /// wip
    pub fn hash(&self) -> &[u8] {
        &self.hash
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::Io(ref err) => err.description(),
            ParseError::MissingKeyword(_) => "missing keyword in manifest",
            ParseError::ParseInt(ref err) => err.description(),
            ParseError::Utf8(ref err) => err.description(),
        }
    }
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::Io(ref e) => write!(fmt, "{}", e),
            ParseError::MissingKeyword(ref e) => write!(fmt, "missing keyword '{}' in manifest", e),
            ParseError::ParseInt(ref e) => write!(fmt, "{}", e),
            ParseError::Utf8(ref e) => write!(fmt, "{}", e),
        }
    }
}

impl From<io::Error> for ParseError {
    fn from(err: io::Error) -> ParseError {
        ParseError::Io(err)
    }
}

impl From<ParseIntError> for ParseError {
    fn from(err: ParseIntError) -> ParseError {
        ParseError::ParseInt(err)
    }
}

impl From<FromUtf8Error> for ParseError {
    fn from(err: FromUtf8Error) -> ParseError {
        ParseError::Utf8(err)
    }
}

impl<R: BufRead> ManifestParser<R> {
    pub fn new(input: R) -> Self {
        ManifestParser {
            input: input,
            buf: vec![],
        }
    }

    pub fn parse(mut self) -> Result<Manifest, ParseError> {
        let hostname = try!(self.read_param_str("Hostname"));
        let local_dir = RawPath::with_bytes(try!(self.read_param_bytes("Localdir")));

        let mut volumes = Vec::new();
        while let Some((vol, i)) = try!(self.read_volume()) {
            // resize volumes if necessary
            if i >= volumes.len() {
                volumes.reserve(i + 1);
                for _ in volumes.len()..i + 1 {
                    volumes.push(None);
                }
            }
            volumes[i] = Some(vol);
        }

        Ok(Manifest {
            hostname: hostname,
            local_dir: local_dir,
            volumes: volumes,
        })
    }

    fn read_volume(&mut self) -> Result<Option<(Volume, usize)>, ParseError> {
        // volume number
        let mut param = try!(self.read_param_str("Volume"));
        if param.ends_with(":") {
            param.pop();
        }
        let num = try!(usize::from_str(&param));
        let start_path = try!(self.read_path_block("StartingPath"));
        let end_path = try!(self.read_path_block("EndingPath"));
        let (htype, h) = try!(self.read_hash_param());

        let vol = Volume {
            start_path: start_path,
            end_path: end_path,
            hash_type: htype,
            hash: h,
        };
        Ok(Some((vol, num)))
    }

    fn read_path_block(&mut self, key: &str) -> Result<PathBlock, ParseError> {
        try!(self.consume_whitespace());
        if !try!(self.consume_keyword(key)) {
            return Err(ParseError::MissingKeyword(key.to_owned()));
        }
        try!(self.consume_whitespace());
        let path = try!(self.read_param_value());
        try!(self.consume_whitespace());
        let block = if !try!(self.consume_byte(b'\n')) {
            let bytes = try!(self.read_param_value());
            let s = try!(String::from_utf8(bytes));
            let num = try!(usize::from_str(&s));
            Some(num)
        } else {
            None
        };
        Ok(PathBlock {
            path: RawPath::with_bytes(path),
            block: block,
        })
    }

    fn read_hash_param(&mut self) -> Result<(String, Vec<u8>), ParseError> {
        try!(self.consume_whitespace());
        if !try!(self.consume_keyword("Hash")) {
            return Err(ParseError::MissingKeyword("Hash".to_owned()));
        }
        try!(self.consume_whitespace());
        let htype = try!(self.read_param_value_str());
        try!(self.consume_whitespace());
        let mut hash = try!(self.read_param_value());
        for b in &mut hash {
            *b -= b'0'
        }
        try!(self.consume_newline());

        Ok((htype, hash))
    }

    fn read_param_bytes(&mut self, key: &str) -> Result<Vec<u8>, ParseError> {
        try!(self.consume_whitespace());
        if !try!(self.consume_keyword(key)) {
            return Err(ParseError::MissingKeyword(key.to_owned()));
        }
        try!(self.consume_whitespace());
        match self.read_param_value() {
            Ok(res) => {
                try!(self.consume_newline());
                Ok(res)
            }
            Err(e) => Err(From::from(e)),
        }
    }

    fn read_param_str(&mut self, key: &str) -> Result<String, ParseError> {
        let bytes = try!(self.read_param_bytes(key));
        String::from_utf8(bytes).map_err(From::from)
    }

    fn consume_keyword(&mut self, key: &str) -> io::Result<bool> {
        let mut size = try!(self.input.read_until(b' ', &mut self.buf));
        if size > 0 && self.buf[size - 1] == b' ' {
            size -= 1
        }
        Ok(match_keyword(&self.buf[..size], key))
    }

    fn consume_newline(&mut self) -> io::Result<()> {
        self.consume_until(|b| {
            match b {
                b' ' | b'\t' | b'\r' | b'\n' => false,
                _ => true,
            }
        })
    }

    fn consume_whitespace(&mut self) -> io::Result<()> {
        self.consume_until(|b| {
            match b {
                b' ' | b'\t' => false,
                _ => true,
            }
        })
    }

    fn consume_until<F>(&mut self, mut f: F) -> io::Result<()>
        where F: FnMut(u8) -> bool
    {
        loop {
            let (pos, end) = {
                let buf = try!(self.input.fill_buf());
                match buf.iter().cloned().position(&mut f) {
                    Some(p) => (p, true),
                    None => (buf.len(), buf.is_empty()),
                }
            };
            self.input.consume(pos);
            if end {
                return Ok(());
            }
        }
    }

    fn read_param_value_str(&mut self) -> Result<String, ParseError> {
        let bytes = try!(self.read_param_value());
        String::from_utf8(bytes).map_err(From::from)
    }

    fn read_param_value(&mut self) -> io::Result<Vec<u8>> {
        if try!(self.consume_byte(b'"')) {
            try!(self.input.read_until(b'"', &mut self.buf));
        } else {
            try!(self.input.read_until(b'\n', &mut self.buf));
        }
        let mut result = Vec::with_capacity(self.buf.len());
        // unescape
        for (i, b) in self.buf.iter().cloned().enumerate() {
            if b != b'\\' {
                result.push(b);
            } else {
                // expects a \xNN where NN is a number string representing the escaped char in hex
                // e.g. \x20 is the space ' '
                if self.buf.len() - i >= 4 && self.buf[i + 1] == b'x' {
                    let num = ((self.buf[i + 2] - b'0') << 4) + self.buf[i + 3] - b'0';
                    result.push(num);
                }
            }
        }
        Ok(result)
    }

    fn consume_byte(&mut self, expected: u8) -> io::Result<bool> {
        let found = {
            let buf = try!(self.input.fill_buf());
            buf.first().map_or(false, |b| *b == expected)
        };
        if found {
            self.input.consume(1);
        }
        Ok(found)
    }
}

#[inline]
fn match_keyword(buf: &[u8], key: &str) -> bool {
    str::from_utf8(&buf).ok().map_or(false, |s| s == key)
}

#[cfg(test)]
mod test {
    use super::*;
    use std::fs::File;
    use std::io::BufReader;

    #[test]
    fn parse_no_err() {
        let file = File::open("tests/manifest/full1.manifest").unwrap();
        let mut bfile = BufReader::new(file);
        Manifest::parse(&mut bfile).unwrap();
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use style::attr::AttrValue;
use util::str::DOMString;

#[test]
fn test_from_limited_i32_should_be_default_when_less_than_0() {
    let value = DOMString::from("-1");
    match AttrValue::from_limited_i32(value, 0) {
        AttrValue::Int(_, 0) => (),
        _ => panic!("expected an IndexSize error")
    }
}

#[test]
fn test_from_limited_i32_should_parse_a_uint_when_value_is_0_or_greater() {
    match AttrValue::from_limited_i32(DOMString::from("1"), 0) {
        AttrValue::Int(_, 1) => (),
        _ => panic!("expected an successful parsing")
    }
}

#[test]
fn test_from_limited_i32_should_keep_parsed_value_when_not_an_int() {
    match AttrValue::from_limited_i32(DOMString::from("parsed-value"), 0) {
        AttrValue::Int(p, 0) => {
            assert_eq!(p, DOMString::from("parsed_value"))
        },
        _ => panic!("expected an successful parsing")
    }
}
<commit_msg>Fixes typo in test literal<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use style::attr::AttrValue;
use util::str::DOMString;

#[test]
fn test_from_limited_i32_should_be_default_when_less_than_0() {
    let value = DOMString::from("-1");
    match AttrValue::from_limited_i32(value, 0) {
        AttrValue::Int(_, 0) => (),
        _ => panic!("expected an IndexSize error")
    }
}

#[test]
fn test_from_limited_i32_should_parse_a_uint_when_value_is_0_or_greater() {
    match AttrValue::from_limited_i32(DOMString::from("1"), 0) {
        AttrValue::Int(_, 1) => (),
        _ => panic!("expected an successful parsing")
    }
}

#[test]
fn test_from_limited_i32_should_keep_parsed_value_when_not_an_int() {
    match AttrValue::from_limited_i32(DOMString::from("parsed-value"), 0) {
        AttrValue::Int(p, 0) => {
            assert_eq!(p, DOMString::from("parsed-value"))
        },
        _ => panic!("expected an successful parsing")
    }
}
<|endoftext|>


<commit_before>//
// Copyright 2020 The Project Oak Authors
//
// 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.
//

//! Database proxy Node for Project Oak.
//!
//! This shows how an Oak Node can privately retrieve information from an external database.
//!
//! In order to provide privacy while being able to request entries from the database, the following
//! scheme is implemented:
//! - The module receives a request for a specific database entry specified by key.
//! - Starts continuously requesting chunks of data from the database.
//! - Processes them and finds the requested entry.
//! - Sends a response only when all chunks have been requested from the database (even though it
//!   might have found the requested value earlier).
//!
//! This is necessary so we will not leak information about a particular chunk that contains the
//! requested entry, since an attacker could analyse network traffic.

pub mod proto {
    include!(concat!(env!("OUT_DIR"), "/oak.examples.database.rs"));
}

use anyhow::{anyhow, Context};
use oak::grpc;
use oak_abi::label::Label;
pub use proto::DatabaseProxyClient;
use proto::{
    DatabaseClient, DatabaseEntry, DatabaseProxy, DatabaseProxyDispatcher, GetDatabaseEntryRequest,
    GetDatabaseEntryResponse, ListDatabaseEntriesRequest,
};

const NODE_MODULE_NAME: &str = "database_proxy";
const NODE_ENTRYPOINT_NAME: &str = "database_proxy_main";

/// Expected number of database entries per request.
const DATABASE_PAGE_SIZE: u32 = 5;

pub fn get_database_entry(id: &str, database_url: &str) -> grpc::Result<DatabaseEntry> {
    let client = oak::grpc::client::Client::new_with_label(
        &oak::node_config::wasm(NODE_MODULE_NAME, NODE_ENTRYPOINT_NAME),
        &Label::public_untrusted(),
    )
    .map(DatabaseProxyClient)
    .ok_or_else(|| {
        grpc::build_status(
            grpc::Code::Unavailable,
            "Couldn't create database proxy Node",
        )
    })?;

    let request = GetDatabaseEntryRequest {
        key: id.to_string(),
        database_url: database_url.to_string(),
    };
    client.get_database_entry(request).and_then(|response| {
        response
            .entry
            .ok_or_else(|| grpc::build_status(grpc::Code::Internal, "Malformed response"))
    })
}

/// Oak Node that connects to an external database.
#[derive(Default)]
pub struct DatabaseProxyNode;

impl DatabaseProxyNode {
    /// Create a gRPC client pseudo-Node.
    fn get_grpc_client(database_url: &str) -> anyhow::Result<DatabaseClient> {
        oak::grpc::client::Client::new_with_label(
            &oak::node_config::grpc_client(database_url),
            &Label::public_untrusted(),
        )
        .map(DatabaseClient)
        .context("Couldn't create gRPC client")
    }

    /// Load a database subset defined by `offset` and the number of requested elements
    /// (`page_size`).
    fn list_database_entries(
        offset: u32,
        page_size: u32,
        database_url: &str,
    ) -> anyhow::Result<Vec<DatabaseEntry>> {
        let request = ListDatabaseEntriesRequest {
            offset: offset as i32,
            page_size: page_size as i32,
        };
        Self::get_grpc_client(database_url)?
            .list_database_entries(request)
            .map(|response| response.entries)
            .map_err(|error| anyhow!("gRPC send error: {:?}", error))
    }
}

/// A gRPC service implementation for the database proxy Node.
impl DatabaseProxy for DatabaseProxyNode {
    fn get_database_entry(
        &mut self,
        request: GetDatabaseEntryRequest,
    ) -> grpc::Result<GetDatabaseEntryResponse> {
        // Request entries from the database until the last entry page is reached.
        let mut requested_entry = None;
        let mut current_offset = 0;
        loop {
            let entries = Self::list_database_entries(
                current_offset,
                DATABASE_PAGE_SIZE,
                &request.database_url,
            )
            .map_err(|error| {
                grpc::build_status(
                    grpc::Code::NotFound,
                    // &format!("Database error: {:?}", error)[..],
                    format!("Database error: {:?}", error).as_ref(),
                )
            })?;

            // When the requested entry is found, we continue requesting new database entries, so
            // the database doesn't learn, which entry was requested.
            if let Some(entry) = entries.iter().find(|e| e.key == request.key) {
                requested_entry = Some(entry.clone());
            }

            // If the response contains fewer entries than requested, then it's the last database
            // page.
            if entries.len() < DATABASE_PAGE_SIZE as usize {
                break;
            }
            current_offset += DATABASE_PAGE_SIZE;
        }

        requested_entry
            .map(|entry| GetDatabaseEntryResponse { entry: Some(entry) })
            .ok_or_else(|| grpc::build_status(grpc::Code::NotFound, ""))
    }
}

oak::entrypoint!(database_proxy_main => |in_channel| {
    oak::logger::init_default();
    let dispatcher = DatabaseProxyDispatcher::new(DatabaseProxyNode::default());
    oak::run_event_loop(dispatcher, oak::io::Receiver::<grpc::Invocation>::new(in_channel));
});

oak::entrypoint!(grpc_database_proxy_main => |_in_channel| {
    oak::logger::init_default();
    let dispatcher = DatabaseProxyDispatcher::new(DatabaseProxyNode::default());
    let grpc_channel =
        oak::grpc::server::init("[::]:8080").expect("Couldn't create gRPC server pseudo-Node");
    oak::run_event_loop(dispatcher, grpc_channel);
});
<commit_msg>Remove commented code in TIR (#1566)<commit_after>//
// Copyright 2020 The Project Oak Authors
//
// 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.
//

//! Database proxy Node for Project Oak.
//!
//! This shows how an Oak Node can privately retrieve information from an external database.
//!
//! In order to provide privacy while being able to request entries from the database, the following
//! scheme is implemented:
//! - The module receives a request for a specific database entry specified by key.
//! - Starts continuously requesting chunks of data from the database.
//! - Processes them and finds the requested entry.
//! - Sends a response only when all chunks have been requested from the database (even though it
//!   might have found the requested value earlier).
//!
//! This is necessary so we will not leak information about a particular chunk that contains the
//! requested entry, since an attacker could analyse network traffic.

pub mod proto {
    include!(concat!(env!("OUT_DIR"), "/oak.examples.database.rs"));
}

use anyhow::{anyhow, Context};
use oak::grpc;
use oak_abi::label::Label;
pub use proto::DatabaseProxyClient;
use proto::{
    DatabaseClient, DatabaseEntry, DatabaseProxy, DatabaseProxyDispatcher, GetDatabaseEntryRequest,
    GetDatabaseEntryResponse, ListDatabaseEntriesRequest,
};

const NODE_MODULE_NAME: &str = "database_proxy";
const NODE_ENTRYPOINT_NAME: &str = "database_proxy_main";

/// Expected number of database entries per request.
const DATABASE_PAGE_SIZE: u32 = 5;

pub fn get_database_entry(id: &str, database_url: &str) -> grpc::Result<DatabaseEntry> {
    let client = oak::grpc::client::Client::new_with_label(
        &oak::node_config::wasm(NODE_MODULE_NAME, NODE_ENTRYPOINT_NAME),
        &Label::public_untrusted(),
    )
    .map(DatabaseProxyClient)
    .ok_or_else(|| {
        grpc::build_status(
            grpc::Code::Unavailable,
            "Couldn't create database proxy Node",
        )
    })?;

    let request = GetDatabaseEntryRequest {
        key: id.to_string(),
        database_url: database_url.to_string(),
    };
    client.get_database_entry(request).and_then(|response| {
        response
            .entry
            .ok_or_else(|| grpc::build_status(grpc::Code::Internal, "Malformed response"))
    })
}

/// Oak Node that connects to an external database.
#[derive(Default)]
pub struct DatabaseProxyNode;

impl DatabaseProxyNode {
    /// Create a gRPC client pseudo-Node.
    fn get_grpc_client(database_url: &str) -> anyhow::Result<DatabaseClient> {
        oak::grpc::client::Client::new_with_label(
            &oak::node_config::grpc_client(database_url),
            &Label::public_untrusted(),
        )
        .map(DatabaseClient)
        .context("Couldn't create gRPC client")
    }

    /// Load a database subset defined by `offset` and the number of requested elements
    /// (`page_size`).
    fn list_database_entries(
        offset: u32,
        page_size: u32,
        database_url: &str,
    ) -> anyhow::Result<Vec<DatabaseEntry>> {
        let request = ListDatabaseEntriesRequest {
            offset: offset as i32,
            page_size: page_size as i32,
        };
        Self::get_grpc_client(database_url)?
            .list_database_entries(request)
            .map(|response| response.entries)
            .map_err(|error| anyhow!("gRPC send error: {:?}", error))
    }
}

/// A gRPC service implementation for the database proxy Node.
impl DatabaseProxy for DatabaseProxyNode {
    fn get_database_entry(
        &mut self,
        request: GetDatabaseEntryRequest,
    ) -> grpc::Result<GetDatabaseEntryResponse> {
        // Request entries from the database until the last entry page is reached.
        let mut requested_entry = None;
        let mut current_offset = 0;
        loop {
            let entries = Self::list_database_entries(
                current_offset,
                DATABASE_PAGE_SIZE,
                &request.database_url,
            )
            .map_err(|error| {
                grpc::build_status(
                    grpc::Code::NotFound,
                    format!("Database error: {:?}", error).as_ref(),
                )
            })?;

            // When the requested entry is found, we continue requesting new database entries, so
            // the database doesn't learn, which entry was requested.
            if let Some(entry) = entries.iter().find(|e| e.key == request.key) {
                requested_entry = Some(entry.clone());
            }

            // If the response contains fewer entries than requested, then it's the last database
            // page.
            if entries.len() < DATABASE_PAGE_SIZE as usize {
                break;
            }
            current_offset += DATABASE_PAGE_SIZE;
        }

        requested_entry
            .map(|entry| GetDatabaseEntryResponse { entry: Some(entry) })
            .ok_or_else(|| grpc::build_status(grpc::Code::NotFound, ""))
    }
}

oak::entrypoint!(database_proxy_main => |in_channel| {
    oak::logger::init_default();
    let dispatcher = DatabaseProxyDispatcher::new(DatabaseProxyNode::default());
    oak::run_event_loop(dispatcher, oak::io::Receiver::<grpc::Invocation>::new(in_channel));
});

oak::entrypoint!(grpc_database_proxy_main => |_in_channel| {
    oak::logger::init_default();
    let dispatcher = DatabaseProxyDispatcher::new(DatabaseProxyNode::default());
    let grpc_channel =
        oak::grpc::server::init("[::]:8080").expect("Couldn't create gRPC server pseudo-Node");
    oak::run_event_loop(dispatcher, grpc_channel);
});
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate unicode_xid;

mod bottom_up;
mod db;
mod matching;
mod name_table;
mod parser;
mod program;
mod types;

pub struct Context {
    evaluator: bottom_up::BottomUpEvaluator,
}

#[derive(Debug)]
pub enum Error<'a> {
    Internal {
    },
    SourceMsg {
        source: &'a str
    },
}

pub type Result<'a, T> = std::result::Result<T, Error<'a>>;

impl Context {
    pub fn new_from_source(source: &str) -> Result<Self> {
        parser::db(source)
            .map(|(db, _)| Context {
                evaluator: bottom_up::BottomUpEvaluator::new(db),
            })
            .map_err(|_| {
                Error::Internal{}
            })
    }

    pub fn facts_as_string(&mut self) -> String {
        self.evaluator.run();
        return self.evaluator.db.facts_as_string();
    }
}
<commit_msg>Add minimal display of syntax errors.<commit_after>#[macro_use]
extern crate log;
extern crate unicode_xid;

mod bottom_up;
mod db;
mod matching;
mod name_table;
mod parser;
mod program;
mod types;

pub struct Context {
    evaluator: bottom_up::BottomUpEvaluator,
}

#[derive(Debug)]
pub enum Error<'a> {
    Internal {
    },
    SourceMsg {
        msg: &'static str,
        source: &'a str,
    },
}

pub type Result<'a, T> = std::result::Result<T, Error<'a>>;

impl Context {
    pub fn new_from_source(source: &str) -> Result<Self> {
        parser::db(source)
            .map(|(db, _)| Context {
                evaluator: bottom_up::BottomUpEvaluator::new(db),
            })
            .map_err(|e| {
                match e {
                    parser::Error::Msg{msg, rest} => {
                        Error::SourceMsg{
                            msg: msg,
                            source: rest,
                        }
                    }
                }
            })
    }

    pub fn facts_as_string(&mut self) -> String {
        self.evaluator.run();
        return self.evaluator.db.facts_as_string();
    }
}
<|endoftext|>