<commit_before>
extern crate bytes;
extern crate futures;
extern crate kcp;
extern crate mio;
#[macro_use]
extern crate tokio_core;
extern crate tokio_io;
extern crate rand;
extern crate time;

use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::net::SocketAddr;
use std::rc::Rc;
use std::time::{Duration, Instant};

use bytes::BytesMut;
use bytes::buf::FromBuf;
use futures::{Poll, Async, Future};
use futures::stream::Stream;
use kcp::prelude::*;
use mio::{Ready, Registration, PollOpt, Token, SetReadiness};
use mio::event::Evented;
use tokio_core::net::UdpSocket;
use tokio_core::reactor::{Handle, PollEvented, Timeout};
use tokio_io::{AsyncRead, AsyncWrite};

#[inline]
fn current() -> u32 {
    let timespec = time::get_time();
    (timespec.sec * 1000 + timespec.nsec as i64 / 1000 / 1000) as u32
}

pub struct KcpOutput {
    udp: Rc<UdpSocket>,
    peer: SocketAddr,
}

impl Write for KcpOutput {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.udp.send_to(buf, &self.peer)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

struct KcpTimer {
    kcp: Rc<RefCell<Kcp<KcpOutput>>>,
    timer: Rc<RefCell<Timeout>>,
}

impl Stream for KcpTimer {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<()>, io::Error> {
        let mut timer = self.timer.borrow_mut();
        match timer.poll() {
            Ok(Async::Ready(())) => {
                let mut kcp = self.kcp.borrow_mut();
                kcp.update(current())?;
                let dur = kcp.check(current());
                let next = Instant::now() + Duration::from_millis(dur as u64);
                timer.reset(next);
                Ok(Async::Ready(Some(())))
            }
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
    }
}

struct KcpIo {
    kcp: Rc<RefCell<Kcp<KcpOutput>>>,
    registration: Registration,
    set_readiness: SetReadiness,
}

impl Read for KcpIo {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.kcp.borrow_mut().recv(buf)
    }
}

impl Write for KcpIo {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut kcp = self.kcp.borrow_mut();
        kcp.send(&mut BytesMut::from_buf(buf)).and_then(|n| {
            kcp.flush().map(|_| n)
        })
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Evented for KcpIo {
    fn register(
        &self,
        poll: &mio::Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> io::Result<()> {
        self.registration.register(poll, token, interest, opts)
    }

    fn reregister(
        &self,
        poll: &mio::Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> io::Result<()> {
        self.registration.reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        <Registration as Evented>::deregister(&self.registration, poll)
    }
}

pub struct KcpClientStream {
    udp: Rc<UdpSocket>,
    io: PollEvented<KcpIo>,
}

impl Read for KcpClientStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if let Ok((n, _)) = self.udp.recv_from(buf) {
            self.io.get_ref().kcp.borrow_mut().input(
                &mut BytesMut::from_buf(
                    &buf[..n],
                ),
            )?;
            self.io.get_ref().set_readiness.set_readiness(
                mio::Ready::readable(),
            )?;
        }
        self.io.read(buf)
    }
}

impl AsyncRead for KcpClientStream {}

impl AsyncWrite for KcpClientStream {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        Ok(().into())
    }
}

impl Write for KcpClientStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.get_ref().set_readiness.set_readiness(
            mio::Ready::writable(),
        )?;
        self.io.write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

pub struct KcpStreamNew {
    inner: Option<KcpClientStream>,
}

impl Future for KcpStreamNew {
    type Item = KcpClientStream;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<KcpClientStream, io::Error> {
        Ok(Async::Ready(self.inner.take().unwrap()))
    }
}

pub struct KcpStream {
    io: PollEvented<KcpIo>,
}

impl KcpStream {
    pub fn connect(addr: &SocketAddr, handle: &Handle) -> KcpStreamNew {
        let local: SocketAddr = "0.0.0.0:0".parse().unwrap();

        let (registration, set_readiness) = Registration::new2();

        let timer = match Timeout::new_at(Instant::now(), handle) {
            Ok(timeout) => Rc::new(RefCell::new(timeout)),
            _ => return KcpStreamNew { inner: None },
        };

        let udp = match UdpSocket::bind(&local, handle) {
            Ok(udp) => Rc::new(udp),
            _ => return KcpStreamNew { inner: None },
        };

        let kcp = Rc::new(RefCell::new(Kcp::new(
            rand::random::<u32>(),
            KcpOutput {
                udp: udp.clone(),
                peer: *addr,
            },
        )));

        let io = KcpIo {
            kcp: kcp.clone(),
            registration: registration,
            set_readiness: set_readiness.clone(),
        };

        let io = match PollEvented::new(io, handle) {
            Ok(evented) => evented,
            _ => return KcpStreamNew { inner: None },
        };

        let interval = KcpTimer {
            kcp: kcp.clone(),
            timer: timer.clone(),
        };

        handle.spawn(interval.for_each(|_| Ok(())).then(|_| Ok(())));

        KcpStreamNew { inner: Some(KcpClientStream { udp: udp, io: io }) }
    }
}

impl Read for KcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.io.read(buf)
    }
}

impl Write for KcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.get_ref().set_readiness.set_readiness(
            mio::Ready::writable(),
        )?;
        self.io.write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

impl AsyncRead for KcpStream {}

impl AsyncWrite for KcpStream {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        Ok(().into())
    }
}

struct KcpSession {
    kcp: Rc<RefCell<Kcp<KcpOutput>>>,
    set_readiness: SetReadiness,
}

pub struct KcpListener {
    udp: Rc<UdpSocket>,
    sessions: HashMap<SocketAddr, KcpSession>,
    handle: Handle,
}

pub struct Incoming {
    inner: KcpListener,
}

impl Stream for Incoming {
    type Item = (KcpStream, SocketAddr);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, io::Error> {
        Ok(Async::Ready(Some(try_nb!(self.inner.accept()))))
    }
}

impl KcpListener {
    pub fn bind(addr: &SocketAddr, handle: &Handle) -> io::Result<KcpListener> {
        UdpSocket::bind(addr, handle).map(|udp| {
            KcpListener {
                udp: Rc::new(udp),
                sessions: HashMap::new(),
                handle: handle.clone(),
            }
        })
    }

    pub fn accept(&mut self) -> io::Result<(KcpStream, SocketAddr)> {
        let mut buf = [0; 1500];

        loop {
            let (size, addr) = self.udp.recv_from(&mut buf)?;

            if let Some(session) = self.sessions.get(&addr) {
                session.kcp.borrow_mut().input(&mut BytesMut::from_buf(
                    &buf[..size],
                ))?;
                session.set_readiness.set_readiness(mio::Ready::readable())?;
                continue;
            }

            let kcp = Kcp::new(
                get_conv(&buf),
                KcpOutput {
                    udp: self.udp.clone(),
                    peer: addr,
                },
            );
            let kcp = Rc::new(RefCell::new(kcp));
            let (registration, set_readiness) = Registration::new2();
            let timer = Rc::new(RefCell::new(Timeout::new_at(Instant::now(), &self.handle)?));
            let io = KcpIo {
                kcp: kcp.clone(),
                registration: registration,
                set_readiness: set_readiness.clone(),
            };
            let interval = KcpTimer {
                kcp: kcp.clone(),
                timer: timer.clone(),
            };
            self.handle.spawn(
                interval.for_each(|_| Ok(())).then(|_| Ok(())),
            );
            let io = PollEvented::new(io, &self.handle).unwrap();
            let stream = KcpStream { io: io };
            stream.io.get_ref().kcp.borrow_mut().input(
                &mut BytesMut::from_buf(&buf[..size]),
            )?;

            stream.io.get_ref().set_readiness.set_readiness(
                mio::Ready::readable(),
            )?;

            let session = KcpSession {
                kcp: kcp.clone(),
                set_readiness: set_readiness.clone(),
            };
            self.sessions.insert(addr, session);
            return Ok((stream, addr));
        }
    }

    pub fn incoming(self) -> Incoming {
        Incoming { inner: self }
    }
}
<commit_msg>add session timeout, hard code as 90s<commit_after>
extern crate bytes;
extern crate futures;
extern crate kcp;
extern crate mio;
#[macro_use]
extern crate tokio_core;
extern crate tokio_io;
extern crate rand;
extern crate time;

use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::net::SocketAddr;
use std::rc::Rc;
use std::time::{Duration, Instant};

use bytes::BytesMut;
use bytes::buf::FromBuf;
use futures::{Poll, Async, Future};
use futures::stream::Stream;
use kcp::prelude::*;
use mio::{Ready, Registration, PollOpt, Token, SetReadiness};
use mio::event::Evented;
use tokio_core::net::UdpSocket;
use tokio_core::reactor::{Handle, PollEvented, Timeout};
use tokio_io::{AsyncRead, AsyncWrite};

#[inline]
fn current() -> u32 {
    let timespec = time::get_time();
    (timespec.sec * 1000 + timespec.nsec as i64 / 1000 / 1000) as u32
}

pub struct KcpOutput {
    udp: Rc<UdpSocket>,
    peer: SocketAddr,
}

impl Write for KcpOutput {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.udp.send_to(buf, &self.peer)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[derive(Clone)]
struct KcpSession {
    kcp: Rc<RefCell<Kcp<KcpOutput>>>,
    timer: Rc<RefCell<Timeout>>,
    elapsed: Rc<RefCell<Instant>>,
    set_readiness: SetReadiness,
    owner: Option<(SocketAddr, Rc<RefCell<HashMap<SocketAddr, KcpSession>>>)>,
}

impl Stream for KcpSession {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<()>, io::Error> {
        let mut timer = self.timer.borrow_mut();
        match timer.poll() {
            Ok(Async::Ready(())) => {
                let mut kcp = self.kcp.borrow_mut();
                if self.elapsed.borrow().elapsed().as_secs() < 90 {
                    kcp.update(current())?;
                    let duration = Duration::from_millis(kcp.check(current()) as u64);
                    let next = Instant::now() + duration;
                    timer.reset(next);
                    Ok(Async::Ready(Some(())))
                } else {
                    kcp.expired();
                    self.set_readiness.set_readiness(Ready::readable())?;
                    if let Some(ref owner) = self.owner {
                        owner.1.borrow_mut().remove(&owner.0);
                    }
                    Ok(Async::NotReady)
                }
            }
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
    }
}

struct KcpIo {
    kcp: Rc<RefCell<Kcp<KcpOutput>>>,
    registration: Registration,
    set_readiness: SetReadiness,
}

impl Read for KcpIo {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.kcp.borrow_mut().recv(buf)
    }
}

impl Write for KcpIo {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let mut kcp = self.kcp.borrow_mut();
        kcp.send(&mut BytesMut::from_buf(buf)).and_then(|n| {
            kcp.flush().map(|_| n)
        })
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Evented for KcpIo {
    fn register(
        &self,
        poll: &mio::Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> io::Result<()> {
        self.registration.register(poll, token, interest, opts)
    }

    fn reregister(
        &self,
        poll: &mio::Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> io::Result<()> {
        self.registration.reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        <Registration as Evented>::deregister(&self.registration, poll)
    }
}

pub struct KcpClientStream {
    udp: Rc<UdpSocket>,
    io: PollEvented<KcpIo>,
    elapsed: Rc<RefCell<Instant>>,
}

impl Read for KcpClientStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if let Ok((n, _)) = self.udp.recv_from(buf) {
            let elapsed = self.elapsed.borrow().elapsed();
            *self.elapsed.borrow_mut() += elapsed;
            self.io.get_ref().kcp.borrow_mut().input(
                &mut BytesMut::from_buf(
                    &buf[..n],
                ),
            )?;
            self.io.get_ref().set_readiness.set_readiness(
                Ready::readable(),
            )?;
        }
        self.io.read(buf)
    }
}

impl AsyncRead for KcpClientStream {}

impl AsyncWrite for KcpClientStream {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        Ok(().into())
    }
}

impl Write for KcpClientStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.get_ref().set_readiness.set_readiness(
            mio::Ready::writable(),
        )?;
        self.io.write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

pub struct KcpStreamNew {
    inner: Option<KcpClientStream>,
}

impl Future for KcpStreamNew {
    type Item = KcpClientStream;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<KcpClientStream, io::Error> {
        Ok(Async::Ready(self.inner.take().unwrap()))
    }
}

pub struct KcpStream {
    io: PollEvented<KcpIo>,
}

impl KcpStream {
    pub fn connect(addr: &SocketAddr, handle: &Handle) -> KcpStreamNew {
        let local: SocketAddr = "0.0.0.0:0".parse().unwrap();

        let (registration, set_readiness) = Registration::new2();

        let timer = match Timeout::new_at(Instant::now(), handle) {
            Ok(timeout) => Rc::new(RefCell::new(timeout)),
            _ => return KcpStreamNew { inner: None },
        };

        let udp = match UdpSocket::bind(&local, handle) {
            Ok(udp) => Rc::new(udp),
            _ => return KcpStreamNew { inner: None },
        };

        let kcp = Rc::new(RefCell::new(Kcp::new(
            rand::random::<u32>(),
            KcpOutput {
                udp: udp.clone(),
                peer: *addr,
            },
        )));

        let io = KcpIo {
            kcp: kcp.clone(),
            registration: registration,
            set_readiness: set_readiness.clone(),
        };

        let io = match PollEvented::new(io, handle) {
            Ok(evented) => evented,
            _ => return KcpStreamNew { inner: None },
        };

        let elapsed = Rc::new(RefCell::new(Instant::now()));

        let interval = KcpSession {
            kcp: kcp.clone(),
            timer: timer.clone(),
            elapsed: elapsed.clone(),
            set_readiness: set_readiness.clone(),
            owner: None,
        };

        handle.spawn(interval.for_each(|_| Ok(())).then(|_| Ok(())));

        KcpStreamNew {
            inner: Some(KcpClientStream {
                udp: udp,
                io: io,
                elapsed: elapsed,
            }),
        }
    }
}

impl Read for KcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.io.read(buf)
    }
}

impl Write for KcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.get_ref().set_readiness.set_readiness(
            mio::Ready::writable(),
        )?;
        self.io.write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

impl AsyncRead for KcpStream {}

impl AsyncWrite for KcpStream {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        Ok(().into())
    }
}

pub struct KcpListener {
    udp: Rc<UdpSocket>,
    sessions: Rc<RefCell<HashMap<SocketAddr, KcpSession>>>,
    handle: Handle,
}

pub struct Incoming {
    inner: KcpListener,
}

impl Stream for Incoming {
    type Item = (KcpStream, SocketAddr);
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, io::Error> {
        Ok(Async::Ready(Some(try_nb!(self.inner.accept()))))
    }
}

impl KcpListener {
    pub fn bind(addr: &SocketAddr, handle: &Handle) -> io::Result<KcpListener> {
        UdpSocket::bind(addr, handle).map(|udp| {
            KcpListener {
                udp: Rc::new(udp),
                sessions: Rc::new(RefCell::new(HashMap::new())),
                handle: handle.clone(),
            }
        })
    }

    pub fn accept(&mut self) -> io::Result<(KcpStream, SocketAddr)> {
        let mut buf = [0; 1500];

        loop {
            let (size, addr) = self.udp.recv_from(&mut buf)?;

            if let Some(session) = self.sessions.borrow_mut().get_mut(&addr) {
                let elapsed = session.elapsed.borrow().elapsed();
                *session.elapsed.borrow_mut() += elapsed;
                session.kcp.borrow_mut().input(&mut BytesMut::from_buf(
                    &buf[..size],
                ))?;
                session.set_readiness.set_readiness(Ready::readable())?;
                continue;
            }

            let kcp = Kcp::new(
                get_conv(&buf),
                KcpOutput {
                    udp: self.udp.clone(),
                    peer: addr,
                },
            );

            let kcp = Rc::new(RefCell::new(kcp));

            let (registration, set_readiness) = Registration::new2();

            let timer = Rc::new(RefCell::new(Timeout::new_at(Instant::now(), &self.handle)?));

            let io = KcpIo {
                kcp: kcp.clone(),
                registration: registration,
                set_readiness: set_readiness.clone(),
            };

            let session = KcpSession {
                kcp: kcp.clone(),
                timer: timer.clone(),
                elapsed: Rc::new(RefCell::new(Instant::now())),
                set_readiness: set_readiness.clone(),
                owner: Some((addr, self.sessions.clone())),
            };

            self.handle.spawn(
                session.clone().for_each(|_| Ok(())).then(
                    |_| Ok(()),
                ),
            );
            let io = PollEvented::new(io, &self.handle).unwrap();
            let stream = KcpStream { io: io };
            stream.io.get_ref().kcp.borrow_mut().input(
                &mut BytesMut::from_buf(&buf[..size]),
            )?;

            stream.io.get_ref().set_readiness.set_readiness(
                mio::Ready::readable(),
            )?;

            self.sessions.borrow_mut().insert(addr, session);
            return Ok((stream, addr));
        }
    }

    pub fn incoming(self) -> Incoming {
        Incoming { inner: self }
    }
}
<|endoftext|>


<commit_before>//! Functions to find the difference between two texts (strings).
//! Usage
//! ----------
//!
//! Add the following to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! difference = "0.4"
//! ```
//!
//! Now you can use the crate in your code
//!
//! ```ignore
//! extern crate difference;
//! ```

#![crate_name = "difference"]
#![doc(html_root_url = "https://johannhof.github.io/difference.rs/")]

// I can basically feel the karma already
#![deny(missing_docs)]

mod lcs;
mod merge;

use lcs::lcs;
use merge::merge;

/// Defines the contents of a changeset
/// Changesets will be delivered in order of appearance in the original string
/// Sequences of the same kind will be grouped into one Difference
#[derive(PartialEq, Debug)]
pub enum Difference {
    /// Sequences that are the same
    Same(String),
    /// Sequences that are an addition (don't appear in the first string)
    Add(String),
    /// Sequences that are a removal (don't appear in the second string)
    Rem(String),
}

/// Calculates the edit distance and the changeset for two given strings.
/// The first string is assumed to be the "original", the second to be an
/// edited version of the first. The third parameter specifies how to split
/// the input strings, leading to a more or less exact comparison.
///
/// Common splits are `""` for char-level, `" "` for word-level and `"\n"` for line-level.
///
/// Outputs the edit distance (how much the two strings differ) and a "changeset", that is
/// a `Vec` containing `Difference`s.
///
/// # Examples
///
/// ```
/// use difference::diff;
/// use difference::Difference;
///
/// let (dist, changeset) = diff("test", "tent", "");
///
/// assert_eq!(changeset, vec![
///     Difference::Same("te".to_string()),
///     Difference::Rem("s".to_string()),
///     Difference::Add("n".to_string()),
///     Difference::Same("t".to_string())
/// ]);
/// ```
pub fn diff(orig: &str, edit: &str, split: &str) -> (i32, Vec<Difference>) {
    let (dist, common) = lcs(orig, edit, split);
    (dist, merge(orig, edit, &common, split))
}

/// Assert the difference between two strings. Works like diff, but takes
/// a fourth parameter that is the expected edit distance (e.g. 0 if you want to
/// test for equality).
///
/// Remember that edit distance might not be equal to your understanding of difference,
/// for example the words "Rust" and "Dust" have an edit distance of 2 because two changes (a
/// removal and an addition) are required to make them look the same.
///
/// Will print an error with a colorful diff using `print_diff` in case of failure.
#[macro_export]
macro_rules! assert_diff {
    ($orig:expr , $edit:expr, $split: expr, $expected: expr) => ({
        let orig = $orig;
        let edit = $edit;

        let (d, _) = $crate::diff(orig, edit, &($split));
        if d != $expected {
            $crate::print_diff(orig, edit, &($split));
            panic!("assertion failed: edit distance between {:?} and {:?} is {} and not {}, see \
                    diffset above",
                   orig,
                   edit,
                   d,
                   &($expected))
        }
    })
}

/// Prints a colorful visual representation of the diff.
/// This is just a convenience function for those who want quick results.
///
/// I recommend checking out the examples on how to build your
/// own diff output.
/// # Examples
///
/// ```
/// use difference::print_diff;
/// print_diff("Diffs are awesome", "Diffs are cool", " ");
/// ```
pub fn print_diff(orig: &str, edit: &str, split: &str) {
    let (_, changeset) = diff(orig, edit, split);
    let mut ret = String::new();

    for seq in changeset {
        match seq {
            Difference::Same(ref x) => {
                ret.push_str(x);
                ret.push_str(split);
            }
            Difference::Add(ref x) => {
                ret.push_str("\x1B[92m");
                ret.push_str(x);
                ret.push_str("\x1B[0m");
                ret.push_str(split);
            }
            Difference::Rem(ref x) => {
                ret.push_str("\x1B[91m");
                ret.push_str(x);
                ret.push_str("\x1B[0m");
                ret.push_str(split);
            }
        }
    }
    println!("{}", ret);
}

#[test]
fn test_diff() {
    let text1 = "Roses are red, violets are blue,\n\
                 I wrote this library,\n\
                 just for you.\n\
                 (It's true).";

    let text2 = "Roses are red, violets are blue,\n\
                 I wrote this documentation,\n\
                 just for you.\n\
                 (It's quite true).";

    let (dist, changeset) = diff(text1, text2, "\n");

    assert_eq!(dist, 4);

    assert_eq!(changeset,
               vec![Difference::Same("Roses are red, violets are blue,".to_string()),
                    Difference::Rem("I wrote this library,".to_string()),
                    Difference::Add("I wrote this documentation,".to_string()),
                    Difference::Same("just for you.".to_string()),
                    Difference::Rem("(It's true).".to_string()),
                    Difference::Add("(It's quite true).".to_string())]);
}

#[test]
#[should_panic]
fn test_assert_diff_panic() {
    let text1 = "Roses are red, violets are blue,\n\
                 I wrote this library,\n\
                 just for you.\n\
                 (It's true).";

    let text2 = "Roses are red, violets are blue,\n\
                 I wrote this documentation,\n\
                 just for you.\n\
                 (It's quite true).";

    assert_diff!(text1, text2, "\n'", 0);
}

#[test]
fn test_assert_diff() {
    let text1 = "Roses are red, violets are blue";

    let text2 = "Roses are green, violets are blue";

    assert_diff!(text1, text2, " ", 2);
}
<commit_msg>Update assert_diff doc comment for including the macro<commit_after>//! Functions to find the difference between two texts (strings).
//! Usage
//! ----------
//!
//! Add the following to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! difference = "0.4"
//! ```
//!
//! Now you can use the crate in your code
//!
//! ```ignore
//! extern crate difference;
//! ```

#![crate_name = "difference"]
#![doc(html_root_url = "https://johannhof.github.io/difference.rs/")]

// I can basically feel the karma already
#![deny(missing_docs)]

mod lcs;
mod merge;

use lcs::lcs;
use merge::merge;

/// Defines the contents of a changeset
/// Changesets will be delivered in order of appearance in the original string
/// Sequences of the same kind will be grouped into one Difference
#[derive(PartialEq, Debug)]
pub enum Difference {
    /// Sequences that are the same
    Same(String),
    /// Sequences that are an addition (don't appear in the first string)
    Add(String),
    /// Sequences that are a removal (don't appear in the second string)
    Rem(String),
}

/// Calculates the edit distance and the changeset for two given strings.
/// The first string is assumed to be the "original", the second to be an
/// edited version of the first. The third parameter specifies how to split
/// the input strings, leading to a more or less exact comparison.
///
/// Common splits are `""` for char-level, `" "` for word-level and `"\n"` for line-level.
///
/// Outputs the edit distance (how much the two strings differ) and a "changeset", that is
/// a `Vec` containing `Difference`s.
///
/// # Examples
///
/// ```
/// use difference::diff;
/// use difference::Difference;
///
/// let (dist, changeset) = diff("test", "tent", "");
///
/// assert_eq!(changeset, vec![
///     Difference::Same("te".to_string()),
///     Difference::Rem("s".to_string()),
///     Difference::Add("n".to_string()),
///     Difference::Same("t".to_string())
/// ]);
/// ```
pub fn diff(orig: &str, edit: &str, split: &str) -> (i32, Vec<Difference>) {
    let (dist, common) = lcs(orig, edit, split);
    (dist, merge(orig, edit, &common, split))
}

/// Assert the difference between two strings. Works like diff, but takes
/// a fourth parameter that is the expected edit distance (e.g. 0 if you want to
/// test for equality).
///
/// To include this macro use:
///
/// ```
/// #[macro_use(assert_diff)]
/// extern crate difference;
/// ```
///
/// Remember that edit distance might not be equal to your understanding of difference,
/// for example the words "Rust" and "Dust" have an edit distance of 2 because two changes (a
/// removal and an addition) are required to make them look the same.
///
/// Will print an error with a colorful diff using `print_diff` in case of failure.
#[macro_export]
macro_rules! assert_diff {
    ($orig:expr , $edit:expr, $split: expr, $expected: expr) => ({
        let orig = $orig;
        let edit = $edit;

        let (d, _) = $crate::diff(orig, edit, &($split));
        if d != $expected {
            $crate::print_diff(orig, edit, &($split));
            panic!("assertion failed: edit distance between {:?} and {:?} is {} and not {}, see \
                    diffset above",
                   orig,
                   edit,
                   d,
                   &($expected))
        }
    })
}

/// Prints a colorful visual representation of the diff.
/// This is just a convenience function for those who want quick results.
///
/// I recommend checking out the examples on how to build your
/// own diff output.
/// # Examples
///
/// ```
/// use difference::print_diff;
/// print_diff("Diffs are awesome", "Diffs are cool", " ");
/// ```
pub fn print_diff(orig: &str, edit: &str, split: &str) {
    let (_, changeset) = diff(orig, edit, split);
    let mut ret = String::new();

    for seq in changeset {
        match seq {
            Difference::Same(ref x) => {
                ret.push_str(x);
                ret.push_str(split);
            }
            Difference::Add(ref x) => {
                ret.push_str("\x1B[92m");
                ret.push_str(x);
                ret.push_str("\x1B[0m");
                ret.push_str(split);
            }
            Difference::Rem(ref x) => {
                ret.push_str("\x1B[91m");
                ret.push_str(x);
                ret.push_str("\x1B[0m");
                ret.push_str(split);
            }
        }
    }
    println!("{}", ret);
}

#[test]
fn test_diff() {
    let text1 = "Roses are red, violets are blue,\n\
                 I wrote this library,\n\
                 just for you.\n\
                 (It's true).";

    let text2 = "Roses are red, violets are blue,\n\
                 I wrote this documentation,\n\
                 just for you.\n\
                 (It's quite true).";

    let (dist, changeset) = diff(text1, text2, "\n");

    assert_eq!(dist, 4);

    assert_eq!(changeset,
               vec![Difference::Same("Roses are red, violets are blue,".to_string()),
                    Difference::Rem("I wrote this library,".to_string()),
                    Difference::Add("I wrote this documentation,".to_string()),
                    Difference::Same("just for you.".to_string()),
                    Difference::Rem("(It's true).".to_string()),
                    Difference::Add("(It's quite true).".to_string())]);
}

#[test]
#[should_panic]
fn test_assert_diff_panic() {
    let text1 = "Roses are red, violets are blue,\n\
                 I wrote this library,\n\
                 just for you.\n\
                 (It's true).";

    let text2 = "Roses are red, violets are blue,\n\
                 I wrote this documentation,\n\
                 just for you.\n\
                 (It's quite true).";

    assert_diff!(text1, text2, "\n'", 0);
}

#[test]
fn test_assert_diff() {
    let text1 = "Roses are red, violets are blue";

    let text2 = "Roses are green, violets are blue";

    assert_diff!(text1, text2, " ", 2);
}
<|endoftext|>


<commit_before>extern crate lmdb;
extern crate lmdb_sys;

use std::{result, str};
use std::path::Path;
use lmdb::{Transaction, Cursor, DUP_SORT, INTEGER_KEY};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
}

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

struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

struct RwTransaction<'a> {
    lmdb_txn: lmdb::RwTransaction<'a>,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
struct Id(u64);

struct Node<'a> {
    id: Id,
    parent_id: Id,
    name: &'a str,
}

struct Entry<'a> {
    txn: &'a RwTransaction<'a>,
    node: Node<'a>,
    objectclass: &'a str,
}

impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_parent_id_and_bytes(parent_id: Id, bytes: &[u8]) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));

        let name = match std::str::from_utf8(&bytes[8..]) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create_database(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new()
                            .set_max_dbs(8)
                            .open_with_permissions(&path, 0o600) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbCreateError),
        };

        let nodes = match env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        let entries = match env.create_db(Some("entries"), INTEGER_KEY) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open_database(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new().open(&path) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let nodes = match env.open_db(Some("nodes")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let entries = match env.open_db(Some("entries")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction { lmdb_txn: txn }),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id(&self, txn: &mut RwTransaction) -> Result<Id> {
        let cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
            Ok(c) => c,
            Err(_) => return Err(Error::TransactionError),
        };

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &'a mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        {
            let ref mut lmdb_txn = txn.lmdb_txn;

            match lmdb_txn.put(self.nodes,
                               &parent_id.as_bytes(),
                               &node.to_bytes(),
                               lmdb::WriteFlags::empty()) {
                Ok(_) => (),
                Err(_) => return Err(Error::DbWriteError),
            }

            match lmdb_txn.put(self.entries,
                               &id.as_bytes(),
                               &objectclass,
                               lmdb::WriteFlags::empty()) {
                Ok(_) => (),
                Err(_) => return Err(Error::DbWriteError),
            }
        }

        Ok(Entry {
            txn: txn,
            node: node,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a>(&'a self, txn: &'a mut RwTransaction, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = match txn.lmdb_txn.get(self.entries, &node.id.as_bytes()) {
            Ok(bytes) => bytes,
            Err(_) => return Err(Error::DbCorruptError),
        };

        let objectclass = match std::str::from_utf8(&entry_bytes) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Entry {
            txn: txn,
            node: node,
            objectclass: objectclass,
        })
    }

    fn find_node(&self, txn: &mut RwTransaction, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        // Perform a hierarchical path lookup
        // TODO: since LMDB is ordered, we could e.g. perform a binary search
        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            let parent_id = try!(parent_node).id;

            let mut cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
                Ok(c) => c,
                Err(_) => return Err(Error::TransactionError),
            };

            let mut child_node = None;

            for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
                if id != parent_id.as_bytes() {
                    return Err(Error::NotFoundError);
                }

                let node = try!(Node::from_parent_id_and_bytes(parent_id, node_bytes));

                if node.name == *component {
                    child_node = Some(node);
                    break;
                }
            }

            match child_node {
                Some(node) => Ok(node),
                None => return Err(Error::NotFoundError),
            }
        })
    }
}

impl<'a> RwTransaction<'a> {
    pub fn commit(self) -> Result<()> {
        match self.lmdb_txn.commit() {
            Ok(_) => Ok(()),
            Err(_) => return Err(Error::TransactionError),
        }
    }
}

#[test]
fn test_entry_lookup() {
    let path = Path::new("./tmp");
    let adapter = LmdbAdapter::create_database(path).unwrap();

    {
        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&mut txn).unwrap();
        adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

        let hosts_id = domain_id.next();
        adapter.create_entry(&mut txn, hosts_id, domain_id, "hosts", "ou").unwrap();

        let host_id = hosts_id.next();
        adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host").unwrap();

        txn.commit().unwrap();
    }

    {
        let mut txn = adapter.rw_transaction().unwrap();

        {
            let mut entry = adapter.find_entry(&mut txn, "/example.com/hosts/master.example.com")
                                   .unwrap();

            assert_eq!(entry.node.name, "master.example.com");
            assert_eq!(entry.objectclass, "host");
        }

        txn.commit().unwrap();
    }
}
<commit_msg>Add comments about use of transmute for Ids<commit_after>extern crate lmdb;
extern crate lmdb_sys;

use std::{result, str};
use std::path::Path;
use lmdb::{Transaction, Cursor, DUP_SORT, INTEGER_KEY};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
}

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

struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

struct RwTransaction<'a> {
    lmdb_txn: lmdb::RwTransaction<'a>,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
struct Id(u64);

struct Node<'a> {
    id: Id,
    parent_id: Id,
    name: &'a str,
}

struct Entry<'a> {
    txn: &'a RwTransaction<'a>,
    node: Node<'a>,
    objectclass: &'a str,
}

// Ids are 64-bit integers in host-native byte order
// LMDB has special optimizations for host-native integers as keys
impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_parent_id_and_bytes(parent_id: Id, bytes: &[u8]) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));

        let name = match std::str::from_utf8(&bytes[8..]) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create_database(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new()
                            .set_max_dbs(8)
                            .open_with_permissions(&path, 0o600) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbCreateError),
        };

        let nodes = match env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        let entries = match env.create_db(Some("entries"), INTEGER_KEY) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open_database(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new().open(&path) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let nodes = match env.open_db(Some("nodes")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let entries = match env.open_db(Some("entries")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction { lmdb_txn: txn }),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id(&self, txn: &mut RwTransaction) -> Result<Id> {
        let cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
            Ok(c) => c,
            Err(_) => return Err(Error::TransactionError),
        };

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &'a mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        {
            let ref mut lmdb_txn = txn.lmdb_txn;

            match lmdb_txn.put(self.nodes,
                               &parent_id.as_bytes(),
                               &node.to_bytes(),
                               lmdb::WriteFlags::empty()) {
                Ok(_) => (),
                Err(_) => return Err(Error::DbWriteError),
            }

            match lmdb_txn.put(self.entries,
                               &id.as_bytes(),
                               &objectclass,
                               lmdb::WriteFlags::empty()) {
                Ok(_) => (),
                Err(_) => return Err(Error::DbWriteError),
            }
        }

        Ok(Entry {
            txn: txn,
            node: node,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a>(&'a self, txn: &'a mut RwTransaction, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = match txn.lmdb_txn.get(self.entries, &node.id.as_bytes()) {
            Ok(bytes) => bytes,
            Err(_) => return Err(Error::DbCorruptError),
        };

        let objectclass = match std::str::from_utf8(&entry_bytes) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Entry {
            txn: txn,
            node: node,
            objectclass: objectclass,
        })
    }

    fn find_node(&self, txn: &mut RwTransaction, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        // Perform a hierarchical path lookup
        // TODO: since LMDB is ordered, we could e.g. perform a binary search
        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            let parent_id = try!(parent_node).id;

            let mut cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
                Ok(c) => c,
                Err(_) => return Err(Error::TransactionError),
            };

            let mut child_node = None;

            for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
                if id != parent_id.as_bytes() {
                    return Err(Error::NotFoundError);
                }

                let node = try!(Node::from_parent_id_and_bytes(parent_id, node_bytes));

                if node.name == *component {
                    child_node = Some(node);
                    break;
                }
            }

            match child_node {
                Some(node) => Ok(node),
                None => return Err(Error::NotFoundError),
            }
        })
    }
}

impl<'a> RwTransaction<'a> {
    pub fn commit(self) -> Result<()> {
        match self.lmdb_txn.commit() {
            Ok(_) => Ok(()),
            Err(_) => return Err(Error::TransactionError),
        }
    }
}

#[test]
fn test_entry_lookup() {
    let path = Path::new("./tmp");
    let adapter = LmdbAdapter::create_database(path).unwrap();

    {
        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&mut txn).unwrap();
        adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

        let hosts_id = domain_id.next();
        adapter.create_entry(&mut txn, hosts_id, domain_id, "hosts", "ou").unwrap();

        let host_id = hosts_id.next();
        adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host").unwrap();

        txn.commit().unwrap();
    }

    {
        let mut txn = adapter.rw_transaction().unwrap();

        {
            let mut entry = adapter.find_entry(&mut txn, "/example.com/hosts/master.example.com")
                                   .unwrap();

            assert_eq!(entry.node.name, "master.example.com");
            assert_eq!(entry.objectclass, "host");
        }

        txn.commit().unwrap();
    }
}
<|endoftext|>


<commit_before>//!  Linear algebra package for [rust-ndarray](https://github.com/bluss/rust-ndarray) using LAPACK via [stainless-steel/lapack](https://github.com/stainless-steel/lapack)
//!
//!  Linear algebra methods
//!  -----------------------
//!  - [QR decomposition](qr/trait.QR.html)
//!  - [singular value decomposition](svd/trait.SVD.html)
//!  - [solve linear problem](solve/index.html)
//!  - [solve linear problem for triangular matrix](triangular/trait.SolveTriangular.html)
//!  - [inverse matrix](solve/trait.Inverse.html)
//!  - [eigenvalue decomposition for Hermite matrix][eigh]
//!
//!  [eigh]:eigh/trait.Eigh.html
//!
//!  Utilities
//!  -----------
//!  - [assertions for array](index.html#macros)
//!  - [generator functions](generate/index.html)
//!  - [Scalar trait](types/trait.Field.html)
//!
//!  Usage
//!  ------
//!  Most functions in this crate is defined as [self-consuming trait technique][sct] like [serde]
//!  does.
//!
//!  For example, we can execute [eigh][eigh] using three types of interfaces:
//!
//!  ```rust
//!  let a = random((3, 3));
//!  let (eval, evec) = a.eigh(UPLO::Upper)?;
//!  let (eval, evec) = (&a).eigh(UPLO::Upper)?;
//!  let (eval, evec) = (&mut a).eigh(UPLO::Upper)?;
//!  ```
//!
//!  The first type `a.eigh()` consumes `a`, and the memory of `a` is used for `evec`.
//!  The second type `(&a).eigh()` consumes the reference (not `a` itself),
//!  and the memory for `evec` is newly allocated.
//!  The last one `(&mut a).eigh()` is similar to the first one;
//!  It borrows `a` mutably, and rewrite it to contains `evec`.
//!  In all cases, the array `eval` is newly allocated.
//!
//!  [sct]:https://github.com/serde-rs/serde/releases/tag/v0.9.0
//!  [serde]:https://github.com/serde-rs/serde

extern crate blas;
extern crate lapack;
extern crate num_traits;
extern crate num_complex;
extern crate rand;
#[macro_use(s)]
extern crate ndarray;
#[macro_use]
extern crate enum_error_derive;
#[macro_use]
extern crate derive_new;

#[macro_use]
pub mod types;
pub mod error;
pub mod layout;
pub mod lapack_traits;

pub mod cholesky;
pub mod eigh;
pub mod opnorm;
pub mod qr;
pub mod solve;
pub mod svd;
pub mod triangular;

pub mod generate;
pub mod assert;
pub mod norm;
pub mod trace;

pub use assert::*;
pub use generate::*;
pub use layout::*;
pub use types::*;

pub use cholesky::*;
pub use eigh::*;
pub use norm::*;
pub use opnorm::*;
pub use qr::*;
pub use solve::*;
pub use svd::*;
pub use trace::*;
pub use triangular::*;
<commit_msg>Add ignore flag<commit_after>//!  Linear algebra package for [rust-ndarray](https://github.com/bluss/rust-ndarray) using LAPACK via [stainless-steel/lapack](https://github.com/stainless-steel/lapack)
//!
//!  Linear algebra methods
//!  -----------------------
//!  - [QR decomposition](qr/trait.QR.html)
//!  - [singular value decomposition](svd/trait.SVD.html)
//!  - [solve linear problem](solve/index.html)
//!  - [solve linear problem for triangular matrix](triangular/trait.SolveTriangular.html)
//!  - [inverse matrix](solve/trait.Inverse.html)
//!  - [eigenvalue decomposition for Hermite matrix][eigh]
//!
//!  [eigh]:eigh/trait.Eigh.html
//!
//!  Utilities
//!  -----------
//!  - [assertions for array](index.html#macros)
//!  - [generator functions](generate/index.html)
//!  - [Scalar trait](types/trait.Field.html)
//!
//!  Usage
//!  ------
//!  Most functions in this crate is defined as [self-consuming trait technique][sct] like [serde]
//!  does.
//!
//!  For example, we can execute [eigh][eigh] using three types of interfaces:
//!
//!  ```rust,ignore
//!  let a = random((3, 3));
//!  let (eval, evec) = a.eigh(UPLO::Upper)?;
//!  let (eval, evec) = (&a).eigh(UPLO::Upper)?;
//!  let (eval, evec) = (&mut a).eigh(UPLO::Upper)?;
//!  ```
//!
//!  The first type `a.eigh()` consumes `a`, and the memory of `a` is used for `evec`.
//!  The second type `(&a).eigh()` consumes the reference (not `a` itself),
//!  and the memory for `evec` is newly allocated.
//!  The last one `(&mut a).eigh()` is similar to the first one;
//!  It borrows `a` mutably, and rewrite it to contains `evec`.
//!  In all cases, the array `eval` is newly allocated.
//!
//!  [sct]:https://github.com/serde-rs/serde/releases/tag/v0.9.0
//!  [serde]:https://github.com/serde-rs/serde

extern crate blas;
extern crate lapack;
extern crate num_traits;
extern crate num_complex;
extern crate rand;
#[macro_use(s)]
extern crate ndarray;
#[macro_use]
extern crate enum_error_derive;
#[macro_use]
extern crate derive_new;

#[macro_use]
pub mod types;
pub mod error;
pub mod layout;
pub mod lapack_traits;

pub mod cholesky;
pub mod eigh;
pub mod opnorm;
pub mod qr;
pub mod solve;
pub mod svd;
pub mod triangular;

pub mod generate;
pub mod assert;
pub mod norm;
pub mod trace;

pub use assert::*;
pub use generate::*;
pub use layout::*;
pub use types::*;

pub use cholesky::*;
pub use eigh::*;
pub use norm::*;
pub use opnorm::*;
pub use qr::*;
pub use solve::*;
pub use svd::*;
pub use trace::*;
pub use triangular::*;
<|endoftext|>


<commit_before>mod error;
pub use self::error::Error;

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

pub struct ViewHandle(u64);

pub struct Rect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

impl Rect {
    pub fn new(x: f32, y: f32, width: f32, height: f32) -> Rect {
        Rect {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

pub struct View {
    pub handle: ViewHandle,
    pub rect: Rect
}

pub enum Direction {
    Vertical,
    Horizontal,
    Full,
}

pub struct Container {
    pub views: Vec<View>,
}

pub struct Split {
    pub split: Option<Box<Split>>,
    pub left_top: Container,
    pub right_bottom: Container,
    pub percent: f32,
    pub direction: Direction,
}

pub struct Workspace {
    pub split: Option<Box<Split>>,
    pub rect: Rect,
}

impl Workspace {
    /// Construct a new workspace. The rect has to be y >= 0, x >= 0, width > 0 and height > 0
    pub fn new(rect: Rect) -> Result<Workspace> {
        if rect.x < 0.0 {
            return Err(Error::IllegalSize("x has to be non-negative".to_owned()));
        }

        if rect.y < 0.0 {
            return Err(Error::IllegalSize("y has to be non-negative".to_owned()));
        }

        if rect.width <= 0.0 {
            return Err(Error::IllegalSize("width has to be larger than 0.0".to_owned()));
        }

        if rect.height <= 0.0 {
            return Err(Error::IllegalSize("height has to be larger than 0.0".to_owned()));
        }

        Ok(Workspace {
            split: None,
            rect: rect })
    }
}

#[cfg(test)]
mod test {
    use {Workspace, Rect};

    #[test]
    fn test_validate_x_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(-0.1, 0.0, 1.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_y_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, -0.1, 1.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_width_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 0.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_height_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 1.0, 0.0)).is_err(), true);
    }

    #[test]
    fn test_validate_width_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, -1.0, 0.0)).is_err(), true);
    }

    #[test]
    fn test_validate_height_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 0.0, -1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_workspace_ok() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 1024.0, 1024.0)).is_ok(), true);
    }
}
<commit_msg>WIP on sizing<commit_after>mod error;
pub use self::error::Error;

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

#[derive(Clone, Copy)]
pub struct ViewHandle(u64);

#[derive(Default, Clone)]
pub struct Rect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

impl Rect {
    pub fn new(x: f32, y: f32, width: f32, height: f32) -> Rect {
        Rect {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

#[derive(Clone)]
pub struct View {
    pub handle: ViewHandle,
    pub rect: Rect
}

impl View {
    fn new(view_handle: ViewHandle) -> View {
        View {
            handle: view_handle,
            rect: Rect::default(),
        }
    }
}

pub enum Direction {
    Vertical,
    Horizontal,
    Full,
}

#[derive(Clone)]
pub struct Container {
    pub views: Vec<View>,
}

pub struct Split {
    /// left/top slipit
    pub left: Option<Box<Split>>,
    /// right/bottom split
    pub right: Option<Box<Split>>,
    /// left/top views
    pub left_views: Container,
    /// right/top views
    pub right_views: Container,
    /// ratioage value of how much of each side that is visible. 1.0 = right/bottom fully visible
    pub ratio: f32,
    /// Direction of the split
    pub direction: Direction,
}

impl Split {
    pub fn new(direction: Direction) -> Split {
        Split {
            left: None,
            right: None,
            left_views: Container { views: Vec::new() },
            right_views: Container { views: Vec::new() },
            ratio: 0.0,
            direction: direction,
        }
    }

    pub fn no_split(&mut self, view_handle: ViewHandle) -> bool {
        if self.left_views.views.len() == 0 {
            self.left_views.views.push(View::new(view_handle));
            self.ratio = 0.5;
            return true;
        }

        if self.right_views.views.len() == 0 {
            self.right_views.views.push(View::new(view_handle));
            self.ratio = 0.5;
            return true;
        }

        false
    }

    pub fn split_left(&mut self, view_handle: ViewHandle, direction: Direction) {
        if Self::no_split(self, view_handle) {
            return;
        } else {
            let mut split = Box::new(Split::new(direction));
            split.right_views = self.left_views.clone();
            split.left_views.views.push(View::new(view_handle));
            self.left = Some(split);
            self.right_views.views.clear();
        }

        /*
        // this case only happens when a view happen to be fullscreen
        if self.left_top.len() == 1 && self.right_bottom.len() == 0 {
            self.direction = direction;
            self.ratio = 0.5;
            self.right_bottom.push(View::new(view_handle));
        } else {

        }
        */
    }

    pub fn split_right(&mut self, view_handle: ViewHandle, direction: Direction) {
        if Self::no_split(self, view_handle) {
            return;
        } else {
            let mut split = Box::new(Split::new(direction));
            split.left_views = self.right_views.clone();
            split.right_views.views.push(View::new(view_handle));
            self.right = Some(split);
            self.left_views.views.clear();
        }
    }
}

pub struct Workspace {
    pub split: Option<Box<Split>>,
    pub rect: Rect,
    /// border size of the windows (in pixels)
    pub window_border: f32,
}

impl Workspace {
    /// Construct a new workspace. The rect has to be y >= 0, x >= 0, width > 0 and height > 0
    pub fn new(rect: Rect) -> Result<Workspace> {
        if rect.x < 0.0 {
            return Err(Error::IllegalSize("x has to be non-negative".to_owned()));
        }

        if rect.y < 0.0 {
            return Err(Error::IllegalSize("y has to be non-negative".to_owned()));
        }

        if rect.width <= 0.0 {
            return Err(Error::IllegalSize("width has to be larger than 0.0".to_owned()));
        }

        if rect.height <= 0.0 {
            return Err(Error::IllegalSize("height has to be larger than 0.0".to_owned()));
        }

        Ok(Workspace {
            split: None,
            rect: rect,
            window_border: 4.0,
        })
    }

    /// This code gets called when the top split is None. This mean that the view will be
    /// set to fullscreen as there are no other splits to be done
    fn split_new(&mut self, view_handle: ViewHandle) {
        let mut split = Box::new(Split::new(Direction::Full));
        split.ratio = 1.0;
        split.left_views.views.push(View::new(view_handle));
        self.split = Some(split);
    }

    pub fn split_top(&mut self, view_handle: ViewHandle, direction: Direction) {
        if let Some(ref mut split) = self.split {
            split.split_left(view_handle, direction);
        } else {
            Self::split_new(self, view_handle);
        }
    }

    pub fn calc_horizontal_sizing(rect: Rect, ratio: f32) -> (Rect, Rect) {
        let h = rect.height * ratio;

        let rect_top = Rect {
            x: rect.x,
            y: rect.y,
            width: rect.width,
            height: h,
        };

        let rect_bottom = Rect {
            x: rect.x,
            y: rect.y + h,
            width: rect.width,
            height: rect.height - h,
        };

        (rect_top, rect_bottom)
    }

    pub fn calc_vertical_sizing(rect: Rect, ratio: f32) -> (Rect, Rect) {
        let w = rect.width * ratio;

        let rect_left = Rect {
            x: rect.x,
            y: rect.y,
            width: w,
            height: rect.height,
        };

        let rect_right = Rect {
            x: rect.x + w,
            y: rect.y,
            width: rect.width - w,
            height: rect.height,
        };

        (rect_left, rect_right)
    }

    fn recursive_update(&mut self, _rect: Rect, _level: usize) {
        // update the size on this level

        /*
        match self.direction {
            Direction::Vertical => {

            }

            Direction::Horizontal => {

            }
        }
        */
    }

    pub fn update(&mut self) {
        let rect = self.rect.clone();
        Self::recursive_update(self, rect, 0);
    }
}

#[cfg(test)]
mod test {
    use {Workspace, Rect, ViewHandle, Direction};

    fn check_range(inv: f32, value: f32, delta: f32) -> bool {
        (inv - value).abs() < delta
    }

    #[test]
    fn test_validate_x_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(-0.1, 0.0, 1.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_y_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, -0.1, 1.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_width_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 0.0, 1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_height_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 1.0, 0.0)).is_err(), true);
    }

    #[test]
    fn test_validate_width_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, -1.0, 0.0)).is_err(), true);
    }

    #[test]
    fn test_validate_height_less_than_zero() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 0.0, -1.0)).is_err(), true);
    }

    #[test]
    fn test_validate_workspace_ok() {
        assert_eq!(Workspace::new(Rect::new(0.0, 0.0, 1024.0, 1024.0)).is_ok(), true);
    }

    #[test]
    fn test_split_top() {
        let mut ws = Workspace::new(Rect::new(0.0, 0.0, 1024.0, 1024.0)).unwrap();
        ws.split_top(ViewHandle(1), Direction::Vertical);

        assert_eq!(ws.split.is_some(), true);
        let split = ws.split.unwrap();

        assert_eq!(split.left_views.views.len(), 1);
    }

    #[test]
    fn test_split_top_2() {
        let mut ws = Workspace::new(Rect::new(0.0, 0.0, 1024.0, 1024.0)).unwrap();
        ws.split_top(ViewHandle(1), Direction::Vertical);
        ws.split_top(ViewHandle(2), Direction::Vertical);

        assert_eq!(ws.split.is_some(), true);
        let split = ws.split.unwrap();

        assert_eq!(split.right_views.views.len(), 1);
        assert_eq!(split.left_views.views.len(), 1);
        assert_eq!(check_range(split.ratio, 0.5, 0.01), true);
    }

    #[test]
    fn test_calc_rect_horz_half() {
        let rects = Workspace::calc_horizontal_sizing(Rect::new(0.0, 0.0, 1024.0, 1024.0), 0.5);

        assert_eq!(check_range(rects.0.x, 0.0, 0.001), true);
        assert_eq!(check_range(rects.0.y, 0.0, 0.001), true);
        assert_eq!(check_range(rects.0.width, 1024.0, 0.001), true);
        assert_eq!(check_range(rects.0.height, 512.0, 0.001), true);

        assert_eq!(check_range(rects.1.x, 0.0, 0.001), true);
        assert_eq!(check_range(rects.1.y, 512.0, 0.001), true);
        assert_eq!(check_range(rects.1.width, 1024.0, 0.001), true);
        assert_eq!(check_range(rects.1.height, 512.0, 0.001), true);
    }

    #[test]
    fn test_calc_rect_horz_25_per() {
        let rects = Workspace::calc_horizontal_sizing(Rect::new(0.0, 0.0, 1024.0, 1024.0), 0.25);

        assert_eq!(check_range(rects.0.x, 0.0, 0.001), true);
        assert_eq!(check_range(rects.0.y, 0.0, 0.001), true);
        assert_eq!(check_range(rects.0.width, 1024.0, 0.001), true);
        assert_eq!(check_range(rects.0.height, 256.0, 0.001), true);

        assert_eq!(check_range(rects.1.x, 0.0, 0.001), true);
        assert_eq!(check_range(rects.1.y, 256.0, 0.001), true);
        assert_eq!(check_range(rects.1.width, 1024.0, 0.001), true);
        assert_eq!(check_range(rects.1.height, 768.0, 0.001), true);
    }

    #[test]
    fn test_calc_rect_horz_25_per_2() {
        let rects = Workspace::calc_horizontal_sizing(Rect::new(16.0, 32.0, 512.0, 1024.0), 0.25);

        assert_eq!(check_range(rects.0.x, 16.0, 0.001), true);
        assert_eq!(check_range(rects.0.y, 32.0, 0.001), true);
        assert_eq!(check_range(rects.0.width, 512.0, 0.001), true);
        assert_eq!(check_range(rects.0.height, 256.0, 0.001), true);

        assert_eq!(check_range(rects.1.x, 32.0, 0.001), true);
        assert_eq!(check_range(rects.1.y, 288.0, 0.001), true);
        assert_eq!(check_range(rects.1.width, 512.0, 0.001), true);
        assert_eq!(check_range(rects.1.height, 768.0, 0.001), true);
    }
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/async-dnssd/0.4.0")]
#![warn(missing_docs)]
//! # Asynchronous wrapper for DNS-SD C libraries
//!
//! Interesting entry points:
//!
//! * [Browse for available services][`browse`]
//! * [Create Connection to register records with][`connect`]
//! * [Enumerate domains that are recommended for registration or browsing][`enumerate_domains`]
//! * [Query for an arbitrary DNS record][`query_record`]
//! * [Register a service][`register`]
//! * [Add a record to a registered service][`Registration::add_record`]
//! * [Register record][`Connection::register_record`]
//! * [Find hostname and port (and more) for a service][`resolve`]
//!
//! Also the following things might be interesting:
//!
//! * [Purge record from cache][`reconfirm_record`]
//! * [Construct full name][`FullName::construct`]
//! * [Stream timeouts][`TimeoutStream`]
//!
//! ## Porting from dnssd C API
//!
//! | C API                           | functionality in this crate                                  |
//! |---------------------------------|--------------------------------------------------------------|
//! | [`DNSServiceAddRecord`]         | [`Registration::add_record`], [`Register::add_record`]       |
//! | [`DNSServiceBrowse`]            | [`browse`]                                                   |
//! | [`DNSServiceConstructFullName`] | [`FullName::construct`]                                      |
//! | [`DNSServiceCreateConnection`]  | [`connect`]                                                  |
//! | [`DNSServiceEnumerateDomains`]  | [`enumerate_domains`]                                        |
//! | [`DNSServiceQueryRecord`]       | [`query_record`]                                             |
//! | [`DNSServiceReconfirmRecord`]   | [`reconfirm_record`]                                         |
//! | [`DNSServiceRegister`]          | [`register`]                                                 |
//! | [`DNSServiceRegisterRecord`]    | [`Connection::register_record`]                              |
//! | [`DNSServiceResolve`]           | [`resolve`]                                                  |
//! | [`DNSServiceUpdateRecord`]      | [`Record::update_record`], [`RegisterRecord::update_record`] |
//!
//! The following functions are called automatically when needed:
//! * [`DNSServiceProcessResult`] driving callbacks (event loop)
//! * [`DNSServiceRefDeallocate`] called when dropping various resource handles
//! * [`DNSServiceRefSockFD`] used for integration with tokio (event loop)
//! * [`DNSServiceRemoveRecord`] called when dropping [`Record`](struct.Record.html)
//!
//! The `TXTRecord*` "TXT Record Construction Functions" are not
//! wrapped; [`TxtRecord`] provides a native rust implementation with
//! similar functionality.
//!
//! [`DNSServiceAddRecord`]: https://developer.apple.com/documentation/dnssd/1804730-dnsserviceaddrecord
//! [`DNSServiceBrowse`]: https://developer.apple.com/documentation/dnssd/1804742-dnsservicebrowse
//! [`DNSServiceConstructFullName`]: https://developer.apple.com/documentation/dnssd/1804753-dnsserviceconstructfullname
//! [`DNSServiceCreateConnection`]: https://developer.apple.com/documentation/dnssd/1804724-dnsservicecreateconnection
//! [`DNSServiceEnumerateDomains`]: https://developer.apple.com/documentation/dnssd/1804754-dnsserviceenumeratedomains
//! [`DNSServiceQueryRecord`]: https://developer.apple.com/documentation/dnssd/1804747-dnsservicequeryrecord
//! [`DNSServiceReconfirmRecord`]: https://developer.apple.com/documentation/dnssd/1804726-dnsservicereconfirmrecord
//! [`DNSServiceRegister`]: https://developer.apple.com/documentation/dnssd/1804733-dnsserviceregister
//! [`DNSServiceRegisterRecord`]: https://developer.apple.com/documentation/dnssd/1804727-dnsserviceregisterrecord
//! [`DNSServiceResolve`]: https://developer.apple.com/documentation/dnssd/1804744-dnsserviceresolve
//! [`DNSServiceUpdateRecord`]: https://developer.apple.com/documentation/dnssd/1804739-dnsserviceupdaterecord
//! [`DNSServiceProcessResult`]: https://developer.apple.com/documentation/dnssd/1804696-dnsserviceprocessresult
//! [`DNSServiceRefDeallocate`]: https://developer.apple.com/documentation/dnssd/1804697-dnsservicerefdeallocate
//! [`DNSServiceRefSockFD`]: https://developer.apple.com/documentation/dnssd/1804698-dnsservicerefsockfd
//! [`DNSServiceRemoveRecord`]: https://developer.apple.com/documentation/dnssd/1804736-dnsserviceremoverecord
//! [`Registration::add_record`]: struct.Registration.html#method.add_record
//! [`Register::add_record`]: struct.Register.html#method.add_record
//! [`browse`]: fn.browse.html
//! [`FullName::construct`]: struct.FullName.html#method.construct
//! [`connect`]: fn.connect.html
//! [`enumerate_domains`]: fn.enumerate_domains.html
//! [`query_record`]: fn.query_record.html
//! [`reconfirm_record`]: fn.reconfirm_record.html
//! [`register`]: fn.register.html
//! [`Connection::register_record`]: struct.Connection.html#method.register_record
//! [`resolve`]: fn.resolve.html
//! [`Record::update_record`]: struct.Record.html#method.update_record
//! [`RegisterRecord::update_record`]: struct.RegisterRecord.html#method.update_record
//! [`TimeoutStream`]: struct.TimeoutStream.html
//! [`TxtRecord`]: struct.TxtRecord.html

pub use self::{
	dns_consts::{
		Class,
		Type,
	},
	error::Error,
	ffi::MAX_DOMAIN_NAME,
	interface::{
		Interface,
		InterfaceIndex,
	},
	service::*,
	timeout_stream::{
		StreamTimeoutExt,
		TimeoutStream,
		TimeoutStreamError,
	},
	txt_record::{
		TxtRecord,
		TxtRecordError,
		TxtRecordIter,
	},
};

mod cstr;
mod dns_consts;
mod error;
mod evented;
mod ffi;
mod future;
mod interface;
mod raw;
mod service;
mod stream;
mod timeout_stream;
mod txt_record;

fn init() {
	#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
	{
		use std::sync::Once;

		static INIT: Once = Once::new();
		INIT.call_once(|| {
			const AVAHI_COMPAT_NOWARN: &str = "AVAHI_COMPAT_NOWARN";
			if std::env::var_os(AVAHI_COMPAT_NOWARN).is_none() {
				std::env::set_var(AVAHI_COMPAT_NOWARN, "1");
			}
		});
	}
}
<commit_msg>edition 2018: enable idiom warnings<commit_after>#![doc(html_root_url = "https://docs.rs/async-dnssd/0.4.0")]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
//! # Asynchronous wrapper for DNS-SD C libraries
//!
//! Interesting entry points:
//!
//! * [Browse for available services][`browse`]
//! * [Create Connection to register records with][`connect`]
//! * [Enumerate domains that are recommended for registration or browsing][`enumerate_domains`]
//! * [Query for an arbitrary DNS record][`query_record`]
//! * [Register a service][`register`]
//! * [Add a record to a registered service][`Registration::add_record`]
//! * [Register record][`Connection::register_record`]
//! * [Find hostname and port (and more) for a service][`resolve`]
//!
//! Also the following things might be interesting:
//!
//! * [Purge record from cache][`reconfirm_record`]
//! * [Construct full name][`FullName::construct`]
//! * [Stream timeouts][`TimeoutStream`]
//!
//! ## Porting from dnssd C API
//!
//! | C API                           | functionality in this crate                                  |
//! |---------------------------------|--------------------------------------------------------------|
//! | [`DNSServiceAddRecord`]         | [`Registration::add_record`], [`Register::add_record`]       |
//! | [`DNSServiceBrowse`]            | [`browse`]                                                   |
//! | [`DNSServiceConstructFullName`] | [`FullName::construct`]                                      |
//! | [`DNSServiceCreateConnection`]  | [`connect`]                                                  |
//! | [`DNSServiceEnumerateDomains`]  | [`enumerate_domains`]                                        |
//! | [`DNSServiceQueryRecord`]       | [`query_record`]                                             |
//! | [`DNSServiceReconfirmRecord`]   | [`reconfirm_record`]                                         |
//! | [`DNSServiceRegister`]          | [`register`]                                                 |
//! | [`DNSServiceRegisterRecord`]    | [`Connection::register_record`]                              |
//! | [`DNSServiceResolve`]           | [`resolve`]                                                  |
//! | [`DNSServiceUpdateRecord`]      | [`Record::update_record`], [`RegisterRecord::update_record`] |
//!
//! The following functions are called automatically when needed:
//! * [`DNSServiceProcessResult`] driving callbacks (event loop)
//! * [`DNSServiceRefDeallocate`] called when dropping various resource handles
//! * [`DNSServiceRefSockFD`] used for integration with tokio (event loop)
//! * [`DNSServiceRemoveRecord`] called when dropping [`Record`](struct.Record.html)
//!
//! The `TXTRecord*` "TXT Record Construction Functions" are not
//! wrapped; [`TxtRecord`] provides a native rust implementation with
//! similar functionality.
//!
//! [`DNSServiceAddRecord`]: https://developer.apple.com/documentation/dnssd/1804730-dnsserviceaddrecord
//! [`DNSServiceBrowse`]: https://developer.apple.com/documentation/dnssd/1804742-dnsservicebrowse
//! [`DNSServiceConstructFullName`]: https://developer.apple.com/documentation/dnssd/1804753-dnsserviceconstructfullname
//! [`DNSServiceCreateConnection`]: https://developer.apple.com/documentation/dnssd/1804724-dnsservicecreateconnection
//! [`DNSServiceEnumerateDomains`]: https://developer.apple.com/documentation/dnssd/1804754-dnsserviceenumeratedomains
//! [`DNSServiceQueryRecord`]: https://developer.apple.com/documentation/dnssd/1804747-dnsservicequeryrecord
//! [`DNSServiceReconfirmRecord`]: https://developer.apple.com/documentation/dnssd/1804726-dnsservicereconfirmrecord
//! [`DNSServiceRegister`]: https://developer.apple.com/documentation/dnssd/1804733-dnsserviceregister
//! [`DNSServiceRegisterRecord`]: https://developer.apple.com/documentation/dnssd/1804727-dnsserviceregisterrecord
//! [`DNSServiceResolve`]: https://developer.apple.com/documentation/dnssd/1804744-dnsserviceresolve
//! [`DNSServiceUpdateRecord`]: https://developer.apple.com/documentation/dnssd/1804739-dnsserviceupdaterecord
//! [`DNSServiceProcessResult`]: https://developer.apple.com/documentation/dnssd/1804696-dnsserviceprocessresult
//! [`DNSServiceRefDeallocate`]: https://developer.apple.com/documentation/dnssd/1804697-dnsservicerefdeallocate
//! [`DNSServiceRefSockFD`]: https://developer.apple.com/documentation/dnssd/1804698-dnsservicerefsockfd
//! [`DNSServiceRemoveRecord`]: https://developer.apple.com/documentation/dnssd/1804736-dnsserviceremoverecord
//! [`Registration::add_record`]: struct.Registration.html#method.add_record
//! [`Register::add_record`]: struct.Register.html#method.add_record
//! [`browse`]: fn.browse.html
//! [`FullName::construct`]: struct.FullName.html#method.construct
//! [`connect`]: fn.connect.html
//! [`enumerate_domains`]: fn.enumerate_domains.html
//! [`query_record`]: fn.query_record.html
//! [`reconfirm_record`]: fn.reconfirm_record.html
//! [`register`]: fn.register.html
//! [`Connection::register_record`]: struct.Connection.html#method.register_record
//! [`resolve`]: fn.resolve.html
//! [`Record::update_record`]: struct.Record.html#method.update_record
//! [`RegisterRecord::update_record`]: struct.RegisterRecord.html#method.update_record
//! [`TimeoutStream`]: struct.TimeoutStream.html
//! [`TxtRecord`]: struct.TxtRecord.html

pub use self::{
	dns_consts::{
		Class,
		Type,
	},
	error::Error,
	ffi::MAX_DOMAIN_NAME,
	interface::{
		Interface,
		InterfaceIndex,
	},
	service::*,
	timeout_stream::{
		StreamTimeoutExt,
		TimeoutStream,
		TimeoutStreamError,
	},
	txt_record::{
		TxtRecord,
		TxtRecordError,
		TxtRecordIter,
	},
};

mod cstr;
mod dns_consts;
mod error;
mod evented;
mod ffi;
mod future;
mod interface;
mod raw;
mod service;
mod stream;
mod timeout_stream;
mod txt_record;

fn init() {
	#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
	{
		use std::sync::Once;

		static INIT: Once = Once::new();
		INIT.call_once(|| {
			const AVAHI_COMPAT_NOWARN: &str = "AVAHI_COMPAT_NOWARN";
			if std::env::var_os(AVAHI_COMPAT_NOWARN).is_none() {
				std::env::set_var(AVAHI_COMPAT_NOWARN, "1");
			}
		});
	}
}
<|endoftext|>


<commit_before>//! An XML-RPC implementation in Rust.
//!
//! The `xmlrpc` crate provides a minimal implementation of the [XML-RPC specification].
//!
//! [XML-RPC specification]: http://xmlrpc.scripting.com/spec.html

#![doc(html_root_url = "https://docs.rs/xmlrpc/0.11.1")]
#![warn(missing_debug_implementations)]

extern crate base64;
extern crate iso8601;
extern crate xml;

mod error;
mod parser;
mod request;
mod value;
mod utils;
mod transport;

pub use error::{Error, Fault};
pub use request::Request;
pub use value::{Value, Index};
pub use transport::Transport;

#[cfg(feature = "reqwest")]
pub use transport::http;
<commit_msg>Warn for missing docs<commit_after>//! An XML-RPC implementation in Rust.
//!
//! The `xmlrpc` crate provides a minimal implementation of the [XML-RPC specification].
//!
//! [XML-RPC specification]: http://xmlrpc.scripting.com/spec.html

#![doc(html_root_url = "https://docs.rs/xmlrpc/0.11.1")]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]

extern crate base64;
extern crate iso8601;
extern crate xml;

mod error;
mod parser;
mod request;
mod value;
mod utils;
mod transport;

pub use error::{Error, Fault};
pub use request::Request;
pub use value::{Value, Index};
pub use transport::Transport;

#[cfg(feature = "reqwest")]
pub use transport::http;
<|endoftext|>


<commit_before>//! # rdf-rs
//!
//! A crate for the Resource Description Framework (RDF) and SPARQL.
//!
//! todo
//!
//! ## Usage
//!
//! todo

use std::result;

pub mod uri;
pub mod namespace;
pub mod node;
pub mod triple;
pub mod graph;
pub mod error;

pub type Result<T> = result::Result<T, error::Error>;

pub mod writer {
  pub mod formatter {
    pub mod rdf_formatter;
    pub mod turtle_formatter;
    pub mod n_triples_formatter;
  }

  pub mod rdf_writer;
  pub mod turtle_writer;
  pub mod n_triples_writer;
}

pub mod reader {
  pub mod lexer {
    pub mod token;
    pub mod rdf_lexer;
    pub mod n_triples_lexer;
    pub mod turtle_lexer;
  }

  pub mod rdf_parser;
  pub mod n_triples_parser;
  pub mod turtle_parser;
  pub mod input_reader;
}

pub mod specs {
  pub mod xml_specs;
  pub mod turtle_specs;
  pub mod rdf_syntax_specs;
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Add crate description with basic usage examples<commit_after>//! # rdf-rs
//!
//! A crate for the Resource Description Framework (RDF) and SPARQL.
//!
//! ---
//!
//! This crate enables to parse certain RDF formats to an RDF graph, as well as writing
//! an RDF graph as RDF syntax.
//!
//! Currently supported RDF formats are:
//!
//! * Turtle
//! * N-Triples
//!
//!
//! ## Usage
//!
//! Each module contains a comprehensive documentation with usage examples.
//! In the following, only the basic functionality is introduced.
//!
//! RDF triples can be stored and represented in a graph.
//!
//! ```
//! use rdf_rs::graph::Graph;
//! use rdf_rs::uri::Uri;
//! use rdf_rs::triple::Triple;
//!
//! let mut graph = Graph::new(None);
//!
//! let subject = graph.create_blank_node();
//! let predicate = graph.create_uri_node(&Uri::new("http://example.org/show/localName".to_string()));
//! let object = graph.create_blank_node();
//! let triple = Triple::new(&subject, &predicate, &object);
//!
//! graph.add_triple(&triple);
//! ```
//!
//! RDF graphs can be serialized to a supported format.
//!
//! ```
//! use rdf_rs::writer::n_triples_writer::NTriplesWriter;
//! use rdf_rs::writer::rdf_writer::RdfWriter;
//! use rdf_rs::graph::Graph;
//! use rdf_rs::uri::Uri;
//! use rdf_rs::triple::Triple;
//!
//! let writer = NTriplesWriter::new();
//!
//! let mut graph = Graph::new(None);
//! let subject = graph.create_blank_node();
//! let predicate = graph.create_uri_node(&Uri::new("http://example.org/show/localName".to_string()));
//! let object = graph.create_blank_node();
//! let triple = Triple::new(&subject, &predicate, &object);
//!
//! graph.add_triple(&triple);
//!
//! assert_eq!(writer.write_to_string(&graph).unwrap(),
//!            "_:auto0 <http://example.org/show/localName> _:auto1 .\n".to_string());
//! ```
//!
//! RDF syntax can also be parsed and transformed into an RDF graph.
//!
//! ```
//! use rdf_rs::reader::turtle_parser::TurtleParser;
//! use rdf_rs::reader::rdf_parser::RdfParser;
//! use rdf_rs::uri::Uri;
//!
//! let input = "@base <http://example.org/> .
//! @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
//! @prefix foaf: <http://xmlns.com/foaf/0.1/> .
//!
//! <http://www.w3.org/2001/sw/RDFCore/ntriples/> rdf:type foaf:Document ;
//! <http://purl.org/dc/terms/title> \"N-Triples\"@en-US ;
//! foaf:maker _:art .";
//!
//! let mut reader = TurtleParser::from_string(input.to_string());
//!
//! match reader.decode() {
//!   Ok(graph) => {
//!     assert_eq!(graph.count(), 3);
//!     assert_eq!(graph.namespaces().len(), 2);
//!     assert_eq!(graph.base_uri(), &Some(Uri::new("http://example.org/".to_string())))
//!   },
//!   Err(_) => assert!(false)
//! }
//! ```

use std::result;

pub mod uri;
pub mod namespace;
pub mod node;
pub mod triple;
pub mod graph;
pub mod error;

pub type Result<T> = result::Result<T, error::Error>;

pub mod writer {
  pub mod formatter {
    pub mod rdf_formatter;
    pub mod turtle_formatter;
    pub mod n_triples_formatter;
  }

  pub mod rdf_writer;
  pub mod turtle_writer;
  pub mod n_triples_writer;
}

pub mod reader {
  pub mod lexer {
    pub mod token;
    pub mod rdf_lexer;
    pub mod n_triples_lexer;
    pub mod turtle_lexer;
  }

  pub mod rdf_parser;
  pub mod n_triples_parser;
  pub mod turtle_parser;
  pub mod input_reader;
}

pub mod specs {
  pub mod xml_specs;
  pub mod turtle_specs;
  pub mod rdf_syntax_specs;
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>