<commit_before>/*
 * Simple web server in Rust.
 * For now, the pool_size argument is not used: there is at most only
 * one client at a time.
 */
extern mod std;
use std::getopts::*;
use std::net::tcp;
use std::net::ip;
use std::task;
use std::uv;
use pipes::{stream, Port, Chan};

type ConnectMsg = (tcp::TcpNewConnection, core::oldcomm::Chan<Option<tcp::TcpErrData>>);

fn print_usage(program: ~str) {
   fail fmt!("Usage: %s -p port -s pool_size -d web_dir", program);
}

// Another version to parse the arguments, which uses getopts
fn parse_arguments_with_getopts(args: ~[~str]) -> (uint, uint, ~str) {
   let opts = ~[
      optopt("p"),
      optopt("s"),
      optopt("d")
   ];
   let matches = match getopts(vec::tail(args), opts) {
      result::Ok(m) => { m }
      result::Err(f) => { fail fail_str(f) }
   };
   let port = uint::from_str(opt_str(&matches, "p")).get();
   let pool_size = uint::from_str(opt_str(&matches, "s")).get();
   let web_dir = opt_str(&matches, "d");

   if port == -1 || pool_size == -1 || web_dir == ~"" {
      io::println("Bad arguments values: ");
      print_usage(copy args[0]);
   }

   (port, pool_size, web_dir)
}

/* read the file path */
fn read_file(path: ~str) -> (~[u8], int) {
   let res = io::read_whole_file(&Path(path));
   if result::is_err(&res) {
      // XXX how to make the difference between file not found and not authorized?
      // In both cases res = Err(~"error opening file")
      (~[], 404)
   } else {
      (res.get(), 200)
   }
}

/*
 * Read an HTTP request and return a couple (line, code).
 * Block until a line has been read, in which case line is
 * the line that has been read and code=0, or return the line
 * that has been read so far and code=1 in case of error.
 */
fn read_request(socket: &tcp::TcpSocket) -> (~str, uint) {
   let mut req: ~str = ~"";
   loop {
      let result = socket.read(0u);
      if result.is_err() {
         return (req, 1);
      }

      let req2 = req + str::from_bytes(result.get());
      req = move req2;
      if str::contains(req, "\n") {
         return (req, 0);
      }
   }
}

fn clienterror(socket: &tcp::TcpSocket, cause: ~str, errnum: @str, shortmsg: @str, longmsg: @str) {
   io::println(fmt!("Client error: %s -> %s %s %s", cause, errnum, shortmsg, longmsg));

   let body = ~"<title>Simple Web Server Error</title>\r\n"
      + fmt!("%s: %s\r\n", errnum, shortmsg)
      + fmt!("
%s: %s
\r\n", longmsg, cause)
      + ~"
The Simple Web Server\r\n";
   let header = fmt!("HTTP/1.0 %s %s\r\n", errnum, shortmsg) + ~"Content-type: text/html\r\n" + fmt!("Content-length: %u\r\n\r\n", body.len());

   socket.write(str::to_bytes(header));
   socket.write(str::to_bytes(body));
}

fn get_file_type(filename: ~str) -> ~str {
   if str::ends_with(filename, ~".html") {
      ~"text/html"
   } else if str::ends_with(filename, ~".gif") {
      ~"image/gif"
   } else if str::ends_with(filename, ~".jpg") {
      ~"image/jpeg"
   } else {
      ~"text/plain"
   }
}

fn clientsuccess(socket: &tcp::TcpSocket, filename: ~str, content: ~[u8]) {
   let filetype = get_file_type(filename);

   let header = ~"HTTP/1.0 200 OK\r\nServer: Simple Web Server\r\n"
      +fmt!("Content-length: %u\r\n", content.len())
      +fmt!("Content-type: %s\r\n\r\n", filetype);

   socket.write(str::to_bytes(header));
   socket.write(content);
}

fn handle_connection(port_endpoint: ~Port<ConnectMsg>, web_dir: ~str) {
   // this is the task which accepts new connections
   do task::spawn{
      loop {
         let (conn, kill_ch) = port_endpoint.recv();
         io::println("Going to accept a new connection");
         match tcp::accept(conn) {
            result::Err(err) => {
               io::println(fmt!("Connection error: %?", err));
               kill_ch.send(Some(err));
            },
            result::Ok(socket) => {
               let peer_addr: ~str = ip::format_addr(&socket.get_peer_addr());
               io::println(fmt!("Connection accepted from %s", peer_addr));

               let (request, code) = read_request(&socket);
               if code == 0 {
                  let words = str::words(request);
                  if words.len() < 3 {
                     clienterror(&socket, request, @"400", @"Bad request", @"The request is not well-formatted");
                  } else if words[0] != ~"GET" {
                     clienterror(&socket, request, @"501", @"Not implemented", @"The request is not implemented");
                  } else if words[2] != ~"HTTP/1.0" {
                     clienterror(&socket, request, @"505", @"HTTP version not supported", @"The server does not implement this version of HTTP");
                  } else {
                     let (content, code) = read_file(web_dir + words[1]);
                     if code == 200 {
                        clientsuccess(&socket, copy words[1], content);
                     } else if code == 404 {
                        clienterror(&socket, copy words[1], @"404", @"Not found", @"The file cannot be found");
                     } else if code == 401 {
                        clienterror(&socket, copy words[1], @"401", @"Not authorized", @"The file cannot be accessed");
                     } else {
                        fail fmt!("Unknown error code: %d", code);
                     }
                  }
               }
            }
         }
      }
   }
}

fn main()  {
   let args : ~[~str] = os::args();
   if (args.len() != 7) {
      io::print("Bad length: ");
      print_usage(copy args[0]);
   }

   let (port, pool_size, web_dir) = parse_arguments_with_getopts(args);

   //to play with string concatenation
   io::println(~"port is " + uint::to_str(port, 10));
   io::println(~"pool size is " + uint::to_str(pool_size, 10));
   io::println(~"web dir is " + web_dir);

   //Connection information will be transmitted using this Port and Chan
   let (port_endpoint, chan_endpoint): (Port<ConnectMsg>, Chan<ConnectMsg>) = stream();

   handle_connection(~port_endpoint, web_dir);

   let result = tcp::listen(ip::v4::parse_addr("127.0.0.1"), port, 100,
         uv::global_loop::get(),
         |_|{
            io::println("Server is now listening!");
         },
         |conn, kill_chan| {
            // The connection must be accepted from another task or the server will block.
            chan_endpoint.send((conn, kill_chan));
         }
   );

   if result.is_err() {
      fail fmt!("failed listen: %?", result.get_err());
   }
}

<commit_msg>rust 0.6 and some cleanup<commit_after>/*
 * Simple web server in Rust.
 * For now, the pool_size argument is not used: there is at most only
 * one client at a time.
 */
extern mod std;
use std::getopts::*;
use std::net::tcp;
use std::net::ip;
use std::task;
use std::uv;
//use pipes::{stream, Port, Chan};

use StatusCodes::StatusCode;
mod StatusCodes {
   // HTTP Status code
   pub struct StatusCode(int);
   impl StatusCode {
      fn shortmsg(&self) -> &'static str {
        match **self {
            401 => "Not authorized",
            404 => "Not found",
            505 => "HTTP Version Not Supported",
            _   => {fail!(fmt!("shortmsg not implemented for error code %?", self));}
         }
      }
      fn longmsg(&self) -> &'static str {
         match **self {
            400 => "The request is not well-formatted",
            401 => "The file cannot be accessed",
            404 => "The requested resource could not be found",
            505 => "The server does not support the HTTP protocol version used in the request",
            _   => {fail!(fmt!("longmsg not implemented for error code %?", self));}
         }
      }
   }
}

// TODO: investigate core::unstable::Exclusive
type ConnectMsg = (tcp::TcpNewConnection, core::unstable::Exclusive<core::comm::Chan<Option<tcp::TcpErrData>>>);

fn print_usage(program: ~str) {
   fail!(fmt!("Usage: %s -p port -s pool_size -d web_dir", program));
}

// Another version to parse the arguments, which uses getopts
fn parse_arguments_with_getopts(args: ~[~str]) -> (uint, uint, ~str) {
   let opts = ~[
      optopt("p"),
      optopt("s"),
      optopt("d")
   ];
   let matches = match getopts(vec::tail(args), opts) {
      result::Ok(m) => { m }
      result::Err(f) => {fail!(fail_str(f));}
   };
   let port = uint::from_str(opt_str(&matches, "p")).get();
   let pool_size = uint::from_str(opt_str(&matches, "s")).get();
   let web_dir = opt_str(&matches, "d");

   if port == -1 || pool_size == -1 || web_dir == ~"" {
      io::println("Bad arguments values: ");
      print_usage(copy args[0]);
   }

   (port, pool_size, web_dir)
}

/* read the file path */
fn read_file(path: ~str) -> (~[u8], int) {
   let res = io::read_whole_file(&Path(path));
   if result::is_err(&res) {
      // XXX how to make the difference between file not found and not authorized?
      // In both cases res = Err(~"error opening file")
      (~[], 404)
   } else {
      (res.get(), 200)
   }
}

/*
 * Read an HTTP request and return a couple (line, code).
 * Block until a line has been read, in which case line is
 * the line that has been read and code=0, or return the line
 * that has been read so far and code=1 in case of error.
 */
fn read_request(socket: &tcp::TcpSocket) -> (~str, uint) {
   let mut req: ~str = ~"";
   loop {
      let result = socket.read(0u);
      if result.is_err() {
         return (req, 1);
      }

      let req2 = req + str::from_bytes(result.get());
      let req = req2;
      if str::contains(req, "\n") {
         return (req, 0);
      }
   }
}

fn clienterror(socket: &tcp::TcpSocket, cause: &str, errorcode: StatusCodes::StatusCode) {
   let errnum = errorcode.to_str();
   let shortmsg = errorcode.shortmsg();
   let longmsg = errorcode.longmsg();
   io::println(fmt!("Client error: %s -> %s %s %s", cause, errnum, shortmsg, longmsg));

   let body = ~"<title>Simple Web Server Error</title>\r\n"
      + fmt!("%s: %s\r\n", errnum, shortmsg)
      + fmt!("
%s: %s
\r\n", longmsg, cause)
      + ~"
The Simple Web Server\r\n";
   let header = fmt!("HTTP/1.0 %s %s\r\n", errnum, shortmsg) + ~"Content-type: text/html\r\n" + fmt!("Content-length: %u\r\n\r\n", body.len());

   socket.write(str::to_bytes(header));
   socket.write(str::to_bytes(body));
}

fn get_file_type(filename: &str) -> ~str {
   if str::ends_with(filename, ~".html") {
      ~"text/html"
   } else if str::ends_with(filename, ~".gif") {
      ~"image/gif"
   } else if str::ends_with(filename, ~".jpg") {
      ~"image/jpeg"
   } else {
      ~"text/plain"
   }
}

fn clientsuccess(socket: &tcp::TcpSocket, filename: &str, content: ~[u8]) {
   let filetype = get_file_type(filename);

   let header = ~"HTTP/1.0 200 OK\r\nServer: Simple Web Server\r\n"
      +fmt!("Content-length: %u\r\n", content.len())
      +fmt!("Content-type: %s\r\n\r\n", filetype);

   socket.write(str::to_bytes(header));
   socket.write(content);
}

fn handle_connection(port_endpoint: ~Port<ConnectMsg>, web_dir: ~str) {
   // this is the task which accepts new connections
   do task::spawn{
      loop {
         let (conn, kill_ch) = port_endpoint.recv();
         io::println("Going to accept a new connection");
         match tcp::accept(conn) {
            result::Err(err) => {
               io::println(fmt!("Connection error: %?", err));
               kill_ch.send(Some(err));
            },
            result::Ok(socket) => {
               let peer_addr: ~str = ip::format_addr(&socket.get_peer_addr());
               io::println(fmt!("Connection accepted from %s", peer_addr));

               let (request, code) = read_request(&socket);
               if code == 0 {
                  // FIXME: hacky
                  let mut words = ~[];
                  for str::each_word(request) |word| { words.push(word) }

                  if words.len() < 3 {
                     clienterror(&socket, request, StatusCode(400));
                  } else if words[0] != ~"GET" {
                     clienterror(&socket, request, StatusCode(501));
                  } else if words[2] != ~"HTTP/1.1" {
                     clienterror(&socket, request, StatusCode(505));
                  } else {
                     let (content, code) = read_file(web_dir + words[1]);
                     match code {
                        200 => {clientsuccess(&socket, copy words[1], content);},
                        404 => {clienterror(&socket, copy words[1], StatusCode(404));},
                        401 => {clienterror(&socket, copy words[1], StatusCode(401));},
                        _   => {fail!(fmt!("Unknown error code: %d", code));}
                     }
                  }
               }
            }
         }
      }
   }
}

fn main()  {
   let args : ~[~str] = os::args();
   if (args.len() != 7) {
      io::print("Bad length: ");
      print_usage(copy args[0]);
   }

   let (port, pool_size, web_dir) = parse_arguments_with_getopts(args);

   //to play with string concatenation
   io::println(~"port is " + uint::to_str(port));
   io::println(~"pool size is " + uint::to_str(pool_size));
   io::println(~"web dir is " + web_dir);

   //Connection information will be transmitted using this Port and Chan
   let (port_endpoint, chan_endpoint): (Port<ConnectMsg>, Chan<ConnectMsg>) = stream();

   handle_connection(~port_endpoint, web_dir);

   let result = tcp::listen(ip::v4::parse_addr("127.0.0.1"), port, 100,
         &uv::global_loop::get(),
         |_|{
            io::println("Server is now listening!");
         },
         |conn, kill_chan| {
            // The connection must be accepted from another task or the server will block.
            chan_endpoint.send((conn, kill_chan));
         }
   );

   if result.is_err() {
      fail!(fmt!("failed listen: %?", result.get_err()));
   }
}

<|endoftext|>


<commit_before>//! This module provides an oct-tree of `Cube`s, which are the basic building
//! blocks of **Bismuth**. The tree is internally comprised of `Node`s.
//! `BranchNode`s contain links to sub-trees and `LeafNode`s contain geometric
//! data associated with their respective spatial partition. However, `Node`s do
//! not contain any spatial data (origin, partition, etc.); instead, this is
//! calculated during traversals by `Cube`, which acts as a recursive view over
//! the `Node`s in the tree and provides the primary interface for interacting
//! with trees.
//!
//! Leaf `Cube`s provide the geometric and spatial data that together represent
//! the shape and layout of the game world.
//!
//! `Cube`s reference `Node`s in the tree, and abstract over the mutability of
//! those references. This module exposes the `CubeRef` and `CubeMut` type
//! definitions for immutable and mutable `Cube`s, respectively.
//!
//! Because `Cube`s reference `Node`s and `Node`s may reference other `Node`s
//! in a tree, orphan types are provided that only expose payloads and no links.
//! This is useful when collecting `Cube`s, because otherwise the references
//! into the rest of the tree would lead to aliasing. `OrphanCubeRef` and
//! `OrphanCubeMut` are the orphan analogues of `CubeRef` and `CubeMut`,
//! respectively. Orphans of course do not support indexing or traversal.
//!
//! `Root` can be used to create a new tree, and owns the root `Node`. `Root`s
//! expose `Cube`s to manipulate the tree.
//!
//! # Examples
//!
//! Subdividing and iterating over the cubes in a tree:
//!
//! ```
//! let mut root = Root::new(LogWidth::max_value());
//! let _ = root.to_cube_mut().subdivide();
//! for cube in root.to_cube().iter() {
//!     println!("origin: {}; width: {}", cube.partition().origin(), cube.partition().width());
//! }
//! ```

mod edit;
mod geometry;
mod space;
mod tree;

use self::tree::{Cube, OrphanCube};

pub use self::edit::Cursor;
pub use self::geometry::{Edge, Geometry, Offset};
pub use self::space::{AABB, Axis, Direction, LogWidth, Orientation, Partition, Spatial};
pub use self::tree::{BranchNode, BranchPayload, LeafNode, LeafPayload, Node, OrphanNode, Root};

pub type CubeRef<'a> = Cube<'a, &'a Node>;
pub type CubeMut<'a> = Cube<'a, &'a mut Node>;
pub type OrphanCubeRef<'a> = OrphanCube<'a, &'a LeafPayload, &'a BranchPayload>;
pub type OrphanCubeMut<'a> = OrphanCube<'a, &'a mut LeafPayload, &'a mut BranchPayload>;

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Fix `cube` module's doc example.<commit_after>//! This module provides an oct-tree of `Cube`s, which are the basic building
//! blocks of **Bismuth**. The tree is internally comprised of `Node`s.
//! `BranchNode`s contain links to sub-trees and `LeafNode`s contain geometric
//! data associated with their respective spatial partition. However, `Node`s do
//! not contain any spatial data (origin, partition, etc.); instead, this is
//! calculated during traversals by `Cube`, which acts as a recursive view over
//! the `Node`s in the tree and provides the primary interface for interacting
//! with trees.
//!
//! Leaf `Cube`s provide the geometric and spatial data that together represent
//! the shape and layout of the game world.
//!
//! `Cube`s reference `Node`s in the tree, and abstract over the mutability of
//! those references. This module exposes the `CubeRef` and `CubeMut` type
//! definitions for immutable and mutable `Cube`s, respectively.
//!
//! Because `Cube`s reference `Node`s and `Node`s may reference other `Node`s
//! in a tree, orphan types are provided that only expose payloads and no links.
//! This is useful when collecting `Cube`s, because otherwise the references
//! into the rest of the tree would lead to aliasing. `OrphanCubeRef` and
//! `OrphanCubeMut` are the orphan analogues of `CubeRef` and `CubeMut`,
//! respectively. Orphans of course do not support indexing or traversal.
//!
//! `Root` can be used to create a new tree, and owns the root `Node`. `Root`s
//! expose `Cube`s to manipulate the tree.
//!
//! # Examples
//!
//! Subdividing and iterating over the cubes in a tree:
//!
//! ```
//! use bismuth::cube::{LogWidth, Root, Spatial};
//!
//! let mut root = Root::new(LogWidth::max_value());
//! let _ = root.to_cube_mut().subdivide();
//! for cube in root.to_cube().iter() {
//!     println!("origin: {}; width: {}",
//!              cube.partition().origin(),
//!              cube.partition().width().to_inner());
//! }
//! ```

mod edit;
mod geometry;
mod space;
mod tree;

use self::tree::{Cube, OrphanCube};

pub use self::edit::Cursor;
pub use self::geometry::{Edge, Geometry, Offset};
pub use self::space::{AABB, Axis, Direction, LogWidth, Orientation, Partition, Spatial};
pub use self::tree::{BranchNode, BranchPayload, LeafNode, LeafPayload, Node, OrphanNode, Root};

pub type CubeRef<'a> = Cube<'a, &'a Node>;
pub type CubeMut<'a> = Cube<'a, &'a mut Node>;
pub type OrphanCubeRef<'a> = OrphanCube<'a, &'a LeafPayload, &'a BranchPayload>;
pub type OrphanCubeMut<'a> = OrphanCube<'a, &'a mut LeafPayload, &'a mut BranchPayload>;

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>


<commit_before>//! Directory module for managing Algorithmia Data Directories
//!
//! # Examples
//!
//! ```no_run
//! use algorithmia::Algorithmia;
//! use std::fs::File;
//!
//! let client = Algorithmia::client("111112222233333444445555566");
//! let my_dir = client.dir(".my/my_dir");
//!
//! my_dir.create();
//! my_dir.put_file("/path/to/file");
//! ```

extern crate hyper;
extern crate chrono;

use {Algorithmia, AlgorithmiaError, ApiErrorResponse, HttpClient};
use hyper::Url;
use hyper::status::StatusCode;
use rustc_serialize::{json, Decoder, Decodable};
use std::io::Read;
use std::fs::File;
use std::path::Path;
use std::vec::IntoIter;
use hyper::header::ContentType;
use hyper::mime::{Mime, TopLevel, SubLevel};
use self::chrono::{DateTime, UTC};
use super::{parse_data_uri, HasDataPath, DataFile, FileAddedResult, FileAdded, DeletedResult, XDataType};
use std::error::Error;
use std::ops::Deref;

/// Algorithmia Data Directory
pub struct DataDir {
    path: String,
    client: HttpClient,
}

pub type DirectoryCreatedResult = Result<(), AlgorithmiaError>;
pub type DirectoryDeletedResult = Result<DirectoryDeleted, AlgorithmiaError>;

#[derive(RustcDecodable, Debug)]
pub struct DirectoryUpdated {
    pub acl: Option<DataAcl>,
}

/// Response when deleting a new Directory
#[derive(RustcDecodable, Debug)]
pub struct DirectoryDeleted {
    // Omitting deleted.number and error.number for now
    pub result: DeletedResult,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct FolderEntry {
    pub name: String,
    pub acl: Option<DataAcl>,
}

#[derive(Debug)]
pub struct FileEntry {
    pub filename: String,
    pub size: u64,
    pub last_modified: DateTime<UTC>,
}

// Manual implemented Decodable: https://github.com/lifthrasiir/rust-chrono/issues/43
impl Decodable for FileEntry {
    fn decode<D: Decoder>(d: &mut D) -> Result<FileEntry, D::Error> {
        d.read_struct("root", 0, |d| {
            Ok(FileEntry{
                filename: try!(d.read_struct_field("filename", 0, |d| Decodable::decode(d))),
                size: try!(d.read_struct_field("size", 0, |d| Decodable::decode(d))),
                last_modified: {
                    let json_str: String = try!(d.read_struct_field("last_modified", 0, |d| Decodable::decode(d)));
                    match json_str.parse() {
                        Ok(datetime) => datetime,
                        Err(err) => return Err(d.error(err.description())),
                    }
                },
            })
        })
    }
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct DataAcl {
    pub read: Vec<String>
}

/// Response when querying an existing Directory
#[derive(RustcDecodable, Debug)]
struct DirectoryShow {
    pub acl: Option<DataAcl>,
    pub folders: Option<Vec<FolderEntry>>,
    pub files: Option<Vec<FileEntry>>,
    pub marker: Option<String>,
}

pub struct DirectoryListing<'a> {
    pub acl: Option<DataAcl>,
    dir: &'a DataDir,
    folders: IntoIter<FolderEntry>,
    files: IntoIter<FileEntry>,
    marker: Option<String>,
}

impl <'a> DirectoryListing<'a> {
    fn new(dir: &'a DataDir) -> DirectoryListing<'a> {
        DirectoryListing {
            acl: None,
            dir: dir,
            folders: Vec::new().into_iter(),
            files: Vec::new().into_iter(),
            marker: None,
        }
    }
}

pub struct DataFileEntry {
    pub size: u64,
    pub last_modified: DateTime<UTC>,
    file: DataFile,
}

impl Deref for DataFileEntry {
    type Target = DataFile;
    fn deref(&self) -> &DataFile {&self.file}
}

pub enum DirEntry {
    File(DataFileEntry),
    Dir(DataDir),
}

impl <'a> Iterator for DirectoryListing<'a> {
    type Item = Result<DirEntry, AlgorithmiaError>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.folders.next() {
            Some(d) => Some(Ok(DirEntry::Dir(self.dir.child(&d.name)))),
            None => match self.files.next() {
                Some(f) => Some(Ok(DirEntry::File(
                    DataFileEntry{
                        size: f.size,
                        last_modified: f.last_modified,
                        file: self.dir.child(&f.filename),
                    }
                ))),
                None => match self.marker.clone() {
                    Some(m) => match get_directory(self.dir, Some(m)) {
                        Ok(ds) => {
                            self.folders = ds.folders.unwrap_or(Vec::new()).into_iter();
                            self.files = ds.files.unwrap_or(Vec::new()).into_iter();
                            self.marker = ds.marker;
                            self.next()
                        }
                        Err(err) => Some(Err(err)),
                    },
                    None => None,
                }
            }
        }
    }
}

fn get_directory(dir: &DataDir, marker: Option<String>) -> Result<DirectoryShow, AlgorithmiaError> {
    let url = match marker {
        Some(m) => Url::parse(&format!("{}?marker={}", dir.to_url(), m)).unwrap(),
        None => dir.to_url(),
    };

    let req = dir.client.get(url);
    let mut res = try!(req.send());

    if let Some(data_type) = res.headers.get::<XDataType>() {
        if "directory" != data_type.to_string() {
            return Err(AlgorithmiaError::DataTypeError(format!("Expected directory, Received {}", data_type)));
        }
    }

    let mut res_json = String::new();
    try!(res.read_to_string(&mut res_json));

    match json::decode::<DirectoryShow>(&res_json) {
        Ok(result) => Ok(result),
        Err(why) => match json::decode::<ApiErrorResponse>(&res_json) {
            Ok(err_res) => Err(AlgorithmiaError::AlgorithmiaApiError(err_res.error)),
            Err(_) => Err(AlgorithmiaError::DecoderErrorWithContext(why, res_json)),
        }
    }
}

impl HasDataPath for DataDir {
    fn new(client: HttpClient, path: &str) -> Self { DataDir { client: client, path: parse_data_uri(path).to_string() } }
    fn path(&self) -> &str { &self.path }
    fn client(&self) -> &HttpClient { &self.client }
}

impl DataDir {
    /// Display Directory details if it exists
    ///
    /// # Examples
    /// ```no_run
    /// # use algorithmia::Algorithmia;
    /// # use algorithmia::data::{DirEntry, HasDataPath};
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let my_dir = client.dir(".my/my_dir");
    /// let dir_list = my_dir.list();
    /// for entry in dir_list {
    ///     match entry {
    ///         Ok(DirEntry::File(f)) => println!("File: {}", f.to_data_uri()),
    ///         Ok(DirEntry::Dir(d)) => println!("Dir: {}", d.to_data_uri()),
    ///         Err(err) => { println!("Error: {:?}", err); break; },
    ///     }
    /// };
    /// ```
    pub fn list(&self) -> DirectoryListing {
        DirectoryListing::new(self)
    }

    /// Create a Directory
    ///
    /// # Examples
    /// ```no_run
    /// # use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let my_dir = client.dir(".my/my_dir");
    /// match my_dir.create() {
    ///   Ok(_) => println!("Successfully created Directory"),
    ///   Err(e) => println!("ERROR creating Directory: {:?}", e),
    /// };
    /// ```
    pub fn create(&self) -> DirectoryCreatedResult {
        let url = self.parent().unwrap().to_url(); //TODO: don't unwrap this

        // TODO: complete abuse of this structure
        let input_data = FolderEntry {
            name: self.basename().unwrap().to_string(), //TODO: don't unwrap this
            acl: Some(DataAcl { read: vec![] }),
        };
        let raw_input = try!(json::encode(&input_data));

        // POST request
        let req = self.client.post(url)
            .header(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])))
            .body(&raw_input);

        // Parse response
        let mut res = try!(req.send());

        match res.status {
            StatusCode::Ok | StatusCode::Created => Ok(()),
            _ => {
                let mut res_json = String::new();
                try!(res.read_to_string(&mut res_json));
                Err(Algorithmia::decode_to_error(res_json))
            }
        }
    }

    /// Delete a Directory
    ///
    /// # Examples
    /// ```no_run
    /// # use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let my_dir = client.dir(".my/my_dir");
    /// match my_dir.delete(false) {
    ///   Ok(_) => println!("Successfully deleted Directory"),
    ///   Err(e) => println!("ERROR deleting Directory: {:?}", e),
    /// };
    /// ```
    pub fn delete(&self, force: bool) -> DirectoryDeletedResult {
        // DELETE request
        let url_string = format!("{}?force={}", self.to_url(), force.to_string());
        let url = Url::parse(&url_string).unwrap();
        let req = self.client.delete(url);

        // Parse response
        let mut res = try!(req.send());
        let mut res_json = String::new();
        try!(res.read_to_string(&mut res_json));

        Algorithmia::decode_to_result::<DirectoryDeleted>(res_json)
    }

    /// Upload a file to an existing Directory
    ///
    /// # Examples
    /// ```no_run
    /// # use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let my_dir = client.dir(".my/my_dir");
    ///
    /// match my_dir.put_file("/path/to/file") {
    ///   Ok(response) => println!("Successfully uploaded to: {}", response.result),
    ///   Err(e) => println!("ERROR uploading file: {:?}", e),
    /// };
    /// ```
    pub fn put_file<P: AsRef<Path>>(&self, file_path: P) -> FileAddedResult {
        // FIXME: A whole lot of unwrap going on here...
        let path_ref = file_path.as_ref();
        let url_string = format!("{}/{}",
            self.to_url(),
            path_ref.file_name().unwrap().to_str().unwrap()
        );
        let url = Url::parse(&url_string).unwrap();

        let mut file = File::open(path_ref).unwrap();
        let req = self.client.put(url).body(&mut file);

        let mut res = try!(req.send());
        let mut res_json = String::new();
        try!(res.read_to_string(&mut res_json));

        Algorithmia::decode_to_result::<FileAdded>(res_json)
    }

    pub fn child<T: HasDataPath>(&self, filename: &str) -> T {
        T::new(self.client.clone(), &format!("{}/{}", self.to_data_uri(), filename))
    }
}

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

    fn mock_client() -> Algorithmia { Algorithmia::client("") }

    #[test]
    fn test_to_url() {
        let dir = DataDir::new(mock_client().http_client, "data://anowell/foo");
        assert_eq!(dir.to_url().serialize(), format!("{}/v1/data/anowell/foo", Algorithmia::get_base_url()));
    }

    #[test]
    fn test_to_data_uri() {
        let dir = DataDir::new(mock_client().http_client, "/anowell/foo");
        assert_eq!(dir.to_data_uri(), "data://anowell/foo".to_string());
    }

    #[test]
    fn test_parent() {
        let dir = DataDir::new(mock_client().http_client, "data://anowell/foo");
        let expected = DataDir::new(mock_client().http_client, "data://anowell");
        assert_eq!(dir.parent().unwrap().path, expected.path);
    }
}<commit_msg>Fix dir listing to actually return results<commit_after>//! Directory module for managing Algorithmia Data Directories
//!
//! # Examples
//!
//! ```no_run
//! use algorithmia::Algorithmia;
//! use std::fs::File;
//!
//! let client = Algorithmia::client("111112222233333444445555566");
//! let my_dir = client.dir(".my/my_dir");
//!
//! my_dir.create();
//! my_dir.put_file("/path/to/file");
//! ```

extern crate hyper;
extern crate chrono;

use {Algorithmia, AlgorithmiaError, ApiErrorResponse, HttpClient};
use hyper::Url;
use hyper::status::StatusCode;
use rustc_serialize::{json, Decoder, Decodable};
use std::io::Read;
use std::fs::File;
use std::path::Path;
use std::vec::IntoIter;
use hyper::header::ContentType;
use hyper::mime::{Mime, TopLevel, SubLevel};
use self::chrono::{DateTime, UTC};
use super::{parse_data_uri, HasDataPath, DataFile, FileAddedResult, FileAdded, DeletedResult, XDataType};
use std::error::Error;
use std::ops::Deref;

/// Algorithmia Data Directory
pub struct DataDir {
    path: String,
    client: HttpClient,
}

pub type DirectoryCreatedResult = Result<(), AlgorithmiaError>;
pub type DirectoryDeletedResult = Result<DirectoryDeleted, AlgorithmiaError>;

#[derive(RustcDecodable, Debug)]
pub struct DirectoryUpdated {
    pub acl: Option<DataAcl>,
}

/// Response when deleting a new Directory
#[derive(RustcDecodable, Debug)]
pub struct DirectoryDeleted {
    // Omitting deleted.number and error.number for now
    pub result: DeletedResult,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct FolderEntry {
    pub name: String,
    pub acl: Option<DataAcl>,
}

#[derive(Debug)]
pub struct FileEntry {
    pub filename: String,
    pub size: u64,
    pub last_modified: DateTime<UTC>,
}

// Manual implemented Decodable: https://github.com/lifthrasiir/rust-chrono/issues/43
impl Decodable for FileEntry {
    fn decode<D: Decoder>(d: &mut D) -> Result<FileEntry, D::Error> {
        d.read_struct("root", 0, |d| {
            Ok(FileEntry{
                filename: try!(d.read_struct_field("filename", 0, |d| Decodable::decode(d))),
                size: try!(d.read_struct_field("size", 0, |d| Decodable::decode(d))),
                last_modified: {
                    let json_str: String = try!(d.read_struct_field("last_modified", 0, |d| Decodable::decode(d)));
                    match json_str.parse() {
                        Ok(datetime) => datetime,
                        Err(err) => return Err(d.error(err.description())),
                    }
                },
            })
        })
    }
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct DataAcl {
    pub read: Vec<String>
}

/// Response when querying an existing Directory
#[derive(RustcDecodable, Debug)]
struct DirectoryShow {
    pub acl: Option<DataAcl>,
    pub folders: Option<Vec<FolderEntry>>,
    pub files: Option<Vec<FileEntry>>,
    pub marker: Option<String>,
}

pub struct DirectoryListing<'a> {
    pub acl: Option<DataAcl>,
    dir: &'a DataDir,
    folders: IntoIter<FolderEntry>,
    files: IntoIter<FileEntry>,
    marker: Option<String>,
    query_count: u32,
}

impl <'a> DirectoryListing<'a> {
    fn new(dir: &'a DataDir) -> DirectoryListing<'a> {
        DirectoryListing {
            acl: None,
            dir: dir,
            folders: Vec::new().into_iter(),
            files: Vec::new().into_iter(),
            marker: None,
            query_count: 0,
        }
    }
}

pub struct DataFileEntry {
    pub size: u64,
    pub last_modified: DateTime<UTC>,
    file: DataFile,
}

impl Deref for DataFileEntry {
    type Target = DataFile;
    fn deref(&self) -> &DataFile {&self.file}
}

pub enum DirEntry {
    File(DataFileEntry),
    Dir(DataDir),
}

impl <'a> Iterator for DirectoryListing<'a> {
    type Item = Result<DirEntry, AlgorithmiaError>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.folders.next() {
            // Return folders first
            Some(d) => Some(Ok(DirEntry::Dir(self.dir.child(&d.name)))),
            None => match self.files.next() {
                // Return files second
                Some(f) => Some(Ok(DirEntry::File(
                    DataFileEntry{
                        size: f.size,
                        last_modified: f.last_modified,
                        file: self.dir.child(&f.filename),
                    }
                ))),
                None => {
                    // Query if there is another page of files/folders
                    if self.query_count == 0 || self.marker.is_some() {
                        match get_directory(self.dir, self.marker.clone()) {
                            Ok(ds) => {
                                self.query_count = self.query_count + 1;
                                self.folders = ds.folders.unwrap_or(Vec::new()).into_iter();
                                self.files = ds.files.unwrap_or(Vec::new()).into_iter();
                                self.marker = ds.marker;
                                self.next()
                            }
                            Err(err) => Some(Err(err)),
                        }
                    } else {
                        None
                    }
                }
            }
        }
    }
}

fn get_directory(dir: &DataDir, marker: Option<String>) -> Result<DirectoryShow, AlgorithmiaError> {
    let url = match marker {
        Some(m) => Url::parse(&format!("{}?marker={}", dir.to_url(), m)).unwrap(),
        None => dir.to_url(),
    };

    let req = dir.client.get(url);
    let mut res = try!(req.send());

    if let Some(data_type) = res.headers.get::<XDataType>() {
        if "directory" != data_type.to_string() {
            return Err(AlgorithmiaError::DataTypeError(format!("Expected directory, Received {}", data_type)));
        }
    }

    let mut res_json = String::new();
    try!(res.read_to_string(&mut res_json));

    match json::decode::<DirectoryShow>(&res_json) {
        Ok(result) => Ok(result),
        Err(why) => match json::decode::<ApiErrorResponse>(&res_json) {
            Ok(err_res) => Err(AlgorithmiaError::AlgorithmiaApiError(err_res.error)),
            Err(_) => Err(AlgorithmiaError::DecoderErrorWithContext(why, res_json)),
        }
    }
}

impl HasDataPath for DataDir {
    fn new(client: HttpClient, path: &str) -> Self { DataDir { client: client, path: parse_data_uri(path).to_string() } }
    fn path(&self) -> &str { &self.path }
    fn client(&self) -> &HttpClient { &self.client }
}

impl DataDir {
    /// Display Directory details if it exists
    ///
    /// # Examples
    /// ```no_run
    /// # use algorithmia::Algorithmia;
    /// # use algorithmia::data::{DirEntry, HasDataPath};
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let my_dir = client.dir(".my/my_dir");
    /// let dir_list = my_dir.list();
    /// for entry in dir_list {
    ///     match entry {
    ///         Ok(DirEntry::File(f)) => println!("File: {}", f.to_data_uri()),
    ///         Ok(DirEntry::Dir(d)) => println!("Dir: {}", d.to_data_uri()),
    ///         Err(err) => { println!("Error: {:?}", err); break; },
    ///     }
    /// };
    /// ```
    pub fn list(&self) -> DirectoryListing {
        DirectoryListing::new(self)
    }

    /// Create a Directory
    ///
    /// # Examples
    /// ```no_run
    /// # use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let my_dir = client.dir(".my/my_dir");
    /// match my_dir.create() {
    ///   Ok(_) => println!("Successfully created Directory"),
    ///   Err(e) => println!("ERROR creating Directory: {:?}", e),
    /// };
    /// ```
    pub fn create(&self) -> DirectoryCreatedResult {
        let url = self.parent().unwrap().to_url(); //TODO: don't unwrap this

        // TODO: complete abuse of this structure
        let input_data = FolderEntry {
            name: self.basename().unwrap().to_string(), //TODO: don't unwrap this
            acl: Some(DataAcl { read: vec![] }),
        };
        let raw_input = try!(json::encode(&input_data));

        // POST request
        let req = self.client.post(url)
            .header(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])))
            .body(&raw_input);

        // Parse response
        let mut res = try!(req.send());

        match res.status {
            StatusCode::Ok | StatusCode::Created => Ok(()),
            _ => {
                let mut res_json = String::new();
                try!(res.read_to_string(&mut res_json));
                Err(Algorithmia::decode_to_error(res_json))
            }
        }
    }

    /// Delete a Directory
    ///
    /// # Examples
    /// ```no_run
    /// # use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let my_dir = client.dir(".my/my_dir");
    /// match my_dir.delete(false) {
    ///   Ok(_) => println!("Successfully deleted Directory"),
    ///   Err(e) => println!("ERROR deleting Directory: {:?}", e),
    /// };
    /// ```
    pub fn delete(&self, force: bool) -> DirectoryDeletedResult {
        // DELETE request
        let url_string = format!("{}?force={}", self.to_url(), force.to_string());
        let url = Url::parse(&url_string).unwrap();
        let req = self.client.delete(url);

        // Parse response
        let mut res = try!(req.send());
        let mut res_json = String::new();
        try!(res.read_to_string(&mut res_json));

        Algorithmia::decode_to_result::<DirectoryDeleted>(res_json)
    }

    /// Upload a file to an existing Directory
    ///
    /// # Examples
    /// ```no_run
    /// # use algorithmia::Algorithmia;
    /// let client = Algorithmia::client("111112222233333444445555566");
    /// let my_dir = client.dir(".my/my_dir");
    ///
    /// match my_dir.put_file("/path/to/file") {
    ///   Ok(response) => println!("Successfully uploaded to: {}", response.result),
    ///   Err(e) => println!("ERROR uploading file: {:?}", e),
    /// };
    /// ```
    pub fn put_file<P: AsRef<Path>>(&self, file_path: P) -> FileAddedResult {
        // FIXME: A whole lot of unwrap going on here...
        let path_ref = file_path.as_ref();
        let url_string = format!("{}/{}",
            self.to_url(),
            path_ref.file_name().unwrap().to_str().unwrap()
        );
        let url = Url::parse(&url_string).unwrap();

        let mut file = File::open(path_ref).unwrap();
        let req = self.client.put(url).body(&mut file);

        let mut res = try!(req.send());
        let mut res_json = String::new();
        try!(res.read_to_string(&mut res_json));

        Algorithmia::decode_to_result::<FileAdded>(res_json)
    }

    pub fn child<T: HasDataPath>(&self, filename: &str) -> T {
        T::new(self.client.clone(), &format!("{}/{}", self.to_data_uri(), filename))
    }
}

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

    fn mock_client() -> Algorithmia { Algorithmia::client("") }

    #[test]
    fn test_to_url() {
        let dir = DataDir::new(mock_client().http_client, "data://anowell/foo");
        assert_eq!(dir.to_url().serialize(), format!("{}/v1/data/anowell/foo", Algorithmia::get_base_url()));
    }

    #[test]
    fn test_to_data_uri() {
        let dir = DataDir::new(mock_client().http_client, "/anowell/foo");
        assert_eq!(dir.to_data_uri(), "data://anowell/foo".to_string());
    }

    #[test]
    fn test_parent() {
        let dir = DataDir::new(mock_client().http_client, "data://anowell/foo");
        let expected = DataDir::new(mock_client().http_client, "data://anowell");
        assert_eq!(dir.parent().unwrap().path, expected.path);
    }
}<|endoftext|>


<commit_before>use crate::text::{Attributes, Text};
use crate::widgets::{Widget, WidgetStream};
use alsa::mixer::{SelemChannelId, SelemId};
use alsa::{self, Mixer, PollDescriptors};
use anyhow::{anyhow, Error, Result};
use mio::unix::SourceFd;
use mio::{event, Interest, Registry, Token};
use std::io;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::RawFd;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::unix::AsyncFd;
use tokio_stream::{Stream, StreamExt};

/// Shows the current volume of the default ALSA output.
///
/// This widget shows the current volume of the default ALSA output, or '`M`' if
/// the output is muted.
///
/// The widget uses `alsa-lib` to receive events when the volume changes,
/// avoiding expensive polling. If you do not have `alsa-lib` installed, you
/// can disable the `volume-widget` feature on the `cnx` crate to avoid
/// compiling this widget.
pub struct Volume {
    attr: Attributes,
}

impl Volume {
    /// Creates a new Volume widget.
    ///
    /// Creates a new `Volume` widget, whose text will be displayed
    /// with the given [`Attributes`].
    ///
    /// The [`Cnx`] instance is borrowed during construction in order to get
    /// access to handles of its event loop. However, it is not borrowed for the
    /// lifetime of the widget. See the [`cnx_add_widget!()`] for more discussion
    /// about the lifetime of the borrow.
    ///
    /// [`Attributes`]: ../text/struct.Attributes.html
    /// [`Cnx`]: ../struct.Cnx.html
    /// [`cnx_add_widget!()`]: ../macro.cnx_add_widget.html
    ///
    /// # Examples
    ///
    /// ```
    /// # #[macro_use]
    /// # extern crate cnx;
    /// #
    /// # use cnx::*;
    /// # use cnx::text::*;
    /// # use cnx::widgets::*;
    /// #
    /// # fn run() -> ::cnx::Result<()> {
    /// let attr = Attributes {
    ///     font: Font::new("SourceCodePro 21"),
    ///     fg_color: Color::white(),
    ///     bg_color: None,
    ///     padding: Padding::new(8.0, 8.0, 0.0, 0.0),
    /// };
    ///
    /// let mut cnx = Cnx::new(Position::Top)?;
    /// cnx_add_widget!(cnx, Volume::new(&cnx, attr.clone()));
    /// # Ok(())
    /// # }
    /// # fn main() { run().unwrap(); }
    /// ```
    pub fn new(attr: Attributes) -> Volume {
        Volume { attr }
    }
}

// https://github.com/mjkillough/cnx/blob/92c24238be541c75d88181208862505739be33fd/src/widgets/volume.rs

impl Widget for Volume {
    fn into_stream(self: Box<Self>) -> Result<WidgetStream> {
        let mixer_name = "default";
        // We don't attempt to use the same mixer to listen for events and to
        // recompute the mixer state (in the callback below) as the Mixer seems
        // to cache the state from when it was created. It's relatively cheap
        // create a new mixer each time we get an event though.
        let mixer = Mixer::new(mixer_name, true)?;
        // .with_context(|_| format!("Failed to open ALSA mixer: {}", mixer_name))?;
        let stream = AlsaEventStream::new(mixer).unwrap().map(move |()| {
            // FrontLeft has special meaning in ALSA and is the channel
            // that's used when the mixer is mono.
            let channel = SelemChannelId::FrontLeft;

            let mixer = Mixer::new(mixer_name, true)?;
            let master = mixer.find_selem(&SelemId::new("Master", 0)).unwrap();
            // .ok_or_else(|| format!("Couldn't open Master channel"))?;

            let mute = master.get_playback_switch(channel)? == 0;

            let text = if !mute {
                let volume = master.get_playback_volume(channel)?;
                let (min, max) = master.get_playback_volume_range();
                let percentage = (volume as f64 / (max as f64 - min as f64)) * 100.0;
                format!("{:.0}%", percentage)
            } else {
                "M".to_owned()
            };

            Ok(vec![Text {
                attr: self.attr.clone(),
                text: text,
                stretch: false,
            }])
        });

        Ok(Box::pin(stream))
    }
}

struct AlsaEvented(Mixer);

impl AlsaEvented {
    fn mixer(&self) -> &Mixer {
        &self.0
    }

    fn fds(&self) -> Vec<RawFd> {
        self.0
            .get()
            .unwrap()
            .iter()
            .map(|pollfd| pollfd.fd)
            .collect()
    }
}

// impl event::Source for AlsaEvented {
//     fn register(
//         &mut self,
//         registry: &Registry,
//         token: Token,
//         interests: Interest,
//     ) -> io::Result<()> {
//         for fd in &self.fds() {
//             SourceFd(fd).register(registry, token, interests)?
//         }
//         Ok(())
//     }

//     fn reregister(
//         &mut self,
//         registry: &Registry,
//         token: Token,
//         interests: Interest,
//     ) -> io::Result<()> {
//         for fd in &self.fds() {
//             SourceFd(fd).reregister(registry, token, interests);
//         }
//         Ok(())
//     }

//     fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
//         // XXX If the set of fds changes (it won't), should we deregister the
//         // original set?
//         for fd in &self.fds() {
//             SourceFd(fd).deregister(registry);
//         }
//         Ok(())
//     }
// }

struct AlsaEventStream {
    poll: AsyncFd<AlsaEvented>,
    initial: bool,
}

impl AsRawFd for AlsaEvented {
    fn as_raw_fd(&self) -> RawFd {
        // todo: is this even correce
        self.fds().into_iter().nth(0).unwrap()
    }
}

// I'm porting one of the crates tokio 0.2 series. Since PollEvented is removed, I'm using AsyncFd for most of them and it works well. But in one of the cases - I have to watch a bucn

impl AlsaEventStream {
    fn new(mixer: Mixer) -> Result<AlsaEventStream> {
        Ok(AlsaEventStream {
            poll: AsyncFd::new(AlsaEvented(mixer))?,
            // The first few calls to poll() need to process any existing events.
            // We don't know what state the fds are in when we give them to tokio
            // and it's edge-triggered.
            initial: true,
        })
    }
}

impl Stream for AlsaEventStream {
    // We don't bother yielding the events and just yield unit each time we get
    // an event. This stream is used only to get woken up when the ALSA state
    // changes - the caller is expected to requery all necessary state when
    // it receives a new item from the stream.
    type Item = ();

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
        // Always assume we're ready initially, so that we can clear the
        // state of the fds.
        if !self.initial {
            if let Poll::Pending = self.poll.poll_read_ready(cx) {
                return Poll::Pending;
            }
        }
        self.initial = false;

        // Do a poll with a timeout of 0 to figure out exactly which fds were
        // woken up, followed by a call to revents() which clears the pending
        // events. We don't actually care what the events are - we're just
        // using it as a wake-up so we can check the volume again.

        // let mixer = self.poll.get_ref().mixer();
        // let ready = alsa::poll::poll_all(&[mixer], 0).unwrap();
        // let poll_descriptors = ready.into_iter().map(|(p, _)| p);
        // for poll_descriptor in poll_descriptors {
        //     mixer
        //         .revents(poll_descriptor.get().unwrap().as_slice())
        //         .unwrap();
        // }
        // All events have been consumed - tell Tokio we're interested in waiting
        // for more again.
        // todo
        // self.poll.need_read();
        match self.poll.poll_read_ready(cx) {
            Poll::Ready(Ok(mut r)) => {
                let mixer = self.poll.get_ref().mixer();
                let ready = alsa::poll::poll_all(&[mixer], 0).unwrap();
                let poll_descriptors = ready.into_iter().map(|(p, _)| p);
                for poll_descriptor in poll_descriptors {
                    mixer
                        .revents(poll_descriptor.get().unwrap().as_slice())
                        .unwrap();
                }
                r.clear_ready();
                return Poll::Ready(Some(()));
                // todo!()
            }
            Poll::Ready(Err(_)) => return Poll::Ready(None),
            Poll::Pending => return Poll::Pending,
        }
        // Poll::Ready(Some(()))
        // Poll::Ready(Some(()))
    }
}
<commit_msg>Minor refactor<commit_after>use crate::text::{Attributes, Text};
use crate::widgets::{Widget, WidgetStream};
use alsa::mixer::{SelemChannelId, SelemId};
use alsa::{self, Mixer, PollDescriptors};
use anyhow::{anyhow, Error, Result};
use mio::unix::SourceFd;
use mio::{event, Interest, Registry, Token};
use std::io;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::RawFd;
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::unix::AsyncFd;
use tokio_stream::{Stream, StreamExt};

/// Shows the current volume of the default ALSA output.
///
/// This widget shows the current volume of the default ALSA output, or '`M`' if
/// the output is muted.
///
/// The widget uses `alsa-lib` to receive events when the volume changes,
/// avoiding expensive polling. If you do not have `alsa-lib` installed, you
/// can disable the `volume-widget` feature on the `cnx` crate to avoid
/// compiling this widget.
pub struct Volume {
    attr: Attributes,
}

impl Volume {
    /// Creates a new Volume widget.
    ///
    /// Creates a new `Volume` widget, whose text will be displayed
    /// with the given [`Attributes`].
    ///
    /// The [`Cnx`] instance is borrowed during construction in order to get
    /// access to handles of its event loop. However, it is not borrowed for the
    /// lifetime of the widget. See the [`cnx_add_widget!()`] for more discussion
    /// about the lifetime of the borrow.
    ///
    /// [`Attributes`]: ../text/struct.Attributes.html
    /// [`Cnx`]: ../struct.Cnx.html
    /// [`cnx_add_widget!()`]: ../macro.cnx_add_widget.html
    ///
    /// # Examples
    ///
    /// ```
    /// # #[macro_use]
    /// # extern crate cnx;
    /// #
    /// # use cnx::*;
    /// # use cnx::text::*;
    /// # use cnx::widgets::*;
    /// #
    /// # fn run() -> ::cnx::Result<()> {
    /// let attr = Attributes {
    ///     font: Font::new("SourceCodePro 21"),
    ///     fg_color: Color::white(),
    ///     bg_color: None,
    ///     padding: Padding::new(8.0, 8.0, 0.0, 0.0),
    /// };
    ///
    /// let mut cnx = Cnx::new(Position::Top)?;
    /// cnx_add_widget!(cnx, Volume::new(&cnx, attr.clone()));
    /// # Ok(())
    /// # }
    /// # fn main() { run().unwrap(); }
    /// ```
    pub fn new(attr: Attributes) -> Volume {
        Volume { attr }
    }
}

// https://github.com/mjkillough/cnx/blob/92c24238be541c75d88181208862505739be33fd/src/widgets/volume.rs

impl Widget for Volume {
    fn into_stream(self: Box<Self>) -> Result<WidgetStream> {
        let mixer_name = "default";
        // We don't attempt to use the same mixer to listen for events and to
        // recompute the mixer state (in the callback below) as the Mixer seems
        // to cache the state from when it was created. It's relatively cheap
        // create a new mixer each time we get an event though.
        let mixer = Mixer::new(mixer_name, true)?;
        // .with_context(|_| format!("Failed to open ALSA mixer: {}", mixer_name))?;
        let stream = AlsaEventStream::new(mixer).unwrap().map(move |()| {
            // FrontLeft has special meaning in ALSA and is the channel
            // that's used when the mixer is mono.
            let channel = SelemChannelId::FrontLeft;

            let mixer = Mixer::new(mixer_name, true)?;
            let master = mixer.find_selem(&SelemId::new("Master", 0)).unwrap();
            // .ok_or_else(|| format!("Couldn't open Master channel"))?;

            let mute = master.get_playback_switch(channel)? == 0;

            let text = if !mute {
                let volume = master.get_playback_volume(channel)?;
                let (min, max) = master.get_playback_volume_range();
                let percentage = (volume as f64 / (max as f64 - min as f64)) * 100.0;
                format!("{:.0}%", percentage)
            } else {
                "M".to_owned()
            };

            Ok(vec![Text {
                attr: self.attr.clone(),
                text: text,
                stretch: false,
            }])
        });

        Ok(Box::pin(stream))
    }
}

struct AlsaEvented(Mixer);

impl AlsaEvented {
    fn mixer(&self) -> &Mixer {
        &self.0
    }

    fn fds(&self) -> Vec<RawFd> {
        self.0
            .get()
            .unwrap()
            .iter()
            .map(|pollfd| pollfd.fd)
            .collect()
    }
}

// impl event::Source for AlsaEvented {
//     fn register(
//         &mut self,
//         registry: &Registry,
//         token: Token,
//         interests: Interest,
//     ) -> io::Result<()> {
//         for fd in &self.fds() {
//             SourceFd(fd).register(registry, token, interests)?
//         }
//         Ok(())
//     }

//     fn reregister(
//         &mut self,
//         registry: &Registry,
//         token: Token,
//         interests: Interest,
//     ) -> io::Result<()> {
//         for fd in &self.fds() {
//             SourceFd(fd).reregister(registry, token, interests);
//         }
//         Ok(())
//     }

//     fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
//         // XXX If the set of fds changes (it won't), should we deregister the
//         // original set?
//         for fd in &self.fds() {
//             SourceFd(fd).deregister(registry);
//         }
//         Ok(())
//     }
// }

struct AlsaEventStream {
    poll: AsyncFd<AlsaEvented>,
    initial: bool,
}

impl AsRawFd for AlsaEvented {
    fn as_raw_fd(&self) -> RawFd {
        // todo: is this even correce
        self.fds().into_iter().nth(0).unwrap()
    }
}

// I'm porting one of the crates tokio 0.2 series. Since PollEvented is removed, I'm using AsyncFd for most of them and it works well. But in one of the cases - I have to watch a bucn

impl AlsaEventStream {
    fn new(mixer: Mixer) -> Result<AlsaEventStream> {
        Ok(AlsaEventStream {
            poll: AsyncFd::new(AlsaEvented(mixer))?,
            // The first few calls to poll() need to process any existing events.
            // We don't know what state the fds are in when we give them to tokio
            // and it's edge-triggered.
            initial: true,
        })
    }
}

impl Stream for AlsaEventStream {
    // We don't bother yielding the events and just yield unit each time we get
    // an event. This stream is used only to get woken up when the ALSA state
    // changes - the caller is expected to requery all necessary state when
    // it receives a new item from the stream.
    type Item = ();

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
        // Always assume we're ready initially, so that we can clear the
        // state of the fds.

        // Do a poll with a timeout of 0 to figure out exactly which fds were
        // woken up, followed by a call to revents() which clears the pending
        // events. We don't actually care what the events are - we're just
        // using it as a wake-up so we can check the volume again.
        if self.initial {
            let mixer = self.poll.get_ref().mixer();
            let ready = alsa::poll::poll_all(&[mixer], 0).unwrap();
            let poll_descriptors = ready.into_iter().map(|(p, _)| p);
            for poll_descriptor in poll_descriptors {
                mixer
                    .revents(poll_descriptor.get().unwrap().as_slice())
                    .unwrap();
            }
            self.initial = false;
            return Poll::Ready(Some(()));
        }
        // All events have been consumed - tell Tokio we're interested in waiting
        // for more again.
        // todo
        // self.poll.need_read();
        match self.poll.poll_read_ready(cx) {
            Poll::Ready(Ok(mut r)) => {
                let mixer = self.poll.get_ref().mixer();
                let ready = alsa::poll::poll_all(&[mixer], 0).unwrap();
                let poll_descriptors = ready.into_iter().map(|(p, _)| p);
                for poll_descriptor in poll_descriptors {
                    mixer
                        .revents(poll_descriptor.get().unwrap().as_slice())
                        .unwrap();
                }
                r.clear_ready();
                return Poll::Ready(Some(()));
                // todo!()
            }
            Poll::Ready(Err(_)) => return Poll::Ready(None),
            Poll::Pending => return Poll::Pending,
        }
        // Poll::Ready(Some(()))
        // Poll::Ready(Some(()))
    }
}
<|endoftext|>


<commit_before>mod args;
mod benchmarks;

use std;
use std::io::{Read, Write};

use env_logger;

use quic::threaded::{QuicConnection, QuicListener};

fn run_server(address: String) -> i32 {
    let listener = match QuicListener::bind(&*address) {
        Ok(listener) => {
            listener
        },
        Err(e) => {
            error!("Cannot bind to the address: {}", e);
            return 1;
        },
    };

    info!("Server on {}: listening for connections...", address);

    loop {
        let connection = match listener.accept() {
            Ok(connection) => {
                connection
            },
            Err(e) => {
                error!("Cannot accept a connection: {}", e);
                return 1;
            },
        };

        let mut stream = connection.get_stream(2);

        let mut buf = [0; 256];
        let amt = stream.read(&mut buf).unwrap();
        let buf = &buf[..amt];

        let inc_string = std::str::from_utf8(&buf).unwrap();
        info!("Got message: {}", inc_string);

        stream.write(buf).unwrap();
    }
}

fn run_client(address: String) -> i32 {
    let connection = match QuicConnection::new(&*address) {
        Ok(connection) => {
            connection
        },
        Err(e) => {
            error!("Cannot create a connection: {}", e);
            return 1;
        },
    };

    info!("Running client connected to {}", address);

    let mut stream = connection.get_stream(2);

    let message = "Hello";
    let out_buf = message.as_bytes();
    stream.write(out_buf).unwrap();

    let mut inc_buf = [0; 256];
    let amt = stream.read(&mut inc_buf).unwrap();
    let inc_buf = &inc_buf[..amt];
    let inc_string = std::str::from_utf8(&inc_buf).unwrap();
    info!("Got message: {}", inc_string);

    0
}

pub fn mig_demo() -> i32 {
    env_logger::init().unwrap();

    match args::parse_command() {
        Ok(args::MigCommand::Version) => {
            println!("{}", ::VERSION);
            0
        },
        Ok(args::MigCommand::Bench) => {
            benchmarks::run_all_benchmarks();
            0
        },
        Ok(args::MigCommand::Server { address }) => {
            run_server(address)
        },
        Ok(args::MigCommand::Client { address }) => {
            run_client(address)
        },
        Err(err) => {
            println!("{}", &err.message);
            err.exit_code
        },
    }
}
<commit_msg>Avoid partial reads/writes<commit_after>mod args;
mod benchmarks;

use std;
use std::io::{Read, Write};

use env_logger;

use quic::threaded::{QuicConnection, QuicListener};

fn run_server(address: String) -> i32 {
    let listener = match QuicListener::bind(&*address) {
        Ok(listener) => {
            listener
        },
        Err(e) => {
            error!("Cannot bind to the address: {}", e);
            return 1;
        },
    };

    info!("Server on {}: listening for connections...", address);

    loop {
        let connection = match listener.accept() {
            Ok(connection) => {
                connection
            },
            Err(e) => {
                error!("Cannot accept a connection: {}", e);
                return 1;
            },
        };

        let mut stream = connection.get_stream(2);

        let mut buf = vec![];
        let amt = stream.read_to_end(&mut buf).unwrap();
        let buf = &buf[..amt];

        let inc_string = std::str::from_utf8(&buf).unwrap();
        info!("Got message: {}", inc_string);

        stream.write_all(buf).unwrap();
    }
}

fn run_client(address: String) -> i32 {
    let connection = match QuicConnection::new(&*address) {
        Ok(connection) => {
            connection
        },
        Err(e) => {
            error!("Cannot create a connection: {}", e);
            return 1;
        },
    };

    info!("Running client connected to {}", address);

    let mut stream = connection.get_stream(2);

    let message = "Hello";
    let out_buf = message.as_bytes();
    stream.write_all(out_buf).unwrap();

    let mut inc_buf = vec![];
    let amt = stream.read_to_end(&mut inc_buf).unwrap();
    let inc_buf = &inc_buf[..amt];
    let inc_string = std::str::from_utf8(&inc_buf).unwrap();
    info!("Got message: {}", inc_string);

    0
}

pub fn mig_demo() -> i32 {
    env_logger::init().unwrap();

    match args::parse_command() {
        Ok(args::MigCommand::Version) => {
            println!("{}", ::VERSION);
            0
        },
        Ok(args::MigCommand::Bench) => {
            benchmarks::run_all_benchmarks();
            0
        },
        Ok(args::MigCommand::Server { address }) => {
            run_server(address)
        },
        Ok(args::MigCommand::Client { address }) => {
            run_client(address)
        },
        Err(err) => {
            println!("{}", &err.message);
            err.exit_code
        },
    }
}
<|endoftext|>


<commit_before>// -*- flycheck-rust-crate-root: "lib.rs" -*-
use super::ffi as ffi;
use super::context::Context;
use std::c_str::ToCStr;

/// The XML document
pub struct Document {
    xmlDocument: *const ffi::Document
}

impl Document {
    /// Creates a new Document from a string representation
    pub fn from_str(body: &str) -> Option<Document> {
        unsafe {
            let doc = body.with_c_str(|cstr| ffi::xmlParseDoc(cstr));
            raw_doc_to_option(doc)
        }
    }

    /// Creates a new Document from a file
    pub fn from_file(filename: &str) -> Option<Document> {
        unsafe {
            let doc = filename.with_c_str(|cstr| ffi::xmlParseFile(cstr));
            raw_doc_to_option(doc)
        }
    }

    /// Creates a new Context
    pub fn new_context<'a>(&'a self) -> Option<Context<'a>> {
        super::context::from_raw_document(self.xmlDocument)
    }
}

impl Drop for Document {
    fn drop(&mut self) {
        unsafe {
            ffi::xmlFreeDoc(self.xmlDocument);
        }
    }
}

unsafe fn raw_doc_to_option(doc: *const ffi::Document) -> Option<Document> {
    if doc.is_null() {
        None
    } else {
        Some(Document { xmlDocument: doc })
    }
}
<commit_msg>Use proper variable naming convention<commit_after>// -*- flycheck-rust-crate-root: "lib.rs" -*-
use super::ffi as ffi;
use super::context::Context;
use std::c_str::ToCStr;

/// The XML document
pub struct Document {
    xml_document: *const ffi::Document
}

impl Document {
    /// Creates a new Document from a string representation
    pub fn from_str(body: &str) -> Option<Document> {
        unsafe {
            let doc = body.with_c_str(|cstr| ffi::xmlParseDoc(cstr));
            raw_doc_to_option(doc)
        }
    }

    /// Creates a new Document from a file
    pub fn from_file(filename: &str) -> Option<Document> {
        unsafe {
            let doc = filename.with_c_str(|cstr| ffi::xmlParseFile(cstr));
            raw_doc_to_option(doc)
        }
    }

    /// Creates a new Context
    pub fn new_context<'a>(&'a self) -> Option<Context<'a>> {
        super::context::from_raw_document(self.xml_document)
    }
}

impl Drop for Document {
    fn drop(&mut self) {
        unsafe {
            ffi::xmlFreeDoc(self.xml_document);
        }
    }
}

unsafe fn raw_doc_to_option(doc: *const ffi::Document) -> Option<Document> {
    if doc.is_null() {
        None
    } else {
        Some(Document { xml_document: doc })
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use lexer;

pub type Token = lexer::Token;
pub type Lexer = lexer::Lexer;

pub struct Parser {
    lexer: Lexer,
}

impl Parser {
    pub fn new() -> Self {
        Parser{lexer: Lexer::new()}
    }
    pub fn parse(&mut self, input: String) -> Result<f64, String> {
        self.lexer.set_input(input);
        let expression_value: f64 = match self.expression() {
            Ok(v) => v,
            Err(msg) => return Err(msg)
        };
        let token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        match token.get_kind() {
            lexer::SubToken::End => {
                return Ok(expression_value);
            }
            _ => {
                return Err(String::from("End expected"));
            }
        }
    }
    pub fn expression(&mut self) -> Result<f64, String> {
        let mut component1: f64 = match self.factor() {
            Ok(x) => x,
            Err(msg) => return Err(msg)
        };
        let mut token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        loop {
            match token.get_kind() {
                lexer::SubToken::Plus => {
                    let component2 = match self.factor() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    component1 += component2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Minus => {
                    let component2 = match self.factor() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    component1 -= component2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                _ => {
                    break;
                }
            }
        }
        self.lexer.revert();
        Ok(component1)
    }
    pub fn factor(&mut self) -> Result<f64, String> {
        let mut factor1: f64 = match self.number() {
            Ok(x) => x,
            Err(msg) => return Err(msg)
        };
        let mut token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        loop {
            match token.get_kind() {
                lexer::SubToken::Multiply => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 *= factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Divide => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 /= factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Power => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 = factor1.powf(factor2);
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Modulo => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 = factor1 % factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                _ => {
                    break;
                }
            }
        }
        self.lexer.revert();
        Ok(factor1)
    }
    pub fn number(&mut self) -> Result<f64, String> {
        let token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        let value: f64;
        match token.get_kind() {
            lexer::SubToken::LParen => {
                value = match self.expression() {
                    Ok(v) => v,
                    Err(msg) => return Err(msg)
                };
                match self.lexer.get_next_token() {
                    Err(msg) => return Err(msg),
                    _ => ()
                };
            }
            lexer::SubToken::Number => {
                value = match token.get_value() {
                    Some(v) => v,
                    None => return Err(String::from("No value"))
                };
            }
            lexer::SubToken::Minus => {
                value = match self.factor() {
                    Ok(x) => x*-1.0,
                    Err(msg) => return Err(msg)
                };
            }
            _ => {
                return Err(String::from("Not a number"));
            }
        }
        Ok(value)
    }
}<commit_msg>Added fields for variables in Parser<commit_after>#![allow(dead_code)]

use regex::Regex;
use std::collections::HashMap;
use lexer;

pub type Token = lexer::Token;
pub type Lexer = lexer::Lexer;

pub struct Parser {
    lexer: Lexer,
    variables: HashMap<String, f64>,
    variable_regex: Regex,
}

impl Parser {
    pub fn new() -> Self {
        Parser{lexer: Lexer::new(), variables: HashMap::new(), variable_regex: Regex::new(r"\A\w+=").unwrap()}
    }
    pub fn parse(&mut self, input: String) -> Result<f64, String> {
        self.lexer.set_input(input);
        let expression_value: f64 = match self.expression() {
            Ok(v) => v,
            Err(msg) => return Err(msg)
        };
        let token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        match token.get_kind() {
            lexer::SubToken::End => {
                return Ok(expression_value);
            }
            _ => {
                return Err(String::from("End expected"));
            }
        }
    }
    pub fn expression(&mut self) -> Result<f64, String> {
        let mut component1: f64 = match self.factor() {
            Ok(x) => x,
            Err(msg) => return Err(msg)
        };
        let mut token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        loop {
            match token.get_kind() {
                lexer::SubToken::Plus => {
                    let component2 = match self.factor() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    component1 += component2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Minus => {
                    let component2 = match self.factor() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    component1 -= component2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                _ => {
                    break;
                }
            }
        }
        self.lexer.revert();
        Ok(component1)
    }
    pub fn factor(&mut self) -> Result<f64, String> {
        let mut factor1: f64 = match self.number() {
            Ok(x) => x,
            Err(msg) => return Err(msg)
        };
        let mut token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        loop {
            match token.get_kind() {
                lexer::SubToken::Multiply => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 *= factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Divide => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 /= factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Power => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 = factor1.powf(factor2);
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                lexer::SubToken::Modulo => {
                    let factor2: f64 = match self.number() {
                        Ok(x) => x,
                        Err(msg) => return Err(msg)
                    };
                    factor1 = factor1 % factor2;
                    token = match self.lexer.get_next_token() {
                        Ok(t) => t,
                        Err(msg) => return Err(msg)
                    };
                }
                _ => {
                    break;
                }
            }
        }
        self.lexer.revert();
        Ok(factor1)
    }
    pub fn number(&mut self) -> Result<f64, String> {
        let token: Token = match self.lexer.get_next_token() {
            Ok(t) => t,
            Err(msg) => return Err(msg)
        };
        let value: f64;
        match token.get_kind() {
            lexer::SubToken::LParen => {
                value = match self.expression() {
                    Ok(v) => v,
                    Err(msg) => return Err(msg)
                };
                match self.lexer.get_next_token() {
                    Err(msg) => return Err(msg),
                    _ => ()
                };
            }
            lexer::SubToken::Number => {
                value = match token.get_value() {
                    Some(v) => v,
                    None => return Err(String::from("No value"))
                };
            }
            lexer::SubToken::Minus => {
                value = match self.factor() {
                    Ok(x) => x*-1.0,
                    Err(msg) => return Err(msg)
                };
            }
            _ => {
                return Err(String::from("Not a number"));
            }
        }
        Ok(value)
    }
}<|endoftext|>