<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

#![feature(plugin)]
#![plugin(tarpc_plugins)]

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate tarpc;
extern crate env_logger;
extern crate futures;
extern crate serde;
extern crate tokio_core;

use std::io::{Read, Write, stdout};
use std::net;
use std::sync::Arc;
use std::thread;
use std::time;
use tarpc::{client, server};
use tarpc::client::sync::ClientExt;
use tarpc::util::{FirstSocketAddr, Never};
use tokio_core::reactor;

lazy_static! {
    static ref BUF: Arc<serde::bytes::ByteBuf> = Arc::new(gen_vec(CHUNK_SIZE as usize).into());
}

fn gen_vec(size: usize) -> Vec<u8> {
    let mut vec: Vec<u8> = Vec::with_capacity(size);
    for i in 0..size {
        vec.push(((i % 2) << 8) as u8);
    }
    vec
}

service! {
    rpc read() -> Arc<serde::bytes::ByteBuf>;
}

#[derive(Clone)]
struct Server;

impl FutureService for Server {
    type ReadFut = Result<Arc<serde::bytes::ByteBuf>, Never>;

    fn read(&self) -> Self::ReadFut {
        Ok(BUF.clone())
    }
}

const CHUNK_SIZE: u32 = 1 << 19;

fn bench_tarpc(target: u64) {
    let reactor = reactor::Core::new().unwrap();
    let (addr, server) = Server.listen("localhost:0".first_socket_addr(),
                &reactor.handle(),
                server::Options::default())
        .unwrap();
    reactor.handle().spawn(server);
    let mut client = SyncClient::connect(addr, client::Options::default()).unwrap();
    let start = time::Instant::now();
    let mut nread = 0;
    while nread < target {
        nread += client.read().unwrap().len() as u64;
        print!(".");
        stdout().flush().unwrap();
    }
    println!("done");
    let duration = time::Instant::now() - start;
    println!("TARPC: {}MB/s",
             (target as f64 / (1024f64 * 1024f64)) /
             (duration.as_secs() as f64 + duration.subsec_nanos() as f64 / 10E9));
}

fn bench_tcp(target: u64) {
    let l = net::TcpListener::bind("localhost:0").unwrap();
    let addr = l.local_addr().unwrap();
    thread::spawn(move || {
        let (mut stream, _) = l.accept().unwrap();
        while let Ok(_) = stream.write_all(&*BUF) {}
    });
    let mut stream = net::TcpStream::connect(&addr).unwrap();
    let mut buf = vec![0; CHUNK_SIZE as usize];
    let start = time::Instant::now();
    let mut nread = 0;
    while nread < target {
        stream.read_exact(&mut buf[..]).unwrap();
        nread += CHUNK_SIZE as u64;
        print!(".");
        stdout().flush().unwrap();
    }
    println!("done");
    let duration = time::Instant::now() - start;
    println!("TCP:   {}MB/s",
             (target as f64 / (1024f64 * 1024f64)) /
             (duration.as_secs() as f64 + duration.subsec_nanos() as f64 / 10E9));
}

fn main() {
    let _ = env_logger::init();
    let _ = *BUF; // To non-lazily initialize it.
    bench_tcp(256 << 20);
    bench_tarpc(256 << 20);
}
<commit_msg>Actually run the server future<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

#![feature(plugin)]
#![plugin(tarpc_plugins)]

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate tarpc;
extern crate env_logger;
extern crate futures;
extern crate serde;
extern crate tokio_core;

use std::io::{Read, Write, stdout};
use std::net;
use std::sync::Arc;
use std::sync::mpsc;
use std::thread;
use std::time;
use tarpc::{client, server};
use tarpc::client::sync::ClientExt;
use tarpc::util::{FirstSocketAddr, Never};
use tokio_core::reactor;

lazy_static! {
    static ref BUF: Arc<serde::bytes::ByteBuf> = Arc::new(gen_vec(CHUNK_SIZE as usize).into());
}

fn gen_vec(size: usize) -> Vec<u8> {
    let mut vec: Vec<u8> = Vec::with_capacity(size);
    for i in 0..size {
        vec.push(((i % 2) << 8) as u8);
    }
    vec
}

service! {
    rpc read() -> Arc<serde::bytes::ByteBuf>;
}

#[derive(Clone)]
struct Server;

impl FutureService for Server {
    type ReadFut = Result<Arc<serde::bytes::ByteBuf>, Never>;

    fn read(&self) -> Self::ReadFut {
        Ok(BUF.clone())
    }
}

const CHUNK_SIZE: u32 = 1 << 19;

fn bench_tarpc(target: u64) {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let mut reactor = reactor::Core::new().unwrap();
        let (addr, server) = Server.listen("localhost:0".first_socket_addr(),
                    &reactor.handle(),
                    server::Options::default())
            .unwrap();
        tx.send(addr).unwrap();
        reactor.run(server).unwrap();
    });
    let mut client = SyncClient::connect(rx.recv().unwrap(), client::Options::default()).unwrap();
    let start = time::Instant::now();
    let mut nread = 0;
    while nread < target {
        nread += client.read().unwrap().len() as u64;
        print!(".");
        stdout().flush().unwrap();
    }
    println!("done");
    let duration = time::Instant::now() - start;
    println!("TARPC: {}MB/s",
             (target as f64 / (1024f64 * 1024f64)) /
             (duration.as_secs() as f64 + duration.subsec_nanos() as f64 / 10E9));
}

fn bench_tcp(target: u64) {
    let l = net::TcpListener::bind("localhost:0").unwrap();
    let addr = l.local_addr().unwrap();
    thread::spawn(move || {
        let (mut stream, _) = l.accept().unwrap();
        while let Ok(_) = stream.write_all(&*BUF) {}
    });
    let mut stream = net::TcpStream::connect(&addr).unwrap();
    let mut buf = vec![0; CHUNK_SIZE as usize];
    let start = time::Instant::now();
    let mut nread = 0;
    while nread < target {
        stream.read_exact(&mut buf[..]).unwrap();
        nread += CHUNK_SIZE as u64;
        print!(".");
        stdout().flush().unwrap();
    }
    println!("done");
    let duration = time::Instant::now() - start;
    println!("TCP:   {}MB/s",
             (target as f64 / (1024f64 * 1024f64)) /
             (duration.as_secs() as f64 + duration.subsec_nanos() as f64 / 10E9));
}

fn main() {
    let _ = env_logger::init();
    let _ = *BUF; // To non-lazily initialize it.
    bench_tcp(256 << 20);
    bench_tarpc(256 << 20);
}
<|endoftext|>


<commit_before>// This file is part of Twig (ported to Rust).
//
// For the copyright and license information, please view the LICENSE
// file that was distributed with this source code.

//! Twig Error Handling
//!
//! # Examples
//!
//! ```rust,macro_test
//! #[macro_use] extern crate twig; // Macros must be imported *explicitly*
//!
//! use std::fmt;
//! use twig::api::error::Traced;
//! use std::error::Error;
//!
//! // Implement a custom error code.
//! type MyTracedSimpleError = Traced<MySimpleError>;
//!
//! #[derive(Debug)]
//! enum MySimpleError {
//!     Critical,
//!     Recoverable
//! }
//!
//! impl Error for MySimpleError {
//!     fn description(&self) -> &str {
//!         match *self {
//!             MySimpleError::Critical => "Critical error.",
//!             MySimpleError::Recoverable => "Recoverable error."
//!         }
//!     }
//! }
//!
//! impl fmt::Display for MySimpleError {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f, "{} With human readable details", self.description())
//!     }
//! }
//!
//! fn main() {
//!     // Create a twig error, wrapping this error code + code location.
//!     let result: Result<(), Traced<MySimpleError>> = traced_err!(MySimpleError::Critical);
//!
//!     if let Err(error) = result {
//!         assert!(error.to_string().starts_with("Critical error. With human readable details at <anon>:"));
//!     }
//! }
//! ```

#[macro_use] mod macros;
use std::fmt::{self, Debug, Display};
use std::error::Error; // use std Error-trait to improve cross-crate compatibility
use std::ops::{Deref, DerefMut};

/// Extension trait for std::error::Error
///
/// adds conversion to `Traced` error
pub trait ErrorExt: Error {
    /// Returns generic twig error for this error code.
    /// You must provide the location, where the error occured.
    fn at(self, location: Location) -> Traced<Self>
        where Self: Sized
    {
        Traced::new(self, location)
    }
}

impl<T> ErrorExt for T where T: Error {}

/// Record current state of complex objects
///
/// The purpose of a dump is to be wrapped in error codes instead of complex objects.
/// This abstraction allows to
/// * keep error codes free of any lifetimes
/// * maintain the ability of receiver of error codes to decide about verbosity
///
/// The Dump::Data type may not contain lifetimes.
/// In practice this means cloning all referenced data into the dump.
///
/// For a type `X: Dump` you can reference the associated dump type via `<X as Dump>::Data`.
pub trait Dump {
    type Data: Debug + Display + 'static;

    fn dump(&self) -> Self::Data;
}

/// Generic twig error
///
/// Wrapper around some `ErrorCode` - adds location support and error-chaining.
pub struct Traced<T>
    where T: Error
{
    // the error codes are going to be structured enums
    error: T,

    /// Backtrace
    trace: Trace,
}

impl<T> Traced<T> where
    T: Error
{
    /// Create a new twig error out of some generic error code.
    ///
    /// # Examples
    ///
    /// ```
    /// # #[macro_use] extern crate twig;
    /// # fn main() {
    /// use twig::api::error;
    /// use std::env::VarError;
    ///
    /// error::Traced::new(VarError::NotPresent, loc!()); // shorthand: `trace!(VarError::NotPresent)`
    /// # }
    /// ```
    pub fn new(error: T, location: Location) -> Traced<T> {
        Traced {
            error: error,
            trace: Trace(vec![location]),
        }
    }

    /// Return the associated error code.
    #[allow(dead_code)] // only used by tests
    pub fn error(&self) -> &T {
        &self.error
    }

    /// Return the first location the error occured.
    pub fn location(&self) -> Option<&Location> {
        self.trace.first()
    }

    pub fn backtrace(&self) -> &[Location] {
        &self.trace
    }

    // should not name it `at`, because `Traced` implements `ErrorExt`, too
    pub fn trace<R>(self, loc: Location) -> Traced<R>
        where T: Into<R>,
              R: Error
    {
        let Traced { error, mut trace } = self;
        trace.push(loc);

        Traced {
            error: error.into(),
            trace: trace
        }
    }

    /// Creates an iterator to iterate along the error cause-chain.
    pub fn iter(&self) -> ErrorIter {
        ErrorIter {
            next: Some(&self.error),
        }
    }
}

// delegate to inner error
impl<T> Error for Traced<T> where
    T: Error
{
    fn description(&self) -> &str {
        &self.error.description()
    }

    fn cause<'a>(&'a self) -> Option<&'a Error> {
        self.error.cause()
    }
}

/// Iterator to iterate along the error cause-chain.
pub struct ErrorIter<'a> {
    next: Option<&'a Error>
}

impl<'a> Iterator for ErrorIter<'a> {
    type Item = &'a Error;

    fn next(&mut self) -> Option<Self::Item> {
        return match self.next {
            Some(err) => {
                self.next = err.cause();
                Some(err)
            }
            None => None,
        }
    }
}

impl<T> Debug for Traced<T> where
    T: Error
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        f.debug_struct("Traced")
            .field("error", &self.error)
            .field("at", &self.trace)
            .finish()
    }
}

impl<T> Display for Traced<T> where
    T: Error
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{error} at {trace}\n",
            error = self.error,
            trace = &self.trace)
    }
}

/// Trace wraps `Vec<Location>`  with specialized `Display` and `Debug` impls.
///
/// For everything else it just derefs to `Vec<Location>`.
pub struct Trace(Vec<Location>);

impl Deref for Trace {
    type Target = Vec<Location>;

    fn deref(&self) -> &Self::Target {
        let Trace(ref trace) = *self;

        trace
    }
}

impl DerefMut for Trace {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let Trace(ref mut trace) = *self;

        trace
    }
}

impl Debug for Trace {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.iter().enumerate().fold(
            &mut f.debug_struct("Trace"),
            |s, i| s.field(&format!("#{}", i.0), i.1)
        ).finish()
    }
}

impl Display for Trace {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.first() {
            Some(location) => write!(f, "{:?}", location),
            None =>  write!(f, "unknown (no backtrace)")
        }
    }
}

/// Location in rust source code
///
/// Debug::fmt() output is formatted in a compact way: `"{filename}:{line}:{column}"`.
#[derive(PartialEq)]
pub struct Location {
    pub filename : &'static str,    // e.g. /src/lexer/job/state/shared_traits.rs
    pub line : u32,
    pub column : u32,
}

impl Debug for Location {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{filename}:{line}:{column}",
            filename = self.filename,
            line     = self.line,
            column   = self.column)
    }
}
<commit_msg>cleanup<commit_after>// This file is part of Twig (ported to Rust).
//
// For the copyright and license information, please view the LICENSE
// file that was distributed with this source code.

//! Twig Error Handling
//!
//! # Examples
//!
//! ```rust,macro_test
//! #[macro_use] extern crate twig; // Macros must be imported *explicitly*
//!
//! use std::fmt;
//! use twig::api::error::Traced;
//! use std::error::Error;
//!
//! // Implement a custom error code.
//! type MyTracedSimpleError = Traced<MySimpleError>;
//!
//! #[derive(Debug)]
//! enum MySimpleError {
//!     Critical,
//!     Recoverable
//! }
//!
//! impl Error for MySimpleError {
//!     fn description(&self) -> &str {
//!         match *self {
//!             MySimpleError::Critical => "Critical error.",
//!             MySimpleError::Recoverable => "Recoverable error."
//!         }
//!     }
//! }
//!
//! impl fmt::Display for MySimpleError {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f, "{} With human readable details", self.description())
//!     }
//! }
//!
//! fn main() {
//!     // Create a twig error, wrapping this error code + code location.
//!     let result: Result<(), Traced<MySimpleError>> = traced_err!(MySimpleError::Critical);
//!
//!     if let Err(error) = result {
//!         assert!(error.to_string().starts_with("Critical error. With human readable details at <anon>:"));
//!     }
//! }
//! ```

#[macro_use] mod macros;
use std::fmt::{self, Debug, Display};
use std::error::Error; // use std Error-trait to improve cross-crate compatibility
use std::ops::{Deref, DerefMut};

/// Extension trait for std::error::Error
///
/// adds conversion to `Traced` error
pub trait ErrorExt: Error {
    /// Returns generic twig error for this error code.
    /// You must provide the location, where the error occured.
    fn at(self, location: Location) -> Traced<Self>
        where Self: Sized
    {
        Traced::new(self, location)
    }
}

impl<T> ErrorExt for T where T: Error {}

/// Record current state of complex objects
///
/// The purpose of a dump is to be wrapped in error codes instead of complex objects.
/// This abstraction allows to
/// * keep error codes free of any lifetimes
/// * maintain the ability of receiver of error codes to decide about verbosity
///
/// The Dump::Data type may not contain lifetimes.
/// In practice this means cloning all referenced data into the dump.
///
/// For a type `X: Dump` you can reference the associated dump type via `<X as Dump>::Data`.
pub trait Dump {
    type Data: Debug + Display + 'static;

    fn dump(&self) -> Self::Data;
}

/// Generic error with backtrace.
///
/// Wrapper around some error type `T` implementing `std::error::Error`.
/// * Adds support for a backtrace.
/// * Automatically derefs to the inner error.
pub struct Traced<T>
    where T: Error
{
    // the error codes are going to be structured enums
    error: T,

    /// Backtrace
    trace: Trace,
}

impl<T> Traced<T> where
    T: Error
{
    /// Create a new twig error out of some generic error code.
    ///
    /// # Examples
    ///
    /// ```
    /// # #[macro_use] extern crate twig;
    /// # fn main() {
    /// use twig::api::error;
    /// use std::env::VarError;
    ///
    /// error::Traced::new(VarError::NotPresent, loc!()); // shorthand: `trace!(VarError::NotPresent)`
    /// # }
    /// ```
    pub fn new(error: T, location: Location) -> Traced<T> {
        Traced {
            error: error,
            trace: Trace(vec![location]),
        }
    }

    /// Return the first location the error occured.
    pub fn location(&self) -> Option<&Location> {
        self.trace.first()
    }

    pub fn backtrace(&self) -> &[Location] {
        &self.trace
    }

    // should not name it `at`, because `Traced` derefs to `Error` which impl `ErrorExt::at()`
    pub fn trace<R>(self, loc: Location) -> Traced<R>
        where T: Into<R>,
              R: Error
    {
        let Traced { error, mut trace } = self;
        trace.push(loc);

        Traced {
            error: error.into(),
            trace: trace
        }
    }

    /// Creates an iterator to iterate along the error cause-chain.
    pub fn iter(&self) -> ErrorIter {
        ErrorIter {
            next: Some(&self.error),
        }
    }
}

impl<T> Deref for Traced<T> where
    T: Error
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.error
    }
}

/// Iterator to iterate along the error cause-chain.
pub struct ErrorIter<'a> {
    next: Option<&'a Error>
}

impl<'a> Iterator for ErrorIter<'a> {
    type Item = &'a Error;

    fn next(&mut self) -> Option<Self::Item> {
        return match self.next {
            Some(err) => {
                self.next = err.cause();
                Some(err)
            }
            None => None,
        }
    }
}

impl<T> Debug for Traced<T> where
    T: Error
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        f.debug_struct("Traced")
            .field("error", &self.error)
            .field("at", &self.trace)
            .finish()
    }
}

impl<T> Display for Traced<T> where
    T: Error
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{error} at {trace}\n",
            error = self.error,
            trace = &self.trace)
    }
}

/// Trace wraps `Vec<Location>`  with specialized `Display` and `Debug` impls.
///
/// For everything else it just derefs to `Vec<Location>`.
pub struct Trace(Vec<Location>);

impl Deref for Trace {
    type Target = Vec<Location>;

    fn deref(&self) -> &Self::Target {
        let Trace(ref trace) = *self;

        trace
    }
}

impl DerefMut for Trace {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let Trace(ref mut trace) = *self;

        trace
    }
}

impl Debug for Trace {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.iter().enumerate().fold(
            &mut f.debug_struct("Trace"),
            |s, i| s.field(&format!("#{}", i.0), i.1)
        ).finish()
    }
}

impl Display for Trace {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.first() {
            Some(location) => write!(f, "{:?}", location),
            None =>  write!(f, "unknown (no backtrace)")
        }
    }
}

/// Location in rust source code
///
/// Debug::fmt() output is formatted in a compact way: `"{filename}:{line}:{column}"`.
#[derive(PartialEq)]
pub struct Location {
    pub filename : &'static str,    // e.g. /src/lexer/job/state/shared_traits.rs
    pub line : u32,
    pub column : u32,
}

impl Debug for Location {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{filename}:{line}:{column}",
            filename = self.filename,
            line     = self.line,
            column   = self.column)
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017-2018 Ben Ashford
 *
 * 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.
 */

use std::collections::VecDeque;
use std::mem;
use std::net::SocketAddr;

use futures::{
    future, future::Either, sync::{mpsc, oneshot}, Async, AsyncSink, Future, Poll, Sink, Stream,
};

use tokio_executor::{DefaultExecutor, Executor};

use super::connect::{connect, RespConnection};
use error;
use resp;

enum SendStatus {
    Ok,
    End,
    Full(resp::RespValue, bool),
}

impl SendStatus {
    fn full(msg: resp::RespValue) -> Self {
        SendStatus::Full(msg, false)
    }
}

enum FlushStatus {
    Ok,
    Required,
}

#[derive(Debug)]
enum ReceiveStatus {
    ReadyFinished,
    ReadyMore,
    NotReady,
}

struct PairedConnectionInner {
    connection: RespConnection,
    out_rx: mpsc::UnboundedReceiver<(resp::RespValue, oneshot::Sender<resp::RespValue>)>,
    waiting: VecDeque<oneshot::Sender<resp::RespValue>>,

    send_status: SendStatus,
    flush_status: FlushStatus,
}

impl PairedConnectionInner {
    fn new(
        con: RespConnection,
        out_rx: mpsc::UnboundedReceiver<(resp::RespValue, oneshot::Sender<resp::RespValue>)>,
    ) -> Self {
        PairedConnectionInner {
            connection: con,
            out_rx: out_rx,
            waiting: VecDeque::new(),
            send_status: SendStatus::Ok,
            flush_status: FlushStatus::Ok,
        }
    }

    fn impl_start_send(&mut self, msg: resp::RespValue) -> Result<bool, ()> {
        match self
            .connection
            .start_send(msg)
            .map_err(|e| error!("Error sending message to connection: {}", e))?
        {
            AsyncSink::Ready => {
                self.send_status = SendStatus::Ok;
                self.flush_status = FlushStatus::Required;
                Ok(true)
            }
            AsyncSink::NotReady(msg) => {
                self.send_status = SendStatus::full(msg);
                self.flush_status = FlushStatus::Required;
                Ok(false)
            }
        }
    }

    fn poll_start_send(&mut self) -> Result<bool, ()> {
        let message = match self.send_status {
            SendStatus::End | SendStatus::Full(_, false) => return Ok(false),
            SendStatus::Full(ref mut msg_rf, true) => unsafe {
                mem::replace(msg_rf, mem::uninitialized())
            },
            SendStatus::Ok => match self
                .out_rx
                .poll()
                .map_err(|_| error!("Error polling for messages to send"))?
            {
                Async::Ready(Some((msg, tx))) => {
                    self.waiting.push_back(tx);
                    msg
                }
                Async::Ready(None) => {
                    self.send_status = SendStatus::End;
                    return Ok(false);
                }
                Async::NotReady => return Ok(false),
            },
        };

        self.impl_start_send(message)
    }

    fn poll_complete(&mut self) -> Result<(), ()> {
        match self.flush_status {
            FlushStatus::Ok => (),
            FlushStatus::Required => {
                match self
                    .connection
                    .poll_complete()
                    .map_err(|e| error!("Error polling for completeness: {}", e))?
                {
                    Async::Ready(()) => self.flush_status = FlushStatus::Ok,
                    Async::NotReady => (),
                }
                if let SendStatus::Full(_, ref mut post) = self.send_status {
                    if *post == false {
                        *post = true;
                    }
                }
            }
        }
        Ok(())
    }

    fn receive(&mut self) -> Result<ReceiveStatus, ()> {
        if let SendStatus::End = self.send_status {
            if self.waiting.is_empty() {
                return Ok(ReceiveStatus::ReadyFinished);
            }
        }
        match self
            .connection
            .poll()
            .map_err(|e| error!("Error polling to receive messages: {}", e))?
        {
            Async::Ready(None) => {
                error!("Connection to Redis closed unexpectedly");
                Err(())
            }
            Async::Ready(Some(msg)) => {
                let tx = match self.waiting.pop_front() {
                    Some(tx) => tx,
                    None => panic!("Received unexpected message: {:?}", msg),
                };
                let _ = tx.send(msg);
                Ok(ReceiveStatus::ReadyMore)
            }
            Async::NotReady => Ok(ReceiveStatus::NotReady),
        }
    }
}

impl Future for PairedConnectionInner {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // If there's something to send, send it...
        let mut sending = true;
        while sending {
            sending = self.poll_start_send()?;
        }

        self.poll_complete()?;

        // If there's something to receive, receive it...
        loop {
            match self.receive()? {
                ReceiveStatus::NotReady => return Ok(Async::NotReady),
                ReceiveStatus::ReadyMore => (),
                ReceiveStatus::ReadyFinished => return Ok(Async::Ready(())),
            }
        }
    }
}

/// A shareable and cheaply cloneable connection to which Redis commands can be sent
#[derive(Clone)]
pub struct PairedConnection {
    out_tx: mpsc::UnboundedSender<(resp::RespValue, oneshot::Sender<resp::RespValue>)>,
}

/// The default starting point to use most default Redis functionality.
///
/// Returns a future that resolves to a `PairedConnection`.
pub fn paired_connect(
    addr: &SocketAddr,
) -> impl Future<Item = PairedConnection, Error = error::Error> {
    connect(addr).map_err(|e| e.into()).and_then(|connection| {
        let (out_tx, out_rx) = mpsc::unbounded();
        let paired_connection_inner = Box::new(PairedConnectionInner::new(connection, out_rx));
        let mut executor = DefaultExecutor::current();

        if let Err(e) = executor.spawn(paired_connection_inner) {
            return Err(error::Error::Internal(format!(
                "Cannot spawn paired connection: {:?}",
                e
            )));
        }
        Ok(PairedConnection { out_tx })
    })
}

impl PairedConnection {
    /// Sends a command to Redis.
    ///
    /// The message must be in the format of a single RESP message, this can be constructed
    /// manually or with the `resp_array!` macro.  Returned is a future that resolves to the value
    /// returned from Redis.  The type must be one for which the `resp::FromResp` trait is defined.
    ///
    /// The future will fail for numerous reasons, including but not limited to: IO issues, conversion
    /// problems, and server-side errors being returned by Redis.
    ///
    /// Behind the scenes the message is queued up and sent to Redis asynchronously before the
    /// future is realised.  As such, it is guaranteed that messages are sent in the same order
    /// that `send` is called.
    pub fn send<T>(&self, msg: resp::RespValue) -> impl Future<Item = T, Error = error::Error>
    where
        T: resp::FromResp,
    {
        match &msg {
            &resp::RespValue::Array(_) => (),
            _ => {
                return Either::B(future::err(error::internal(
                    "Command must be a RespValue::Array",
                )))
            }
        }

        let (tx, rx) = oneshot::channel();
        if let Err(_e) = self.out_tx.unbounded_send((msg, tx)) {
            // receiving end of a channel droppped
            return Either::B(future::err(error::Error::EndOfStream));
        }

        Either::A(rx.then(|v| match v {
            Ok(v) => future::result(T::from_resp(v)),
            Err(e) => future::err(e.into()),
        }))
    }

    pub fn send_and_forget(&self, msg: resp::RespValue) {
        let _ = self.send::<resp::RespValue>(msg);
    }
}
<commit_msg>remove unsafe code<commit_after>/*
 * Copyright 2017-2018 Ben Ashford
 *
 * 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.
 */

use std::collections::VecDeque;
use std::net::SocketAddr;

use futures::{future,
              future::Either,
              sync::{mpsc, oneshot},
              Async,
              AsyncSink,
              Future,
              Poll,
              Sink,
              Stream};

use tokio_executor::{DefaultExecutor, Executor};

use super::connect::{connect, RespConnection};
use error;
use resp;

enum SendStatus {
    Ok,
    End,
    Full(resp::RespValue),
}

#[derive(Debug)]
enum ReceiveStatus {
    ReadyFinished,
    ReadyMore,
    NotReady,
}

struct PairedConnectionInner {
    connection: RespConnection,
    out_rx: mpsc::UnboundedReceiver<(resp::RespValue, oneshot::Sender<resp::RespValue>)>,
    waiting: VecDeque<oneshot::Sender<resp::RespValue>>,

    send_status: SendStatus,
}

impl PairedConnectionInner {
    fn new(
        con: RespConnection,
        out_rx: mpsc::UnboundedReceiver<(resp::RespValue, oneshot::Sender<resp::RespValue>)>,
    ) -> Self {
        PairedConnectionInner {
            connection: con,
            out_rx: out_rx,
            waiting: VecDeque::new(),
            send_status: SendStatus::Ok,
        }
    }

    fn impl_start_send(&mut self, msg: resp::RespValue) -> Result<bool, ()> {
        match self.connection
            .start_send(msg)
            .map_err(|e| error!("Error sending message to connection: {}", e))?
        {
            AsyncSink::Ready => {
                self.send_status = SendStatus::Ok;
                Ok(true)
            }
            AsyncSink::NotReady(msg) => {
                self.send_status = SendStatus::Full(msg);
                Ok(false)
            }
        }
    }

    fn poll_start_send(&mut self) -> Result<bool, ()> {
        let mut status = SendStatus::Ok;
        ::std::mem::swap(&mut status, &mut self.send_status);

        let message = match status {
            SendStatus::End => {
                self.send_status = SendStatus::End;
                return Ok(false);
            }
            SendStatus::Full(msg) => msg,
            SendStatus::Ok => match self.out_rx
                .poll()
                .map_err(|_| error!("Error polling for messages to send"))?
            {
                Async::Ready(Some((msg, tx))) => {
                    self.waiting.push_back(tx);
                    msg
                }
                Async::Ready(None) => {
                    self.send_status = SendStatus::End;
                    return Ok(false);
                }
                Async::NotReady => return Ok(false),
            },
        };

        self.impl_start_send(message)
    }

    fn poll_complete(&mut self) -> Result<(), ()> {
        self.connection
            .poll_complete()
            .map_err(|e| error!("Error polling for completeness: {}", e))?;
        Ok(())
    }

    fn receive(&mut self) -> Result<ReceiveStatus, ()> {
        if let SendStatus::End = self.send_status {
            if self.waiting.is_empty() {
                return Ok(ReceiveStatus::ReadyFinished);
            }
        }
        match self.connection
            .poll()
            .map_err(|e| error!("Error polling to receive messages: {}", e))?
        {
            Async::Ready(None) => {
                error!("Connection to Redis closed unexpectedly");
                Err(())
            }
            Async::Ready(Some(msg)) => {
                let tx = match self.waiting.pop_front() {
                    Some(tx) => tx,
                    None => panic!("Received unexpected message: {:?}", msg),
                };
                let _ = tx.send(msg);
                Ok(ReceiveStatus::ReadyMore)
            }
            Async::NotReady => Ok(ReceiveStatus::NotReady),
        }
    }
}

impl Future for PairedConnectionInner {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // If there's something to send, send it...
        let mut sending = true;
        while sending {
            sending = self.poll_start_send()?;
        }

        self.poll_complete()?;

        // If there's something to receive, receive it...
        loop {
            match self.receive()? {
                ReceiveStatus::NotReady => return Ok(Async::NotReady),
                ReceiveStatus::ReadyMore => (),
                ReceiveStatus::ReadyFinished => return Ok(Async::Ready(())),
            }
        }
    }
}

/// A shareable and cheaply cloneable connection to which Redis commands can be sent
#[derive(Clone)]
pub struct PairedConnection {
    out_tx: mpsc::UnboundedSender<(resp::RespValue, oneshot::Sender<resp::RespValue>)>,
}

/// The default starting point to use most default Redis functionality.
///
/// Returns a future that resolves to a `PairedConnection`.
pub fn paired_connect(
    addr: &SocketAddr,
) -> impl Future<Item = PairedConnection, Error = error::Error> {
    connect(addr).map_err(|e| e.into()).and_then(|connection| {
        let (out_tx, out_rx) = mpsc::unbounded();
        let paired_connection_inner = Box::new(PairedConnectionInner::new(connection, out_rx));
        let mut executor = DefaultExecutor::current();

        if let Err(e) = executor.spawn(paired_connection_inner) {
            return Err(error::Error::Internal(format!(
                "Cannot spawn paired connection: {:?}",
                e
            )));
        }
        Ok(PairedConnection { out_tx })
    })
}

impl PairedConnection {
    /// Sends a command to Redis.
    ///
    /// The message must be in the format of a single RESP message, this can be constructed
    /// manually or with the `resp_array!` macro.  Returned is a future that resolves to the value
    /// returned from Redis.  The type must be one for which the `resp::FromResp` trait is defined.
    ///
    /// The future will fail for numerous reasons, including but not limited to: IO issues, conversion
    /// problems, and server-side errors being returned by Redis.
    ///
    /// Behind the scenes the message is queued up and sent to Redis asynchronously before the
    /// future is realised.  As such, it is guaranteed that messages are sent in the same order
    /// that `send` is called.
    pub fn send<T>(&self, msg: resp::RespValue) -> impl Future<Item = T, Error = error::Error>
    where
        T: resp::FromResp,
    {
        match &msg {
            &resp::RespValue::Array(_) => (),
            _ => {
                return Either::B(future::err(error::internal(
                    "Command must be a RespValue::Array",
                )))
            }
        }

        let (tx, rx) = oneshot::channel();
        if let Err(_e) = self.out_tx.unbounded_send((msg, tx)) {
            // receiving end of a channel droppped
            return Either::B(future::err(error::Error::EndOfStream));
        }

        Either::A(rx.then(|v| match v {
            Ok(v) => future::result(T::from_resp(v)),
            Err(e) => future::err(e.into()),
        }))
    }

    pub fn send_and_forget(&self, msg: resp::RespValue) {
        let _ = self.send::<resp::RespValue>(msg);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::File;

mod lexer;
mod parser;
mod token;
mod view_writer;

fn get_file_contents() -> Result<~[u8], io::IoError> {
    let path = from_str::<Path>("src/compiler/index.rs.html").unwrap();

    File::open(&path).and_then(|file| {
        let mut file = file;
        file.read_to_end()
    })
}

fn main() {
    let contents = match get_file_contents() {
        Ok(contents) => std::str::from_utf8_owned(contents).expect("Non-utf8 source file"),
        Err(e) => fail!(e)
    };

    let mut lexer = lexer::Lexer::new(contents);
    let mut parser = parser::Parser::new(&mut lexer);
    parser.parse();

    println!("Lines: {}\nLast column: {}", parser.lexer.line, parser.lexer.column);

    //debug!("{}", parser.sections);

    view_writer::write_view(&Path::new("src/compiler/index.rs"), parser.sections.as_slice());
}
<commit_msg>Update for rust changes<commit_after>use std::io;
use std::io::File;

mod lexer;
mod parser;
mod token;
mod view_writer;

fn get_file_contents() -> Result<~str, io::IoError> {
    let path = from_str::<Path>("src/compiler/index.rs.html").unwrap();

    File::open(&path).and_then(|file| {
        let mut file = file;
        file.read_to_str()
    })
}

fn main() {
    let contents = match get_file_contents() {
        Ok(contents) => contents,
        Err(e) => fail!(e)
    };

    let mut lexer = lexer::Lexer::new(contents);
    let mut parser = parser::Parser::new(&mut lexer);
    parser.parse();

    println!("Lines: {}\nLast column: {}", parser.lexer.line, parser.lexer.column);

    //debug!("{}", parser.sections);

    view_writer::write_view(&Path::new("src/compiler/index.rs"), parser.sections.as_slice());
}
<|endoftext|>


<commit_before>use std::slice::SliceExt;

#[derive(Show)]
pub struct Configuration {
    pub choices: Vec<String>,
    pub visible_limit: usize,
    pub initial_search: String,
}

impl Configuration {
    pub fn from_inputs(choice: Vec<String>,
                       initial_search: Option<String>,
                       visible_limit: Option<usize>) -> Configuration {

        let cleaned = choice.iter().map(clean as fn(&String) -> String).collect::<Vec<String>>();
        let limit = visible_limit.unwrap_or(choice.len());
        let search = initial_search.unwrap_or("".to_string());

        Configuration { choices: cleaned,
                        initial_search: search,
                        visible_limit: limit }
    }

    fn parse_options(input: Vec<String>) -> Option<String> {
        match input.position_elem(&"-s".to_string()) {
            Some(ref idx) => Some(input[*idx + 1].clone()),
            None => None,
        }
    }

    fn choices(self) -> Vec<String> {
        self.choices
    }
}

fn clean(input: &String) -> String {
    let slice = input.as_slice();
    slice.trim().to_string()
}

#[cfg(test)]

#[test]
fn removes_leading_and_trailing_whitespace() {
    let input = vec![" a choice ".to_string()];
    let config = Configuration::from_inputs(input, None, None);

    assert_eq!(config.choices(), vec!("a choice"));
}

#[test]
fn can_specify_initial_search() {
    let input = vec!["foo".to_string()];
    let options = vec!["-s".to_string(),
                       "some search".to_string()];
    let config = Configuration::from_inputs(input, Configuration::parse_options(options), None);

    assert_eq!(config.initial_search.as_slice(), "some search");
}

#[test]
fn initial_search_is_optional() {
    let input = vec!["foo".to_string()];
    let options = vec![];
    let config = Configuration::from_inputs(input, Configuration::parse_options(options), None);

    assert_eq!(config.initial_search, "");
}
<commit_msg>Remove redundant method that just accesses a struct field<commit_after>use std::slice::SliceExt;

#[derive(Show)]
pub struct Configuration {
    pub choices: Vec<String>,
    pub visible_limit: usize,
    pub initial_search: String,
}

impl Configuration {
    pub fn from_inputs(choice: Vec<String>,
                       initial_search: Option<String>,
                       visible_limit: Option<usize>) -> Configuration {

        let cleaned = choice.iter().map(clean as fn(&String) -> String).collect::<Vec<String>>();
        let limit = visible_limit.unwrap_or(choice.len());
        let search = initial_search.unwrap_or("".to_string());

        Configuration { choices: cleaned,
                        initial_search: search,
                        visible_limit: limit }
    }

    fn parse_options(input: Vec<String>) -> Option<String> {
        match input.position_elem(&"-s".to_string()) {
            Some(ref idx) => Some(input[*idx + 1].clone()),
            None => None,
        }
    }
}

fn clean(input: &String) -> String {
    let slice = input.as_slice();
    slice.trim().to_string()
}

#[cfg(test)]

#[test]
fn removes_leading_and_trailing_whitespace() {
    let input = vec![" a choice ".to_string()];
    let config = Configuration::from_inputs(input, None, None);

    assert_eq!(config.choices, vec!("a choice"));
}

#[test]
fn can_specify_initial_search() {
    let input = vec!["foo".to_string()];
    let options = vec!["-s".to_string(),
                       "some search".to_string()];
    let config = Configuration::from_inputs(input, Configuration::parse_options(options), None);

    assert_eq!(config.initial_search.as_slice(), "some search");
}

#[test]
fn initial_search_is_optional() {
    let input = vec!["foo".to_string()];
    let options = vec![];
    let config = Configuration::from_inputs(input, Configuration::parse_options(options), None);

    assert_eq!(config.initial_search, "");
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate perl_xs;
#[macro_use]
extern crate perl_sys;

use perl_xs::{ SV, AV, IV, NV };

xs! {
    package XSBench::RS;

    sub rs_sum_loop(ctx, param: SV) {
        let array: AV = param.deref_av().expect("not an array ref");
        let mut sum = 0.0;
        for i in 0..array.top_index() + 1 {
            if let Some(val) = array.fetch(i) {
                sum += val;
            }
        }
        xs_return!(ctx, sum);
    }

    sub rs_sum_iter(ctx, param: SV) {
        let array: AV = param.deref_av().expect("not an array ref");
        let sum: NV = array.iter().map(|v| v.unwrap_or(0.0)).sum();
        xs_return!(ctx, sum);
    }

    sub rs_gcd(ctx, a: IV, b: IV) {
        let mut a = a;
        let mut b = b;
        while b > 0 {
            let t = a;
            a = b;
            b = t % b;
        }

        let res = if a < 0 {
            -a
        } else {
            a
        };

        xs_return!(ctx, res);
    }
}

xs! {
    bootstrap boot_XSBench__RS;
    use self;
}
<commit_msg>Use automatic dereference in benchmark<commit_after>#[macro_use]
extern crate perl_xs;
#[macro_use]
extern crate perl_sys;

use perl_xs::{ AV, IV, NV };

xs! {
    package XSBench::RS;

    sub rs_sum_loop(ctx, array: AV) {
        let mut sum = 0.0;
        for i in 0..array.top_index() + 1 {
            if let Some(val) = array.fetch(i) {
                sum += val;
            }
        }
        xs_return!(ctx, sum);
    }

    sub rs_sum_iter(ctx, array: AV) {
        let sum: NV = array.iter().map(|v| v.unwrap_or(0.0)).sum();
        xs_return!(ctx, sum);
    }

    sub rs_gcd(ctx, a: IV, b: IV) {
        let mut a = a;
        let mut b = b;
        while b > 0 {
            let t = a;
            a = b;
            b = t % b;
        }

        let res = if a < 0 {
            -a
        } else {
            a
        };

        xs_return!(ctx, res);
    }
}

xs! {
    bootstrap boot_XSBench__RS;
    use self;
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};

use libc::{c_void, size_t};
use std::mem;
use std::ptr;

pub type CGDataProviderGetBytesCallback = *const u8;
pub type CGDataProviderReleaseInfoCallback = *const u8;
pub type CGDataProviderRewindCallback = *const u8;
pub type CGDataProviderSkipBytesCallback = *const u8;
pub type CGDataProviderSkipForwardCallback = *const u8;

pub type CGDataProviderGetBytePointerCallback = *const u8;
pub type CGDataProviderGetBytesAtOffsetCallback = *const u8;
pub type CGDataProviderReleaseBytePointerCallback = *const u8;
pub type CGDataProviderReleaseDataCallback = *const u8;
pub type CGDataProviderGetBytesAtPositionCallback = *const u8;

struct __CGDataProvider;

pub type CGDataProviderRef = *const __CGDataProvider;

pub struct CGDataProvider {
    obj: CGDataProviderRef,
}

impl Drop for CGDataProvider {
    fn drop(&mut self) {
        unsafe {
            CFRelease(self.as_CFTypeRef())
        }
    }
}

impl TCFType<CGDataProviderRef> for CGDataProvider {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGDataProviderRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGDataProviderRef) -> CGDataProvider {
        let reference: CGDataProviderRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGDataProviderRef) -> CGDataProvider {
        CGDataProvider {
            obj: obj,
        }
    }

    #[inline]
    fn type_id(_: Option<CGDataProvider>) -> CFTypeID {
        unsafe {
            CGDataProviderGetTypeID()
        }
    }
}

impl CGDataProvider {
    pub fn from_buffer(buffer: &[u8]) -> CGDataProvider {
        unsafe {
            let result = CGDataProviderCreateWithData(ptr::mut_null(),
                                                      buffer.as_ptr() as *const c_void,
                                                      buffer.len() as size_t,
                                                      ptr::null());
            TCFType::wrap_under_create_rule(result)
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    //fn CGDataProviderCopyData
    //fn CGDataProviderCreateDirect
    //fn CGDataProviderCreateSequential
    //fn CGDataProviderCreateWithCFData
    fn CGDataProviderCreateWithData(info: *mut c_void,
                                    data: *const c_void,
                                    size: size_t,
                                    releaseData: CGDataProviderReleaseDataCallback
                                   ) -> CGDataProviderRef;
    //fn CGDataProviderCreateWithFilename(filename: *c_char) -> CGDataProviderRef;
    //fn CGDataProviderCreateWithURL
    fn CGDataProviderGetTypeID() -> CFTypeID;
    //fn CGDataProviderRelease(provider: CGDataProviderRef);
    //fn CGDataProviderRetain(provider: CGDataProviderRef) -> CGDataProviderRef;
}
<commit_msg>Changed mut_null to null_mut<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};

use libc::{c_void, size_t};
use std::mem;
use std::ptr;

pub type CGDataProviderGetBytesCallback = *const u8;
pub type CGDataProviderReleaseInfoCallback = *const u8;
pub type CGDataProviderRewindCallback = *const u8;
pub type CGDataProviderSkipBytesCallback = *const u8;
pub type CGDataProviderSkipForwardCallback = *const u8;

pub type CGDataProviderGetBytePointerCallback = *const u8;
pub type CGDataProviderGetBytesAtOffsetCallback = *const u8;
pub type CGDataProviderReleaseBytePointerCallback = *const u8;
pub type CGDataProviderReleaseDataCallback = *const u8;
pub type CGDataProviderGetBytesAtPositionCallback = *const u8;

struct __CGDataProvider;

pub type CGDataProviderRef = *const __CGDataProvider;

pub struct CGDataProvider {
    obj: CGDataProviderRef,
}

impl Drop for CGDataProvider {
    fn drop(&mut self) {
        unsafe {
            CFRelease(self.as_CFTypeRef())
        }
    }
}

impl TCFType<CGDataProviderRef> for CGDataProvider {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGDataProviderRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGDataProviderRef) -> CGDataProvider {
        let reference: CGDataProviderRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGDataProviderRef) -> CGDataProvider {
        CGDataProvider {
            obj: obj,
        }
    }

    #[inline]
    fn type_id(_: Option<CGDataProvider>) -> CFTypeID {
        unsafe {
            CGDataProviderGetTypeID()
        }
    }
}

impl CGDataProvider {
    pub fn from_buffer(buffer: &[u8]) -> CGDataProvider {
        unsafe {
            let result = CGDataProviderCreateWithData(ptr::null_mut(),
                                                      buffer.as_ptr() as *const c_void,
                                                      buffer.len() as size_t,
                                                      ptr::null());
            TCFType::wrap_under_create_rule(result)
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    //fn CGDataProviderCopyData
    //fn CGDataProviderCreateDirect
    //fn CGDataProviderCreateSequential
    //fn CGDataProviderCreateWithCFData
    fn CGDataProviderCreateWithData(info: *mut c_void,
                                    data: *const c_void,
                                    size: size_t,
                                    releaseData: CGDataProviderReleaseDataCallback
                                   ) -> CGDataProviderRef;
    //fn CGDataProviderCreateWithFilename(filename: *c_char) -> CGDataProviderRef;
    //fn CGDataProviderCreateWithURL
    fn CGDataProviderGetTypeID() -> CFTypeID;
    //fn CGDataProviderRelease(provider: CGDataProviderRef);
    //fn CGDataProviderRetain(provider: CGDataProviderRef) -> CGDataProviderRef;
}
<|endoftext|>


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

    #[test]
    fn one_result() {
        let query = "duct";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(
            vec!["safe, fast, productive."],
            search(query, contents)
        );
    }
}

use std::error::Error;
use std::fs::File;
use std::io::prelude::*;

pub struct Config {
    pub query: String,
    pub filename: String,
}

impl Config {
    pub fn new(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("not enough arguments");
        }

        let query = args[1].clone();
        let filename = args[2].clone();

        Ok(Config {
            query: query,
            filename: filename,
        })
    }
}

pub fn run(config: Config) -> Result<(), Box<Error>>{
    let mut f = File::open(config.filename)?;

    let mut contents = String::new();
    f.read_to_string(&mut contents)?;

    for line in search(&config.query, &contents) {
        println!("{}", line);
    }
    // println!("With text:\n\n{}", contents);

    Ok(())
}

fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }

    results
}<commit_msg>add case_insensitive and test<commit_after>#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn one_result() {
        let query = "duct";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.";

        assert_eq!(
            vec!["safe, fast, productive."],
            search(query, contents)
        );
    }

        #[test]
    fn case_sensitive() {
        let query = "duct";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.
Duct tape.";

        assert_eq!(
            vec!["safe, fast, productive."],
            search(query, contents)
        );
    }

    #[test]
    fn case_insensitive() {
        let query = "rUsT";
        let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.";

        assert_eq!(
            vec!["Rust:", "Trust me."],
            search_case_insensitive(query, contents)
        );
    }
}

use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::env;

pub struct Config {
    pub query: String,
    pub filename: String,
    pub case_sensitive: bool,
}

impl Config {
    pub fn new(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("not enough arguments");
        }

        let query = args[1].clone();
        let filename = args[2].clone();
        let case_sensitive = env::var("CASE_INSENSITIVE").is_err();

        Ok(Config {
            query: query,
            filename: filename,
            case_sensitive: case_sensitive,
        })
    }
}

pub fn run(config: Config) -> Result<(), Box<Error>>{
    let mut f = File::open(config.filename)?;

    let mut contents = String::new();
    f.read_to_string(&mut contents)?;

    let results = if config.case_sensitive {
        search(&config.query, &contents)
    } else {
        search_case_insensitive(&config.query, &contents)
    };

    for line in results {
        println!("{}", line);
    }
    // println!("With text:\n\n{}", contents);

    Ok(())
}

fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }

    results
}

fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let query = query.to_lowercase();
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.to_lowercase().contains(&query) {
            results.push(line);
        }
    }

    results
}<|endoftext|>


<commit_before>use serde::ser;
use Value;
use super::{Encoder, Error};

impl ser::Serializer for Encoder {
    type Error = Error;

    fn visit_bool(&mut self, v: bool) -> Result<(), Error> {
        self.emit_value(Value::Boolean(v))
    }
    fn visit_i64(&mut self, v: i64) -> Result<(), Error> {
        self.emit_value(Value::Integer(v))
    }
    fn visit_u64(&mut self, v: u64) -> Result<(), Error> {
        self.visit_i64(v as i64)
    }
    fn visit_f64(&mut self, v: f64) -> Result<(), Error> {
        self.emit_value(Value::Float(v))
    }
    fn visit_str(&mut self, value: &str) -> Result<(), Error> {
        self.emit_value(Value::String(value.to_string()))
    }
    fn visit_unit(&mut self) -> Result<(), Error> {
        Ok(())
    }
    fn visit_none(&mut self) -> Result<(), Error> {
        self.emit_none()
    }
    fn visit_some<V>(&mut self, value: V) -> Result<(), Error>
        where V: ser::Serialize
    {
        value.serialize(self)
    }
    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), Error>
        where V: ser::SeqVisitor
    {
        self.seq(|me| {
            while try!(visitor.visit(me)).is_some() {}
            Ok(())
        })
    }
    fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Error>
        where T: ser::Serialize
    {
        value.serialize(self)
    }
    fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), Error>
        where V: ser::MapVisitor
    {
        self.table(|me| {
            while try!(visitor.visit(me)).is_some() {}
            Ok(())
        })
    }
    fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
        where K: ser::Serialize, V: ser::Serialize
    {
        try!(self.table_key(|me| key.serialize(me)));
        try!(value.serialize(self));
        Ok(())
    }
}

impl ser::Serialize for Value {
    fn serialize<E>(&self, e: &mut E) -> Result<(), E::Error>
        where E: ser::Serializer
    {
        match *self {
            Value::String(ref s) => e.visit_str(s),
            Value::Integer(i) => e.visit_i64(i),
            Value::Float(f) => e.visit_f64(f),
            Value::Boolean(b) => e.visit_bool(b),
            Value::Datetime(ref s) => e.visit_str(s),
            Value::Array(ref a) => {
                e.visit_seq(ser::impls::SeqIteratorVisitor::new(a.iter(),
                                                                Some(a.len())))
            }
            Value::Table(ref t) => {
                e.visit_map(ser::impls::MapIteratorVisitor::new(t.iter(),
                                                                Some(t.len())))
            }
        }
    }
}
<commit_msg>Implement Serialize::visit_newtype_{struct,variant}<commit_after>use serde::ser;
use Value;
use super::{Encoder, Error};

impl ser::Serializer for Encoder {
    type Error = Error;

    fn visit_bool(&mut self, v: bool) -> Result<(), Error> {
        self.emit_value(Value::Boolean(v))
    }
    fn visit_i64(&mut self, v: i64) -> Result<(), Error> {
        self.emit_value(Value::Integer(v))
    }
    fn visit_u64(&mut self, v: u64) -> Result<(), Error> {
        self.visit_i64(v as i64)
    }
    fn visit_f64(&mut self, v: f64) -> Result<(), Error> {
        self.emit_value(Value::Float(v))
    }
    fn visit_str(&mut self, value: &str) -> Result<(), Error> {
        self.emit_value(Value::String(value.to_string()))
    }
    fn visit_unit(&mut self) -> Result<(), Error> {
        Ok(())
    }
    fn visit_none(&mut self) -> Result<(), Error> {
        self.emit_none()
    }
    fn visit_some<V>(&mut self, value: V) -> Result<(), Error>
        where V: ser::Serialize
    {
        value.serialize(self)
    }
    fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), Error>
        where V: ser::SeqVisitor
    {
        self.seq(|me| {
            while try!(visitor.visit(me)).is_some() {}
            Ok(())
        })
    }
    fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Error>
        where T: ser::Serialize
    {
        value.serialize(self)
    }
    fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), Error>
        where V: ser::MapVisitor
    {
        self.table(|me| {
            while try!(visitor.visit(me)).is_some() {}
            Ok(())
        })
    }
    fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
        where K: ser::Serialize, V: ser::Serialize
    {
        try!(self.table_key(|me| key.serialize(me)));
        try!(value.serialize(self));
        Ok(())
    }
    fn visit_newtype_struct<T>(&mut self,
                               _name: &'static str,
                               value: T) -> Result<(), Self::Error>
        where T: ser::Serialize,
    {
        // Don't serialize the newtype struct in a tuple.
        value.serialize(self)
    }
    fn visit_newtype_variant<T>(&mut self,
                                _name: &'static str,
                                _variant_index: usize,
                                _variant: &'static str,
                                value: T) -> Result<(), Self::Error>
        where T: ser::Serialize,
    {
        // Don't serialize the newtype struct variant in a tuple.
        value.serialize(self)
    }
}

impl ser::Serialize for Value {
    fn serialize<E>(&self, e: &mut E) -> Result<(), E::Error>
        where E: ser::Serializer
    {
        match *self {
            Value::String(ref s) => e.visit_str(s),
            Value::Integer(i) => e.visit_i64(i),
            Value::Float(f) => e.visit_f64(f),
            Value::Boolean(b) => e.visit_bool(b),
            Value::Datetime(ref s) => e.visit_str(s),
            Value::Array(ref a) => {
                e.visit_seq(ser::impls::SeqIteratorVisitor::new(a.iter(),
                                                                Some(a.len())))
            }
            Value::Table(ref t) => {
                e.visit_map(ser::impls::MapIteratorVisitor::new(t.iter(),
                                                                Some(t.len())))
            }
        }
    }
}
<|endoftext|>


<commit_before>// (c) 2016 Productize SPRL <joost@productize.be>

use Sexp;
use symbolic_expressions::IntoSexp;
use footprint::data::*;
use symbolic_expressions::Rules;

impl IntoSexp for Module {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("module"));
        v.push(Sexp::new_string(&self.name));
        for e in &self.elements {
            v.push(e.into_sexp())
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Element {
    fn into_sexp(&self) -> Sexp {
        match *self {
            Element::Layer(ref s) => Sexp::new_named("layer", s),
            Element::Descr(ref s) => Sexp::new_named("descr", s),
            Element::Tags(ref s) => Sexp::new_named("tags", s),
            Element::Attr(ref s) => Sexp::new_named("attr", s),
            Element::FpText(ref p) => p.into_sexp(),
            Element::Pad(ref pad) => pad.into_sexp(),
            Element::FpPoly(ref p) => p.into_sexp(),
            Element::FpLine(ref p) => p.into_sexp(),
            Element::FpCircle(ref p) => p.into_sexp(),
            Element::TEdit(ref p) => Sexp::new_named("tedit", p),
            Element::TStamp(ref p) => Sexp::new_named("tstamp", p),
            Element::Path(ref p) => Sexp::new_named("path", p),
            Element::At(ref p) => p.into_sexp(),
            Element::Model(ref p) => p.into_sexp(),
            Element::Locked => Sexp::new_string("locked"),
        }
    }
}

impl IntoSexp for FpText {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("fp_text"));
        v.push(Sexp::new_string(&self.name));
        v.push(Sexp::new_string(&self.value));
        v.push(self.at.into_sexp());
        v.push(Sexp::new_named("layer", &self.layer));
        if self.hide {
            v.push(Sexp::new_string("hide"));
        }
        v.push(self.effects.into_sexp());
        Sexp::new_list(v)
    }
}

impl IntoSexp for At {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("at"));
        v.push(Sexp::new_string(self.x));
        v.push(Sexp::new_string(self.y));
        if self.rot != 0.0 {
            v.push(Sexp::new_string(self.rot));
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Font {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("font"));
        let mut v1 = vec![];
        v1.push(Sexp::new_string("size"));
        v1.push(Sexp::new_string(self.size.x));
        v1.push(Sexp::new_string(self.size.y));
        v.push(Sexp::new_list(v1));
        v.push(Sexp::new_named("thickness", self.thickness));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Effects {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("effects"));
        v.push(self.font.into_sexp());
        if let Some(ref j) = self.justify {
            v.push(j.into_sexp())
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Justify {
    fn into_sexp(&self) -> Sexp {
        match *self {
            Justify::Mirror => Sexp::new_named("justify","mirror"),
        }
    }
}

impl IntoSexp for Xy {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string(match self.t {
            XyType::Xy => "xy",
            XyType::Start => "start",
            XyType::End => "end",
            XyType::Size => "size",
            XyType::Center => "center",
        }));
        v.push(Sexp::new_string(self.x));
        v.push(Sexp::new_string(self.y));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Pts {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("pts"));
        for x in &self.elements {
            v.push(x.into_sexp())
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Drill {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("drill"));
        if let Some(ref s) = self.shape {
            v.push(Sexp::new_string(s))
        }
        v.push(Sexp::new_string(self.drill));
        if let Some(ref s) = self.drill2 {
            v.push(Sexp::new_string(s))
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for PadType {
    fn into_sexp(&self) -> Sexp {
        Sexp::new_string(match *self {
            PadType::Smd => "smd",
            PadType::Pth => "thru_hole",
            PadType::NpPth => "np_thru_hole",
        })
    }
}

impl IntoSexp for PadShape {
    fn into_sexp(&self) -> Sexp {
        Sexp::new_string(match *self {
            PadShape::Rect => "rect",
            PadShape::Circle => "circle",
            PadShape::Oval => "oval",
        })
    }
}

impl IntoSexp for Layer {
    fn into_sexp(&self) -> Sexp {
        Sexp::new_string(&self)
    }
}

impl IntoSexp for Layers {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("layers"));
        for layer in &self.layers {
            v.push(layer.into_sexp())
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Pad {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("pad"));
        v.push(Sexp::new_string(&self.name));
        v.push(self.t.into_sexp());
        v.push(self.shape.into_sexp());
        v.push(self.size.into_sexp());
        v.push(self.at.into_sexp());
        v.push(self.layers.into_sexp());
        if let Some(ref net) = self.net {
            v.push(net.into_sexp());
        }
        if let Some(ref drill) = self.drill {
            v.push(drill.into_sexp());
        }
        if let Some(ref spm) = self.solder_paste_margin {
            v.push(Sexp::new_named("solder_paste_margin", spm));
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for FpPoly {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("fp_poly"));
        v.push(self.pts.into_sexp());
        v.push(Sexp::new_named("layer", &self.layer));
        v.push(Sexp::new_named("width", self.width));
        Sexp::new_list(v)
    }
}

impl IntoSexp for FpLine {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("fp_line"));
        v.push(self.start.into_sexp());
        v.push(self.end.into_sexp());
        v.push(Sexp::new_named("layer", &self.layer));
        v.push(Sexp::new_named("width", self.width));
        Sexp::new_list(v)
    }
}

impl IntoSexp for FpCircle {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("fp_circle"));
        v.push(self.center.into_sexp());
        v.push(self.end.into_sexp());
        v.push(Sexp::new_named("layer", &self.layer));
        v.push(Sexp::new_named("width", self.width));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Net {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("net"));
        v.push(Sexp::new_string(self.num));
        v.push(Sexp::new_string(&self.name));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Model {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("model"));
        v.push(Sexp::new_string(&self.name));
        v.push(Sexp::new_named_sexp("at", &self.at));
        v.push(Sexp::new_named_sexp("scale", &self.scale));
        v.push(Sexp::new_named_sexp("rotate", &self.rotate));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Xyz {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("xyz"));
        v.push(Sexp::new_string(self.x));
        v.push(Sexp::new_string(self.y));
        v.push(Sexp::new_string(self.z));
        Sexp::new_list(v)
    }
}

pub fn new_rules() -> Rules {
    let mut rules = Rules::new();
    rules.insert("descr", 1);
    rules.insert("fp_text", 1);
    rules.insert("effects", 2);
    rules.insert("fp_line", 1);
    rules.insert("fp_poly", 1);
    rules.insert("fp_circle", 1);
    rules.insert("fp_poly", 1);
    rules.insert("xp", 2);
    rules.insert("pad", 1);
    rules.insert("model", 1);
    rules
}
<commit_msg>swap at and size in pad<commit_after>// (c) 2016 Productize SPRL <joost@productize.be>

use Sexp;
use symbolic_expressions::IntoSexp;
use footprint::data::*;
use symbolic_expressions::Rules;

impl IntoSexp for Module {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("module"));
        v.push(Sexp::new_string(&self.name));
        for e in &self.elements {
            v.push(e.into_sexp())
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Element {
    fn into_sexp(&self) -> Sexp {
        match *self {
            Element::Layer(ref s) => Sexp::new_named("layer", s),
            Element::Descr(ref s) => Sexp::new_named("descr", s),
            Element::Tags(ref s) => Sexp::new_named("tags", s),
            Element::Attr(ref s) => Sexp::new_named("attr", s),
            Element::FpText(ref p) => p.into_sexp(),
            Element::Pad(ref pad) => pad.into_sexp(),
            Element::FpPoly(ref p) => p.into_sexp(),
            Element::FpLine(ref p) => p.into_sexp(),
            Element::FpCircle(ref p) => p.into_sexp(),
            Element::TEdit(ref p) => Sexp::new_named("tedit", p),
            Element::TStamp(ref p) => Sexp::new_named("tstamp", p),
            Element::Path(ref p) => Sexp::new_named("path", p),
            Element::At(ref p) => p.into_sexp(),
            Element::Model(ref p) => p.into_sexp(),
            Element::Locked => Sexp::new_string("locked"),
        }
    }
}

impl IntoSexp for FpText {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("fp_text"));
        v.push(Sexp::new_string(&self.name));
        v.push(Sexp::new_string(&self.value));
        v.push(self.at.into_sexp());
        v.push(Sexp::new_named("layer", &self.layer));
        if self.hide {
            v.push(Sexp::new_string("hide"));
        }
        v.push(self.effects.into_sexp());
        Sexp::new_list(v)
    }
}

impl IntoSexp for At {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("at"));
        v.push(Sexp::new_string(self.x));
        v.push(Sexp::new_string(self.y));
        if self.rot != 0.0 {
            v.push(Sexp::new_string(self.rot));
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Font {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("font"));
        let mut v1 = vec![];
        v1.push(Sexp::new_string("size"));
        v1.push(Sexp::new_string(self.size.x));
        v1.push(Sexp::new_string(self.size.y));
        v.push(Sexp::new_list(v1));
        v.push(Sexp::new_named("thickness", self.thickness));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Effects {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("effects"));
        v.push(self.font.into_sexp());
        if let Some(ref j) = self.justify {
            v.push(j.into_sexp())
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Justify {
    fn into_sexp(&self) -> Sexp {
        match *self {
            Justify::Mirror => Sexp::new_named("justify","mirror"),
        }
    }
}

impl IntoSexp for Xy {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string(match self.t {
            XyType::Xy => "xy",
            XyType::Start => "start",
            XyType::End => "end",
            XyType::Size => "size",
            XyType::Center => "center",
        }));
        v.push(Sexp::new_string(self.x));
        v.push(Sexp::new_string(self.y));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Pts {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("pts"));
        for x in &self.elements {
            v.push(x.into_sexp())
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Drill {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("drill"));
        if let Some(ref s) = self.shape {
            v.push(Sexp::new_string(s))
        }
        v.push(Sexp::new_string(self.drill));
        if let Some(ref s) = self.drill2 {
            v.push(Sexp::new_string(s))
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for PadType {
    fn into_sexp(&self) -> Sexp {
        Sexp::new_string(match *self {
            PadType::Smd => "smd",
            PadType::Pth => "thru_hole",
            PadType::NpPth => "np_thru_hole",
        })
    }
}

impl IntoSexp for PadShape {
    fn into_sexp(&self) -> Sexp {
        Sexp::new_string(match *self {
            PadShape::Rect => "rect",
            PadShape::Circle => "circle",
            PadShape::Oval => "oval",
        })
    }
}

impl IntoSexp for Layer {
    fn into_sexp(&self) -> Sexp {
        Sexp::new_string(&self)
    }
}

impl IntoSexp for Layers {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("layers"));
        for layer in &self.layers {
            v.push(layer.into_sexp())
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Pad {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("pad"));
        v.push(Sexp::new_string(&self.name));
        v.push(self.t.into_sexp());
        v.push(self.shape.into_sexp());
        v.push(self.at.into_sexp());
        v.push(self.size.into_sexp());
        v.push(self.layers.into_sexp());
        if let Some(ref net) = self.net {
            v.push(net.into_sexp());
        }
        if let Some(ref drill) = self.drill {
            v.push(drill.into_sexp());
        }
        if let Some(ref spm) = self.solder_paste_margin {
            v.push(Sexp::new_named("solder_paste_margin", spm));
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for FpPoly {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("fp_poly"));
        v.push(self.pts.into_sexp());
        v.push(Sexp::new_named("layer", &self.layer));
        v.push(Sexp::new_named("width", self.width));
        Sexp::new_list(v)
    }
}

impl IntoSexp for FpLine {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("fp_line"));
        v.push(self.start.into_sexp());
        v.push(self.end.into_sexp());
        v.push(Sexp::new_named("layer", &self.layer));
        v.push(Sexp::new_named("width", self.width));
        Sexp::new_list(v)
    }
}

impl IntoSexp for FpCircle {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("fp_circle"));
        v.push(self.center.into_sexp());
        v.push(self.end.into_sexp());
        v.push(Sexp::new_named("layer", &self.layer));
        v.push(Sexp::new_named("width", self.width));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Net {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("net"));
        v.push(Sexp::new_string(self.num));
        v.push(Sexp::new_string(&self.name));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Model {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("model"));
        v.push(Sexp::new_string(&self.name));
        v.push(Sexp::new_named_sexp("at", &self.at));
        v.push(Sexp::new_named_sexp("scale", &self.scale));
        v.push(Sexp::new_named_sexp("rotate", &self.rotate));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Xyz {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("xyz"));
        v.push(Sexp::new_string(self.x));
        v.push(Sexp::new_string(self.y));
        v.push(Sexp::new_string(self.z));
        Sexp::new_list(v)
    }
}

pub fn new_rules() -> Rules {
    let mut rules = Rules::new();
    rules.insert("descr", 1);
    rules.insert("fp_text", 1);
    rules.insert("effects", 2);
    rules.insert("fp_line", 1);
    rules.insert("fp_poly", 1);
    rules.insert("fp_circle", 1);
    rules.insert("fp_poly", 1);
    rules.insert("xp", 2);
    rules.insert("pad", 1);
    rules.insert("model", 1);
    rules
}
<|endoftext|>


<commit_before>use bridges;
use email_address::EmailAddress;
use error::BrokerError;
use futures::future::{self, Future, Either};
use http::{ContextHandle, HandlerResult, json_response};
use hyper::Method;
use std::rc::Rc;
use std::time::Duration;
use store_limits::addr_limiter;
use tokio_core::reactor::Timeout;
use validation::parse_redirect_uri;
use webfinger::{self, Link, Relation};

/// Request handler to return the OpenID Discovery document.
///
/// Most of this is hard-coded for now, although the URLs are constructed by
/// using the base URL as configured in the `public_url` configuration value.
pub fn discovery(ctx_handle: &ContextHandle) -> HandlerResult {
    let ctx = ctx_handle.borrow();

    let obj = json!({
        "issuer": ctx.app.public_url,
        "authorization_endpoint": format!("{}/auth", ctx.app.public_url),
        "jwks_uri": format!("{}/keys.json", ctx.app.public_url),
        "scopes_supported": vec!["openid", "email"],
        "claims_supported": vec!["aud", "email", "email_verified", "exp", "iat", "iss", "sub"],
        "response_types_supported": vec!["id_token"],
        "response_modes_supported": vec!["form_post"],
        "grant_types_supported": vec!["implicit"],
        "subject_types_supported": vec!["public"],
        "id_token_signing_alg_values_supported": vec!["RS256"],
    });
    Box::new(json_response(&obj, ctx.app.discovery_ttl))
}

/// Request handler for the JSON Web Key Set document.
///
/// Respond with the JWK key set containing all of the configured keys.
///
/// Relying Parties will need to fetch this data to be able to verify identity
/// tokens issued by this daemon instance.
pub fn key_set(ctx_handle: &ContextHandle) -> HandlerResult {
    let ctx = ctx_handle.borrow();

    let obj = json!({
        "keys": ctx.app.keys.iter()
            .map(|key| key.public_jwk())
            .collect::<Vec<_>>(),
    });
    Box::new(json_response(&obj, ctx.app.keys_ttl))
}

/// Request handler for authentication requests from the RP.
///
/// Calls the `oidc::request()` function if the provided email address's
/// domain matches one of the configured famous providers. Otherwise, calls the
/// `email::request()` function to allow authentication through the email loop.
pub fn auth(ctx_handle: &ContextHandle) -> HandlerResult {
    let mut ctx = ctx_handle.borrow_mut();
    let mut params = match ctx.method {
        Method::Get => ctx.query_params(),
        Method::Post => ctx.form_params(),
        _ => unreachable!(),
    };

    let redirect_uri = try_get_input_param!(params, "redirect_uri");
    let client_id = try_get_input_param!(params, "client_id");
    if try_get_input_param!(params, "response_mode", "fragment".to_owned()) != "form_post" {
        return Box::new(future::err(BrokerError::Input(
            "unsupported response_mode, only form_post is supported".to_owned())));
    }

    let redirect_uri = match parse_redirect_uri(&redirect_uri, "redirect_uri") {
        Ok(url) => url,
        Err(e) => return Box::new(future::err(BrokerError::Input(format!("{}", e)))),
    };

    if client_id != redirect_uri.origin().ascii_serialization() {
        return Box::new(future::err(BrokerError::Input(
            "the client_id must be the origin of the redirect_uri".to_owned())));
    }

    // Per the OAuth2 spec, we may redirect to the RP once we have validated client_id and
    // redirect_uri. In our case, this means we make redirect_uri available to error handling.
    ctx.redirect_uri = Some(redirect_uri.clone());

    if let Some(ref whitelist) = ctx.app.allowed_origins {
        if !whitelist.contains(&client_id) {
            return Box::new(future::err(BrokerError::Input(
                "the origin is not whitelisted".to_owned())));
        }
    }

    let nonce = try_get_input_param!(params, "nonce");
    let login_hint = try_get_input_param!(params, "login_hint");
    if try_get_input_param!(params, "response_type") != "id_token" {
        return Box::new(future::err(BrokerError::Input(
            "unsupported response_type, only id_token is supported".to_owned())));
    }

    // Verify and normalize the email.
    let email_addr = match login_hint.parse::<EmailAddress>() {
        Ok(addr) => Rc::new(addr),
        Err(_) => return Box::new(future::err(BrokerError::Input(
            "login_hint is not a valid email address".to_owned()))),
    };

    // Enforce ratelimit based on the normalized email.
    match addr_limiter(&ctx.app.store, email_addr.as_str(), &ctx.app.limit_per_email) {
        Err(err) => return Box::new(future::err(err)),
        Ok(false) => return Box::new(future::err(BrokerError::RateLimited)),
        _ => {},
    }

    // Create the session with common data, but do not yet save it.
    ctx.start_session(&client_id, &login_hint, &email_addr, &nonce);

    // Discover the authentication endpoints based on the email domain.
    let f = if let Some(mapped) = ctx.app.domain_overrides.get(email_addr.domain()) {
        Box::new(future::ok(mapped.clone()))
    } else {
        webfinger::query(&ctx.app, &email_addr)
    };

    // Try to authenticate with the first provider.
    // TODO: Queue discovery of links and process in order, with individual timeouts.
    let ctx_handle2 = Rc::clone(ctx_handle);
    let email_addr2 = Rc::clone(&email_addr);
    let f = f.and_then(move |links| {
        match links.first() {
            // Portier and Google providers share an implementation
            Some(link @ &Link { rel: Relation::Portier, .. })
                | Some(link @ &Link { rel: Relation::Google, .. })
                => bridges::oidc::auth(&ctx_handle2, &email_addr2, link),
            _ => Box::new(future::err(BrokerError::ProviderCancelled)),
        }
    });

    // Apply a timeout to discovery.
    let ctx_handle2 = Rc::clone(ctx_handle);
    let email_addr2 = Rc::clone(&email_addr);
    let f = Timeout::new(Duration::from_secs(5), &ctx.app.handle)
        .expect("failed to create discovery timeout")
        .select2(f)
        .then(move |result| {
            match result {
                // Timeout resolved first.
                Ok(Either::A((_, f))) => {
                    // Continue the discovery future in the background.
                    ctx_handle2.borrow().app.handle.spawn(
                        f.map(|_| ()).map_err(|e| { e.log(); () }));
                    Err(BrokerError::Provider(
                        format!("discovery timed out for {}", email_addr2)))
                },
                Err(Either::A((e, _))) => {
                    panic!("error in discovery timeout: {}", e)
                },
                // Discovery resolved first.
                Ok(Either::B((v, _))) => {
                    Ok(v)
                },
                Err(Either::B((e, _))) => {
                    Err(e)
                },
            }
        });

    // Fall back to email loop authentication.
    let ctx_handle2 = Rc::clone(ctx_handle);
    let f = f.or_else(move |e| {
        e.log();
        match e {
            BrokerError::Provider(_)
                | BrokerError::ProviderCancelled
                => bridges::email::auth(&ctx_handle2, &email_addr),
            _ => Box::new(future::err(e))
        }
    });

    Box::new(f)
}
<commit_msg>Adjust supported claims to mirror spec<commit_after>use bridges;
use email_address::EmailAddress;
use error::BrokerError;
use futures::future::{self, Future, Either};
use http::{ContextHandle, HandlerResult, json_response};
use hyper::Method;
use std::rc::Rc;
use std::time::Duration;
use store_limits::addr_limiter;
use tokio_core::reactor::Timeout;
use validation::parse_redirect_uri;
use webfinger::{self, Link, Relation};

/// Request handler to return the OpenID Discovery document.
///
/// Most of this is hard-coded for now, although the URLs are constructed by
/// using the base URL as configured in the `public_url` configuration value.
pub fn discovery(ctx_handle: &ContextHandle) -> HandlerResult {
    let ctx = ctx_handle.borrow();

    let obj = json!({
        "issuer": ctx.app.public_url,
        "authorization_endpoint": format!("{}/auth", ctx.app.public_url),
        "jwks_uri": format!("{}/keys.json", ctx.app.public_url),
        "scopes_supported": vec!["openid", "email"],
        "claims_supported": vec!["iss", "aud", "exp", "iat", "email"],
        "response_types_supported": vec!["id_token"],
        "response_modes_supported": vec!["form_post"],
        "grant_types_supported": vec!["implicit"],
        "subject_types_supported": vec!["public"],
        "id_token_signing_alg_values_supported": vec!["RS256"],
    });
    Box::new(json_response(&obj, ctx.app.discovery_ttl))
}

/// Request handler for the JSON Web Key Set document.
///
/// Respond with the JWK key set containing all of the configured keys.
///
/// Relying Parties will need to fetch this data to be able to verify identity
/// tokens issued by this daemon instance.
pub fn key_set(ctx_handle: &ContextHandle) -> HandlerResult {
    let ctx = ctx_handle.borrow();

    let obj = json!({
        "keys": ctx.app.keys.iter()
            .map(|key| key.public_jwk())
            .collect::<Vec<_>>(),
    });
    Box::new(json_response(&obj, ctx.app.keys_ttl))
}

/// Request handler for authentication requests from the RP.
///
/// Calls the `oidc::request()` function if the provided email address's
/// domain matches one of the configured famous providers. Otherwise, calls the
/// `email::request()` function to allow authentication through the email loop.
pub fn auth(ctx_handle: &ContextHandle) -> HandlerResult {
    let mut ctx = ctx_handle.borrow_mut();
    let mut params = match ctx.method {
        Method::Get => ctx.query_params(),
        Method::Post => ctx.form_params(),
        _ => unreachable!(),
    };

    let redirect_uri = try_get_input_param!(params, "redirect_uri");
    let client_id = try_get_input_param!(params, "client_id");
    if try_get_input_param!(params, "response_mode", "fragment".to_owned()) != "form_post" {
        return Box::new(future::err(BrokerError::Input(
            "unsupported response_mode, only form_post is supported".to_owned())));
    }

    let redirect_uri = match parse_redirect_uri(&redirect_uri, "redirect_uri") {
        Ok(url) => url,
        Err(e) => return Box::new(future::err(BrokerError::Input(format!("{}", e)))),
    };

    if client_id != redirect_uri.origin().ascii_serialization() {
        return Box::new(future::err(BrokerError::Input(
            "the client_id must be the origin of the redirect_uri".to_owned())));
    }

    // Per the OAuth2 spec, we may redirect to the RP once we have validated client_id and
    // redirect_uri. In our case, this means we make redirect_uri available to error handling.
    ctx.redirect_uri = Some(redirect_uri.clone());

    if let Some(ref whitelist) = ctx.app.allowed_origins {
        if !whitelist.contains(&client_id) {
            return Box::new(future::err(BrokerError::Input(
                "the origin is not whitelisted".to_owned())));
        }
    }

    let nonce = try_get_input_param!(params, "nonce");
    let login_hint = try_get_input_param!(params, "login_hint");
    if try_get_input_param!(params, "response_type") != "id_token" {
        return Box::new(future::err(BrokerError::Input(
            "unsupported response_type, only id_token is supported".to_owned())));
    }

    // Verify and normalize the email.
    let email_addr = match login_hint.parse::<EmailAddress>() {
        Ok(addr) => Rc::new(addr),
        Err(_) => return Box::new(future::err(BrokerError::Input(
            "login_hint is not a valid email address".to_owned()))),
    };

    // Enforce ratelimit based on the normalized email.
    match addr_limiter(&ctx.app.store, email_addr.as_str(), &ctx.app.limit_per_email) {
        Err(err) => return Box::new(future::err(err)),
        Ok(false) => return Box::new(future::err(BrokerError::RateLimited)),
        _ => {},
    }

    // Create the session with common data, but do not yet save it.
    ctx.start_session(&client_id, &login_hint, &email_addr, &nonce);

    // Discover the authentication endpoints based on the email domain.
    let f = if let Some(mapped) = ctx.app.domain_overrides.get(email_addr.domain()) {
        Box::new(future::ok(mapped.clone()))
    } else {
        webfinger::query(&ctx.app, &email_addr)
    };

    // Try to authenticate with the first provider.
    // TODO: Queue discovery of links and process in order, with individual timeouts.
    let ctx_handle2 = Rc::clone(ctx_handle);
    let email_addr2 = Rc::clone(&email_addr);
    let f = f.and_then(move |links| {
        match links.first() {
            // Portier and Google providers share an implementation
            Some(link @ &Link { rel: Relation::Portier, .. })
                | Some(link @ &Link { rel: Relation::Google, .. })
                => bridges::oidc::auth(&ctx_handle2, &email_addr2, link),
            _ => Box::new(future::err(BrokerError::ProviderCancelled)),
        }
    });

    // Apply a timeout to discovery.
    let ctx_handle2 = Rc::clone(ctx_handle);
    let email_addr2 = Rc::clone(&email_addr);
    let f = Timeout::new(Duration::from_secs(5), &ctx.app.handle)
        .expect("failed to create discovery timeout")
        .select2(f)
        .then(move |result| {
            match result {
                // Timeout resolved first.
                Ok(Either::A((_, f))) => {
                    // Continue the discovery future in the background.
                    ctx_handle2.borrow().app.handle.spawn(
                        f.map(|_| ()).map_err(|e| { e.log(); () }));
                    Err(BrokerError::Provider(
                        format!("discovery timed out for {}", email_addr2)))
                },
                Err(Either::A((e, _))) => {
                    panic!("error in discovery timeout: {}", e)
                },
                // Discovery resolved first.
                Ok(Either::B((v, _))) => {
                    Ok(v)
                },
                Err(Either::B((e, _))) => {
                    Err(e)
                },
            }
        });

    // Fall back to email loop authentication.
    let ctx_handle2 = Rc::clone(ctx_handle);
    let f = f.or_else(move |e| {
        e.log();
        match e {
            BrokerError::Provider(_)
                | BrokerError::ProviderCancelled
                => bridges::email::auth(&ctx_handle2, &email_addr),
            _ => Box::new(future::err(e))
        }
    });

    Box::new(f)
}
<|endoftext|>


<commit_before><commit_msg>[golang] fix error handling in Deserialize<commit_after><|endoftext|>


<commit_before><commit_msg>plugin: fix health_check error<commit_after><|endoftext|>


<commit_before>#[macro_use]
extern crate duct;

#[test]
fn fixtures() {
    // ignore if this fails
    let _ = cmd!("cargo", "install", "clippy").stderr_capture().run();
    let root_dir = std::env::current_dir().unwrap();

    println!("looking for fixtures in directory: {:?}", root_dir);

    for fixture in std::fs::read_dir(root_dir.join("tests/crates")).unwrap() {
        let fixture = fixture.unwrap();
        if !fixture.file_type().unwrap().is_dir() {
            continue;
        }
        let fixture_path = fixture.path();

        let file = std::fs::File::open(fixture_path.with_extension("sub-path"))
            .and_then(|mut file| {
                use std::io::Read;
                let mut contents = String::new();
                file.read_to_string(&mut contents)?;
                Ok(contents)
            });
        let dir = if let Ok(path) = file {
            fixture_path.join(path.trim())
        } else {
            fixture_path.clone()
        };
        println!("Running tests for {:?}", dir);
        let tests = std::fs::read_dir(root_dir.join("tests/tests").join(fixture_path.file_name().unwrap())).unwrap();

        for entry in tests {
            let test = entry.unwrap().path();
            let yolo = test.file_name().unwrap() == "yolo";

            println!("---");
            println!("Running test: {:?}", test);

            assert!(cmd!("git", "checkout", ".").dir(&dir).run().unwrap().status.success());
            assert!(cmd!("cargo", "clean").dir(&dir).run().unwrap().status.success());
            // we only want to rustfix the final project, not any dependencies
            assert!(cmd!("cargo", "build").dir(&dir).run().unwrap().status.success());

            let manifest = format!("{:?}", root_dir.join("Cargo.toml"));

            println!("Checking {:?} with clippy", test);

            let manifest = format!("--manifest-path={}", &manifest[1..manifest.len() - 1]);
            let cmd = if yolo {
                cmd!("cargo", "run", manifest, "--quiet", "--", "--clippy", "--yolo")
            } else {
                cmd!("cargo", "run", manifest, "--quiet", "--", "--clippy")
            };
            cmd.dir(&dir)
                .stdin(test.join("input.txt"))
                .stdout(dir.join("output.txt"))
                .run()
                .unwrap();

            if std::env::var("APPLY_RUSTFIX").is_ok() {
                std::fs::copy(dir.join("output.txt"), test.join("output.txt")).unwrap();

                cmd!("git", "diff").dir(&dir).stdout(test.join("diff.diff")).run().unwrap();
            } else {
                cmd!("git", "diff").dir(&dir).stdout(dir.join("diff.diff")).run().unwrap();

                let diff = cmd!("diff", dir.join("diff.diff"), test.join("diff.diff"))
                    .dir(&dir)
                    .stdout_capture()
                    .unchecked()
                    .run().unwrap();
                if !diff.status.success() {
                    panic!("Unexpected changes by rustfix:\n{}", std::str::from_utf8(&diff.stdout).unwrap());
                }

                let output = cmd!("diff", dir.join("output.txt"), test.join("output.txt"))
                    .dir(&dir)
                    .stdout_capture()
                    .unchecked()
                    .run().unwrap();
                if !output.status.success() {
                    panic!("Unexpected output by rustfix:\n{}", std::str::from_utf8(&output.stdout).unwrap());
                }
            }

            println!("---");
            println!("Success!");
        }
    }
}
<commit_msg>Allow multiple sub-paths to be specified for each test fixture<commit_after>#[macro_use]
extern crate duct;

use std::io::{BufReader, BufRead};

#[test]
fn fixtures() {
    // ignore if this fails
    let _ = cmd!("cargo", "install", "clippy").stderr_capture().run();
    let root_dir = std::env::current_dir().unwrap();

    println!("looking for fixtures in directory: {:?}\n", root_dir);

    for fixture in std::fs::read_dir(root_dir.join("tests/crates")).unwrap() {
        let fixture = fixture.unwrap();
        if !fixture.file_type().unwrap().is_dir() {
            continue;
        }
        let fixture_path = fixture.path();

        let files: Vec<String> = std::fs::File::open(fixture_path.with_extension("sub-path"))
            .and_then(|file| BufReader::new(file).lines().collect()).unwrap_or_default();
        let dirs = if files.is_empty() {
            vec![fixture_path.clone()]
        } else {
            files.into_iter().map(|file| fixture_path.join(file.trim())).collect()
        };
        for dir in dirs {
            println!("====================================================================");
            println!("Running tests for {:?}\n", dir);
            let tests = std::fs::read_dir(root_dir.join("tests/tests").join(fixture_path.file_name().unwrap())).unwrap();

            for entry in tests {
                let test = entry.unwrap().path();
                let yolo = test.file_name().unwrap() == "yolo";

                println!("Running test: {}", test.file_name().unwrap().to_str().unwrap());

                assert!(cmd!("git", "checkout", ".").dir(&dir).run().unwrap().status.success());
                assert!(cmd!("cargo", "clean").dir(&dir).run().unwrap().status.success());
                // we only want to rustfix the final project, not any dependencies
                assert!(cmd!("cargo", "build").dir(&dir).run().unwrap().status.success());

                let manifest = format!("{:?}", root_dir.join("Cargo.toml"));

                println!("Running cargo clippy to obtain suggestions");

                let manifest = format!("--manifest-path={}", &manifest[1..manifest.len() - 1]);
                let cmd = if yolo {
                    cmd!("cargo", "run", manifest, "--quiet", "--", "--clippy", "--yolo")
                } else {
                    cmd!("cargo", "run", manifest, "--quiet", "--", "--clippy")
                };
                cmd.dir(&dir)
                    .stdin(test.join("input.txt"))
                    .stdout(dir.join("output.txt"))
                    .run()
                    .unwrap();

                if std::env::var("APPLY_RUSTFIX").is_ok() {
                    std::fs::copy(dir.join("output.txt"), test.join("output.txt")).unwrap();

                    cmd!("git", "diff").dir(&dir).stdout(test.join("diff.diff")).run().unwrap();
                } else {
                    cmd!("git", "diff").dir(&dir).stdout(dir.join("diff.diff")).run().unwrap();

                    let diff = cmd!("diff", dir.join("diff.diff"), test.join("diff.diff"))
                        .dir(&dir)
                        .stdout_capture()
                        .unchecked()
                        .run().unwrap();
                    if !diff.status.success() {
                        panic!("Unexpected changes by rustfix:\n{}", std::str::from_utf8(&diff.stdout).unwrap());
                    }

                    let output = cmd!("diff", dir.join("output.txt"), test.join("output.txt"))
                        .dir(&dir)
                        .stdout_capture()
                        .unchecked()
                        .run().unwrap();
                    if !output.status.success() {
                        panic!("Unexpected output by rustfix:\n{}", std::str::from_utf8(&output.stdout).unwrap());
                    }
                }

                println!("Success!\n");
            }
        }
    }
}
<|endoftext|>