<commit_before>//! Asynchronous green-threads.
//!
//! ## What are Tasks?
//!
//! A _task_ is a light weight, non-blocking unit of execution. A task is similar
//! to an OS thread, but rather than being managed by the OS scheduler, they are
//! managed by the [Tokio runtime][rt]. Another name for this general pattern is
//! [green threads]. If you are familiar with [Go's goroutines], [Kotlin's
//! coroutines], or [Erlang's processes], you can think of Tokio's tasks as
//! something similar.
//!
//! Key points about tasks include:
//!
//! * Tasks are **light weight**. Because tasks are scheduled by the Tokio
//!   runtime rather than the operating system, creating new tasks or switching
//!   between tasks does not require a context switch and has fairly low
//!   overhead. Creating, running, and destroying large numbers of tasks is
//!   quite cheap, especially compared to OS threads.
//!
//! * Tasks are scheduled **cooperatively**. Most operating systems implement
//!   _preemptive multitasking_. This is a scheduling technique where the
//!   operating system allows each thread to run for a period of time, and then
//!   _preempts_ it, temporarily pausing that thread and switching to another.
//!   Tasks, on the other hand, implement _cooperative multitasking_. In
//!   cooperative multitasking, a task is allowed to run until it _yields_,
//!   indicating to the Tokio runtime's scheduler that it cannot currently
//!   continue executing. When a task yields, the Tokio runtime switches to
//!   executing the next task.
//!
//! * Tasks are **non-blocking**. Typically, when an OS thread performs I/O or
//!   must synchronize with another thread, it _blocks_, allowing the OS to
//!   schedule another thread. When a task cannot continue executing, it must
//!   yield instead, allowing the Tokio runtime to schedule another task. Tasks
//!   should generally not perform system calls or other operations that could
//!   block a thread, as this would prevent other tasks running on the same
//!   thread from executing as well. Instead, this module provides APIs for
//!   running blocking operations in an asynchronous context.
//!
//! [rt]: crate::runtime
//! [green threads]: https://en.wikipedia.org/wiki/Green_threads
//! [Go's goroutines]: https://tour.golang.org/concurrency/1
//! [Kotlin's coroutines]: https://kotlinlang.org/docs/reference/coroutines-overview.html
//! [Erlang's processes]: http://erlang.org/doc/getting_started/conc_prog.html#processes
//!
//! ## Working with Tasks
//!
//! This module provides the following APIs for working with tasks:
//!
//! ### Spawning
//!
//! Perhaps the most important function in this module is [`task::spawn`]. This
//! function can be thought of as an async equivalent to the standard library's
//! [`thread::spawn`][`std::thread::spawn`]. It takes an `async` block or other
//! [future], and creates a new task to run that work concurrently:
//!
//! ```
//! use tokio::task;
//!
//! # async fn doc() {
//! task::spawn(async {
//!     // perform some work here...
//! });
//! # }
//! ```
//!
//! Like [`std::thread::spawn`], `task::spawn` returns a [`JoinHandle`] struct.
//! A `JoinHandle` is itself a future which may be used to await the output of
//! the spawned task. For example:
//!
//! ```
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let join = task::spawn(async {
//!     // ...
//!     "hello world!"
//! });
//!
//! // ...
//!
//! // Await the result of the spawned task.
//! let result = join.await?;
//! assert_eq!(result, "hello world!");
//! # Ok(())
//! # }
//! ```
//!
//! Again, like `std::thread`'s [`JoinHandle` type][thread_join], if the spawned
//! task panics, awaiting its `JoinHandle` will return a [`JoinError`]. For
//! example:
//!
//! ```
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() {
//! let join = task::spawn(async {
//!     panic!("something bad happened!")
//! });
//!
//! // The returned result indicates that the task failed.
//! assert!(join.await.is_err());
//! # }
//! ```
//!
//! `spawn`, `JoinHandle`, and `JoinError` are present when the "rt"
//! feature flag is enabled.
//!
//! [`task::spawn`]: crate::task::spawn()
//! [future]: std::future::Future
//! [`std::thread::spawn`]: std::thread::spawn
//! [`JoinHandle`]: crate::task::JoinHandle
//! [thread_join]: std::thread::JoinHandle
//! [`JoinError`]: crate::task::JoinError
//!
//! ### Blocking and Yielding
//!
//! As we discussed above, code running in asynchronous tasks should not perform
//! operations that can block. A blocking operation performed in a task running
//! on a thread that is also running other tasks would block the entire thread,
//! preventing other tasks from running.
//!
//! Instead, Tokio provides two APIs for running blocking operations in an
//! asynchronous context: [`task::spawn_blocking`] and [`task::block_in_place`].
//!
//! Be aware that if you call a non-async method from async code, that non-async
//! method is still inside the asynchronous context, so you should also avoid
//! blocking operations there. This includes destructors of objects destroyed in
//! async code.
//!
//! #### spawn_blocking
//!
//! The `task::spawn_blocking` function is similar to the `task::spawn` function
//! discussed in the previous section, but rather than spawning an
//! _non-blocking_ future on the Tokio runtime, it instead spawns a
//! _blocking_ function on a dedicated thread pool for blocking tasks. For
//! example:
//!
//! ```
//! use tokio::task;
//!
//! # async fn docs() {
//! task::spawn_blocking(|| {
//!     // do some compute-heavy work or call synchronous code
//! });
//! # }
//! ```
//!
//! Just like `task::spawn`, `task::spawn_blocking` returns a `JoinHandle`
//! which we can use to await the result of the blocking operation:
//!
//! ```rust
//! # use tokio::task;
//! # async fn docs() -> Result<(), Box<dyn std::error::Error>>{
//! let join = task::spawn_blocking(|| {
//!     // do some compute-heavy work or call synchronous code
//!     "blocking completed"
//! });
//!
//! let result = join.await?;
//! assert_eq!(result, "blocking completed");
//! # Ok(())
//! # }
//! ```
//!
//! #### block_in_place
//!
//! When using the [multi-threaded runtime][rt-multi-thread], the [`task::block_in_place`]
//! function is also available. Like `task::spawn_blocking`, this function
//! allows running a blocking operation from an asynchronous context. Unlike
//! `spawn_blocking`, however, `block_in_place` works by transitioning the
//! _current_ worker thread to a blocking thread, moving other tasks running on
//! that thread to another worker thread. This can improve performance by avoiding
//! context switches.
//!
//! For example:
//!
//! ```
//! use tokio::task;
//!
//! # async fn docs() {
//! let result = task::block_in_place(|| {
//!     // do some compute-heavy work or call synchronous code
//!     "blocking completed"
//! });
//!
//! assert_eq!(result, "blocking completed");
//! # }
//! ```
//!
//! #### yield_now
//!
//! In addition, this module provides a [`task::yield_now`] async function
//! that is analogous to the standard library's [`thread::yield_now`]. Calling
//! and `await`ing this function will cause the current task to yield to the
//! Tokio runtime's scheduler, allowing other tasks to be
//! scheduled. Eventually, the yielding task will be polled again, allowing it
//! to execute. For example:
//!
//! ```rust
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() {
//! async {
//!     task::spawn(async {
//!         // ...
//!         println!("spawned task done!")
//!     });
//!
//!     // Yield, allowing the newly-spawned task to execute first.
//!     task::yield_now().await;
//!     println!("main task done!");
//! }
//! # .await;
//! # }
//! ```
//!
//! ### Cooperative scheduling
//!
//! A single call to [`poll`] on a top-level task may potentially do a lot of
//! work before it returns `Poll::Pending`. If a task runs for a long period of
//! time without yielding back to the executor, it can starve other tasks
//! waiting on that executor to execute them, or drive underlying resources.
//! Since Rust does not have a runtime, it is difficult to forcibly preempt a
//! long-running task. Instead, this module provides an opt-in mechanism for
//! futures to collaborate with the executor to avoid starvation.
//!
//! Consider a future like this one:
//!
//! ```
//! # use tokio_stream::{Stream, StreamExt};
//! async fn drop_all<I: Stream + Unpin>(mut input: I) {
//!     while let Some(_) = input.next().await {}
//! }
//! ```
//!
//! It may look harmless, but consider what happens under heavy load if the
//! input stream is _always_ ready. If we spawn `drop_all`, the task will never
//! yield, and will starve other tasks and resources on the same executor.
//!
//! To account for this, Tokio has explicit yield points in a number of library
//! functions, which force tasks to return to the executor periodically.
//!
//!
//! #### unconstrained
//!
//! If necessary, [`task::unconstrained`] lets you opt out a future of Tokio's cooperative
//! scheduling. When a future is wrapped with `unconstrained`, it will never be forced to yield to
//! Tokio. For example:
//!
//! ```
//! # #[tokio::main]
//! # async fn main() {
//! use tokio::{task, sync::mpsc};
//!
//! let fut = async {
//!     let (tx, mut rx) = mpsc::unbounded_channel();
//!
//!     for i in 0..1000 {
//!         let _ = tx.send(());
//!         // This will always be ready. If coop was in effect, this code would be forced to yield
//!         // periodically. However, if left unconstrained, then this code will never yield.
//!         rx.recv().await;
//!     }
//! };
//!
//! task::unconstrained(fut).await;
//! # }
//! ```
//!
//! [`task::spawn_blocking`]: crate::task::spawn_blocking
//! [`task::block_in_place`]: crate::task::block_in_place
//! [rt-multi-thread]: ../runtime/index.html#threaded-scheduler
//! [`task::yield_now`]: crate::task::yield_now()
//! [`thread::yield_now`]: std::thread::yield_now
//! [`task::unconstrained`]: crate::task::unconstrained()
//! [`poll`]: method@std::future::Future::poll

cfg_rt! {
    pub use crate::runtime::task::{JoinError, JoinHandle};

    cfg_not_wasi! {
        mod blocking;
        pub use blocking::spawn_blocking;
    }

    mod spawn;
    pub use spawn::spawn;

    cfg_rt_multi_thread! {
        pub use blocking::block_in_place;
    }

    mod yield_now;
    pub use yield_now::yield_now;

    cfg_unstable! {
        mod consume_budget;
        pub use consume_budget::consume_budget;
    }

    mod local;
    pub use local::{spawn_local, LocalSet, LocalEnterGuard};

    mod task_local;
    pub use task_local::LocalKey;

    mod unconstrained;
    pub use unconstrained::{unconstrained, Unconstrained};

    #[doc(inline)]
    pub use join_set::JoinSet;
    pub use crate::runtime::task::AbortHandle;

    cfg_not_unstable! {
        mod join_set;
    }

    cfg_unstable! {
        pub use crate::runtime::task::Id;

        pub mod join_set;
    }

    cfg_trace! {
        mod builder;
        pub use builder::Builder;
    }

    /// Task-related futures.
    pub mod futures {
        pub use super::task_local::TaskLocalFuture;
    }
}
<commit_msg>chore: slight re-wording of unconstrained's module docs (#4928)<commit_after>//! Asynchronous green-threads.
//!
//! ## What are Tasks?
//!
//! A _task_ is a light weight, non-blocking unit of execution. A task is similar
//! to an OS thread, but rather than being managed by the OS scheduler, they are
//! managed by the [Tokio runtime][rt]. Another name for this general pattern is
//! [green threads]. If you are familiar with [Go's goroutines], [Kotlin's
//! coroutines], or [Erlang's processes], you can think of Tokio's tasks as
//! something similar.
//!
//! Key points about tasks include:
//!
//! * Tasks are **light weight**. Because tasks are scheduled by the Tokio
//!   runtime rather than the operating system, creating new tasks or switching
//!   between tasks does not require a context switch and has fairly low
//!   overhead. Creating, running, and destroying large numbers of tasks is
//!   quite cheap, especially compared to OS threads.
//!
//! * Tasks are scheduled **cooperatively**. Most operating systems implement
//!   _preemptive multitasking_. This is a scheduling technique where the
//!   operating system allows each thread to run for a period of time, and then
//!   _preempts_ it, temporarily pausing that thread and switching to another.
//!   Tasks, on the other hand, implement _cooperative multitasking_. In
//!   cooperative multitasking, a task is allowed to run until it _yields_,
//!   indicating to the Tokio runtime's scheduler that it cannot currently
//!   continue executing. When a task yields, the Tokio runtime switches to
//!   executing the next task.
//!
//! * Tasks are **non-blocking**. Typically, when an OS thread performs I/O or
//!   must synchronize with another thread, it _blocks_, allowing the OS to
//!   schedule another thread. When a task cannot continue executing, it must
//!   yield instead, allowing the Tokio runtime to schedule another task. Tasks
//!   should generally not perform system calls or other operations that could
//!   block a thread, as this would prevent other tasks running on the same
//!   thread from executing as well. Instead, this module provides APIs for
//!   running blocking operations in an asynchronous context.
//!
//! [rt]: crate::runtime
//! [green threads]: https://en.wikipedia.org/wiki/Green_threads
//! [Go's goroutines]: https://tour.golang.org/concurrency/1
//! [Kotlin's coroutines]: https://kotlinlang.org/docs/reference/coroutines-overview.html
//! [Erlang's processes]: http://erlang.org/doc/getting_started/conc_prog.html#processes
//!
//! ## Working with Tasks
//!
//! This module provides the following APIs for working with tasks:
//!
//! ### Spawning
//!
//! Perhaps the most important function in this module is [`task::spawn`]. This
//! function can be thought of as an async equivalent to the standard library's
//! [`thread::spawn`][`std::thread::spawn`]. It takes an `async` block or other
//! [future], and creates a new task to run that work concurrently:
//!
//! ```
//! use tokio::task;
//!
//! # async fn doc() {
//! task::spawn(async {
//!     // perform some work here...
//! });
//! # }
//! ```
//!
//! Like [`std::thread::spawn`], `task::spawn` returns a [`JoinHandle`] struct.
//! A `JoinHandle` is itself a future which may be used to await the output of
//! the spawned task. For example:
//!
//! ```
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let join = task::spawn(async {
//!     // ...
//!     "hello world!"
//! });
//!
//! // ...
//!
//! // Await the result of the spawned task.
//! let result = join.await?;
//! assert_eq!(result, "hello world!");
//! # Ok(())
//! # }
//! ```
//!
//! Again, like `std::thread`'s [`JoinHandle` type][thread_join], if the spawned
//! task panics, awaiting its `JoinHandle` will return a [`JoinError`]. For
//! example:
//!
//! ```
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() {
//! let join = task::spawn(async {
//!     panic!("something bad happened!")
//! });
//!
//! // The returned result indicates that the task failed.
//! assert!(join.await.is_err());
//! # }
//! ```
//!
//! `spawn`, `JoinHandle`, and `JoinError` are present when the "rt"
//! feature flag is enabled.
//!
//! [`task::spawn`]: crate::task::spawn()
//! [future]: std::future::Future
//! [`std::thread::spawn`]: std::thread::spawn
//! [`JoinHandle`]: crate::task::JoinHandle
//! [thread_join]: std::thread::JoinHandle
//! [`JoinError`]: crate::task::JoinError
//!
//! ### Blocking and Yielding
//!
//! As we discussed above, code running in asynchronous tasks should not perform
//! operations that can block. A blocking operation performed in a task running
//! on a thread that is also running other tasks would block the entire thread,
//! preventing other tasks from running.
//!
//! Instead, Tokio provides two APIs for running blocking operations in an
//! asynchronous context: [`task::spawn_blocking`] and [`task::block_in_place`].
//!
//! Be aware that if you call a non-async method from async code, that non-async
//! method is still inside the asynchronous context, so you should also avoid
//! blocking operations there. This includes destructors of objects destroyed in
//! async code.
//!
//! #### spawn_blocking
//!
//! The `task::spawn_blocking` function is similar to the `task::spawn` function
//! discussed in the previous section, but rather than spawning an
//! _non-blocking_ future on the Tokio runtime, it instead spawns a
//! _blocking_ function on a dedicated thread pool for blocking tasks. For
//! example:
//!
//! ```
//! use tokio::task;
//!
//! # async fn docs() {
//! task::spawn_blocking(|| {
//!     // do some compute-heavy work or call synchronous code
//! });
//! # }
//! ```
//!
//! Just like `task::spawn`, `task::spawn_blocking` returns a `JoinHandle`
//! which we can use to await the result of the blocking operation:
//!
//! ```rust
//! # use tokio::task;
//! # async fn docs() -> Result<(), Box<dyn std::error::Error>>{
//! let join = task::spawn_blocking(|| {
//!     // do some compute-heavy work or call synchronous code
//!     "blocking completed"
//! });
//!
//! let result = join.await?;
//! assert_eq!(result, "blocking completed");
//! # Ok(())
//! # }
//! ```
//!
//! #### block_in_place
//!
//! When using the [multi-threaded runtime][rt-multi-thread], the [`task::block_in_place`]
//! function is also available. Like `task::spawn_blocking`, this function
//! allows running a blocking operation from an asynchronous context. Unlike
//! `spawn_blocking`, however, `block_in_place` works by transitioning the
//! _current_ worker thread to a blocking thread, moving other tasks running on
//! that thread to another worker thread. This can improve performance by avoiding
//! context switches.
//!
//! For example:
//!
//! ```
//! use tokio::task;
//!
//! # async fn docs() {
//! let result = task::block_in_place(|| {
//!     // do some compute-heavy work or call synchronous code
//!     "blocking completed"
//! });
//!
//! assert_eq!(result, "blocking completed");
//! # }
//! ```
//!
//! #### yield_now
//!
//! In addition, this module provides a [`task::yield_now`] async function
//! that is analogous to the standard library's [`thread::yield_now`]. Calling
//! and `await`ing this function will cause the current task to yield to the
//! Tokio runtime's scheduler, allowing other tasks to be
//! scheduled. Eventually, the yielding task will be polled again, allowing it
//! to execute. For example:
//!
//! ```rust
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() {
//! async {
//!     task::spawn(async {
//!         // ...
//!         println!("spawned task done!")
//!     });
//!
//!     // Yield, allowing the newly-spawned task to execute first.
//!     task::yield_now().await;
//!     println!("main task done!");
//! }
//! # .await;
//! # }
//! ```
//!
//! ### Cooperative scheduling
//!
//! A single call to [`poll`] on a top-level task may potentially do a lot of
//! work before it returns `Poll::Pending`. If a task runs for a long period of
//! time without yielding back to the executor, it can starve other tasks
//! waiting on that executor to execute them, or drive underlying resources.
//! Since Rust does not have a runtime, it is difficult to forcibly preempt a
//! long-running task. Instead, this module provides an opt-in mechanism for
//! futures to collaborate with the executor to avoid starvation.
//!
//! Consider a future like this one:
//!
//! ```
//! # use tokio_stream::{Stream, StreamExt};
//! async fn drop_all<I: Stream + Unpin>(mut input: I) {
//!     while let Some(_) = input.next().await {}
//! }
//! ```
//!
//! It may look harmless, but consider what happens under heavy load if the
//! input stream is _always_ ready. If we spawn `drop_all`, the task will never
//! yield, and will starve other tasks and resources on the same executor.
//!
//! To account for this, Tokio has explicit yield points in a number of library
//! functions, which force tasks to return to the executor periodically.
//!
//!
//! #### unconstrained
//!
//! If necessary, [`task::unconstrained`] lets you opt a future out of of Tokio's cooperative
//! scheduling. When a future is wrapped with `unconstrained`, it will never be forced to yield to
//! Tokio. For example:
//!
//! ```
//! # #[tokio::main]
//! # async fn main() {
//! use tokio::{task, sync::mpsc};
//!
//! let fut = async {
//!     let (tx, mut rx) = mpsc::unbounded_channel();
//!
//!     for i in 0..1000 {
//!         let _ = tx.send(());
//!         // This will always be ready. If coop was in effect, this code would be forced to yield
//!         // periodically. However, if left unconstrained, then this code will never yield.
//!         rx.recv().await;
//!     }
//! };
//!
//! task::unconstrained(fut).await;
//! # }
//! ```
//!
//! [`task::spawn_blocking`]: crate::task::spawn_blocking
//! [`task::block_in_place`]: crate::task::block_in_place
//! [rt-multi-thread]: ../runtime/index.html#threaded-scheduler
//! [`task::yield_now`]: crate::task::yield_now()
//! [`thread::yield_now`]: std::thread::yield_now
//! [`task::unconstrained`]: crate::task::unconstrained()
//! [`poll`]: method@std::future::Future::poll

cfg_rt! {
    pub use crate::runtime::task::{JoinError, JoinHandle};

    cfg_not_wasi! {
        mod blocking;
        pub use blocking::spawn_blocking;
    }

    mod spawn;
    pub use spawn::spawn;

    cfg_rt_multi_thread! {
        pub use blocking::block_in_place;
    }

    mod yield_now;
    pub use yield_now::yield_now;

    cfg_unstable! {
        mod consume_budget;
        pub use consume_budget::consume_budget;
    }

    mod local;
    pub use local::{spawn_local, LocalSet, LocalEnterGuard};

    mod task_local;
    pub use task_local::LocalKey;

    mod unconstrained;
    pub use unconstrained::{unconstrained, Unconstrained};

    #[doc(inline)]
    pub use join_set::JoinSet;
    pub use crate::runtime::task::AbortHandle;

    cfg_not_unstable! {
        mod join_set;
    }

    cfg_unstable! {
        pub use crate::runtime::task::Id;

        pub mod join_set;
    }

    cfg_trace! {
        mod builder;
        pub use builder::Builder;
    }

    /// Task-related futures.
    pub mod futures {
        pub use super::task_local::TaskLocalFuture;
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::Path;

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = ".kic";
    let path_to_dir = Path::new(dir_name);
    if dir_exists(path_to_dir) {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let config_file    = "config";
    let path_to_config = Path::new(dir_name).join(config_file);
    if file_exists(path_to_config.as_path()) {
        println!("  OK: \"{}\" file has already exist.", config_file);
    } else {
        match File::create(path_to_config) {
            Ok(mut fp) => {
                println!("  OK: Created \"{}\" file.", config_file);
                match fp.write(b"Hello, world!!\n") {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

fn dir_exists(p: &Path) -> bool {
    p.exists() && p.is_dir()
}

fn file_exists(p: &Path) -> bool {
    p.exists() && p.is_file()
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    println!("sweep");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("destroy");
}
<commit_msg>Remove dir_exists() and file_exists()<commit_after>use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::Path;

pub fn initialize() {
    println!("Initialize ...");

    let dir_name    = ".kic";
    let path_to_dir = Path::new(dir_name);
    if path_to_dir.exists() && path_to_dir.is_dir() {
        println!("  OK: \"{}\" directory has already exist.", dir_name);
    } else {
        match fs::create_dir(path_to_dir) {
            Ok(_)    => println!("  OK: Created \"{}\" directory.", dir_name),
            Err(why) => panic!("{:?}", why),
        }
    }

    let config_file    = "config";
    let path_to_config = Path::new(dir_name).join(config_file);
    if path_to_config.exists() && path_to_config.is_file() {
        println!("  OK: \"{}\" file has already exist.", config_file);
    } else {
        match File::create(path_to_config) {
            Ok(mut fp) => {
                println!("  OK: Created \"{}\" file.", config_file);
                match fp.write(b"Hello, world!!\n") {
                    Ok(_)    => {},
                    Err(why) => panic!("{:?}", why),
                }
            },
            Err(why) => panic!("{:?}", why),
        }
    }
}

pub fn set_params() {
    println!("set parameters");
}

pub fn sweep() {
    println!("sweep");
}

pub fn register_with_cron() {
    println!("register");
}

pub fn unregister_cron() {
    println!("unregister");
}

pub fn destroy() {
    println!("destroy");
}
<|endoftext|>


<commit_before>use std::fmt::Write;
use util::{timing, color, Anchor, V2};
use backend::{Canvas, Event, Key, Fonter};

pub struct Console {
    text: String,
    command: String,
}

impl Console {
    pub fn new() -> Console {
        Console {
            text: "Welcome to console\n".to_string(),
            command: String::new(),
        }
    }

    pub fn update(&mut self, ctx: &mut Canvas) {
        let mut full_text = self.text.clone() + "]" + &self.command[..];

        // Blinking cursor.
        full_text = full_text + if timing::spike(0.5, 0.5) { "_" } else { " " };

        Fonter::new(ctx)
            .color(&color::LIGHTGREEN).border(&color::BLACK)
            .anchor(Anchor::BottomLeft)
            .text(full_text)
            .draw(V2(0.0, 180.0));
    }

    pub fn process(&mut self, event: Event) -> bool {
        match event {
            // Close the console by typing grave again. Can't actually type it
            // in console commands then unless we add escape keys.
            Event::Char('`') => { return false; }
            Event::KeyPressed(Key::Escape) => { return false; }

            Event::KeyPressed(Key::Backspace) => {
                let len = self.command.len();
                if len > 0 {
                    // XXX: This is very bad juju if the string isn't entirely
                    // ASCII7.
                    self.command.truncate(len - 1);
                }
            }
            Event::KeyPressed(Key::Enter) => { self.process_command(); }
            Event::KeyPressed(Key::Tab) => { self.tab_complete(); }
            Event::KeyPressed(Key::Up) => { self.history_prev(); }
            Event::KeyPressed(Key::Down) => { self.history_next(); }

            Event::Char(ch) if (ch as i32) >= 32 && (ch as i32) < 128 => {
                self.command.push(ch);
            }

            Event::Render(ctx) => { self.update(ctx); }
            _ => {}
        }

        return true;
    }

    fn process_command(&mut self) {
        // TODO: Why can't I use write! macros here?
        //writeln!(self.text, "]{}", self.command).unwrap();
        //writeln!(self.text, "TODO: Handle input");
        self.text.write_str(&format!("]{}\n", self.command)[..]).unwrap();
        self.text.write_str("TODO: Handle input").unwrap();
        self.command = "".to_string();
    }

    /// Try to tab-complete the current input string.
    fn tab_complete(&mut self) {
        // TODO
    }

    /// Bring the previous command in command history to current prompt.
    fn history_prev(&mut self) {
        // TODO
    }

    /// Bring the next command in command history to current prompt.
    fn history_next(&mut self) {
        // TODO
    }
}
<commit_msg>Fix console newline<commit_after>use std::fmt::Write;
use util::{timing, color, Anchor, V2};
use backend::{Canvas, Event, Key, Fonter};

pub struct Console {
    text: String,
    command: String,
}

impl Console {
    pub fn new() -> Console {
        Console {
            text: "Welcome to console\n".to_string(),
            command: String::new(),
        }
    }

    pub fn update(&mut self, ctx: &mut Canvas) {
        let mut full_text = self.text.clone() + "]" + &self.command[..];

        // Blinking cursor.
        full_text = full_text + if timing::spike(0.5, 0.5) { "_" } else { " " };

        Fonter::new(ctx)
            .color(&color::LIGHTGREEN).border(&color::BLACK)
            .anchor(Anchor::BottomLeft)
            .text(full_text)
            .draw(V2(0.0, 180.0));
    }

    pub fn process(&mut self, event: Event) -> bool {
        match event {
            // Close the console by typing grave again. Can't actually type it
            // in console commands then unless we add escape keys.
            Event::Char('`') => { return false; }
            Event::KeyPressed(Key::Escape) => { return false; }

            Event::KeyPressed(Key::Backspace) => {
                let len = self.command.len();
                if len > 0 {
                    // XXX: This is very bad juju if the string isn't entirely
                    // ASCII7.
                    self.command.truncate(len - 1);
                }
            }
            Event::KeyPressed(Key::Enter) => { self.process_command(); }
            Event::KeyPressed(Key::Tab) => { self.tab_complete(); }
            Event::KeyPressed(Key::Up) => { self.history_prev(); }
            Event::KeyPressed(Key::Down) => { self.history_next(); }

            Event::Char(ch) if (ch as i32) >= 32 && (ch as i32) < 128 => {
                self.command.push(ch);
            }

            Event::Render(ctx) => { self.update(ctx); }
            _ => {}
        }

        return true;
    }

    fn process_command(&mut self) {
        // TODO: Why can't I use write! macros here?
        //writeln!(self.text, "]{}", self.command).unwrap();
        //writeln!(self.text, "TODO: Handle input");
        self.text.write_str(&format!("]{}\n", self.command)[..]).unwrap();
        self.text.write_str("TODO: Handle input\n").unwrap();
        self.command = "".to_string();
    }

    /// Try to tab-complete the current input string.
    fn tab_complete(&mut self) {
        // TODO
    }

    /// Bring the previous command in command history to current prompt.
    fn history_prev(&mut self) {
        // TODO
    }

    /// Bring the next command in command history to current prompt.
    fn history_next(&mut self) {
        // TODO
    }
}
<|endoftext|>


<commit_before>use std::fmt;
/// We re-export winit so it's easy for people to use the same version as we are
/// without having to mess around figuring it out.
pub use winit;

#[cfg(feature = "audio")]
use crate::audio;
use crate::conf;
use crate::error::GameResult;
use crate::filesystem::Filesystem;
use crate::graphics;
use crate::graphics::GraphicsContext;
use crate::input;
use crate::timer;

/// A `Context` is an object that holds on to global resources.
/// It basically tracks hardware state such as the screen, audio
/// system, timers, and so on.  Generally this type can **not**
/// be shared/sent between threads and only one `Context` can exist at a time.  Trying
/// to create a second one will fail.  It is fine to drop a `Context`
/// and create a new one, but this will also close and re-open your
/// game's window.
///
/// Most functions that interact with the hardware, for instance
/// drawing things, playing sounds, or loading resources will need
/// to access one, or rarely even two, of its sub-contexts.
/// It is an error to create some type that
/// relies upon a `Context`, such as `Image`, and then drop the `Context`
/// and try to draw the old `Image` with the new `Context`.
///
/// The fields in this struct used to be basically undocumented features,
/// only here to make it easier to debug, or to let advanced users
/// hook into the guts of ggez and make it do things it normally
/// can't. Now that `ggez`'s module-level functions, taking the whole `Context`
/// have been deprecated, calling their methods directly is recommended.
pub struct Context {
    /// Filesystem state.
    pub fs: Filesystem,
    /// Graphics state.
    pub gfx: GraphicsContext,
    /// Timer state.
    pub time: timer::TimeContext,
    /// Audio context.
    #[cfg(feature = "audio")]
    pub audio: audio::AudioContext,
    /// Keyboard input context.
    pub keyboard: input::keyboard::KeyboardContext,
    /// Mouse input context.
    pub mouse: input::mouse::MouseContext,
    /// Gamepad input context.
    #[cfg(feature = "gamepad")]
    pub gamepad: input::gamepad::GamepadContext,

    /// The Conf object the Context was created with.
    /// It's here just so that we can see the original settings,
    /// updating it will have no effect.
    pub(crate) conf: conf::Conf,
    /// Controls whether or not the event loop should be running.
    /// This is internally controlled by the outcome of [`quit_event`](crate::event::EventHandler::quit_event), requested through [`event::quit()`](crate::event::quit()).
    pub continuing: bool,
    /// Whether or not a `quit_event` has been requested.
    /// Set this with `ggez::event::quit()`.
    ///
    /// It's exposed here for people who want to roll their own event loop.
    pub quit_requested: bool,
}

// This is ugly and hacky but greatly improves ergonomics.

pub trait Has<T> {
    fn get(&self) -> &T;
}

impl<T> Has<T> for T {
    #[inline]
    fn get(&self) -> &T {
        self
    }
}

impl Has<Filesystem> for Context {
    #[inline]
    fn get(&self) -> &Filesystem {
        &self.fs
    }
}

impl Has<GraphicsContext> for Context {
    #[inline]
    fn get(&self) -> &GraphicsContext {
        &self.gfx
    }
}

#[cfg(feature = "audio")]
impl Has<audio::AudioContext> for Context {
    #[inline]
    fn get(&self) -> &audio::AudioContext {
        &self.audio
    }
}

pub trait HasMut<T> {
    fn get_mut(&mut self) -> &mut T;
}

impl<T> HasMut<T> for T {
    #[inline]
    fn get_mut(&mut self) -> &mut T {
        self
    }
}

impl HasMut<GraphicsContext> for Context {
    #[inline]
    fn get_mut(&mut self) -> &mut GraphicsContext {
        &mut self.gfx
    }
}

pub trait HasTwo<T, U> {
    fn get_first(&self) -> &T;
    fn get_second(&self) -> &U;
}

impl<T, U> HasTwo<T, U> for (&T, &U) {
    #[inline]
    fn get_first(&self) -> &T {
        self.0
    }

    #[inline]
    fn get_second(&self) -> &U {
        self.1
    }
}

impl HasTwo<Filesystem, GraphicsContext> for Context {
    #[inline]
    fn get_first(&self) -> &Filesystem {
        &self.fs
    }

    #[inline]
    fn get_second(&self) -> &GraphicsContext {
        &self.gfx
    }
}

#[cfg(feature = "audio")]
impl HasTwo<Filesystem, crate::audio::AudioContext> for Context {
    fn get_first(&self) -> &Filesystem {
        &self.fs
    }

    fn get_second(&self) -> &crate::audio::AudioContext {
        &self.audio
    }
}

impl fmt::Debug for Context {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Context: {:p}>", self)
    }
}

impl Context {
    /// Tries to create a new Context using settings from the given [`Conf`](../conf/struct.Conf.html) object.
    /// Usually called by [`ContextBuilder::build()`](struct.ContextBuilder.html#method.build).
    fn from_conf(
        conf: conf::Conf,
        mut fs: Filesystem,
    ) -> GameResult<(Context, winit::event_loop::EventLoop<()>)> {
        #[cfg(feature = "audio")]
        let audio_context = audio::AudioContext::new()?;
        let events_loop = winit::event_loop::EventLoop::new();
        let timer_context = timer::TimeContext::new();
        let graphics_context =
            graphics::context::GraphicsContext::new(&events_loop, &conf, &mut fs)?;

        let ctx = Context {
            conf,
            fs,
            gfx: graphics_context,
            continuing: true,
            quit_requested: false,
            time: timer_context,
            #[cfg(feature = "audio")]
            audio: audio_context,
            keyboard: input::keyboard::KeyboardContext::new(),
            mouse: input::mouse::MouseContext::new(),
            #[cfg(feature = "gamepad")]
            gamepad: input::gamepad::GamepadContext::new()?,
        };

        Ok((ctx, events_loop))
    }
}

use std::borrow::Cow;
use std::path;

/// A builder object for creating a [`Context`](struct.Context.html).
#[derive(Debug, Clone, PartialEq)]
pub struct ContextBuilder {
    pub(crate) game_id: String,
    pub(crate) author: String,
    pub(crate) conf: conf::Conf,
    pub(crate) resources_dir_name: String,
    pub(crate) resources_zip_name: String,
    pub(crate) paths: Vec<path::PathBuf>,
    pub(crate) memory_zip_files: Vec<Cow<'static, [u8]>>,
    pub(crate) load_conf_file: bool,
}

impl ContextBuilder {
    /// Create a new `ContextBuilder` with default settings.
    pub fn new(game_id: &str, author: &str) -> Self {
        Self {
            game_id: game_id.to_string(),
            author: author.to_string(),
            conf: conf::Conf::default(),
            resources_dir_name: "resources".to_string(),
            resources_zip_name: "resources.zip".to_string(),
            paths: vec![],
            memory_zip_files: vec![],
            load_conf_file: true,
        }
    }

    /// Sets the window setup settings.
    #[must_use]
    pub fn window_setup(mut self, setup: conf::WindowSetup) -> Self {
        self.conf.window_setup = setup;
        self
    }

    /// Sets the window mode settings.
    #[must_use]
    pub fn window_mode(mut self, mode: conf::WindowMode) -> Self {
        self.conf.window_mode = mode;
        self
    }

    /// Sets the graphics backend.
    #[must_use]
    pub fn backend(mut self, backend: conf::Backend) -> Self {
        self.conf.backend = backend;
        self
    }

    /// Sets all the config options, overriding any previous
    /// ones from [`window_setup()`](#method.window_setup),
    /// [`window_mode()`](#method.window_mode), and
    /// [`backend()`](#method.backend).  These are used as
    /// defaults and are overridden by any external config
    /// file found.
    #[must_use]
    pub fn default_conf(mut self, conf: conf::Conf) -> Self {
        self.conf = conf;
        self
    }

    /// Sets resources dir name.
    /// Default resources dir name is `resources`.
    #[must_use]
    pub fn resources_dir_name(mut self, new_name: impl ToString) -> Self {
        self.resources_dir_name = new_name.to_string();
        self
    }

    /// Sets resources zip name.
    /// Default resources dir name is `resources.zip`.
    #[must_use]
    pub fn resources_zip_name(mut self, new_name: impl ToString) -> Self {
        self.resources_zip_name = new_name.to_string();
        self
    }

    /// Add a new read-only filesystem path to the places to search
    /// for resources.
    #[must_use]
    pub fn add_resource_path<T>(mut self, path: T) -> Self
    where
        T: Into<path::PathBuf>,
    {
        self.paths.push(path.into());
        self
    }

    /// Add a new zip file from bytes whose contents will be searched
    /// for resources. The zip file will be stored in-memory.
    /// You can pass it a static slice, a `Vec` of bytes, etc.
    ///
    /// ```ignore
    /// use ggez::context::ContextBuilder;
    /// let _ = ContextBuilder::new()
    ///     .add_zipfile_bytes(include_bytes!("../resources.zip").to_vec())
    ///     .build();
    /// ```
    #[must_use]
    pub fn add_zipfile_bytes<B>(mut self, bytes: B) -> Self
    where
        B: Into<Cow<'static, [u8]>>,
    {
        let cow = bytes.into();
        self.memory_zip_files.push(cow);
        self
    }

    /// Specifies whether or not to load the `conf.toml` file if it
    /// exists and use its settings to override the provided values.
    /// Defaults to `true` which is usually what you want, but being
    /// able to fiddle with it is sometimes useful for debugging.
    #[must_use]
    pub fn with_conf_file(mut self, load_conf_file: bool) -> Self {
        self.load_conf_file = load_conf_file;
        self
    }

    /// Build the `Context`.
    pub fn build(self) -> GameResult<(Context, winit::event_loop::EventLoop<()>)> {
        let mut fs = Filesystem::new(
            self.game_id.as_ref(),
            self.author.as_ref(),
            &self.resources_dir_name,
            &self.resources_zip_name,
        )?;

        for path in &self.paths {
            fs.mount(path, true);
        }

        for zipfile_bytes in self.memory_zip_files {
            fs.add_zip_file(std::io::Cursor::new(zipfile_bytes))?;
        }

        let config = if self.load_conf_file {
            fs.read_config().unwrap_or(self.conf)
        } else {
            self.conf
        };

        Context::from_conf(config, fs)
    }
}
<commit_msg>Adds some documentation to Has traits<commit_after>use std::fmt;
/// We re-export winit so it's easy for people to use the same version as we are
/// without having to mess around figuring it out.
pub use winit;

#[cfg(feature = "audio")]
use crate::audio;
use crate::conf;
use crate::error::GameResult;
use crate::filesystem::Filesystem;
use crate::graphics;
use crate::graphics::GraphicsContext;
use crate::input;
use crate::timer;

/// A `Context` is an object that holds on to global resources.
/// It basically tracks hardware state such as the screen, audio
/// system, timers, and so on.  Generally this type can **not**
/// be shared/sent between threads and only one `Context` can exist at a time.  Trying
/// to create a second one will fail.  It is fine to drop a `Context`
/// and create a new one, but this will also close and re-open your
/// game's window.
///
/// Most functions that interact with the hardware, for instance
/// drawing things, playing sounds, or loading resources will need
/// to access one, or rarely even two, of its sub-contexts.
/// It is an error to create some type that
/// relies upon a `Context`, such as `Image`, and then drop the `Context`
/// and try to draw the old `Image` with the new `Context`.
///
/// The fields in this struct used to be basically undocumented features,
/// only here to make it easier to debug, or to let advanced users
/// hook into the guts of ggez and make it do things it normally
/// can't. Now that `ggez`'s module-level functions, taking the whole `Context`
/// have been deprecated, calling their methods directly is recommended.
pub struct Context {
    /// Filesystem state.
    pub fs: Filesystem,
    /// Graphics state.
    pub gfx: GraphicsContext,
    /// Timer state.
    pub time: timer::TimeContext,
    /// Audio context.
    #[cfg(feature = "audio")]
    pub audio: audio::AudioContext,
    /// Keyboard input context.
    pub keyboard: input::keyboard::KeyboardContext,
    /// Mouse input context.
    pub mouse: input::mouse::MouseContext,
    /// Gamepad input context.
    #[cfg(feature = "gamepad")]
    pub gamepad: input::gamepad::GamepadContext,

    /// The Conf object the Context was created with.
    /// It's here just so that we can see the original settings,
    /// updating it will have no effect.
    pub(crate) conf: conf::Conf,
    /// Controls whether or not the event loop should be running.
    /// This is internally controlled by the outcome of [`quit_event`](crate::event::EventHandler::quit_event), requested through [`event::quit()`](crate::event::quit()).
    pub continuing: bool,
    /// Whether or not a `quit_event` has been requested.
    /// Set this with `ggez::event::quit()`.
    ///
    /// It's exposed here for people who want to roll their own event loop.
    pub quit_requested: bool,
}

// This is ugly and hacky but greatly improves ergonomics.

/// Used to represent types that can provide a certain context type.
///
/// If you don't know what this is, you most likely want to pass `ctx`.
pub trait Has<T> {
    fn get(&self) -> &T;
}

impl<T> Has<T> for T {
    #[inline]
    fn get(&self) -> &T {
        self
    }
}

impl Has<Filesystem> for Context {
    #[inline]
    fn get(&self) -> &Filesystem {
        &self.fs
    }
}

impl Has<GraphicsContext> for Context {
    #[inline]
    fn get(&self) -> &GraphicsContext {
        &self.gfx
    }
}

#[cfg(feature = "audio")]
impl Has<audio::AudioContext> for Context {
    #[inline]
    fn get(&self) -> &audio::AudioContext {
        &self.audio
    }
}

/// Used to represent types that can provide a certain context type in a mutable form.
///
/// If you don't know what this is, you most likely want to pass `ctx`.
pub trait HasMut<T> {
    fn get_mut(&mut self) -> &mut T;
}

impl<T> HasMut<T> for T {
    #[inline]
    fn get_mut(&mut self) -> &mut T {
        self
    }
}

impl HasMut<GraphicsContext> for Context {
    #[inline]
    fn get_mut(&mut self) -> &mut GraphicsContext {
        &mut self.gfx
    }
}

/// Used to represent types that can provide two context types. See also `Has<T>`.
///
/// If you don't know what this is, you most likely want to pass `ctx`.
pub trait HasTwo<T, U> {
    fn get_first(&self) -> &T;
    fn get_second(&self) -> &U;
}

impl<T, U> HasTwo<T, U> for (&T, &U) {
    #[inline]
    fn get_first(&self) -> &T {
        self.0
    }

    #[inline]
    fn get_second(&self) -> &U {
        self.1
    }
}

impl HasTwo<Filesystem, GraphicsContext> for Context {
    #[inline]
    fn get_first(&self) -> &Filesystem {
        &self.fs
    }

    #[inline]
    fn get_second(&self) -> &GraphicsContext {
        &self.gfx
    }
}

#[cfg(feature = "audio")]
impl HasTwo<Filesystem, crate::audio::AudioContext> for Context {
    fn get_first(&self) -> &Filesystem {
        &self.fs
    }

    fn get_second(&self) -> &crate::audio::AudioContext {
        &self.audio
    }
}

impl fmt::Debug for Context {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "<Context: {:p}>", self)
    }
}

impl Context {
    /// Tries to create a new Context using settings from the given [`Conf`](../conf/struct.Conf.html) object.
    /// Usually called by [`ContextBuilder::build()`](struct.ContextBuilder.html#method.build).
    fn from_conf(
        conf: conf::Conf,
        mut fs: Filesystem,
    ) -> GameResult<(Context, winit::event_loop::EventLoop<()>)> {
        #[cfg(feature = "audio")]
        let audio_context = audio::AudioContext::new()?;
        let events_loop = winit::event_loop::EventLoop::new();
        let timer_context = timer::TimeContext::new();
        let graphics_context =
            graphics::context::GraphicsContext::new(&events_loop, &conf, &mut fs)?;

        let ctx = Context {
            conf,
            fs,
            gfx: graphics_context,
            continuing: true,
            quit_requested: false,
            time: timer_context,
            #[cfg(feature = "audio")]
            audio: audio_context,
            keyboard: input::keyboard::KeyboardContext::new(),
            mouse: input::mouse::MouseContext::new(),
            #[cfg(feature = "gamepad")]
            gamepad: input::gamepad::GamepadContext::new()?,
        };

        Ok((ctx, events_loop))
    }
}

use std::borrow::Cow;
use std::path;

/// A builder object for creating a [`Context`](struct.Context.html).
#[derive(Debug, Clone, PartialEq)]
pub struct ContextBuilder {
    pub(crate) game_id: String,
    pub(crate) author: String,
    pub(crate) conf: conf::Conf,
    pub(crate) resources_dir_name: String,
    pub(crate) resources_zip_name: String,
    pub(crate) paths: Vec<path::PathBuf>,
    pub(crate) memory_zip_files: Vec<Cow<'static, [u8]>>,
    pub(crate) load_conf_file: bool,
}

impl ContextBuilder {
    /// Create a new `ContextBuilder` with default settings.
    pub fn new(game_id: &str, author: &str) -> Self {
        Self {
            game_id: game_id.to_string(),
            author: author.to_string(),
            conf: conf::Conf::default(),
            resources_dir_name: "resources".to_string(),
            resources_zip_name: "resources.zip".to_string(),
            paths: vec![],
            memory_zip_files: vec![],
            load_conf_file: true,
        }
    }

    /// Sets the window setup settings.
    #[must_use]
    pub fn window_setup(mut self, setup: conf::WindowSetup) -> Self {
        self.conf.window_setup = setup;
        self
    }

    /// Sets the window mode settings.
    #[must_use]
    pub fn window_mode(mut self, mode: conf::WindowMode) -> Self {
        self.conf.window_mode = mode;
        self
    }

    /// Sets the graphics backend.
    #[must_use]
    pub fn backend(mut self, backend: conf::Backend) -> Self {
        self.conf.backend = backend;
        self
    }

    /// Sets all the config options, overriding any previous
    /// ones from [`window_setup()`](#method.window_setup),
    /// [`window_mode()`](#method.window_mode), and
    /// [`backend()`](#method.backend).  These are used as
    /// defaults and are overridden by any external config
    /// file found.
    #[must_use]
    pub fn default_conf(mut self, conf: conf::Conf) -> Self {
        self.conf = conf;
        self
    }

    /// Sets resources dir name.
    /// Default resources dir name is `resources`.
    #[must_use]
    pub fn resources_dir_name(mut self, new_name: impl ToString) -> Self {
        self.resources_dir_name = new_name.to_string();
        self
    }

    /// Sets resources zip name.
    /// Default resources dir name is `resources.zip`.
    #[must_use]
    pub fn resources_zip_name(mut self, new_name: impl ToString) -> Self {
        self.resources_zip_name = new_name.to_string();
        self
    }

    /// Add a new read-only filesystem path to the places to search
    /// for resources.
    #[must_use]
    pub fn add_resource_path<T>(mut self, path: T) -> Self
    where
        T: Into<path::PathBuf>,
    {
        self.paths.push(path.into());
        self
    }

    /// Add a new zip file from bytes whose contents will be searched
    /// for resources. The zip file will be stored in-memory.
    /// You can pass it a static slice, a `Vec` of bytes, etc.
    ///
    /// ```ignore
    /// use ggez::context::ContextBuilder;
    /// let _ = ContextBuilder::new()
    ///     .add_zipfile_bytes(include_bytes!("../resources.zip").to_vec())
    ///     .build();
    /// ```
    #[must_use]
    pub fn add_zipfile_bytes<B>(mut self, bytes: B) -> Self
    where
        B: Into<Cow<'static, [u8]>>,
    {
        let cow = bytes.into();
        self.memory_zip_files.push(cow);
        self
    }

    /// Specifies whether or not to load the `conf.toml` file if it
    /// exists and use its settings to override the provided values.
    /// Defaults to `true` which is usually what you want, but being
    /// able to fiddle with it is sometimes useful for debugging.
    #[must_use]
    pub fn with_conf_file(mut self, load_conf_file: bool) -> Self {
        self.load_conf_file = load_conf_file;
        self
    }

    /// Build the `Context`.
    pub fn build(self) -> GameResult<(Context, winit::event_loop::EventLoop<()>)> {
        let mut fs = Filesystem::new(
            self.game_id.as_ref(),
            self.author.as_ref(),
            &self.resources_dir_name,
            &self.resources_zip_name,
        )?;

        for path in &self.paths {
            fs.mount(path, true);
        }

        for zipfile_bytes in self.memory_zip_files {
            fs.add_zip_file(std::io::Cursor::new(zipfile_bytes))?;
        }

        let config = if self.load_conf_file {
            fs.read_config().unwrap_or(self.conf)
        } else {
            self.conf
        };

        Context::from_conf(config, fs)
    }
}
<|endoftext|>


<commit_before>//!Handler context and request body reading extensions.
//!
//!#Context
//!
//!The [`Context`][context] contains all the input data for the request
//!handlers, as well as some utilities. This is where request data, like
//!headers, client address and the request body can be retrieved from and it
//!can safely be picked apart, since its ownership is transferred to the
//!handler.
//!
//!##Accessing Headers
//!
//!The headers are stored in the `headers` field. See the [`Headers`][headers]
//!struct for more information about how to access them.
//!
//!```
//!use rustful::{Context, Response};
//!use rustful::header::UserAgent;
//!
//!fn my_handler(context: Context, response: Response) {
//!    if let Some(&UserAgent(ref user_agent)) = context.headers.get() {
//!        let res = format!("got user agent string \"{}\"", user_agent);
//!        response.into_writer().send(res);
//!    } else {
//!        response.into_writer().send("no user agent string provided");
//!    }
//!}
//!```
//!
//!##Path Variables
//!
//!A router may collect variable data from paths (for example `id` in
//!`/products/:id`). The values from these variables can be accessed through
//!the `variables` field.
//!
//!```
//!use rustful::{Context, Response};
//!
//!fn my_handler(context: Context, response: Response) {
//!    if let Some(id) = context.variables.get("id") {
//!        let res = format!("asking for product with id \"{}\"", id);
//!        response.into_writer().send(res);
//!    } else {
//!        //This will usually not happen, unless the handler is also
//!        //assigned to a path without the `id` variable
//!        response.into_writer().send("no id provided");
//!    }
//!}
//!```
//!
//!##Other URL Parts
//!
//! * Query variables (`http://example.com?a=b&c=d`) can be found in the
//!`query` field and they are accessed in exactly the same fashion as path
//!variables are used.
//!
//! * The fragment (`http://example.com#foo`) is also parsed and can be
//!accessed through `fragment` as an optional `String`.
//!
//!##Logging
//!
//!Rustful has a built in logging infrastructure and it is made available to
//!handlers through the `log` field. This provides logging and error reporting
//!in a unified and more controlled fashion than what panics and `println!`
//!gives. See the [`log`][log] module for more information about the standard
//!alternatives.
//!
//!```
//!# fn something_that_may_fail() -> Result<&'static str, &'static str> { Ok("yo") }
//!use rustful::{Context, Response};
//!use rustful::StatusCode::InternalServerError;
//!
//!fn my_handler(context: Context, mut response: Response) {
//!    match something_that_may_fail() {
//!        Ok(res) => response.into_writer().send(res),
//!        Err(e) => {
//!            context.log.error(&format!("it failed! {}", e));
//!            response.set_status(InternalServerError);
//!        }
//!    }
//!}
//!```
//!
//!##Global Data
//!
//!There is also infrastructure for globally accessible data, that can be
//!accessed through the `global` field. This is meant to provide a place for
//!things like database connections or cached data that should be available to
//!all handlers. The storage space itself is immutable when the server has
//!started, so the only way to change it is through some kind of inner
//!mutability.
//!
//!```
//!use rustful::{Context, Response};
//!use rustful::StatusCode::InternalServerError;
//!
//!fn my_handler(context: Context, mut response: Response) {
//!    if let Some(some_wise_words) = context.global.get::<&str>() {
//!        let res = format!("food for thought: {}", some_wise_words);
//!        response.into_writer().send(res);
//!    } else {
//!        context.log.error("there should be a string literal in `global`");
//!        response.set_status(InternalServerError);
//!    }
//!}
//!```
//!
//!##Request Body
//!
//!The body will not be read in advance, unlike the other parts of the
//!request. It is instead available as a `BodyReader` in the field `body`,
//!through which it can be read and parsed as various data formats, like JSON
//!and query strings. The documentation for [`BodyReader`][body_reader] gives
//!more examples.
//!
//!```
//!use std::io::{BufReader, BufRead};
//!use rustful::{Context, Response};
//!
//!fn my_handler(context: Context, response: Response) {
//!    let mut numbered_lines = BufReader::new(context.body).lines().enumerate();
//!    let mut writer = response.into_writer();
//!
//!    while let Some((line_no, Ok(line))) = numbered_lines.next() {
//!        writer.send(format!("{}: {}", line_no + 1, line));
//!    }
//!}
//!```
//!
//![context]: struct.Context.html
//![headers]: ../header/struct.Headers.html
//![log]: ../log/index.html
//![body_reader]: struct.BodyReader.html

use std::collections::HashMap;
use std::io::{self, Read};
use std::net::SocketAddr;

#[cfg(feature = "rustc_json_body")]
use rustc_serialize::json;
#[cfg(feature = "rustc_json_body")]
use rustc_serialize::Decodable;

use hyper::http::HttpReader;
use hyper::net::NetworkStream;
use hyper::buffer::BufReader;

use utils;

use HttpVersion;
use Method;
use header::Headers;
use log::Log;

use Global;

///A container for things like request data and cache.
///
///A `Context` can be dereferenced to a `BodyReader`, allowing direct access to
///the underlying read methods.
pub struct Context<'a, 'b: 'a, 's> {
    ///Headers from the HTTP request.
    pub headers: Headers,

    ///The HTTP version used in the request.
    pub http_version: HttpVersion,

    ///The client address
    pub address: SocketAddr,

    ///The HTTP method.
    pub method: Method,

    ///The requested path.
    pub path: String,

    ///Hypermedia from the current endpoint.
    pub hypermedia: Hypermedia<'s>,

    ///Route variables.
    pub variables: HashMap<String, String>,

    ///Query variables from the path.
    pub query: HashMap<String, String>,

    ///The fragment part of the URL (after #), if provided.
    pub fragment: Option<String>,

    ///Log for notes, errors and warnings.
    pub log: &'s (Log + 's),

    ///Globally accessible data.
    pub global: &'s Global,

    ///A reader for the request body.
    pub body: BodyReader<'a, 'b>,
}

///A reader for a request body.
pub struct BodyReader<'a, 'b: 'a> {
    request: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>
}

impl<'a, 'b> BodyReader<'a, 'b> {
    pub fn from_reader(request: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>) -> BodyReader<'a, 'b> {
        BodyReader {
            request: request
        }
    }
}

///`BodyReader` extension for reading and parsing a query string.
///
///Examples and more information can be found in [the documentation for
///`BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
pub trait ExtQueryBody {
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>>;
}

impl<'a, 'b> ExtQueryBody for BodyReader<'a, 'b> {
    ///Read and parse the request body as a query string. The body will be
    ///decoded as UTF-8 and plain '+' characters will be replaced with spaces.
    ///
    ///A simplified example of how to parse `a=number&b=number`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtQueryBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as a query string
    ///    let query = context.body.read_query_body().unwrap();
    ///
    ///    //Find "a" and "b" and assume that they are numbers
    ///    let a: f64 = query.get("a").and_then(|number| number.parse().ok()).unwrap();
    ///    let b: f64 = query.get("b").and_then(|number| number.parse().ok()).unwrap();
    ///
    ///    response.into_writer().send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    #[inline]
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>> {
        let mut buf = Vec::new();
        try!(self.read_to_end(&mut buf));
        Ok(utils::parse_parameters(&buf))
    }
}

///`BodyReader` extension for reading and parsing a JSON body.
///
///It is available by default and can be toggled using the `rustc_json_body`
///feature. Examples and more information can be found in [the documentation
///for `BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
#[cfg(feature = "rustc_json_body")]
pub trait ExtJsonBody {
    ///Read the request body into a JSON structure.
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError>;

    ///Parse and decode the request body as some type `T`.
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T>;
}

#[cfg(feature = "rustc_json_body")]
impl<'a, 'b> ExtJsonBody for BodyReader<'a, 'b> {
    ///Read the request body into a generic JSON structure. This structure can
    ///then be navigated and parsed freely.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as JSON
    ///    let json = context.body.read_json_body().unwrap();
    ///
    ///    //Find "a" and "b" in the root object and assume that they are numbers
    ///    let a = json.find("a").and_then(|number| number.as_f64()).unwrap();
    ///    let b = json.find("b").and_then(|number| number.as_f64()).unwrap();
    ///
    ///    response.into_writer().send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError> {
        json::Json::from_reader(self)
    }

    ///Read and decode a request body as a type `T`. The target type must
    ///implement `rustc_serialize::Decodable`.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///extern crate rustful;
    ///extern crate rustc_serialize;
    ///
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///#[derive(RustcDecodable)]
    ///struct Foo {
    ///    a: f64,
    ///    b: f64
    ///}
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Decode a JSON formatted request body into Foo
    ///    let foo: Foo = context.body.decode_json_body().unwrap();
    ///
    ///    let res = format!("{} + {} = {}", foo.a, foo.b, foo.a + foo.b);
    ///    response.into_writer().send(res);
    ///}
    ///# fn main() {}
    ///```
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T> {
        let mut buf = String::new();
        try!(self.read_to_string(&mut buf).map_err(|e| {
            let parse_err = json::ParserError::IoError(e);
            json::DecoderError::ParseError(parse_err)
        }));
        json::decode(&buf)
    }
}

impl<'a, 'b> Read for BodyReader<'a, 'b> {
    ///Read the request body.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.request.read(buf)
    }
}

///Hypermedia connected to an API endpoint.
pub struct Hypermedia<'a> {
    ///Forward links from the current endpoint to other endpoints.
    pub links: Vec<Link<'a>>
}

impl<'a> Hypermedia<'a> {
    ///Create an empty `Hypermedia` structure.
    pub fn new() -> Hypermedia<'a> {
        Hypermedia {
            links: vec![]
        }
    }
}

///A hyperlink.
#[derive(PartialEq, Eq, Debug)]
pub struct Link<'a> {
    ///The HTTP method for which an endpoint is available. It can be left
    ///unspecified if the method doesn't matter.
    pub method: Option<Method>,
    ///A relative path from the current location.
    pub path: Vec<LinkSegment<'a>>
}

///A segment of a hyperlink path.
#[derive(PartialEq, Eq, Debug)]
pub enum LinkSegment<'a> {
    ///A static part of a path.
    Static(&'a str),
    ///A dynamic part of a path. Can be substituted with anything.
    Variable(&'a str),
    ///A recursive wildcard. Will recursively match anything.
    RecursiveWildcard
}
<commit_msg>Fix outdated description of Context<commit_after>//!Handler context and request body reading extensions.
//!
//!#Context
//!
//!The [`Context`][context] contains all the input data for the request
//!handlers, as well as some utilities. This is where request data, like
//!headers, client address and the request body can be retrieved from and it
//!can safely be picked apart, since its ownership is transferred to the
//!handler.
//!
//!##Accessing Headers
//!
//!The headers are stored in the `headers` field. See the [`Headers`][headers]
//!struct for more information about how to access them.
//!
//!```
//!use rustful::{Context, Response};
//!use rustful::header::UserAgent;
//!
//!fn my_handler(context: Context, response: Response) {
//!    if let Some(&UserAgent(ref user_agent)) = context.headers.get() {
//!        let res = format!("got user agent string \"{}\"", user_agent);
//!        response.into_writer().send(res);
//!    } else {
//!        response.into_writer().send("no user agent string provided");
//!    }
//!}
//!```
//!
//!##Path Variables
//!
//!A router may collect variable data from paths (for example `id` in
//!`/products/:id`). The values from these variables can be accessed through
//!the `variables` field.
//!
//!```
//!use rustful::{Context, Response};
//!
//!fn my_handler(context: Context, response: Response) {
//!    if let Some(id) = context.variables.get("id") {
//!        let res = format!("asking for product with id \"{}\"", id);
//!        response.into_writer().send(res);
//!    } else {
//!        //This will usually not happen, unless the handler is also
//!        //assigned to a path without the `id` variable
//!        response.into_writer().send("no id provided");
//!    }
//!}
//!```
//!
//!##Other URL Parts
//!
//! * Query variables (`http://example.com?a=b&c=d`) can be found in the
//!`query` field and they are accessed in exactly the same fashion as path
//!variables are used.
//!
//! * The fragment (`http://example.com#foo`) is also parsed and can be
//!accessed through `fragment` as an optional `String`.
//!
//!##Logging
//!
//!Rustful has a built in logging infrastructure and it is made available to
//!handlers through the `log` field. This provides logging and error reporting
//!in a unified and more controlled fashion than what panics and `println!`
//!gives. See the [`log`][log] module for more information about the standard
//!alternatives.
//!
//!```
//!# fn something_that_may_fail() -> Result<&'static str, &'static str> { Ok("yo") }
//!use rustful::{Context, Response};
//!use rustful::StatusCode::InternalServerError;
//!
//!fn my_handler(context: Context, mut response: Response) {
//!    match something_that_may_fail() {
//!        Ok(res) => response.into_writer().send(res),
//!        Err(e) => {
//!            context.log.error(&format!("it failed! {}", e));
//!            response.set_status(InternalServerError);
//!        }
//!    }
//!}
//!```
//!
//!##Global Data
//!
//!There is also infrastructure for globally accessible data, that can be
//!accessed through the `global` field. This is meant to provide a place for
//!things like database connections or cached data that should be available to
//!all handlers. The storage space itself is immutable when the server has
//!started, so the only way to change it is through some kind of inner
//!mutability.
//!
//!```
//!use rustful::{Context, Response};
//!use rustful::StatusCode::InternalServerError;
//!
//!fn my_handler(context: Context, mut response: Response) {
//!    if let Some(some_wise_words) = context.global.get::<&str>() {
//!        let res = format!("food for thought: {}", some_wise_words);
//!        response.into_writer().send(res);
//!    } else {
//!        context.log.error("there should be a string literal in `global`");
//!        response.set_status(InternalServerError);
//!    }
//!}
//!```
//!
//!##Request Body
//!
//!The body will not be read in advance, unlike the other parts of the
//!request. It is instead available as a `BodyReader` in the field `body`,
//!through which it can be read and parsed as various data formats, like JSON
//!and query strings. The documentation for [`BodyReader`][body_reader] gives
//!more examples.
//!
//!```
//!use std::io::{BufReader, BufRead};
//!use rustful::{Context, Response};
//!
//!fn my_handler(context: Context, response: Response) {
//!    let mut numbered_lines = BufReader::new(context.body).lines().enumerate();
//!    let mut writer = response.into_writer();
//!
//!    while let Some((line_no, Ok(line))) = numbered_lines.next() {
//!        writer.send(format!("{}: {}", line_no + 1, line));
//!    }
//!}
//!```
//!
//![context]: struct.Context.html
//![headers]: ../header/struct.Headers.html
//![log]: ../log/index.html
//![body_reader]: struct.BodyReader.html

use std::collections::HashMap;
use std::io::{self, Read};
use std::net::SocketAddr;

#[cfg(feature = "rustc_json_body")]
use rustc_serialize::json;
#[cfg(feature = "rustc_json_body")]
use rustc_serialize::Decodable;

use hyper::http::HttpReader;
use hyper::net::NetworkStream;
use hyper::buffer::BufReader;

use utils;

use HttpVersion;
use Method;
use header::Headers;
use log::Log;

use Global;

///A container for handler input, like request data and utilities.
pub struct Context<'a, 'b: 'a, 's> {
    ///Headers from the HTTP request.
    pub headers: Headers,

    ///The HTTP version used in the request.
    pub http_version: HttpVersion,

    ///The client address
    pub address: SocketAddr,

    ///The HTTP method.
    pub method: Method,

    ///The requested path.
    pub path: String,

    ///Hypermedia from the current endpoint.
    pub hypermedia: Hypermedia<'s>,

    ///Route variables.
    pub variables: HashMap<String, String>,

    ///Query variables from the path.
    pub query: HashMap<String, String>,

    ///The fragment part of the URL (after #), if provided.
    pub fragment: Option<String>,

    ///Log for notes, errors and warnings.
    pub log: &'s (Log + 's),

    ///Globally accessible data.
    pub global: &'s Global,

    ///A reader for the request body.
    pub body: BodyReader<'a, 'b>,
}

///A reader for a request body.
pub struct BodyReader<'a, 'b: 'a> {
    request: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>
}

impl<'a, 'b> BodyReader<'a, 'b> {
    pub fn from_reader(request: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>) -> BodyReader<'a, 'b> {
        BodyReader {
            request: request
        }
    }
}

///`BodyReader` extension for reading and parsing a query string.
///
///Examples and more information can be found in [the documentation for
///`BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
pub trait ExtQueryBody {
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>>;
}

impl<'a, 'b> ExtQueryBody for BodyReader<'a, 'b> {
    ///Read and parse the request body as a query string. The body will be
    ///decoded as UTF-8 and plain '+' characters will be replaced with spaces.
    ///
    ///A simplified example of how to parse `a=number&b=number`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtQueryBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as a query string
    ///    let query = context.body.read_query_body().unwrap();
    ///
    ///    //Find "a" and "b" and assume that they are numbers
    ///    let a: f64 = query.get("a").and_then(|number| number.parse().ok()).unwrap();
    ///    let b: f64 = query.get("b").and_then(|number| number.parse().ok()).unwrap();
    ///
    ///    response.into_writer().send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    #[inline]
    fn read_query_body(&mut self) -> io::Result<HashMap<String, String>> {
        let mut buf = Vec::new();
        try!(self.read_to_end(&mut buf));
        Ok(utils::parse_parameters(&buf))
    }
}

///`BodyReader` extension for reading and parsing a JSON body.
///
///It is available by default and can be toggled using the `rustc_json_body`
///feature. Examples and more information can be found in [the documentation
///for `BodyReader`][body_reader].
///
///[body_reader]: struct.BodyReader.html
#[cfg(feature = "rustc_json_body")]
pub trait ExtJsonBody {
    ///Read the request body into a JSON structure.
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError>;

    ///Parse and decode the request body as some type `T`.
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T>;
}

#[cfg(feature = "rustc_json_body")]
impl<'a, 'b> ExtJsonBody for BodyReader<'a, 'b> {
    ///Read the request body into a generic JSON structure. This structure can
    ///then be navigated and parsed freely.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Parse the request body as JSON
    ///    let json = context.body.read_json_body().unwrap();
    ///
    ///    //Find "a" and "b" in the root object and assume that they are numbers
    ///    let a = json.find("a").and_then(|number| number.as_f64()).unwrap();
    ///    let b = json.find("b").and_then(|number| number.as_f64()).unwrap();
    ///
    ///    response.into_writer().send(format!("{} + {} = {}", a, b, a + b));
    ///}
    ///```
    fn read_json_body(&mut self) -> Result<json::Json, json::BuilderError> {
        json::Json::from_reader(self)
    }

    ///Read and decode a request body as a type `T`. The target type must
    ///implement `rustc_serialize::Decodable`.
    ///
    ///A simplified example of how to parse `{ "a": number, "b": number }`:
    ///
    ///```
    ///extern crate rustful;
    ///extern crate rustc_serialize;
    ///
    ///use rustful::{Context, Response};
    ///use rustful::context::ExtJsonBody;
    ///
    ///#[derive(RustcDecodable)]
    ///struct Foo {
    ///    a: f64,
    ///    b: f64
    ///}
    ///
    ///fn my_handler(mut context: Context, response: Response) {
    ///    //Decode a JSON formatted request body into Foo
    ///    let foo: Foo = context.body.decode_json_body().unwrap();
    ///
    ///    let res = format!("{} + {} = {}", foo.a, foo.b, foo.a + foo.b);
    ///    response.into_writer().send(res);
    ///}
    ///# fn main() {}
    ///```
    fn decode_json_body<T: Decodable>(&mut self) -> json::DecodeResult<T> {
        let mut buf = String::new();
        try!(self.read_to_string(&mut buf).map_err(|e| {
            let parse_err = json::ParserError::IoError(e);
            json::DecoderError::ParseError(parse_err)
        }));
        json::decode(&buf)
    }
}

impl<'a, 'b> Read for BodyReader<'a, 'b> {
    ///Read the request body.
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.request.read(buf)
    }
}

///Hypermedia connected to an API endpoint.
pub struct Hypermedia<'a> {
    ///Forward links from the current endpoint to other endpoints.
    pub links: Vec<Link<'a>>
}

impl<'a> Hypermedia<'a> {
    ///Create an empty `Hypermedia` structure.
    pub fn new() -> Hypermedia<'a> {
        Hypermedia {
            links: vec![]
        }
    }
}

///A hyperlink.
#[derive(PartialEq, Eq, Debug)]
pub struct Link<'a> {
    ///The HTTP method for which an endpoint is available. It can be left
    ///unspecified if the method doesn't matter.
    pub method: Option<Method>,
    ///A relative path from the current location.
    pub path: Vec<LinkSegment<'a>>
}

///A segment of a hyperlink path.
#[derive(PartialEq, Eq, Debug)]
pub enum LinkSegment<'a> {
    ///A static part of a path.
    Static(&'a str),
    ///A dynamic part of a path. Can be substituted with anything.
    Variable(&'a str),
    ///A recursive wildcard. Will recursively match anything.
    RecursiveWildcard
}
<|endoftext|>


<commit_before>use crate::errors::OscError;
use crate::types::{OscArray, OscBundle, OscColor, OscMessage, OscMidiMessage, OscPacket, OscTime, OscType};
use crate::alloc::{string::{String, ToString}, vec::Vec};

use nom::Offset;
use nom::sequence::terminated;
use nom::bytes::complete::{take, take_till};
use nom::combinator::{map, map_parser};
use nom::multi::many0;
use nom::number::complete::{be_f32, be_f64, be_i32, be_i64, be_u32};
use nom::{IResult,combinator::map_res,sequence::tuple};

/// Common MTU size for ethernet
pub const MTU: usize = 1536;

/// Takes a bytes slice representing a UDP packet and returns the OSC packet as well as a slice of
/// any bytes remaining after the OSC packet.
pub fn decode_udp<'a>(msg: &'a [u8]) -> IResult<&'a [u8], OscPacket, OscError> {
    decode_packet(msg, msg)
}

/// Takes a bytes slice from a TCP stream (or any stream-based protocol) and returns the first OSC
/// packet as well as a slice of the bytes remaining after the packet.
pub fn decode_tcp<'a>(msg: &'a [u8]) -> IResult<&'a [u8], Option<OscPacket>, OscError> {
    let (input, osc_packet_length) = be_u32(msg)?;

    if osc_packet_length as usize > msg.len() {
        return Ok((msg, None));
    }

    decode_packet(input, msg).map(|(remainder, osc_packet)| {
        (remainder, Some(osc_packet))
    })
}

/// Takes a bytes slice from a TCP stream (or any stream-based protocol) and returns a vec of all
/// OSC packets in the slice as well as a slice of the bytes remaining after the last packet.
pub fn decode_tcp_vec<'a>(msg: &'a [u8]) -> IResult<&'a [u8], Vec<OscPacket>, OscError> {
    let mut input = msg;
    let mut osc_packets = vec![];

    while let (remainder, Some(osc_packet)) = decode_tcp(input)? {
        input = remainder;
        osc_packets.push(osc_packet);

        if remainder.len() == 0 {
            break;
        }
    };

    Ok((input, osc_packets))
}

fn decode_packet<'a>(
    input: &'a [u8],
    original_input: &'a[u8],
) -> IResult<&'a [u8], OscPacket, OscError> {
    if input.is_empty() {
        return Err(nom::Err::Error(OscError::BadPacket("Empty packet.")));
    }

    let (input, addr) = read_osc_string(input, original_input)?;

    match addr.chars().next() {
        Some('/') => {
            decode_message(addr, input, original_input)
        }
        Some('#') if &addr == "#bundle" => {
            decode_bundle(input, original_input)
        }
        _ => Err(nom::Err::Error(OscError::BadPacket(
            "Invalid message address or bundle tag"
        ))),
    }
}

fn decode_message<'a>(
    addr: String,
    input: &'a [u8],
    original_input: &'a[u8],
) -> IResult<&'a [u8], OscPacket, OscError> {
    let (input, type_tags) = read_osc_string(input, original_input)?;

    if type_tags.len() > 1 {
        let (input, args) = read_osc_args(
            input,
            original_input,
            type_tags,
        )?;
        Ok((input, OscPacket::Message(OscMessage { addr, args })))
    } else {
        Ok((input, OscPacket::Message(OscMessage { addr, args: vec![] })))
    }
}

fn decode_bundle<'a>(
    input: &'a [u8],
    original_input: &'a[u8],
) -> IResult<&'a [u8], OscPacket, OscError> {
    let (input, (timetag, content)) = tuple((
        read_time_tag,
        many0(|input| read_bundle_element(input, original_input)),
    ))(input)?;

    Ok((
        input,
        OscPacket::Bundle(OscBundle {
            timetag,
            content,
        }),
    ))
}

fn read_bundle_element<'a>(input: &'a [u8], original_input: &'a[u8]) -> IResult<&'a [u8], OscPacket, OscError> {
    let (input, elem_size) = be_u32(input)?;

    let result = map_parser(
        |input| {
            take(elem_size)(input).map_err(|_: nom::Err<OscError>| {
                nom::Err::Error(OscError::BadBundle(
                    "Bundle shorter than expected!".to_string(),
                ))
            })
        },
        |input| decode_packet(input, original_input),
    )(input);
    drop(elem_size);
    result
}

fn read_osc_string<'a>(input: &'a [u8], original_input: &'a[u8]) -> IResult<&'a [u8], String, OscError> {
    map_res(
        terminated(
            take_till(|c| c == 0u8),
            pad_to_32_bit_boundary(original_input),
        ),
        |str_buf: &'a[u8]| {
            String::from_utf8(str_buf.into())
                .map_err(OscError::StringError)
                .map(|s| s.trim_matches(0u8 as char).to_string())
        },
    )(input)
}

fn read_osc_args<'a>(
    mut input: &'a[u8],
    original_input: &'a[u8],
    raw_type_tags: String,
) ->  IResult<&'a [u8], Vec<OscType>, OscError> {
    let type_tags: Vec<char> = raw_type_tags.chars().skip(1).collect();

    let mut args: Vec<OscType> = Vec::with_capacity(type_tags.len());
    let mut stack: Vec<Vec<OscType>> = Vec::new();
    for tag in type_tags {
        if tag == '[' {
            // array start: save current frame and start a new frame
            // for the array's content
            stack.push(args);
            args = Vec::new();
        } else if tag == ']' {
            // found the end of the current array:
            // create array object from current frame and step one level up
            let array = OscType::Array(OscArray { content: args });
            match stack.pop() {
                Some(stashed) => args = stashed,
                None => return Err(nom::Err::Error(OscError::BadMessage(
                    "Encountered ] outside array"
                ))),
            }
            args.push(array);
        } else {
            let input_and_arg = read_osc_arg(input, original_input, tag)?;
            input = input_and_arg.0;
            args.push(input_and_arg.1);
        }
    }
    Ok((input, args))
}

fn read_osc_arg<'a>(input: &'a[u8], original_input: &'a[u8], tag: char) -> IResult<&'a[u8], OscType, OscError> {
    match tag {
        'f' => map(be_f32, OscType::Float)(input),
        'd' => map(be_f64, OscType::Double)(input),
        'i' => map(be_i32, OscType::Int)(input),
        'h' => map(be_i64, OscType::Long)(input),
        's' => {
            read_osc_string(input, original_input)
                .map(|(remainder, string)| (remainder, OscType::String(string)))
        }
        't' => read_time_tag(input).map(|(remainder, time)| {
            (remainder, OscType::Time(time))
        }),
        'b' => read_blob(input, original_input),
        'r' => read_osc_color(input),
        'T' => Ok((input, true.into())),
        'F' => Ok((input, false.into())),
        'N' => Ok((input, OscType::Nil)),
        'I' => Ok((input, OscType::Inf)),
        'c' => read_char(input),
        'm' => read_midi_message(input),
        _ => Err(nom::Err::Error(OscError::BadArg(format!(
            "Type tag \"{}\" is not implemented!",
            tag
        )))),
    }
}

fn read_char(input: &[u8]) -> IResult<&[u8], OscType, OscError> {
    map_res(
        be_u32,
        |b| {
            let opt_char = char::from_u32(b);
            match opt_char {
                Some(c) => Ok(OscType::Char(c)),
                None => Err(OscError::BadArg(
                    "Argument is not a char!".to_string(),
                )),
            }
        },
    )(input)
}

fn read_blob<'a>(input: &'a[u8], original_input: &'a[u8]) -> IResult<&'a[u8], OscType, OscError> {
    let (input, size) = be_u32(input)?;

    map(
        terminated(
            take(size),
            pad_to_32_bit_boundary(original_input),
        ),
        |blob| OscType::Blob(blob.into()),
    )(input)
}

fn read_time_tag<'a>(input: &'a[u8]) -> IResult<&'a[u8], OscTime, OscError> {
    map(
        tuple((be_u32, be_u32)),
        |(seconds, fractional)| OscTime {
            seconds,
            fractional,
        },
    )(input)
}

fn read_midi_message<'a>(input: &'a[u8]) -> IResult<&'a[u8], OscType, OscError> {
    map(take(4usize), |buf: &[u8]| {
        OscType::Midi(OscMidiMessage {
            port: buf[0],
            status: buf[1],
            data1: buf[2],
            data2: buf[3],
        })
    })(input)
}

fn read_osc_color<'a>(input: &'a[u8]) -> IResult<&'a[u8], OscType, OscError> {
    map(take(4usize), |buf: &[u8]| {
        OscType::Color(OscColor {
            red: buf[0],
            green: buf[1],
            blue: buf[2],
            alpha: buf[3],
        })
    })(input)
}

fn pad_to_32_bit_boundary<'a>(
    original_input: &'a[u8]
) -> impl Fn(&'a[u8]) -> IResult<&'a[u8], (), OscError> {
    move |input| {
        let offset = 4 - original_input.offset(input) % 4;
        let (input, _) = take(offset)(input)?;
        Ok((input, ()))
    }
}
<commit_msg>Return Result instead of IResult<commit_after>use crate::errors::OscError;
use crate::types::{OscArray, OscBundle, OscColor, OscMessage, OscMidiMessage, OscPacket, OscTime, OscType};
use crate::alloc::{string::{String, ToString}, vec::Vec};

use nom::Offset;
use nom::sequence::terminated;
use nom::bytes::complete::{take, take_till};
use nom::combinator::{map, map_parser};
use nom::multi::many0;
use nom::number::complete::{be_f32, be_f64, be_i32, be_i64, be_u32};
use nom::{IResult,combinator::map_res,sequence::tuple,Err};
use OscError::BadPacket;

/// Common MTU size for ethernet
pub const MTU: usize = 1536;

/// Takes a bytes slice representing a UDP packet and returns the OSC packet as well as a slice of
/// any bytes remaining after the OSC packet.
pub fn decode_udp<'a>(msg: &'a [u8]) -> Result<(&'a [u8], OscPacket), OscError> {
    match decode_packet(msg, msg) {
        Ok((remainder, osc_packet)) => Ok((remainder, osc_packet)),
        Err(e) => match e {
            Err::Incomplete(_) => Err(BadPacket("Incomplete data")),
            Err::Error(e) => Err(e),
            Err::Failure(e) => Err(e)
        }
    }
}

/// Takes a bytes slice from a TCP stream (or any stream-based protocol) and returns the first OSC
/// packet as well as a slice of the bytes remaining after the packet.
pub fn decode_tcp<'a>(msg: &'a [u8]) -> Result<(&'a [u8], Option<OscPacket>), OscError> {
    let (input, osc_packet_length) = match be_u32(msg) {
        Ok((i, o)) => (i, o),
        Err(e) => match e {
            Err::Incomplete(_) => return Err(BadPacket("Incomplete data")),
            Err::Error(e) => return Err(e),
            Err::Failure(e) => return Err(e)
        }
    };

    if osc_packet_length as usize > msg.len() {
        return Ok((msg, None));
    }

    match decode_packet(input, msg).map(|(remainder, osc_packet)| {
        (remainder, Some(osc_packet))
    }) {
        Ok((remainder, osc_packet)) => Ok((remainder, osc_packet)),
        Err(e) => match e {
            Err::Incomplete(_) => Err(BadPacket("Incomplete data")),
            Err::Error(e) => Err(e),
            Err::Failure(e) => Err(e)
        }
    }
}

/// Takes a bytes slice from a TCP stream (or any stream-based protocol) and returns a vec of all
/// OSC packets in the slice as well as a slice of the bytes remaining after the last packet.
pub fn decode_tcp_vec<'a>(msg: &'a [u8]) -> Result<(&'a [u8], Vec<OscPacket>), OscError> {
    let mut input = msg;
    let mut osc_packets = vec![];

    while let (remainder, Some(osc_packet)) = decode_tcp(input)? {
        input = remainder;
        osc_packets.push(osc_packet);

        if remainder.len() == 0 {
            break;
        }
    };

    Ok((input, osc_packets))
}

fn decode_packet<'a>(
    input: &'a [u8],
    original_input: &'a[u8],
) -> IResult<&'a [u8], OscPacket, OscError> {
    if input.is_empty() {
        return Err(nom::Err::Error(OscError::BadPacket("Empty packet.")));
    }

    let (input, addr) = read_osc_string(input, original_input)?;

    match addr.chars().next() {
        Some('/') => {
            decode_message(addr, input, original_input)
        }
        Some('#') if &addr == "#bundle" => {
            decode_bundle(input, original_input)
        }
        _ => Err(nom::Err::Error(OscError::BadPacket(
            "Invalid message address or bundle tag"
        ))),
    }
}

fn decode_message<'a>(
    addr: String,
    input: &'a [u8],
    original_input: &'a[u8],
) -> IResult<&'a [u8], OscPacket, OscError> {
    let (input, type_tags) = read_osc_string(input, original_input)?;

    if type_tags.len() > 1 {
        let (input, args) = read_osc_args(
            input,
            original_input,
            type_tags,
        )?;
        Ok((input, OscPacket::Message(OscMessage { addr, args })))
    } else {
        Ok((input, OscPacket::Message(OscMessage { addr, args: vec![] })))
    }
}

fn decode_bundle<'a>(
    input: &'a [u8],
    original_input: &'a[u8],
) -> IResult<&'a [u8], OscPacket, OscError> {
    let (input, (timetag, content)) = tuple((
        read_time_tag,
        many0(|input| read_bundle_element(input, original_input)),
    ))(input)?;

    Ok((
        input,
        OscPacket::Bundle(OscBundle {
            timetag,
            content,
        }),
    ))
}

fn read_bundle_element<'a>(input: &'a [u8], original_input: &'a[u8]) -> IResult<&'a [u8], OscPacket, OscError> {
    let (input, elem_size) = be_u32(input)?;

    let result = map_parser(
        |input| {
            take(elem_size)(input).map_err(|_: nom::Err<OscError>| {
                nom::Err::Error(OscError::BadBundle(
                    "Bundle shorter than expected!".to_string(),
                ))
            })
        },
        |input| decode_packet(input, original_input),
    )(input);
    drop(elem_size);
    result
}

fn read_osc_string<'a>(input: &'a [u8], original_input: &'a[u8]) -> IResult<&'a [u8], String, OscError> {
    map_res(
        terminated(
            take_till(|c| c == 0u8),
            pad_to_32_bit_boundary(original_input),
        ),
        |str_buf: &'a[u8]| {
            String::from_utf8(str_buf.into())
                .map_err(OscError::StringError)
                .map(|s| s.trim_matches(0u8 as char).to_string())
        },
    )(input)
}

fn read_osc_args<'a>(
    mut input: &'a[u8],
    original_input: &'a[u8],
    raw_type_tags: String,
) ->  IResult<&'a [u8], Vec<OscType>, OscError> {
    let type_tags: Vec<char> = raw_type_tags.chars().skip(1).collect();

    let mut args: Vec<OscType> = Vec::with_capacity(type_tags.len());
    let mut stack: Vec<Vec<OscType>> = Vec::new();
    for tag in type_tags {
        if tag == '[' {
            // array start: save current frame and start a new frame
            // for the array's content
            stack.push(args);
            args = Vec::new();
        } else if tag == ']' {
            // found the end of the current array:
            // create array object from current frame and step one level up
            let array = OscType::Array(OscArray { content: args });
            match stack.pop() {
                Some(stashed) => args = stashed,
                None => return Err(nom::Err::Error(OscError::BadMessage(
                    "Encountered ] outside array"
                ))),
            }
            args.push(array);
        } else {
            let input_and_arg = read_osc_arg(input, original_input, tag)?;
            input = input_and_arg.0;
            args.push(input_and_arg.1);
        }
    }
    Ok((input, args))
}

fn read_osc_arg<'a>(input: &'a[u8], original_input: &'a[u8], tag: char) -> IResult<&'a[u8], OscType, OscError> {
    match tag {
        'f' => map(be_f32, OscType::Float)(input),
        'd' => map(be_f64, OscType::Double)(input),
        'i' => map(be_i32, OscType::Int)(input),
        'h' => map(be_i64, OscType::Long)(input),
        's' => {
            read_osc_string(input, original_input)
                .map(|(remainder, string)| (remainder, OscType::String(string)))
        }
        't' => read_time_tag(input).map(|(remainder, time)| {
            (remainder, OscType::Time(time))
        }),
        'b' => read_blob(input, original_input),
        'r' => read_osc_color(input),
        'T' => Ok((input, true.into())),
        'F' => Ok((input, false.into())),
        'N' => Ok((input, OscType::Nil)),
        'I' => Ok((input, OscType::Inf)),
        'c' => read_char(input),
        'm' => read_midi_message(input),
        _ => Err(nom::Err::Error(OscError::BadArg(format!(
            "Type tag \"{}\" is not implemented!",
            tag
        )))),
    }
}

fn read_char(input: &[u8]) -> IResult<&[u8], OscType, OscError> {
    map_res(
        be_u32,
        |b| {
            let opt_char = char::from_u32(b);
            match opt_char {
                Some(c) => Ok(OscType::Char(c)),
                None => Err(OscError::BadArg(
                    "Argument is not a char!".to_string(),
                )),
            }
        },
    )(input)
}

fn read_blob<'a>(input: &'a[u8], original_input: &'a[u8]) -> IResult<&'a[u8], OscType, OscError> {
    let (input, size) = be_u32(input)?;

    map(
        terminated(
            take(size),
            pad_to_32_bit_boundary(original_input),
        ),
        |blob| OscType::Blob(blob.into()),
    )(input)
}

fn read_time_tag<'a>(input: &'a[u8]) -> IResult<&'a[u8], OscTime, OscError> {
    map(
        tuple((be_u32, be_u32)),
        |(seconds, fractional)| OscTime {
            seconds,
            fractional,
        },
    )(input)
}

fn read_midi_message<'a>(input: &'a[u8]) -> IResult<&'a[u8], OscType, OscError> {
    map(take(4usize), |buf: &[u8]| {
        OscType::Midi(OscMidiMessage {
            port: buf[0],
            status: buf[1],
            data1: buf[2],
            data2: buf[3],
        })
    })(input)
}

fn read_osc_color<'a>(input: &'a[u8]) -> IResult<&'a[u8], OscType, OscError> {
    map(take(4usize), |buf: &[u8]| {
        OscType::Color(OscColor {
            red: buf[0],
            green: buf[1],
            blue: buf[2],
            alpha: buf[3],
        })
    })(input)
}

fn pad_to_32_bit_boundary<'a>(
    original_input: &'a[u8]
) -> impl Fn(&'a[u8]) -> IResult<&'a[u8], (), OscError> {
    move |input| {
        let offset = 4 - original_input.offset(input) % 4;
        let (input, _) = take(offset)(input)?;
        Ok((input, ()))
    }
}
<|endoftext|>