<commit_before>use super::Rope;
use std::iter;

#[test]
fn rebalance_test_1() {
    let mut r = Rope::from("This is a large string \
                        that will need to be rebalanced.".to_string());
    r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn rebalance_test_2() {
    let mut r =
        Rope::from("Lorem ipsum dolor sit amet, consectetur adipiscing eli\
                    t, sed do eiusmod tempor incididunt ut labore et dolor\
                    e magna aliqua. Ut enim ad minim veniam, quis nostrud \
                    exercitation ullamco laboris nisi ut aliquip ex ea com\
                    modo consequat. Duis aute irure dolor in reprehenderit\
                     in voluptate velit esse cillum dolore eu fugiat nulla\
                     pariatur. Excepteur sint occaecat cupidatat non proid\
                    ent, sunt in culpa qui officia deserunt mollit anim id\
                     est laborum.".to_string());
    r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn big_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn repeated_concat_left_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    for _ in 1..1000 {
        r = r + iter::repeat('a').take(100).collect::<String>();
    }
    assert!(r.is_balanced());
}

#[test]
fn repeated_concat_right_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    for _ in 1..1000 {
        let s2 = iter::repeat('a').take(100).collect::<String>();
        r = Rope::from(s2) + r;
    }
    assert!(r.is_balanced());
}

#[test]
fn append_empty_rope() {
    let mut an_rope = Rope::from("");
    an_rope.append(Rope::from("abcd"));
    assert_eq!(&an_rope, "abcd");

    let mut an_rope = Rope::from("abcd");
    an_rope.append(Rope::from(""));
    assert_eq!(&an_rope, "abcd");
}

#[test]
fn append() {
    let mut an_rope = Rope::from(String::from("abcd"));
    an_rope.append(Rope::from(String::from("efgh")));
    assert_eq!(an_rope, Rope::from(String::from("abcdefgh")) );
}

#[test]
fn with_append_empty_rope() {
    let an_rope = Rope::from("");
    let another_rope = an_rope.with_append(Rope::from("abcd"));
    assert_eq!(&another_rope, "abcd");
    assert_eq!(&an_rope, "");

    let an_rope = Rope::from("abcd");
    let an_rope = an_rope.with_append(Rope::from(""));
    assert_eq!(&an_rope, "abcd");
}

#[test]
fn with_append() {
    let an_rope = Rope::from("abcd");
    let another_rope = an_rope.with_append(Rope::from("efgh"));
    assert_eq!(&another_rope, "abcdefgh");
    assert_eq!(&an_rope, "abcd");
}

#[test]
fn prepend_empty_rope() {
    let mut an_rope = Rope::from("");
    an_rope.prepend(Rope::from("abcd"));
    assert_eq!(&an_rope, "abcd");

    let mut an_rope = Rope::from("abcd");
    an_rope.prepend(Rope::from(""));
    assert_eq!(&an_rope, "abcd");
}

#[test]
fn with_prepend_empty_rope() {
    let an_rope = Rope::from("");
    let another_rope = an_rope.with_prepend(Rope::from("abcd"));
    assert_eq!(&an_rope, "");
    assert_eq!(&another_rope, "abcd");

    let an_rope = Rope::from("abcd");
    let another_rope = an_rope.with_prepend(Rope::from(""));
    assert_eq!(&an_rope, "abcd");
    assert_eq!(&another_rope, &an_rope);
    assert_eq!(&another_rope, "abcd");
}

#[test]
fn with_prepend() {
    let an_rope = Rope::from("efgh");
    let another_rope = an_rope.with_prepend(Rope::from("abcd"));
    assert_eq!(&an_rope, "efgh");
    assert_eq!(&another_rope, "abcdefgh");
}

#[test]
fn prepend() {
    let mut an_rope = Rope::from(String::from("efgh"));
    an_rope.prepend(Rope::from(String::from("abcd")));
    assert_eq!(&an_rope, "abcdefgh");
}

#[test]
fn merge_rebalance_test() {
    let s = "Lorem ipsum dolor sit amet, consectetur adipiscing eli\
             t, sed do eiusmod tempor incididunt ut labore et dolor\
             e magna aliqua. Ut enim ad minim veniam, quis nostrud \
             exercitation ullamco laboris nisi ut aliquip ex ea com\
             modo consequat. Duis aute irure dolor in reprehenderit\
              in voluptate velit esse cillum dolore eu fugiat nulla\
              pariatur. Excepteur sint occaecat cupidatat non proid\
             ent, sunt in culpa qui officia deserunt mollit anim id\
              est laborum.";

     let t = Rope::from(s.to_owned());
     let mut u = t + s;
     u.rebalance();
     assert!(u.is_balanced());
}

#[test]
fn with_insert_rope_balance_test() {
    let s: String = iter::repeat('a').take(10).collect();
    let mut r_1 = Rope::from(s);
    for _ in 0..99 {
        let t: String = iter::repeat('a').take(10).collect();
        r_1 = r_1.with_insert_rope(5, Rope::from(t));
    }
    //  this isn't necessary, with_insert_rope() will automatically rebalance
    //      - eliza, 12/18/2016
    // r_1.rebalance();
    assert!(r_1.is_balanced());
}

#[test]
fn with_insert_rope_test_1() {
    let s: String = iter::repeat('a').take(1_000).collect();
    let r_1 = Rope::from(s);
    let mut r_2 = Rope::new();
    for _ in 0..100 {
        let t: String = iter::repeat('a').take(10).collect();
        r_2 = r_2.with_insert_rope(0, Rope::from(t));
    }
    assert_eq!(r_1, r_2);
}

#[test]
fn with_insert_rope_test_2() {
    let s: String = iter::repeat('a').take(10).collect();
    let mut r_1 = Rope::from(s);
    for _ in 0..99 {
        let t: String = iter::repeat('a').take(10).collect();
        r_1 = r_1.with_insert_rope(5, Rope::from(t));
    }

    let q: String = iter::repeat('a').take(1_000).collect();
    let r_2 = Rope::from(q);
    assert_eq!(r_1, r_2);
}

#[test]
fn mutable_insert_rope_test_1() {
    let mut s_1 = Rope::from(String::from("aaaaa"));
    let mut s_2 = Rope::from(String::from("bbbbb"));
    let s_3 = Rope::from(String::from("ccccc"));
    s_2.insert_rope(0, s_3);
    s_1.insert_rope(0, s_2);
    assert_eq!(&s_1, "cccccbbbbbaaaaa");
}

#[test]
fn mutable_insert_str_test_1() {
    let mut s = Rope::from("aaaaa");
    s.insert_str(0, "bbbbb");
    s.insert_str(10, "ccccc");
    assert_eq!(&s, "bbbbbaaaaaccccc");
}

#[test]
fn mutable_insert_char_test_1() {
    let mut s = Rope::from("aaaaa");
    for _ in 0..5 { s.insert(0, 'b')}
    for _ in 0..5 { s.insert(10, 'c')}
    assert_eq!(&s, "bbbbbaaaaaccccc");
}

#[test]
fn mutable_insert_char_test_2() {
    // this is the same as with_insert_char_test1() except mutable
    let mut s = Rope::from("aaaaa");
    assert_eq!(&s, "aaaaa");
    s.insert(5, 'b');
    assert_eq!(&s, "aaaaab");
    s.insert(4, 'b');
    assert_eq!(&s, "aaaabab");
    s.insert(3, 'b');
    assert_eq!(&s, "aaababab");
    s.insert(2, 'b');
    assert_eq!(&s, "aabababab");
    s.insert(1, 'b');
    assert_eq!(&s, "ababababab");

}

#[test]
fn with_insert_char_test_1() {
    let s = Rope::from("aaaaa");
    let s_1 = s.with_insert(5, 'b');
    let s_2 = s_1.with_insert(4, 'b');
    let s_3 = s_2.with_insert(3, 'b');
    let s_4 = s_3.with_insert(2, 'b');
    let s_5 = s_4.with_insert(1, 'b');
    assert_eq!(&s, "aaaaa");
    assert_eq!(&s_1, "aaaaab");
    assert_eq!(&s_2, "aaaabab");
    assert_eq!(&s_3, "aaababab");
    assert_eq!(&s_4, "aabababab");
    assert_eq!(&s_5, "ababababab");

}

#[test]
fn with_insert_str_test_1() {
    let s = Rope::from("aaaaa");
    let s_1 = s.with_insert_str(5, "ccccc");
    let s_2 = s_1.with_insert_str(5, "bbbbb");
    assert_eq!(&s, "aaaaa");
    assert_eq!(&s_1, "aaaaaccccc");
    assert_eq!(&s_2, "aaaaabbbbbccccc");
}
<commit_msg>rope: add tests for iter::Extend<char> and iter::Extend<String><commit_after>use super::Rope;
use std::iter;

#[test]
fn rebalance_test_1() {
    let mut r = Rope::from("This is a large string \
                        that will need to be rebalanced.".to_string());
    r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn rebalance_test_2() {
    let mut r =
        Rope::from("Lorem ipsum dolor sit amet, consectetur adipiscing eli\
                    t, sed do eiusmod tempor incididunt ut labore et dolor\
                    e magna aliqua. Ut enim ad minim veniam, quis nostrud \
                    exercitation ullamco laboris nisi ut aliquip ex ea com\
                    modo consequat. Duis aute irure dolor in reprehenderit\
                     in voluptate velit esse cillum dolore eu fugiat nulla\
                     pariatur. Excepteur sint occaecat cupidatat non proid\
                    ent, sunt in culpa qui officia deserunt mollit anim id\
                     est laborum.".to_string());
    r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn big_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    r.rebalance();
    assert!(r.is_balanced());
}

#[test]
fn repeated_concat_left_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    for _ in 1..1000 {
        r = r + iter::repeat('a').take(100).collect::<String>();
    }
    assert!(r.is_balanced());
}

#[test]
fn repeated_concat_right_rebalance() {
    let s: String = iter::repeat('a').take(10_000).collect();
    let mut r = Rope::from(s);
    for _ in 1..1000 {
        let s2 = iter::repeat('a').take(100).collect::<String>();
        r = Rope::from(s2) + r;
    }
    assert!(r.is_balanced());
}

#[test]
fn append_empty_rope() {
    let mut an_rope = Rope::from("");
    an_rope.append(Rope::from("abcd"));
    assert_eq!(&an_rope, "abcd");

    let mut an_rope = Rope::from("abcd");
    an_rope.append(Rope::from(""));
    assert_eq!(&an_rope, "abcd");
}

#[test]
fn append() {
    let mut an_rope = Rope::from(String::from("abcd"));
    an_rope.append(Rope::from(String::from("efgh")));
    assert_eq!(an_rope, Rope::from(String::from("abcdefgh")) );
}

#[test]
fn with_append_empty_rope() {
    let an_rope = Rope::from("");
    let another_rope = an_rope.with_append(Rope::from("abcd"));
    assert_eq!(&another_rope, "abcd");
    assert_eq!(&an_rope, "");

    let an_rope = Rope::from("abcd");
    let an_rope = an_rope.with_append(Rope::from(""));
    assert_eq!(&an_rope, "abcd");
}

#[test]
fn with_append() {
    let an_rope = Rope::from("abcd");
    let another_rope = an_rope.with_append(Rope::from("efgh"));
    assert_eq!(&another_rope, "abcdefgh");
    assert_eq!(&an_rope, "abcd");
}

#[test]
fn prepend_empty_rope() {
    let mut an_rope = Rope::from("");
    an_rope.prepend(Rope::from("abcd"));
    assert_eq!(&an_rope, "abcd");

    let mut an_rope = Rope::from("abcd");
    an_rope.prepend(Rope::from(""));
    assert_eq!(&an_rope, "abcd");
}

#[test]
fn with_prepend_empty_rope() {
    let an_rope = Rope::from("");
    let another_rope = an_rope.with_prepend(Rope::from("abcd"));
    assert_eq!(&an_rope, "");
    assert_eq!(&another_rope, "abcd");

    let an_rope = Rope::from("abcd");
    let another_rope = an_rope.with_prepend(Rope::from(""));
    assert_eq!(&an_rope, "abcd");
    assert_eq!(&another_rope, &an_rope);
    assert_eq!(&another_rope, "abcd");
}

#[test]
fn with_prepend() {
    let an_rope = Rope::from("efgh");
    let another_rope = an_rope.with_prepend(Rope::from("abcd"));
    assert_eq!(&an_rope, "efgh");
    assert_eq!(&another_rope, "abcdefgh");
}

#[test]
fn prepend() {
    let mut an_rope = Rope::from(String::from("efgh"));
    an_rope.prepend(Rope::from(String::from("abcd")));
    assert_eq!(&an_rope, "abcdefgh");
}

#[test]
fn merge_rebalance_test() {
    let s = "Lorem ipsum dolor sit amet, consectetur adipiscing eli\
             t, sed do eiusmod tempor incididunt ut labore et dolor\
             e magna aliqua. Ut enim ad minim veniam, quis nostrud \
             exercitation ullamco laboris nisi ut aliquip ex ea com\
             modo consequat. Duis aute irure dolor in reprehenderit\
              in voluptate velit esse cillum dolore eu fugiat nulla\
              pariatur. Excepteur sint occaecat cupidatat non proid\
             ent, sunt in culpa qui officia deserunt mollit anim id\
              est laborum.";

     let t = Rope::from(s.to_owned());
     let mut u = t + s;
     u.rebalance();
     assert!(u.is_balanced());
}

#[test]
fn with_insert_rope_balance_test() {
    let s: String = iter::repeat('a').take(10).collect();
    let mut r_1 = Rope::from(s);
    for _ in 0..99 {
        let t: String = iter::repeat('a').take(10).collect();
        r_1 = r_1.with_insert_rope(5, Rope::from(t));
    }
    //  this isn't necessary, with_insert_rope() will automatically rebalance
    //      - eliza, 12/18/2016
    // r_1.rebalance();
    assert!(r_1.is_balanced());
}

#[test]
fn with_insert_rope_test_1() {
    let s: String = iter::repeat('a').take(1_000).collect();
    let r_1 = Rope::from(s);
    let mut r_2 = Rope::new();
    for _ in 0..100 {
        let t: String = iter::repeat('a').take(10).collect();
        r_2 = r_2.with_insert_rope(0, Rope::from(t));
    }
    assert_eq!(r_1, r_2);
}

#[test]
fn with_insert_rope_test_2() {
    let s: String = iter::repeat('a').take(10).collect();
    let mut r_1 = Rope::from(s);
    for _ in 0..99 {
        let t: String = iter::repeat('a').take(10).collect();
        r_1 = r_1.with_insert_rope(5, Rope::from(t));
    }

    let q: String = iter::repeat('a').take(1_000).collect();
    let r_2 = Rope::from(q);
    assert_eq!(r_1, r_2);
}

#[test]
fn mutable_insert_rope_test_1() {
    let mut s_1 = Rope::from(String::from("aaaaa"));
    let mut s_2 = Rope::from(String::from("bbbbb"));
    let s_3 = Rope::from(String::from("ccccc"));
    s_2.insert_rope(0, s_3);
    s_1.insert_rope(0, s_2);
    assert_eq!(&s_1, "cccccbbbbbaaaaa");
}

#[test]
fn mutable_insert_str_test_1() {
    let mut s = Rope::from("aaaaa");
    s.insert_str(0, "bbbbb");
    s.insert_str(10, "ccccc");
    assert_eq!(&s, "bbbbbaaaaaccccc");
}

#[test]
fn mutable_insert_char_test_1() {
    let mut s = Rope::from("aaaaa");
    for _ in 0..5 { s.insert(0, 'b')}
    for _ in 0..5 { s.insert(10, 'c')}
    assert_eq!(&s, "bbbbbaaaaaccccc");
}

#[test]
fn mutable_insert_char_test_2() {
    // this is the same as with_insert_char_test1() except mutable
    let mut s = Rope::from("aaaaa");
    assert_eq!(&s, "aaaaa");
    s.insert(5, 'b');
    assert_eq!(&s, "aaaaab");
    s.insert(4, 'b');
    assert_eq!(&s, "aaaabab");
    s.insert(3, 'b');
    assert_eq!(&s, "aaababab");
    s.insert(2, 'b');
    assert_eq!(&s, "aabababab");
    s.insert(1, 'b');
    assert_eq!(&s, "ababababab");

}

#[test]
fn with_insert_char_test_1() {
    let s = Rope::from("aaaaa");
    let s_1 = s.with_insert(5, 'b');
    let s_2 = s_1.with_insert(4, 'b');
    let s_3 = s_2.with_insert(3, 'b');
    let s_4 = s_3.with_insert(2, 'b');
    let s_5 = s_4.with_insert(1, 'b');
    assert_eq!(&s, "aaaaa");
    assert_eq!(&s_1, "aaaaab");
    assert_eq!(&s_2, "aaaabab");
    assert_eq!(&s_3, "aaababab");
    assert_eq!(&s_4, "aabababab");
    assert_eq!(&s_5, "ababababab");

}

#[test]
fn with_insert_str_test_1() {
    let s = Rope::from("aaaaa");
    let s_1 = s.with_insert_str(5, "ccccc");
    let s_2 = s_1.with_insert_str(5, "bbbbb");
    assert_eq!(&s, "aaaaa");
    assert_eq!(&s_1, "aaaaaccccc");
    assert_eq!(&s_2, "aaaaabbbbbccccc");
}

#[test]
fn iter_extend_empty_iter () {
    let mut rope = Rope::from("");
    let empty_vec: Vec<String> = vec![];
    rope.extend(empty_vec);
    assert_eq!(&rope, "");
}

#[test]
fn iter_extend_string_empty () {
    let mut rope = Rope::from("");
    rope.extend(vec![ String::from("aaaa")
                    , String::from("bbbb")
                    , String::from("cccc")
                    ]);
    assert_eq!(&rope, "aaaabbbbcccc");
}

#[test]
fn iter_extend_string_nonempty () {
    let mut rope = Rope::from("aaaa");
    rope.extend(vec![String::from("bbbb"), String::from("cccc")]);
    assert_eq!(&rope, "aaaabbbbcccc");
}

#[test]
fn iter_extend_chars_empty () {
    let mut rope = Rope::from("");
    rope.extend(vec!['a', 'b', 'c', 'd']);
    assert_eq!(&rope, "abcd");
}

#[test]
fn iter_extend_chars_nonempty () {
    let mut rope = Rope::from("a");
    rope.extend(vec!['b', 'c', 'd']);
    assert_eq!(&rope, "abcd");
}
<|endoftext|>


<commit_before>#[link(name = "knob",
       vers = "1.0.1",
       package_id = "knob",
       uuid = "3299B6C2-99DE-44FD-8867-8EE7304959D7",
       url = "http://github.com/skade/knob")];

#[crate_type = "lib"];
#[comment = "A convenient Rust settings system"];
#[license = "MIT"];

//! A convenient structure to store and load settings.
//!
//! It is meant for items that are rarely read and stored, like command line flags or
//! application configuration.
//!
//! knob::Settings expects all values to implement ToStr + FromStr and stores them as
//! strings internally. This allows sideloading of settings through multiple means, e.g.
//! the command line or a simple config file. knob is not meant for structured data. If
//! you want to load such data, store the location of the data as a Knob setting and do
//! the loading parsing yourself.
//!
//! knob is typesafe in a sense that it will return you the type you wanted back if possible and
//! fails otherwise.
//!
//! knob allows you to decorate the Settings structure yourself for convenience (see examples).
//!
//! # Storing and fetching values
//!
//! The following example shows you how to store an ip in knob:
//!
//! ~~~{.rust}
//! extern mod knob;
//! use knob::*;
//! use std::rt::io::net::ip::IpAddr;
//!
//! fn main() {
//!   let settings = Settings::new();
//!   settings.set("ip", "0.0.0.0:4567");
//!   let socket: IpAddr = settings.socket();
//!   assert_eq!(socket.to_str(), ~"0.0.0.0:4567")
//! }
//! ~~~
//!
//! This works the same for IPv6 addresses:
//!
//! ~~~{.rust}
//! fn main() {
//!   let settings = Settings::new();
//!   settings.set("ip", "::0.0.0.1");
//!   let socket: IpAddr = settings.fetch("ip");
//!   assert_eq!(socket.to_str(), ~"::0.0.0.1")
//! }
//! ~~~
//!
//! # Providing your own keys
//!
//! You can use enums as keys, as long as they implement ToStr:
//!
//! ~~~{.rust}
//! enum Keys {
//!   Port,
//!   Ip,
//!   Addr,
//! }
//!
//! fn main() {
//!   let settings = Settings::new();
//!   settings.set(Ip, "::0.0.0.1");
//!   let socket: IpAddr = settings.fetch(Ip);
//!   assert_eq!(socket.to_str(), ~"::0.0.0.1")
//! }
//! ~~~
//!
//! # Registering command line options
//!
//! Knob allows you to register command line options to read from the command line later.
//!
//! The options are getopts option groups.
//!
//! If the loading of the command line args fails, an error will be returned.
//!
//! ~~~{.rust}
//! use extra::getopts::groups::*;
//!
//! fn main() {
//!   let settings = Settings::new();
//!   settings.opt(optopt("p", "port", "the port to bind to", "4000"))
//!   settings.opt(reqopt("e", "environment", "the environment to run in", ""));;
//!   let errors = settings.load_os_args();
//!   if errors.is_some() {
//!     println(settings.usage("Try one of these:"))
//!   }
//! }
//! ~~~
//!
//! # Decorating the settings struct
//!
//! To make matters more convenient, you can implement a decorator
//! to implement your own loading behaviour.
//!
//! ~~~{.rust}
//! enum Keys {
//!   Port,
//!   Ip,
//!   Addr,
//! }
//!
//! pub trait SocketSettings {
//!   fn socket(&self) -> SocketAddr;
//!   fn port(&self) -> u16;
//!   fn ip(&self) -> IpAddr;
//! }
//!
//! impl SocketSettings for Settings {
//!   fn socket(&self) -> SocketAddr {
//!     do self.fetch_with(Addr) |addr| {
//!       match addr {
//!         Some(socket_addr) => { socket_addr },
//!         None => {
//!           let port: u16 = self.port();
//!           let ip: IpAddr = self.ip();
//!           SocketAddr { ip: ip, port: port }
//!         }
//!       }
//!     }
//!   }
//!
//!   fn port(&self) -> u16 {
//!     self.fetch(Port).unwrap_or(8080)
//!   }
//!
//!   fn ip(&self) -> IpAddr {
//!     self.fetch(Ip).unwrap_or(Ipv4Addr(127,0,0,1))
//!   }
//! }
//! enum Keys {
//!   Port,
//!   Ip,
//! }
//!
//! fn main() {
//!   let settings = Settings::new();
//!   settings.set(Ip, "::0.0.0.1");
//!   let socket: IpAddr = settings.ip();
//!   assert_eq!(socket.to_str(), ~"::0.0.0.1")
//! }
//! ~~~
//!
//! knob goes up to 11.

extern mod extra;

use std::hashmap::HashMap;
use std::os;

use extra::getopts::groups::{OptGroup,getopts,usage};
use extra::getopts::Fail_;

/// The settings structure we save the options and settings in.
#[deriving(Clone)]
pub struct Settings {
  priv store: HashMap<~str,~str>,
  priv options: ~[OptGroup],
}

impl Settings {
  /// Create a new Settings struct.
  pub fn new() -> Settings {
    Settings { store: HashMap::new(), options: ~[] }
  }

  /// Set a settings key to a value. The value will be serialized.
  pub fn set<A: ToStr, T: ToStr>(&mut self, setting: A, value: T) {
    self.store.swap(setting.to_str(), value.to_str());
  }

  /// Set a value using an Option struct. The value will only be set if the
  /// Some value is given. This way, you can avoid unwrapping the result of a
  /// previous operation by yourself.
  pub fn set_opt<A: ToStr, T: ToStr>(&mut self, setting: A, value: Option<T>) {
    if !value.is_none() {
      self.store.swap(setting.to_str(), value.unwrap().to_str());
    }
  }

  /// Fetch a setting for a key. Fails if the setting is present but could not be
  /// parsed.
  pub fn fetch<A: ToStr, T: FromStr>(&self, setting: A) -> Option<T> {
    match self.store.find(&setting.to_str()) {
      Some(string) => {
        let value = from_str(string.to_owned());
        if value.is_none() {
          fail!("setting could not be parsed:" + setting.to_str())
        }
        value
      },
      None => { None }
    }
  }

  /// Fetch a setting for a key and pass it to given function. The result of the function
  /// will be returned.
  pub fn fetch_with<A: ToStr, T: FromStr>(&self, setting: A, f: |Option<T>| -> T) -> T {
    let value = self.fetch(setting.to_str());
    f(value)
  }

  /// Register a commandline for laster use with load_args.
  ///
  /// Currently, only optopt and reqopt are properly supported.
  pub fn opt(&mut self, opt: OptGroup) {
    self.options.push(opt);
  }

  /// Load the command line argument given by the OS.
  ///
  /// Optionally returns failures.
  pub fn load_os_args(&mut self) -> Option<Fail_> {
    let args = os::args();
    self.load_args(args)
  }

  /// Load a list of command line arguments.
  ///
  /// Automatically sets "knob.progname" to the name of the program.
  ///
  /// Optionally returns failures.
  pub fn load_args(&mut self, args: ~[~str]) -> Option<Fail_> {
    let ref prog_name = args[0];

    self.set("knob.progname", prog_name.clone());

    let matches = match getopts(args.tail(), self.options) {
      Ok(m) => { m }
      Err(fail) => { return Some(fail) }
    };

    let given_options = self.options.clone();
    for opt in given_options.iter() {
      let opt_strings = &[opt.short_name.clone(), opt.long_name.clone()];
      self.set_opt(opt.long_name.clone(), matches.opts_str(opt_strings))
    };
    None
  }

  /// Returns the usage string for the stored OptGroups. Pass `brief`
  /// to have it included.
  pub fn usage(&self, brief: &str) -> ~str {
    usage(brief, self.options)
  }
}

#[cfg(test)]
mod tests {
  use super::Settings;
  use std::io::net::ip::{SocketAddr, IpAddr, Ipv4Addr};
  use extra::getopts::groups::{optopt,reqopt};

  #[deriving(ToStr)]
  enum Keys {
    Ip,
    Port,
    Addr
  }

  pub trait SocketSettings {
    fn socket(&self) -> SocketAddr;
    fn port(&self) -> u16;
    fn ip(&self) -> IpAddr;
  }

  impl SocketSettings for Settings {
    fn socket(&self) -> SocketAddr {
      self.fetch_with(Addr, |addr| {
        match addr {
          Some(socket_addr) => { socket_addr },
          None => {
            let port: u16 = self.port();
            let ip: IpAddr = self.ip();
            SocketAddr { ip: ip, port: port }
          }
        }
      })
    }

    fn port(&self) -> u16 {
      self.fetch(Port).unwrap_or(8080)
    }

    fn ip(&self) -> IpAddr {
      self.fetch(Ip).unwrap_or(Ipv4Addr(127,0,0,1))
    }
  }

  #[test]
  fn test_simple_conversion() {
    let mut settings = Settings::new();
    settings.set("port", 12345);
    let settings = settings.fetch("port");
    assert_eq!(Some(12345), settings)
  }

  #[test]
  #[should_fail]
  fn test_should_fail_on_garbage() {
    let mut settings = Settings::new();
    settings.set("port", "foobar");
    let settings: Option<int> = settings.fetch("port");
    assert_eq!(Some(12345), settings)
  }

  #[test]
  fn test_enum() {
    let mut settings = Settings::new();
    settings.set(Port, 12345);
    let settings = settings.fetch(Port);
    assert_eq!(Some(12345), settings)
  }

  #[test]
  fn test_compound_socket_settings() {
    let mut settings = Settings::new();
    settings.set(Port, "12345");
    settings.set(Ip, "127.0.0.1");
    let socket = settings.socket();
    assert_eq!(socket.to_str(), ~"127.0.0.1:12345")
  }

  #[test]
  fn test_ipv6_addr() {
    let mut settings = Settings::new();
    settings.set(Ip, "::0.0.0.1");
    let ip = settings.ip();
    assert_eq!(ip.to_str(), ~"::0.0.0.1")
  }

  #[test]
  fn test_socket_overrides_port() {
    let mut settings = Settings::new();
    settings.set(Port, "12345");
    settings.set(Ip, "127.0.0.1");
    settings.set(Addr, "0.0.0.0:4567");
    let socket = settings.socket();
    assert_eq!(socket.to_str(), ~"0.0.0.0:4567")
  }

  #[test]
  fn test_opt_parse_optional() {
    let mut settings = Settings::new();
    settings.opt(optopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog", ~"-p", ~"3000"];
    let error = settings.load_args(args);

    assert!(error.is_none());
    assert_eq!(settings.fetch("port"), Some(3000))
  }

  #[test]
  fn test_opt_parse_req_with_given() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog", ~"-p", ~"3000"];
    let error = settings.load_args(args);

    assert!(error.is_none());
    assert_eq!(settings.fetch("port"), Some(3000))
  }

  #[test]
  fn test_opt_parse_req_without_given() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog"];
    let error = settings.load_args(args);

    assert!(error.is_some());
    let port: Option<int> = settings.fetch("port");
    assert_eq!(port, None)
  }

  #[test]
  fn test_usage() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));
    let usage = settings.usage(&"this is how it works");

    assert!(usage.contains("this is how it works"))
    assert!(usage.contains("--port"))
  }

  #[test]
  fn test_goes_up_to_eleven() {
    let mut settings = Settings::new();
    settings.set("knob", 11);
    assert_eq!(settings.fetch("knob"), Some(11));
  }
}<commit_msg>Compile with recent rust<commit_after>//!
//! A convenient structure to store and load settings.
//!
//! It is meant for items that are rarely read and stored, like command line flags or
//! application configuration.
//!
//! knob::Settings expects all values to implement ToStr + FromStr and stores them as
//! strings internally. This allows sideloading of settings through multiple means, e.g.
//! the command line or a simple config file. knob is not meant for structured data. If
//! you want to load such data, store the location of the data as a Knob setting and do
//! the loading parsing yourself.
//!
//! knob is typesafe in a sense that it will return you the type you wanted back if possible and
//! fails otherwise.
//!
//! knob allows you to decorate the Settings structure yourself for convenience (see examples).
//!
//! # Storing and fetching values
//!
//! The following example shows you how to store an ip in knob:
//!
//! ~~~{.rust}
//! extern mod knob;
//! use knob::*;
//! use std::rt::io::net::ip::IpAddr;
//!
//! fn main() {
//!   let settings = Settings::new();
//!   settings.set("ip", "0.0.0.0:4567");
//!   let socket: IpAddr = settings.socket();
//!   assert_eq!(socket.to_str(), ~"0.0.0.0:4567")
//! }
//! ~~~
//!
//! This works the same for IPv6 addresses:
//!
//! ~~~{.rust}
//! fn main() {
//!   let settings = Settings::new();
//!   settings.set("ip", "::0.0.0.1");
//!   let socket: IpAddr = settings.fetch("ip");
//!   assert_eq!(socket.to_str(), ~"::0.0.0.1")
//! }
//! ~~~
//!
//! # Providing your own keys
//!
//! You can use enums as keys, as long as they implement ToStr:
//!
//! ~~~{.rust}
//! enum Keys {
//!   Port,
//!   Ip,
//!   Addr,
//! }
//!
//! fn main() {
//!   let settings = Settings::new();
//!   settings.set(Ip, "::0.0.0.1");
//!   let socket: IpAddr = settings.fetch(Ip);
//!   assert_eq!(socket.to_str(), ~"::0.0.0.1")
//! }
//! ~~~
//!
//! # Registering command line options
//!
//! Knob allows you to register command line options to read from the command line later.
//!
//! The options are getopts option groups.
//!
//! If the loading of the command line args fails, an error will be returned.
//!
//! ~~~{.rust}
//! use extra::getopts::groups::*;
//!
//! fn main() {
//!   let settings = Settings::new();
//!   settings.opt(optopt("p", "port", "the port to bind to", "4000"))
//!   settings.opt(reqopt("e", "environment", "the environment to run in", ""));;
//!   let errors = settings.load_os_args();
//!   if errors.is_some() {
//!     println(settings.usage("Try one of these:"))
//!   }
//! }
//! ~~~
//!
//! # Decorating the settings struct
//!
//! To make matters more convenient, you can implement a decorator
//! to implement your own loading behaviour.
//!
//! ~~~{.rust}
//! enum Keys {
//!   Port,
//!   Ip,
//!   Addr,
//! }
//!
//! pub trait SocketSettings {
//!   fn socket(&self) -> SocketAddr;
//!   fn port(&self) -> u16;
//!   fn ip(&self) -> IpAddr;
//! }
//!
//! impl SocketSettings for Settings {
//!   fn socket(&self) -> SocketAddr {
//!     do self.fetch_with(Addr) |addr| {
//!       match addr {
//!         Some(socket_addr) => { socket_addr },
//!         None => {
//!           let port: u16 = self.port();
//!           let ip: IpAddr = self.ip();
//!           SocketAddr { ip: ip, port: port }
//!         }
//!       }
//!     }
//!   }
//!
//!   fn port(&self) -> u16 {
//!     self.fetch(Port).unwrap_or(8080)
//!   }
//!
//!   fn ip(&self) -> IpAddr {
//!     self.fetch(Ip).unwrap_or(Ipv4Addr(127,0,0,1))
//!   }
//! }
//! enum Keys {
//!   Port,
//!   Ip,
//! }
//!
//! fn main() {
//!   let settings = Settings::new();
//!   settings.set(Ip, "::0.0.0.1");
//!   let socket: IpAddr = settings.ip();
//!   assert_eq!(socket.to_str(), ~"::0.0.0.1")
//! }
//! ~~~
//!
//! knob goes up to 11.

#[crate_id = "knob/1.0.1"];

#[crate_type = "lib"];
#[comment = "A convenient Rust settings system"];
#[license = "MIT"];

extern mod extra;

use std::hashmap::HashMap;
use std::os;

use extra::getopts::groups::{OptGroup,getopts,usage};
use extra::getopts::Fail_;

/// The settings structure we save the options and settings in.
#[deriving(Clone)]
pub struct Settings {
  priv store: HashMap<~str,~str>,
  priv options: ~[OptGroup],
}

impl Settings {
  /// Create a new Settings struct.
  pub fn new() -> Settings {
    Settings { store: HashMap::new(), options: ~[] }
  }

  /// Set a settings key to a value. The value will be serialized.
  pub fn set<A: ToStr, T: ToStr>(&mut self, setting: A, value: T) {
    self.store.swap(setting.to_str(), value.to_str());
  }

  /// Set a value using an Option struct. The value will only be set if the
  /// Some value is given. This way, you can avoid unwrapping the result of a
  /// previous operation by yourself.
  pub fn set_opt<A: ToStr, T: ToStr>(&mut self, setting: A, value: Option<T>) {
    if !value.is_none() {
      self.store.swap(setting.to_str(), value.unwrap().to_str());
    }
  }

  /// Fetch a setting for a key. Fails if the setting is present but could not be
  /// parsed.
  pub fn fetch<A: ToStr, T: FromStr>(&self, setting: A) -> Option<T> {
    match self.store.find(&setting.to_str()) {
      Some(string) => {
        let value = from_str(string.to_owned());
        if value.is_none() {
          fail!("setting could not be parsed:" + setting.to_str())
        }
        value
      },
      None => { None }
    }
  }

  /// Fetch a setting for a key and pass it to given function. The result of the function
  /// will be returned.
  pub fn fetch_with<A: ToStr, T: FromStr>(&self, setting: A, f: |Option<T>| -> T) -> T {
    let value = self.fetch(setting.to_str());
    f(value)
  }

  /// Register a commandline for laster use with load_args.
  ///
  /// Currently, only optopt and reqopt are properly supported.
  pub fn opt(&mut self, opt: OptGroup) {
    self.options.push(opt);
  }

  /// Load the command line argument given by the OS.
  ///
  /// Optionally returns failures.
  pub fn load_os_args(&mut self) -> Option<Fail_> {
    let args = os::args();
    self.load_args(args)
  }

  /// Load a list of command line arguments.
  ///
  /// Automatically sets "knob.progname" to the name of the program.
  ///
  /// Optionally returns failures.
  pub fn load_args(&mut self, args: ~[~str]) -> Option<Fail_> {
    let ref prog_name = args[0];

    self.set("knob.progname", prog_name.clone());

    let matches = match getopts(args.tail(), self.options) {
      Ok(m) => { m }
      Err(fail) => { return Some(fail) }
    };

    let given_options = self.options.clone();
    for opt in given_options.iter() {
      let opt_strings = &[opt.short_name.clone(), opt.long_name.clone()];
      self.set_opt(opt.long_name.clone(), matches.opts_str(opt_strings))
    };
    None
  }

  /// Returns the usage string for the stored OptGroups. Pass `brief`
  /// to have it included.
  pub fn usage(&self, brief: &str) -> ~str {
    usage(brief, self.options)
  }
}

#[cfg(test)]
mod tests {
  use super::Settings;
  use std::io::net::ip::{SocketAddr, IpAddr, Ipv4Addr};
  use extra::getopts::groups::{optopt,reqopt};

  #[deriving(ToStr)]
  enum Keys {
    Ip,
    Port,
    Addr
  }

  pub trait SocketSettings {
    fn socket(&self) -> SocketAddr;
    fn port(&self) -> u16;
    fn ip(&self) -> IpAddr;
  }

  impl SocketSettings for Settings {
    fn socket(&self) -> SocketAddr {
      self.fetch_with(Addr, |addr| {
        match addr {
          Some(socket_addr) => { socket_addr },
          None => {
            let port: u16 = self.port();
            let ip: IpAddr = self.ip();
            SocketAddr { ip: ip, port: port }
          }
        }
      })
    }

    fn port(&self) -> u16 {
      self.fetch(Port).unwrap_or(8080)
    }

    fn ip(&self) -> IpAddr {
      self.fetch(Ip).unwrap_or(Ipv4Addr(127,0,0,1))
    }
  }

  #[test]
  fn test_simple_conversion() {
    let mut settings = Settings::new();
    settings.set("port", 12345);
    let settings = settings.fetch("port");
    assert_eq!(Some(12345), settings)
  }

  #[test]
  #[should_fail]
  fn test_should_fail_on_garbage() {
    let mut settings = Settings::new();
    settings.set("port", "foobar");
    let settings: Option<int> = settings.fetch("port");
    assert_eq!(Some(12345), settings)
  }

  #[test]
  fn test_enum() {
    let mut settings = Settings::new();
    settings.set(Port, 12345);
    let settings = settings.fetch(Port);
    assert_eq!(Some(12345), settings)
  }

  #[test]
  fn test_compound_socket_settings() {
    let mut settings = Settings::new();
    settings.set(Port, "12345");
    settings.set(Ip, "127.0.0.1");
    let socket = settings.socket();
    assert_eq!(socket.to_str(), ~"127.0.0.1:12345")
  }

  #[test]
  fn test_ipv6_addr() {
    let mut settings = Settings::new();
    settings.set(Ip, "::0.0.0.1");
    let ip = settings.ip();
    assert_eq!(ip.to_str(), ~"::0.0.0.1")
  }

  #[test]
  fn test_socket_overrides_port() {
    let mut settings = Settings::new();
    settings.set(Port, "12345");
    settings.set(Ip, "127.0.0.1");
    settings.set(Addr, "0.0.0.0:4567");
    let socket = settings.socket();
    assert_eq!(socket.to_str(), ~"0.0.0.0:4567")
  }

  #[test]
  fn test_opt_parse_optional() {
    let mut settings = Settings::new();
    settings.opt(optopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog", ~"-p", ~"3000"];
    let error = settings.load_args(args);

    assert!(error.is_none());
    assert_eq!(settings.fetch("port"), Some(3000))
  }

  #[test]
  fn test_opt_parse_req_with_given() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog", ~"-p", ~"3000"];
    let error = settings.load_args(args);

    assert!(error.is_none());
    assert_eq!(settings.fetch("port"), Some(3000))
  }

  #[test]
  fn test_opt_parse_req_without_given() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));

    let args = ~[~"myprog"];
    let error = settings.load_args(args);

    assert!(error.is_some());
    let port: Option<int> = settings.fetch("port");
    assert_eq!(port, None)
  }

  #[test]
  fn test_usage() {
    let mut settings = Settings::new();
    settings.opt(reqopt("p", "port", "The port to bind to", "eg: 4000"));
    let usage = settings.usage(&"this is how it works");

    assert!(usage.contains("this is how it works"))
    assert!(usage.contains("--port"))
  }

  #[test]
  fn test_goes_up_to_eleven() {
    let mut settings = Settings::new();
    settings.set("knob", 11);
    assert_eq!(settings.fetch("knob"), Some(11));
  }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A "once initialization" primitive
//!
//! This primitive is meant to be used to run one-time initialization. An
//! example use case would be for initializing an FFI library.

use std::int;
use std::sync::atomics;

use mutex::{StaticMutex, MUTEX_INIT};

/// A type which can be used to run a one-time global initialization. This type
/// is *unsafe* to use because it is built on top of the `Mutex` in this module.
/// It does not know whether the currently running task is in a green or native
/// context, and a blocking mutex should *not* be used under normal
/// circumstances on a green task.
///
/// Despite its unsafety, it is often useful to have a one-time initialization
/// routine run for FFI bindings or related external functionality. This type
/// can only be statically constructed with the `ONCE_INIT` value.
///
/// # Example
///
/// ```rust
/// use sync::one::{Once, ONCE_INIT};
///
/// static mut START: Once = ONCE_INIT;
/// unsafe {
///     START.doit(|| {
///         // run initialization here
///     });
/// }
/// ```
pub struct Once {
    mutex: StaticMutex,
    cnt: atomics::AtomicInt,
    lock_cnt: atomics::AtomicInt,
}

/// Initialization value for static `Once` values.
pub static ONCE_INIT: Once = Once {
    mutex: MUTEX_INIT,
    cnt: atomics::INIT_ATOMIC_INT,
    lock_cnt: atomics::INIT_ATOMIC_INT,
};

impl Once {
    /// Perform an initialization routine once and only once. The given closure
    /// will be executed if this is the first time `doit` has been called, and
    /// otherwise the routine will *not* be invoked.
    ///
    /// This method will block the calling *os thread* if another initialization
    /// routine is currently running.
    ///
    /// When this function returns, it is guaranteed that some initialization
    /// has run and completed (it may not be the closure specified).
    pub fn doit(&self, f: ||) {
        // Implementation-wise, this would seem like a fairly trivial primitive.
        // The stickler part is where our mutexes currently require an
        // allocation, and usage of a `Once` should't leak this allocation.
        //
        // This means that there must be a deterministic destroyer of the mutex
        // contained within (because it's not needed after the initialization
        // has run).
        //
        // The general scheme here is to gate all future threads once
        // initialization has completed with a "very negative" count, and to
        // allow through threads to lock the mutex if they see a non negative
        // count. For all threads grabbing the mutex, exactly one of them should
        // be responsible for unlocking the mutex, and this should only be done
        // once everyone else is done with the mutex.
        //
        // This atomicity is achieved by swapping a very negative value into the
        // shared count when the initialization routine has completed. This will
        // read the number of threads which will at some point attempt to
        // acquire the mutex. This count is then squirreled away in a separate
        // variable, and the last person on the way out of the mutex is then
        // responsible for destroying the mutex.
        //
        // It is crucial that the negative value is swapped in *after* the
        // initialization routine has completed because otherwise new threads
        // calling `doit` will return immediately before the initialization has
        // completed.

        let prev = self.cnt.fetch_add(1, atomics::SeqCst);
        if prev < 0 {
            // Make sure we never overflow, we'll never have int::MIN
            // simultaneous calls to `doit` to make this value go back to 0
            self.cnt.store(int::MIN, atomics::SeqCst);
            return
        }

        // If the count is negative, then someone else finished the job,
        // otherwise we run the job and record how many people will try to grab
        // this lock
        let guard = self.mutex.lock();
        if self.cnt.load(atomics::SeqCst) > 0 {
            f();
            let prev = self.cnt.swap(int::MIN, atomics::SeqCst);
            self.lock_cnt.store(prev, atomics::SeqCst);
        }
        drop(guard);

        // Last one out cleans up after everyone else, no leaks!
        if self.lock_cnt.fetch_add(-1, atomics::SeqCst) == 1 {
            unsafe { self.mutex.destroy() }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{ONCE_INIT, Once};
    use std::task;

    #[test]
    fn smoke_once() {
        static mut o: Once = ONCE_INIT;
        let mut a = 0;
        unsafe { o.doit(|| a += 1); }
        assert_eq!(a, 1);
        unsafe { o.doit(|| a += 1); }
        assert_eq!(a, 1);
    }

    #[test]
    fn stampede_once() {
        static mut o: Once = ONCE_INIT;
        static mut run: bool = false;

        let (tx, rx) = channel();
        for _ in range(0, 10) {
            let tx = tx.clone();
            spawn(proc() {
                for _ in range(0, 4) { task::deschedule() }
                unsafe {
                    o.doit(|| {
                        assert!(!run);
                        run = true;
                    });
                    assert!(run);
                }
                tx.send(());
            });
        }

        unsafe {
            o.doit(|| {
                assert!(!run);
                run = true;
            });
            assert!(run);
        }

        for _ in range(0, 10) {
            rx.recv();
        }
    }
}
<commit_msg>auto merge of #14174 : stepancheg/rust/once, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A "once initialization" primitive
//!
//! This primitive is meant to be used to run one-time initialization. An
//! example use case would be for initializing an FFI library.

use std::int;
use std::sync::atomics;

use mutex::{StaticMutex, MUTEX_INIT};

/// A type which can be used to run a one-time global initialization. This type
/// is *unsafe* to use because it is built on top of the `Mutex` in this module.
/// It does not know whether the currently running task is in a green or native
/// context, and a blocking mutex should *not* be used under normal
/// circumstances on a green task.
///
/// Despite its unsafety, it is often useful to have a one-time initialization
/// routine run for FFI bindings or related external functionality. This type
/// can only be statically constructed with the `ONCE_INIT` value.
///
/// # Example
///
/// ```rust
/// use sync::one::{Once, ONCE_INIT};
///
/// static mut START: Once = ONCE_INIT;
/// unsafe {
///     START.doit(|| {
///         // run initialization here
///     });
/// }
/// ```
pub struct Once {
    mutex: StaticMutex,
    cnt: atomics::AtomicInt,
    lock_cnt: atomics::AtomicInt,
}

/// Initialization value for static `Once` values.
pub static ONCE_INIT: Once = Once {
    mutex: MUTEX_INIT,
    cnt: atomics::INIT_ATOMIC_INT,
    lock_cnt: atomics::INIT_ATOMIC_INT,
};

impl Once {
    /// Perform an initialization routine once and only once. The given closure
    /// will be executed if this is the first time `doit` has been called, and
    /// otherwise the routine will *not* be invoked.
    ///
    /// This method will block the calling *os thread* if another initialization
    /// routine is currently running.
    ///
    /// When this function returns, it is guaranteed that some initialization
    /// has run and completed (it may not be the closure specified).
    pub fn doit(&self, f: ||) {
        // Optimize common path: load is much cheaper than fetch_add.
        if self.cnt.load(atomics::SeqCst) < 0 {
            return
        }

        // Implementation-wise, this would seem like a fairly trivial primitive.
        // The stickler part is where our mutexes currently require an
        // allocation, and usage of a `Once` should't leak this allocation.
        //
        // This means that there must be a deterministic destroyer of the mutex
        // contained within (because it's not needed after the initialization
        // has run).
        //
        // The general scheme here is to gate all future threads once
        // initialization has completed with a "very negative" count, and to
        // allow through threads to lock the mutex if they see a non negative
        // count. For all threads grabbing the mutex, exactly one of them should
        // be responsible for unlocking the mutex, and this should only be done
        // once everyone else is done with the mutex.
        //
        // This atomicity is achieved by swapping a very negative value into the
        // shared count when the initialization routine has completed. This will
        // read the number of threads which will at some point attempt to
        // acquire the mutex. This count is then squirreled away in a separate
        // variable, and the last person on the way out of the mutex is then
        // responsible for destroying the mutex.
        //
        // It is crucial that the negative value is swapped in *after* the
        // initialization routine has completed because otherwise new threads
        // calling `doit` will return immediately before the initialization has
        // completed.

        let prev = self.cnt.fetch_add(1, atomics::SeqCst);
        if prev < 0 {
            // Make sure we never overflow, we'll never have int::MIN
            // simultaneous calls to `doit` to make this value go back to 0
            self.cnt.store(int::MIN, atomics::SeqCst);
            return
        }

        // If the count is negative, then someone else finished the job,
        // otherwise we run the job and record how many people will try to grab
        // this lock
        let guard = self.mutex.lock();
        if self.cnt.load(atomics::SeqCst) > 0 {
            f();
            let prev = self.cnt.swap(int::MIN, atomics::SeqCst);
            self.lock_cnt.store(prev, atomics::SeqCst);
        }
        drop(guard);

        // Last one out cleans up after everyone else, no leaks!
        if self.lock_cnt.fetch_add(-1, atomics::SeqCst) == 1 {
            unsafe { self.mutex.destroy() }
        }
    }
}

#[cfg(test)]
mod test {
    use super::{ONCE_INIT, Once};
    use std::task;

    #[test]
    fn smoke_once() {
        static mut o: Once = ONCE_INIT;
        let mut a = 0;
        unsafe { o.doit(|| a += 1); }
        assert_eq!(a, 1);
        unsafe { o.doit(|| a += 1); }
        assert_eq!(a, 1);
    }

    #[test]
    fn stampede_once() {
        static mut o: Once = ONCE_INIT;
        static mut run: bool = false;

        let (tx, rx) = channel();
        for _ in range(0, 10) {
            let tx = tx.clone();
            spawn(proc() {
                for _ in range(0, 4) { task::deschedule() }
                unsafe {
                    o.doit(|| {
                        assert!(!run);
                        run = true;
                    });
                    assert!(run);
                }
                tx.send(());
            });
        }

        unsafe {
            o.doit(|| {
                assert!(!run);
                run = true;
            });
            assert!(run);
        }

        for _ in range(0, 10) {
            rx.recv();
        }
    }
}
<|endoftext|>


<commit_before>use super::mergesort::comparator::Comparator;
use std::cmp::Ordering;

#[derive(Copy, Clone)]
pub struct Point2D {
    x: f64,
    y: f64
}

struct PolarOrder;

impl Comparator<Point2D> for PolarOrder {
    fn compare(&self, v: &Point2D, w: &Point2D) -> Ordering {
        Ordering::Equal
    }
}

impl Point2D {
    pub fn new(x: f64, y: f64) -> Point2D {
        Point2D { x: x, y: y }
    }

    pub fn ccw(a: Point2D, b: Point2D, c: Point2D) -> i32 {
        let area2 = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
        match area2 {
            _ if area2 < 0f64 => -1,
            _ if area2 > 0f64 =>  1,
            _                 =>  0
        }
    }
}
<commit_msg>convex_hull: impl Point2D PolarOrder<commit_after>use std::cmp::Ordering;
use std::mem;
use super::mergesort::comparator::Comparator;

#[allow(non_snake_case)]
pub struct Point2D {
    x: f64,
    y: f64,
    pub POLAR_ORDER: PolarOrder,
}

pub struct PolarOrder {
    _dummy: f64,              // dummy position
}

// TODO
impl Comparator<Point2D> for PolarOrder {
    fn compare(&self, q1: &Point2D, q2: &Point2D) -> Ordering {

        // ugly hack
        let p: &Point2D = unsafe { mem::transmute((&self._dummy as *const f64).offset(-2)) };

        let y = p.y;
        let dy1 = q1.y - y;
        let dy2 = q2.y - y;

        if dy1 == 0f64 && dy2 == 0f64 {
            // p, q1, q2 horizontal
            unimplemented!()
        } else if dy1 >= 0f64 && dy2 < 0f64 {
            // q1 above p; q2 below p
            Ordering::Less
        } else if dy2 >= 0f64 && dy1 < 0f64 {
            // q1 below p; q2 above p
            Ordering::Greater
        } else {
            // FIXME: type mismatch
            // -Point2D::ccw(self.p, q1, q2)
            unimplemented!()
        }
    }
}

impl Point2D {
    pub fn new(x: f64, y: f64) -> Point2D {
        Point2D { x: x, y: y,
                  POLAR_ORDER: PolarOrder { _dummy: 0.0}
        }
    }

    pub fn ccw(a: &Point2D, b: &Point2D, c: &Point2D) -> i32 {
        let area2 = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
        match area2 {
            _ if area2 < 0f64 => -1,
            _ if area2 > 0f64 =>  1,
            _                 =>  0
        }
    }
}

#[test]
fn test_point2d() {
    let p1 = Point2D::new(0.5, 0.6);
    let p2 = Point2D::new(1.0, 3.0);
    let p3 = Point2D::new(-2.0, -1.0);

    p1.POLAR_ORDER.compare(&p2, &p3);
}
<|endoftext|>


<commit_before>//! Defines a simple point light with some position in the scene and desired light intensity.

use linalg;
use film::Colorf;
use light::{Light, OcclusionTester};

/// A standard point light. Has a position in the scene and light intensity. The point
/// light does have inverse square fall-off
#[derive(Clone, Copy, Debug)]
pub struct Point {
    /// The position of the light
    pos: linalg::Point,
    /// The light intensity
    intensity: Colorf,
}

impl Point {
    /// Create a new point light at `pos` with some light intensity
    pub fn new(pos: &linalg::Point, intensity: &Colorf) -> Point {
        Point { pos: *pos, intensity: *intensity }
    }
}

impl Light for Point {
    fn sample_incident(&self, p: &linalg::Point, _: &(f32, f32)) -> (Colorf, linalg::Vector, f32, OcclusionTester) {
        let w_i = (self.pos - *p).normalized();
        (self.intensity / self.pos.distance_sqr(p), w_i, 1.0, OcclusionTester::test_points(p, &self.pos))
    }
    fn delta_light(&self) -> bool { true }
}

<commit_msg>Wrap long line<commit_after>//! Defines a simple point light with some position in the scene and desired light intensity.

use linalg;
use film::Colorf;
use light::{Light, OcclusionTester};

/// A standard point light. Has a position in the scene and light intensity. The point
/// light does have inverse square fall-off
#[derive(Clone, Copy, Debug)]
pub struct Point {
    /// The position of the light
    pos: linalg::Point,
    /// The light intensity
    intensity: Colorf,
}

impl Point {
    /// Create a new point light at `pos` with some light intensity
    pub fn new(pos: &linalg::Point, intensity: &Colorf) -> Point {
        Point { pos: *pos, intensity: *intensity }
    }
}

impl Light for Point {
    fn sample_incident(&self, p: &linalg::Point, _: &(f32, f32))
        -> (Colorf, linalg::Vector, f32, OcclusionTester) {
        let w_i = (self.pos - *p).normalized();
        (self.intensity / self.pos.distance_sqr(p), w_i, 1.0, OcclusionTester::test_points(p, &self.pos))
    }
    fn delta_light(&self) -> bool { true }
}

<|endoftext|>


<commit_before>use std::ops::{Add, Mul};

/// A pair of coordinates
#[derive(Clone, Copy)]
pub struct Vec2(pub usize, pub usize);

/// A structure of values
pub struct Matrix<T> {
    /// 2 dimensional array of rows and columns
    dim: Vec2,
    /// `Vector` of values in the `Matrix`
    buffer: Vec<T>,
}

impl <T> Matrix<T> {
    /// Returns a new `Matrix`
    ///
    /// # Arguments
    ///
    /// - `dimensions` - 2 dimensional array of rows and columns
    /// - `buffer` - `Vector` of values
    ///
    /// # Example
    ///
    /// ```
    /// let matrix = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0, 1, 2, 3, 4, 5]);
    /// ```
    pub fn new(dimensions: Vec2, buffer: Vec<T>) -> Matrix<T> {
        Matrix {
            dim: dimensions,
            buffer: buffer,
        }
    }

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

impl <T> Matrix<T> where T: Copy {
    /// Returns reference to value at `Vec2`
    ///
    /// # Arguments
    ///
    /// - `Vec2` - coordinates of the value in the `Matrix`
    ///
    /// # Example
    ///
    /// ```
    /// let matrix = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0, 1, 2, 3, 4, 5]);
    /// assert_eq!(matrix.get(ktensor::math::Vec2(1, 2)), 5);
    /// assert_eq!(matrix.get(ktensor::math::Vec2(1, 2)), 5);
    /// ```
    pub fn get(&self, Vec2(x, y): Vec2) -> T {
        self.buffer[x * self.dim.1 + y]
    }
}

//////////////
// Addition //
//////////////

impl<T> Add<Matrix<T>> for Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matricies
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - another matrix
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = matrix1 + matrix2;
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn add(self, rhs: Matrix<T>) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
            buffer.push(i + j);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Add<&'b Matrix<T>> for &'a Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matricies by reference
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - another matrix reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = &matrix1 + &matrix2;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn add(self, rhs: &'b Matrix<T>) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
            buffer.push(i + j);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<T> Add<T> for Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - a constant
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 1.0;
    /// let matrix2 = matrix1 + float;
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
    /// ```
    fn add(self, rhs: T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i + rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Add<&'b T> for &'a Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - a constant reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 1.0;
    /// let matrix2 = &matrix1 + &float;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
    /// assert_eq!(float, 1.0);
    /// ```
    fn add(self, &rhs: &'b T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i + rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

/////////////////////
// Multiplication  //
/////////////////////

impl<T> Mul<Matrix<T>> for Matrix<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matricies
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - another matrix
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(3, 2), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = matrix1 * matrix2;
    /// assert_eq!(matrix3.len(), 4);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn mul(self, rhs: Matrix<T>) -> Matrix<T> {
        let Vec2(x, y) = self.dim;
        let Vec2(x2, y2) = rhs.dim;
        assert_eq!(y, x2);
        let mut buffer = Vec::with_capacity(x * y2);
        for i in 0..x {
            for j in 0..y2 {
                let mut sum = self.get(Vec2(i, 0)) * rhs.get(Vec2(0, j));
                for k in 1..y {
                    sum = sum + self.get(Vec2(i, k)) * rhs.get(Vec2(k, j));
                }
                buffer.push(sum);
            }
        }
        Matrix::new(Vec2(x, y2), buffer)
    }
}

impl<'a, 'b, T> Mul<&'b Matrix<T>> for &'a Matrix<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matricies by reference
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - another matrix reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(3, 2), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = &matrix1 * &matrix2;
    /// assert_eq!(matrix3.len(), 4);
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn mul(self, rhs: &'b Matrix<T>) -> Matrix<T> {
        let Vec2(x, y) = self.dim;
        let Vec2(x2, y2) = rhs.dim;
        assert_eq!(y, x2);
        let mut buffer = Vec::with_capacity(x * y2);
        for i in 0..x {
            for j in 0..y2 {
                let mut sum = self.get(Vec2(i, 0)) * rhs.get(Vec2(0, j));
                for k in 1..y {
                    sum = sum + self.get(Vec2(i, k)) * rhs.get(Vec2(k, j));
                }
                buffer.push(sum);
            }
        }
        Matrix::new(Vec2(x, y2), buffer)
    }
}

impl<T> Mul<T> for Matrix<T> where T: Mul<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - a constant
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 2.0;
    /// let matrix2 = matrix1 * float;
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 2)), 4.0);
    /// ```
    fn mul(self, rhs: T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i * rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Mul<&'b T> for &'a Matrix<T> where T: Mul<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - a constant reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 2.0;
    /// let matrix2 = &matrix1 * &float;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 2)), 2.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 2)), 4.0);
    /// assert_eq!(float, 2.0);
    /// ```
    fn mul(self, &rhs: &'b T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i * rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}
<commit_msg>added matrix length assertions<commit_after>use std::ops::{Add, Mul};

/// A pair of coordinates
#[derive(Clone, Copy)]
pub struct Vec2(pub usize, pub usize);

/// A structure of values
pub struct Matrix<T> {
    /// 2 dimensional array of rows and columns
    dim: Vec2,
    /// `Vector` of values in the `Matrix`
    buffer: Vec<T>,
}

impl <T> Matrix<T> {
    /// Returns a new `Matrix`
    ///
    /// # Arguments
    ///
    /// - `dimensions` - 2 dimensional array of rows and columns
    /// - `buffer` - `Vector` of values
    ///
    /// # Example
    ///
    /// ```
    /// let matrix = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0, 1, 2, 3, 4, 5]);
    /// ```
    pub fn new(dimensions: Vec2, buffer: Vec<T>) -> Matrix<T> {
        Matrix {
            dim: dimensions,
            buffer: buffer,
        }
    }

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

impl <T> Matrix<T> where T: Copy {
    /// Returns reference to value at `Vec2`
    ///
    /// # Arguments
    ///
    /// - `Vec2` - coordinates of the value in the `Matrix`
    ///
    /// # Example
    ///
    /// ```
    /// let matrix = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0, 1, 2, 3, 4, 5]);
    /// assert_eq!(matrix.get(ktensor::math::Vec2(1, 2)), 5);
    /// assert_eq!(matrix.get(ktensor::math::Vec2(1, 2)), 5);
    /// ```
    pub fn get(&self, Vec2(x, y): Vec2) -> T {
        self.buffer[x * self.dim.1 + y]
    }
}

//////////////
// Addition //
//////////////

impl<T> Add<Matrix<T>> for Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matricies
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - another matrix
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = matrix1 + matrix2;
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn add(self, rhs: Matrix<T>) -> Matrix<T> {
        assert_eq!(self.len(), rhs.len());
        let mut buffer = Vec::with_capacity(self.len());
        for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
            buffer.push(i + j);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Add<&'b Matrix<T>> for &'a Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matricies by reference
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - another matrix reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = &matrix1 + &matrix2;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn add(self, rhs: &'b Matrix<T>) -> Matrix<T> {
        assert_eq!(self.len(), rhs.len());
        let mut buffer = Vec::with_capacity(self.len());
        for (&i, &j) in self.buffer.iter().zip(rhs.buffer.iter()) {
            buffer.push(i + j);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<T> Add<T> for Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - a constant
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 1.0;
    /// let matrix2 = matrix1 + float;
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
    /// ```
    fn add(self, rhs: T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i + rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Add<&'b T> for &'a Matrix<T> where T: Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Add Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - a constant reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 1.0;
    /// let matrix2 = &matrix1 + &float;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 1.0);
    /// assert_eq!(float, 1.0);
    /// ```
    fn add(self, &rhs: &'b T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i + rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

/////////////////////
// Multiplication  //
/////////////////////

impl<T> Mul<Matrix<T>> for Matrix<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matricies
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - another matrix
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(3, 2), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = matrix1 * matrix2;
    /// assert_eq!(matrix3.len(), 4);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn mul(self, rhs: Matrix<T>) -> Matrix<T> {
        let Vec2(x, y) = self.dim;
        let Vec2(x2, y2) = rhs.dim;
        assert_eq!(y, x2);
        let mut buffer = Vec::with_capacity(x * y2);
        for i in 0..x {
            for j in 0..y2 {
                let mut sum = self.get(Vec2(i, 0)) * rhs.get(Vec2(0, j));
                for k in 1..y {
                    sum = sum + self.get(Vec2(i, k)) * rhs.get(Vec2(k, j));
                }
                buffer.push(sum);
            }
        }
        Matrix::new(Vec2(x, y2), buffer)
    }
}

impl<'a, 'b, T> Mul<&'b Matrix<T>> for &'a Matrix<T> where T: Mul<Output=T> + Add<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matricies by reference
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - another matrix reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let matrix2 = ktensor::math::Matrix::new(ktensor::math::Vec2(3, 2), vec![5.0, 4.0, 3.0, 2.0, 1.0, 0.0]);
    /// let matrix3 = &matrix1 * &matrix2;
    /// assert_eq!(matrix3.len(), 4);
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 0)), 0.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// assert_eq!(matrix3.get(ktensor::math::Vec2(0, 0)), 5.0);
    /// ```
    fn mul(self, rhs: &'b Matrix<T>) -> Matrix<T> {
        let Vec2(x, y) = self.dim;
        let Vec2(x2, y2) = rhs.dim;
        assert_eq!(y, x2);
        let mut buffer = Vec::with_capacity(x * y2);
        for i in 0..x {
            for j in 0..y2 {
                let mut sum = self.get(Vec2(i, 0)) * rhs.get(Vec2(0, j));
                for k in 1..y {
                    sum = sum + self.get(Vec2(i, k)) * rhs.get(Vec2(k, j));
                }
                buffer.push(sum);
            }
        }
        Matrix::new(Vec2(x, y2), buffer)
    }
}

impl<T> Mul<T> for Matrix<T> where T: Mul<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix
    /// - `rhs` - a constant
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 2.0;
    /// let matrix2 = matrix1 * float;
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 2)), 4.0);
    /// ```
    fn mul(self, rhs: T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i * rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}

impl<'a, 'b, T> Mul<&'b T> for &'a Matrix<T> where T: Mul<Output=T> + Copy {
    type Output = Matrix<T>;

    /// Multiply Matrix and a constant
    ///
    /// # Arguments
    ///
    /// - `self` - this matrix reference
    /// - `rhs` - a constant reference
    ///
    /// # Example
    ///
    /// ```
    /// let matrix1 = ktensor::math::Matrix::new(ktensor::math::Vec2(2, 3), vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0]);
    /// let float = 2.0;
    /// let matrix2 = &matrix1 * &float;
    /// assert_eq!(matrix1.get(ktensor::math::Vec2(0, 2)), 2.0);
    /// assert_eq!(matrix2.get(ktensor::math::Vec2(0, 2)), 4.0);
    /// assert_eq!(float, 2.0);
    /// ```
    fn mul(self, &rhs: &'b T) -> Matrix<T> {
        let mut buffer = Vec::with_capacity(self.len());
        for &i in self.buffer.iter() {
            buffer.push(i * rhs);
        }
        Matrix::new(self.dim, buffer)
    }
}
<|endoftext|>


<commit_before>use core::codepointinfo::CodepointInfo;

// the screen is composed of lines
#[derive(Debug)]
pub struct Screen {
    pub line: Vec<Line>,
    pub used: usize,
    pub width: usize,
    pub height: usize,
}

impl Screen {
    pub fn new(width: usize, height: usize) -> Screen {
        let mut line: Vec<Line> = Vec::new();
        for _ in 0..height {
            line.push(Line::new(width));
        }

        Screen {
            line: line,
            used: 0,
            width: width,
            height: height,
        }
    }

    /// append
    pub fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {
        if self.used == self.height {
            return (false, self.used);
        }
        if self.line[self.used].used >= self.line[self.used].width {
            self.used += 1;
        }
        if self.used >= self.height {
            return (false, self.used);
        }

        let cp = cpi.cp;
        let line = &mut self.line[self.used];
        let (ok, _) = line.push(cpi);

        if ok == true {
            if cp == '\n' || cp == '\r' {
                self.used += 1;
            }
        }
        (ok, self.used)
    }

    pub fn clear(&mut self) {
        for h in 0..self.height {
            self.line[h].clear();
        }
        self.used = 0;
    }
}

// a line is composed of codepoints
#[derive(Debug)]
pub struct Line {
    pub chars: Vec<CodepointInfo>,
    pub used: usize,
    pub width: usize,
}

impl Line {
    fn new(columns: usize) -> Line {

        let mut chars = Vec::new();
        for _ in 0..columns {
            chars.push(CodepointInfo {
                           cp: ' ',
                           displayed_cp: ' ',
                           offset: 0,
                       });
        }

        Line {
            chars: chars,
            used: 0,
            width: columns,
        }
    }

    fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {

        if self.used < self.width {
            self.chars[self.used] = cpi;
            self.used += 1;
            (true, self.used)
        } else {
            (false, self.used)
        }
    }

    pub fn clear(&mut self) {
        for w in 0..self.width {
            self.chars[w].cp = ' ';
            self.chars[w].displayed_cp = ' ';
            self.chars[w].offset = 0;
        }
        self.used = 0;
    }
}
<commit_msg>Line : reserve the correct size at creation (columns)<commit_after>use core::codepointinfo::CodepointInfo;

// the screen is composed of lines
#[derive(Debug)]
pub struct Screen {
    pub line: Vec<Line>,
    pub used: usize,
    pub width: usize,
    pub height: usize,
}

impl Screen {
    pub fn new(width: usize, height: usize) -> Screen {
        let mut line: Vec<Line> = Vec::new();
        for _ in 0..height {
            line.push(Line::new(width));
        }

        Screen {
            line: line,
            used: 0,
            width: width,
            height: height,
        }
    }

    /// append
    pub fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {
        if self.used == self.height {
            return (false, self.used);
        }
        if self.line[self.used].used >= self.line[self.used].width {
            self.used += 1;
        }
        if self.used >= self.height {
            return (false, self.used);
        }

        let cp = cpi.cp;
        let line = &mut self.line[self.used];
        let (ok, _) = line.push(cpi);

        if ok == true {
            if cp == '\n' || cp == '\r' {
                self.used += 1;
            }
        }
        (ok, self.used)
    }

    pub fn clear(&mut self) {
        for h in 0..self.height {
            self.line[h].clear();
        }
        self.used = 0;
    }
}

// a line is composed of codepoints
#[derive(Debug)]
pub struct Line {
    pub chars: Vec<CodepointInfo>,
    pub used: usize,
    pub width: usize,
}

impl Line {
    fn new(columns: usize) -> Line {

        let mut chars = Vec::with_capacity(columns);
        for _ in 0..columns {
            chars.push(CodepointInfo {
                           cp: ' ',
                           displayed_cp: ' ',
                           offset: 0,
                       });
        }

        Line {
            chars: chars,
            used: 0,
            width: columns,
        }
    }

    fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {

        if self.used < self.width {
            self.chars[self.used] = cpi;
            self.used += 1;
            (true, self.used)
        } else {
            (false, self.used)
        }
    }

    pub fn clear(&mut self) {
        for w in 0..self.width {
            self.chars[w].cp = ' ';
            self.chars[w].displayed_cp = ' ';
            self.chars[w].offset = 0;
        }
        self.used = 0;
    }
}
<|endoftext|>