<commit_before>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;

use rocksdb::{DB, Direction, IteratorMode, Options};

fn cba(input: &Box<[u8]>) -> Box<[u8]> {
    input.iter().cloned().collect::<Vec<_>>().into_boxed_slice()
}

#[test]
pub fn test_iterator() {
    let path = "_rust_rocksdb_iteratortest";
    {
        let k1: Box<[u8]> = b"k1".to_vec().into_boxed_slice();
        let k2: Box<[u8]> = b"k2".to_vec().into_boxed_slice();
        let k3: Box<[u8]> = b"k3".to_vec().into_boxed_slice();
        let k4: Box<[u8]> = b"k4".to_vec().into_boxed_slice();
        let v1: Box<[u8]> = b"v1111".to_vec().into_boxed_slice();
        let v2: Box<[u8]> = b"v2222".to_vec().into_boxed_slice();
        let v3: Box<[u8]> = b"v3333".to_vec().into_boxed_slice();
        let v4: Box<[u8]> = b"v4444".to_vec().into_boxed_slice();
        let db = DB::open_default(path).unwrap();
        let p = db.put(&*k1, &*v1);
        assert!(p.is_ok());
        let p = db.put(&*k2, &*v2);
        assert!(p.is_ok());
        let p = db.put(&*k3, &*v3);
        assert!(p.is_ok());
        let expected = vec![(cba(&k1), cba(&v1)), (cba(&k2), cba(&v2)), (cba(&k3), cba(&v3))];
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        // Test that it's idempotent
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        // Test it in reverse a few times
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        // Try it forward again
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }

        let old_iterator = db.iterator(IteratorMode::Start);
        let p = db.put(&*k4, &*v4);
        assert!(p.is_ok());
        let expected2 = vec![(cba(&k1), cba(&v1)),
                             (cba(&k2), cba(&v2)),
                             (cba(&k3), cba(&v3)),
                             (cba(&k4), cba(&v4))];
        {
            assert_eq!(old_iterator.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected2);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Forward));
            let expected = vec![(cba(&k2), cba(&v2)), (cba(&k3), cba(&v3)), (cba(&k4), cba(&v4))];
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Reverse));
            let expected = vec![(cba(&k2), cba(&v2)), (cba(&k1), cba(&v1))];
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k0", Direction::Forward));
            assert!(iterator1.valid());
            let iterator2 = db.iterator(IteratorMode::From(b"k1", Direction::Forward));
            assert!(iterator2.valid());
            let iterator3 = db.iterator(IteratorMode::From(b"k11", Direction::Forward));
            assert!(iterator3.valid());
            let iterator4 = db.iterator(IteratorMode::From(b"k5", Direction::Forward));
            assert!(!iterator4.valid());
            let iterator5 = db.iterator(IteratorMode::From(b"k0", Direction::Reverse));
            assert!(iterator5.valid());
            let iterator6 = db.iterator(IteratorMode::From(b"k1", Direction::Reverse));
            assert!(iterator6.valid());
            let iterator7 = db.iterator(IteratorMode::From(b"k11", Direction::Reverse));
            assert!(iterator7.valid());
            let iterator8 = db.iterator(IteratorMode::From(b"k5", Direction::Reverse));
            assert!(!iterator8.valid());
        }
        {
            let mut iterator1 = db.iterator(IteratorMode::From(b"k4", Direction::Forward));
            iterator1.next();
            assert!(iterator1.valid());
            iterator1.next();
            assert!(!iterator1.valid());
        }
    }
    let opts = Options::default();
    assert!(DB::destroy(&opts, path).is_ok());
}

fn key(k: &[u8]) -> Box<[u8]> { k.to_vec().into_boxed_slice() }

#[test]
pub fn test_prefix_iterator() {
    let path = "_rust_rocksdb_prefixiteratortest";
    {
        let a1: Box<[u8]> = key(b"aaa1");
        let a2: Box<[u8]> = key(b"aaa2");
        let b1: Box<[u8]> = key(b"bbb1");
        let b2: Box<[u8]> = key(b"bbb2");

        let mut opts = Options::default();
        let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(3);
        opts.set_prefix_extractor(prefix_extractor);

        let db = DB::open(&opts, path).unwrap();

        assert!(db.put(&*a1, &*a1).is_ok());
        assert!(db.put(&*a2, &*a2).is_ok());
        assert!(db.put(&*b1, &*b1).is_ok());
        assert!(db.put(&*b2, &*b2).is_ok());

        {
            let expected = vec![(cba(&a1), cba(&a1)), (cba(&a2), cba(&a2))];
            let a_iterator = db.prefix_iterator(b"aaa");
            assert_eq!(a_iterator.collect::<Vec<_>>(), expected)
        }

        {
            let expected = vec![(cba(&b1), cba(&b1)), (cba(&b2), cba(&b2))];
            let b_iterator = db.prefix_iterator(b"bbb");
            assert_eq!(b_iterator.collect::<Vec<_>>(), expected)
        }
    }
}
<commit_msg>fix prefix iterator test<commit_after>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;

use rocksdb::{DB, Direction, IteratorMode, Options};

fn cba(input: &Box<[u8]>) -> Box<[u8]> {
    input.iter().cloned().collect::<Vec<_>>().into_boxed_slice()
}

#[test]
pub fn test_iterator() {
    let path = "_rust_rocksdb_iteratortest";
    {
        let k1: Box<[u8]> = b"k1".to_vec().into_boxed_slice();
        let k2: Box<[u8]> = b"k2".to_vec().into_boxed_slice();
        let k3: Box<[u8]> = b"k3".to_vec().into_boxed_slice();
        let k4: Box<[u8]> = b"k4".to_vec().into_boxed_slice();
        let v1: Box<[u8]> = b"v1111".to_vec().into_boxed_slice();
        let v2: Box<[u8]> = b"v2222".to_vec().into_boxed_slice();
        let v3: Box<[u8]> = b"v3333".to_vec().into_boxed_slice();
        let v4: Box<[u8]> = b"v4444".to_vec().into_boxed_slice();
        let db = DB::open_default(path).unwrap();
        let p = db.put(&*k1, &*v1);
        assert!(p.is_ok());
        let p = db.put(&*k2, &*v2);
        assert!(p.is_ok());
        let p = db.put(&*k3, &*v3);
        assert!(p.is_ok());
        let expected = vec![(cba(&k1), cba(&v1)), (cba(&k2), cba(&v2)), (cba(&k3), cba(&v3))];
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        // Test that it's idempotent
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        // Test it in reverse a few times
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::End);
            let mut tmp_vec = iterator1.collect::<Vec<_>>();
            tmp_vec.reverse();
            assert_eq!(tmp_vec, expected);
        }
        // Try it forward again
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }

        let old_iterator = db.iterator(IteratorMode::Start);
        let p = db.put(&*k4, &*v4);
        assert!(p.is_ok());
        let expected2 = vec![(cba(&k1), cba(&v1)),
                             (cba(&k2), cba(&v2)),
                             (cba(&k3), cba(&v3)),
                             (cba(&k4), cba(&v4))];
        {
            assert_eq!(old_iterator.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::Start);
            assert_eq!(iterator1.collect::<Vec<_>>(), expected2);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Forward));
            let expected = vec![(cba(&k2), cba(&v2)), (cba(&k3), cba(&v3)), (cba(&k4), cba(&v4))];
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k2", Direction::Reverse));
            let expected = vec![(cba(&k2), cba(&v2)), (cba(&k1), cba(&v1))];
            assert_eq!(iterator1.collect::<Vec<_>>(), expected);
        }
        {
            let iterator1 = db.iterator(IteratorMode::From(b"k0", Direction::Forward));
            assert!(iterator1.valid());
            let iterator2 = db.iterator(IteratorMode::From(b"k1", Direction::Forward));
            assert!(iterator2.valid());
            let iterator3 = db.iterator(IteratorMode::From(b"k11", Direction::Forward));
            assert!(iterator3.valid());
            let iterator4 = db.iterator(IteratorMode::From(b"k5", Direction::Forward));
            assert!(!iterator4.valid());
            let iterator5 = db.iterator(IteratorMode::From(b"k0", Direction::Reverse));
            assert!(iterator5.valid());
            let iterator6 = db.iterator(IteratorMode::From(b"k1", Direction::Reverse));
            assert!(iterator6.valid());
            let iterator7 = db.iterator(IteratorMode::From(b"k11", Direction::Reverse));
            assert!(iterator7.valid());
            let iterator8 = db.iterator(IteratorMode::From(b"k5", Direction::Reverse));
            assert!(!iterator8.valid());
        }
        {
            let mut iterator1 = db.iterator(IteratorMode::From(b"k4", Direction::Forward));
            iterator1.next();
            assert!(iterator1.valid());
            iterator1.next();
            assert!(!iterator1.valid());
        }
    }
    let opts = Options::default();
    assert!(DB::destroy(&opts, path).is_ok());
}

fn key(k: &[u8]) -> Box<[u8]> { k.to_vec().into_boxed_slice() }

#[test]
pub fn test_prefix_iterator() {
    let path = "_rust_rocksdb_prefixiteratortest";
    {
        let a1: Box<[u8]> = key(b"aaa1");
        let a2: Box<[u8]> = key(b"aaa2");
        let b1: Box<[u8]> = key(b"bbb1");
        let b2: Box<[u8]> = key(b"bbb2");

        let prefix_extractor = rocksdb::SliceTransform::create_fixed_prefix(3);

        let mut opts = Options::default();
		opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);

        let db = DB::open(&opts, path).unwrap();

        assert!(db.put(&*a1, &*a1).is_ok());
        assert!(db.put(&*a2, &*a2).is_ok());
        assert!(db.put(&*b1, &*b1).is_ok());
        assert!(db.put(&*b2, &*b2).is_ok());

        {
            let expected = vec![(cba(&a1), cba(&a1)), (cba(&a2), cba(&a2))];
            let a_iterator = db.prefix_iterator(b"aaa");
            assert_eq!(a_iterator.collect::<Vec<_>>(), expected)
        }

        {
            let expected = vec![(cba(&b1), cba(&b1)), (cba(&b2), cba(&b2))];
            let b_iterator = db.prefix_iterator(b"bbb");
            assert_eq!(b_iterator.collect::<Vec<_>>(), expected)
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use net::hsts::HSTSList;
use net::hsts::HSTSEntry;
use net_traits::IncludeSubdomains;
use net::hsts::secure_url;
use net::resource_task::ResourceManager;
use std::sync::mpsc::channel;
use url::Url;
use time;

#[test]
fn test_add_hsts_entry_to_resource_manager_adds_an_hsts_entry() {
    let list = HSTSList {
        entries: Vec::new()
    };

    let (tx, _) = channel();
    let mut manager = ResourceManager::new(None, tx, list, None);

    let entry = HSTSEntry::new(
        "mozilla.org".to_string(), IncludeSubdomains::NotIncluded, None
    );

    assert!(!manager.is_host_sts("mozilla.org"));

    manager.add_hsts_entry(entry.unwrap());

    assert!(manager.is_host_sts("mozilla.org"))
}

#[test]
fn test_hsts_entry_is_not_expired_when_it_has_no_timestamp() {
    let entry = HSTSEntry {
        host: "mozilla.org".to_string(),
        include_subdomains: false,
        max_age: Some(20),
        timestamp: None
    };

    assert!(!entry.is_expired());
}

#[test]
fn test_hsts_entry_is_not_expired_when_it_has_no_max_age() {
    let entry = HSTSEntry {
        host: "mozilla.org".to_string(),
        include_subdomains: false,
        max_age: None,
        timestamp: Some(time::get_time().sec as u64)
    };

    assert!(!entry.is_expired());
}

#[test]
fn test_hsts_entry_is_expired_when_it_has_reached_its_max_age() {
    let entry = HSTSEntry {
        host: "mozilla.org".to_string(),
        include_subdomains: false,
        max_age: Some(10),
        timestamp: Some(time::get_time().sec as u64 - 20u64)
    };

    assert!(entry.is_expired());
}

#[test]
fn test_hsts_entry_cant_be_created_with_ipv6_address_as_host() {
    let entry = HSTSEntry::new(
        "2001:0db8:0000:0000:0000:ff00:0042:8329".to_string(), IncludeSubdomains::NotIncluded, None
    );

    assert!(entry.is_none(), "able to create HSTSEntry with IPv6 host");
}

#[test]
fn test_hsts_entry_cant_be_created_with_ipv4_address_as_host() {
    let entry = HSTSEntry::new(
        "4.4.4.4".to_string(), IncludeSubdomains::NotIncluded, None
    );

    assert!(entry.is_none(), "able to create HSTSEntry with IPv4 host");
}

#[test]
fn test_push_entry_with_0_max_age_evicts_entry_from_list() {
    let mut list = HSTSList {
        entries: vec!(HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::NotIncluded, Some(500000u64)).unwrap())
    };

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::NotIncluded, Some(0)).unwrap());

    assert!(list.is_host_secure("mozilla.org") == false)
}

#[test]
fn test_push_entry_to_hsts_list_should_not_add_subdomains_whose_superdomain_is_already_matched() {
    let mut list = HSTSList {
        entries: vec!(HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap())
    };

    list.push(HSTSEntry::new("servo.mozilla.org".to_string(),
        IncludeSubdomains::NotIncluded, None).unwrap());

    assert!(list.entries.len() == 1)
}

#[test]
fn test_push_entry_to_hsts_list_should_update_existing_domain_entrys_include_subdomains() {
    let mut list = HSTSList {
        entries: vec!(HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap())
    };

    assert!(list.is_host_secure("servo.mozilla.org"));

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::NotIncluded, None).unwrap());

    assert!(!list.is_host_secure("servo.mozilla.org"))
}

#[test]
fn test_push_entry_to_hsts_list_should_not_create_duplicate_entry() {
    let mut list = HSTSList {
        entries: vec!(HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::NotIncluded, None).unwrap())
    };

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::NotIncluded, None).unwrap());

    assert!(list.entries.len() == 1)
}

#[test]
fn test_push_multiple_entrie_to_hsts_list_should_add_them_all() {
    let mut list = HSTSList {
        entries: Vec::new()
    };

    assert!(!list.is_host_secure("mozilla.org"));
    assert!(!list.is_host_secure("bugzilla.org"));

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::Included, None).unwrap());
    list.push(HSTSEntry::new("bugzilla.org".to_string(),
        IncludeSubdomains::Included, None).unwrap());

    assert!(list.is_host_secure("mozilla.org"));
    assert!(list.is_host_secure("bugzilla.org"));
}

#[test]
fn test_push_entry_to_hsts_list_should_add_an_entry() {
    let mut list = HSTSList {
        entries: Vec::new()
    };

    assert!(!list.is_host_secure("mozilla.org"));

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::Included, None).unwrap());

    assert!(list.is_host_secure("mozilla.org"));
}

#[test]
fn test_parse_hsts_preload_should_return_none_when_json_invalid() {
    let mock_preload_content = "derp";
    assert!(HSTSList::new_from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed")
}

#[test]
fn test_parse_hsts_preload_should_return_none_when_json_contains_no_entries_key() {
    let mock_preload_content = "{\"nothing\": \"to see here\"}";
    assert!(HSTSList::new_from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed")
}

#[test]
fn test_parse_hsts_preload_should_decode_host_and_includes_subdomains() {
    let mock_preload_content = "{\
                                     \"entries\": [\
                                        {\"host\": \"mozilla.org\",\
                                         \"include_subdomains\": false}\
                                     ]\
                                 }";
    let hsts_list = HSTSList::new_from_preload(mock_preload_content);
    let entries = hsts_list.unwrap().entries;

    assert_eq!(entries[0].host, "mozilla.org");
    assert!(!entries[0].include_subdomains);
}

#[test]
fn test_hsts_list_with_no_entries_does_not_is_host_secure() {
    let hsts_list = HSTSList {
        entries: Vec::new()
    };

    assert!(!hsts_list.is_host_secure("mozilla.org"));
}

#[test]
fn test_hsts_list_with_exact_domain_entry_is_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::NotIncluded, None).unwrap()]
    };

    assert!(hsts_list.is_host_secure("mozilla.org"));
}

#[test]
fn test_hsts_list_with_subdomain_when_include_subdomains_is_true_is_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap()]
    };

    assert!(hsts_list.is_host_secure("servo.mozilla.org"));
}

#[test]
fn test_hsts_list_with_subdomain_when_include_subdomains_is_false_is_not_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::NotIncluded, None).unwrap()]
    };

    assert!(!hsts_list.is_host_secure("servo.mozilla.org"));
}

#[test]
fn test_hsts_list_with_subdomain_when_host_is_not_a_subdomain_is_not_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap()]
    };

    assert!(!hsts_list.is_host_secure("servo-mozilla.org"));
}

#[test]
fn test_hsts_list_with_subdomain_when_host_is_exact_match_is_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap()]
    };

    assert!(hsts_list.is_host_secure("mozilla.org"));
}

#[test]
fn test_hsts_list_with_expired_entry_is_not_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry {
            host: "mozilla.org".to_string(),
            include_subdomains: false,
            max_age: Some(20),
            timestamp: Some(time::get_time().sec as u64 - 100u64)
        }]
    };

    assert!(!hsts_list.is_host_secure("mozilla.org"));
}

#[test]
fn test_secure_url_does_not_change_explicit_port() {
    let url = Url::parse("http://mozilla.org:8080/").unwrap();
    let secure = secure_url(&url);

    assert!(secure.port().unwrap() == 8080u16);
}

#[test]
fn test_secure_url_does_not_affect_non_http_schemas() {
    let url = Url::parse("file://mozilla.org").unwrap();
    let secure = secure_url(&url);

    assert_eq!(&secure.scheme, "file");
}

#[test]
fn test_secure_url_forces_an_http_host_in_list_to_https() {
    let url = Url::parse("http://mozilla.org").unwrap();
    let secure = secure_url(&url);

    assert_eq!(&secure.scheme, "https");
}

<commit_msg>Auto merge of #6793 - notriddle:hsts-preload, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use net::hsts::HSTSList;
use net::hsts::HSTSEntry;
use net_traits::IncludeSubdomains;
use net::hsts::{secure_url, preload_hsts_domains};
use net::resource_task::ResourceManager;
use std::sync::mpsc::channel;
use url::Url;
use time;

#[test]
fn test_add_hsts_entry_to_resource_manager_adds_an_hsts_entry() {
    let list = HSTSList {
        entries: Vec::new()
    };

    let (tx, _) = channel();
    let mut manager = ResourceManager::new(None, tx, list, None);

    let entry = HSTSEntry::new(
        "mozilla.org".to_string(), IncludeSubdomains::NotIncluded, None
    );

    assert!(!manager.is_host_sts("mozilla.org"));

    manager.add_hsts_entry(entry.unwrap());

    assert!(manager.is_host_sts("mozilla.org"))
}

#[test]
fn test_hsts_entry_is_not_expired_when_it_has_no_timestamp() {
    let entry = HSTSEntry {
        host: "mozilla.org".to_string(),
        include_subdomains: false,
        max_age: Some(20),
        timestamp: None
    };

    assert!(!entry.is_expired());
}

#[test]
fn test_hsts_entry_is_not_expired_when_it_has_no_max_age() {
    let entry = HSTSEntry {
        host: "mozilla.org".to_string(),
        include_subdomains: false,
        max_age: None,
        timestamp: Some(time::get_time().sec as u64)
    };

    assert!(!entry.is_expired());
}

#[test]
fn test_hsts_entry_is_expired_when_it_has_reached_its_max_age() {
    let entry = HSTSEntry {
        host: "mozilla.org".to_string(),
        include_subdomains: false,
        max_age: Some(10),
        timestamp: Some(time::get_time().sec as u64 - 20u64)
    };

    assert!(entry.is_expired());
}

#[test]
fn test_hsts_entry_cant_be_created_with_ipv6_address_as_host() {
    let entry = HSTSEntry::new(
        "2001:0db8:0000:0000:0000:ff00:0042:8329".to_string(), IncludeSubdomains::NotIncluded, None
    );

    assert!(entry.is_none(), "able to create HSTSEntry with IPv6 host");
}

#[test]
fn test_hsts_entry_cant_be_created_with_ipv4_address_as_host() {
    let entry = HSTSEntry::new(
        "4.4.4.4".to_string(), IncludeSubdomains::NotIncluded, None
    );

    assert!(entry.is_none(), "able to create HSTSEntry with IPv4 host");
}

#[test]
fn test_push_entry_with_0_max_age_evicts_entry_from_list() {
    let mut list = HSTSList {
        entries: vec!(HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::NotIncluded, Some(500000u64)).unwrap())
    };

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::NotIncluded, Some(0)).unwrap());

    assert!(list.is_host_secure("mozilla.org") == false)
}

#[test]
fn test_push_entry_to_hsts_list_should_not_add_subdomains_whose_superdomain_is_already_matched() {
    let mut list = HSTSList {
        entries: vec!(HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap())
    };

    list.push(HSTSEntry::new("servo.mozilla.org".to_string(),
        IncludeSubdomains::NotIncluded, None).unwrap());

    assert!(list.entries.len() == 1)
}

#[test]
fn test_push_entry_to_hsts_list_should_update_existing_domain_entrys_include_subdomains() {
    let mut list = HSTSList {
        entries: vec!(HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap())
    };

    assert!(list.is_host_secure("servo.mozilla.org"));

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::NotIncluded, None).unwrap());

    assert!(!list.is_host_secure("servo.mozilla.org"))
}

#[test]
fn test_push_entry_to_hsts_list_should_not_create_duplicate_entry() {
    let mut list = HSTSList {
        entries: vec!(HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::NotIncluded, None).unwrap())
    };

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::NotIncluded, None).unwrap());

    assert!(list.entries.len() == 1)
}

#[test]
fn test_push_multiple_entrie_to_hsts_list_should_add_them_all() {
    let mut list = HSTSList {
        entries: Vec::new()
    };

    assert!(!list.is_host_secure("mozilla.org"));
    assert!(!list.is_host_secure("bugzilla.org"));

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::Included, None).unwrap());
    list.push(HSTSEntry::new("bugzilla.org".to_string(),
        IncludeSubdomains::Included, None).unwrap());

    assert!(list.is_host_secure("mozilla.org"));
    assert!(list.is_host_secure("bugzilla.org"));
}

#[test]
fn test_push_entry_to_hsts_list_should_add_an_entry() {
    let mut list = HSTSList {
        entries: Vec::new()
    };

    assert!(!list.is_host_secure("mozilla.org"));

    list.push(HSTSEntry::new("mozilla.org".to_string(),
        IncludeSubdomains::Included, None).unwrap());

    assert!(list.is_host_secure("mozilla.org"));
}

#[test]
fn test_parse_hsts_preload_should_return_none_when_json_invalid() {
    let mock_preload_content = "derp";
    assert!(HSTSList::new_from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed")
}

#[test]
fn test_parse_hsts_preload_should_return_none_when_json_contains_no_entries_key() {
    let mock_preload_content = "{\"nothing\": \"to see here\"}";
    assert!(HSTSList::new_from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed")
}

#[test]
fn test_parse_hsts_preload_should_decode_host_and_includes_subdomains() {
    let mock_preload_content = "{\
                                     \"entries\": [\
                                        {\"host\": \"mozilla.org\",\
                                         \"include_subdomains\": false}\
                                     ]\
                                 }";
    let hsts_list = HSTSList::new_from_preload(mock_preload_content);
    let entries = hsts_list.unwrap().entries;

    assert_eq!(entries[0].host, "mozilla.org");
    assert!(!entries[0].include_subdomains);
}

#[test]
fn test_hsts_list_with_no_entries_does_not_is_host_secure() {
    let hsts_list = HSTSList {
        entries: Vec::new()
    };

    assert!(!hsts_list.is_host_secure("mozilla.org"));
}

#[test]
fn test_hsts_list_with_exact_domain_entry_is_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::NotIncluded, None).unwrap()]
    };

    assert!(hsts_list.is_host_secure("mozilla.org"));
}

#[test]
fn test_hsts_list_with_subdomain_when_include_subdomains_is_true_is_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap()]
    };

    assert!(hsts_list.is_host_secure("servo.mozilla.org"));
}

#[test]
fn test_hsts_list_with_subdomain_when_include_subdomains_is_false_is_not_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::NotIncluded, None).unwrap()]
    };

    assert!(!hsts_list.is_host_secure("servo.mozilla.org"));
}

#[test]
fn test_hsts_list_with_subdomain_when_host_is_not_a_subdomain_is_not_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap()]
    };

    assert!(!hsts_list.is_host_secure("servo-mozilla.org"));
}

#[test]
fn test_hsts_list_with_subdomain_when_host_is_exact_match_is_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry::new("mozilla.org".to_string(),
            IncludeSubdomains::Included, None).unwrap()]
    };

    assert!(hsts_list.is_host_secure("mozilla.org"));
}

#[test]
fn test_hsts_list_with_expired_entry_is_not_is_host_secure() {
    let hsts_list = HSTSList {
        entries: vec![HSTSEntry {
            host: "mozilla.org".to_string(),
            include_subdomains: false,
            max_age: Some(20),
            timestamp: Some(time::get_time().sec as u64 - 100u64)
        }]
    };

    assert!(!hsts_list.is_host_secure("mozilla.org"));
}

#[test]
fn test_preload_hsts_domains_well_formed() {
    let hsts_list = preload_hsts_domains().unwrap();
    assert!(hsts_list.entries.len() != 0);
}

#[test]
fn test_secure_url_does_not_change_explicit_port() {
    let url = Url::parse("http://mozilla.org:8080/").unwrap();
    let secure = secure_url(&url);

    assert!(secure.port().unwrap() == 8080u16);
}

#[test]
fn test_secure_url_does_not_affect_non_http_schemas() {
    let url = Url::parse("file://mozilla.org").unwrap();
    let secure = secure_url(&url);

    assert_eq!(&secure.scheme, "file");
}

#[test]
fn test_secure_url_forces_an_http_host_in_list_to_https() {
    let url = Url::parse("http://mozilla.org").unwrap();
    let secure = secure_url(&url);

    assert_eq!(&secure.scheme, "https");
}

<|endoftext|>


<commit_before>use ::arch::debug;
use core::fmt::{Error,Write};
use spin::{MutexGuard,StaticMutex,STATIC_MUTEX_INIT};

pub struct Writer<'a> {
    _state: MutexGuard<'a, ()>
}

static LOGGING_LOCK: StaticMutex = STATIC_MUTEX_INIT;

impl<'a> Writer<'a> {
	pub fn get(module: &str) -> Writer {
		let mut ret = Writer { _state: LOGGING_LOCK.lock() };

		{
			use core::fmt::Write;
			let _ = write!(&mut ret, "[{}] ", module);
		}

		ret
	}
}

impl<'a> Write for Writer<'a>
{
	fn write_str(&mut self, s: &str) -> Result<(), Error> {
        debug::puts(s);
		Ok(())
	}
}

<commit_msg>Remove locking around log! statements<commit_after>use ::arch::debug;
use core::fmt::{Error,Write};

pub struct Writer;

impl Writer {
	pub fn get(module: &str) -> Writer {
        use core::fmt::Write;
        let mut writer = Writer;
        let _ = write!(&mut writer, "[{}] ", module);
        writer
	}
}

impl Write for Writer {
	fn write_str(&mut self, s: &str) -> Result<(), Error> {
        debug::puts(s);
		Ok(())
	}
}

<|endoftext|>


<commit_before>extern mod cairo;

use azure_hl::{BackendType, CairoBackend, CoreGraphicsAcceleratedBackend, CoreGraphicsBackend};
use azure_hl::{Direct2DBackend, NoBackend, RecordingBackend, SkiaBackend};
use bindgen::{AzCreateScaledFontForNativeFont, AzReleaseScaledFont};
use cairo::{cairo_font_face_t, cairo_matrix_t, cairo_scaled_font_t};
use cairo::bindgen::{cairo_font_face_destroy, cairo_font_options_create};
use cairo::bindgen::{cairo_font_options_destroy, cairo_matrix_init_identity, cairo_matrix_scale};
use cairo::bindgen::{cairo_scaled_font_create};

#[cfg(target_os="macos")]
type NativeFont = CTFont;

type SkTypeface = *c_void;

pub struct ScaledFont {
    azure_scaled_font: AzScaledFontRef,

    drop {
        AzReleaseScaledFont(self.azure_scaled_font);
    }
}

impl ScaledFont {
    static priv fn create_cairo_font(face: *cairo_font_face_t, size: AzFloat)
                                  -> *cairo_scaled_font_t {
        // FIXME: error handling

        let idmatrix: cairo_matrix_t = {
            xx: 0 as c_double,
            yx: 0 as c_double,
            xy: 0 as c_double,
            yy: 0 as c_double,
            x0: 0 as c_double,
            y0: 0 as c_double
        };
        cairo_matrix_init_identity(ptr::to_unsafe_ptr(&idmatrix));

        let fontmatrix = idmatrix;
        cairo_matrix_scale(ptr::to_unsafe_ptr(&fontmatrix), size as c_double, size as c_double);
        let options = cairo_font_options_create();
        let cfont = cairo_scaled_font_create(face,
                                             ptr::to_unsafe_ptr(&fontmatrix),
                                             ptr::to_unsafe_ptr(&idmatrix),
                                             options);
        cairo_font_options_destroy(options);

        return cfont;
    }

    /// Mac-specific function to create a font for the given backend.
    #[cfg(target_os="macos")]
    static pub fn new(backend: BackendType, native_font: &const CTFont, size: AzFloat)
                   -> ScaledFont {
        use core_graphics::font::CGFontRef;
        use core_text::font::{CTFont, CTFontRef};
        use cairo::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;

        let mut azure_native_font = {
            mType: 0,
            mFont: ptr::null()
        };

        match backend {
            CoreGraphicsBackend | CoreGraphicsAcceleratedBackend | SkiaBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_MAC_FONT_FACE;

                unsafe {
                    azure_native_font.mFont = cast::transmute(native_font.copy_to_CGFont());
                }
            }
            CairoBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_CAIRO_FONT_FACE;

                // TODO(Issue #184): may want to just reuse CGFont stored in servo's QuartzFontHandle.
                // This would require creating some trait like CGFontProvider with .get_CGFont().
                let cg_font = native_font.copy_to_CGFont();
                let face = cairo_quartz_font_face_create_for_cgfont(cg_font);
                if face == ptr::null() { fail; }

                let cairo_font = ScaledFont::create_cairo_font(face, size);
                cairo_font_face_destroy(face);

                unsafe {
                    azure_native_font.mFont = cast::transmute(cairo_font);
                }
            }
            NoBackend | Direct2DBackend | RecordingBackend => {
                fail ~"don't know how to make a scaled font for this backend";
            }
        }

        let azure_native_font_ptr = ptr::to_unsafe_ptr(&azure_native_font);
        let azure_scaled_font = AzCreateScaledFontForNativeFont(azure_native_font_ptr, size);
        ScaledFont { azure_scaled_font: move azure_scaled_font }
    }
}

// FIXME: Move this stuff to a rust-skia?
// FIXME: Demangle the names!!!
#[link_args="-lskia"]
extern {
    #[cfg(target_os="macos")]
    pub fn _Z26SkCreateTypefaceFromCTFontPK8__CTFont(font: CTFontRef) -> *SkTypeface;
}

<commit_msg>Hide OSX-specific things inside a OSX-only module which is conditionally wildcard-imported into current scope.<commit_after>extern mod cairo;

use azure_hl::{BackendType, CairoBackend, CoreGraphicsAcceleratedBackend, CoreGraphicsBackend};
use azure_hl::{Direct2DBackend, NoBackend, RecordingBackend, SkiaBackend};
use bindgen::{AzCreateScaledFontForNativeFont, AzReleaseScaledFont};
use cairo::{cairo_font_face_t, cairo_matrix_t, cairo_scaled_font_t};
use cairo::bindgen::{cairo_font_face_destroy, cairo_font_options_create};
use cairo::bindgen::{cairo_font_options_destroy, cairo_matrix_init_identity, cairo_matrix_scale};
use cairo::bindgen::{cairo_scaled_font_create};

#[cfg(target_os="macos")]
priv mod macos {
    extern mod core_graphics;
    extern mod core_text;
    use core_graphics::font::CGFontRef;
    use core_text::font::{CTFont, CTFontRef};
    use cairo::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;

    type NativeFont = CTFont;
}
#[cfg(target_os="macos")]
priv use macos::*;

type SkTypeface = *c_void;

pub struct ScaledFont {
    azure_scaled_font: AzScaledFontRef,

    drop {
        AzReleaseScaledFont(self.azure_scaled_font);
    }
}

impl ScaledFont {
    static priv fn create_cairo_font(face: *cairo_font_face_t, size: AzFloat)
                                  -> *cairo_scaled_font_t {
        // FIXME: error handling

        let idmatrix: cairo_matrix_t = {
            xx: 0 as c_double,
            yx: 0 as c_double,
            xy: 0 as c_double,
            yy: 0 as c_double,
            x0: 0 as c_double,
            y0: 0 as c_double
        };
        cairo_matrix_init_identity(ptr::to_unsafe_ptr(&idmatrix));

        let fontmatrix = idmatrix;
        cairo_matrix_scale(ptr::to_unsafe_ptr(&fontmatrix), size as c_double, size as c_double);
        let options = cairo_font_options_create();
        let cfont = cairo_scaled_font_create(face,
                                             ptr::to_unsafe_ptr(&fontmatrix),
                                             ptr::to_unsafe_ptr(&idmatrix),
                                             options);
        cairo_font_options_destroy(options);

        return cfont;
    }

    /// Mac-specific function to create a font for the given backend.
    #[cfg(target_os="macos")]
    static pub fn new(backend: BackendType, native_font: &const CTFont, size: AzFloat)
                   -> ScaledFont {
        let mut azure_native_font = {
            mType: 0,
            mFont: ptr::null()
        };

        match backend {
            CoreGraphicsBackend | CoreGraphicsAcceleratedBackend | SkiaBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_MAC_FONT_FACE;

                unsafe {
                    azure_native_font.mFont = cast::transmute(native_font.copy_to_CGFont());
                }
            }
            CairoBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_CAIRO_FONT_FACE;

                // TODO(Issue #184): may want to just reuse CGFont stored in servo's QuartzFontHandle.
                // This would require creating some trait like CGFontProvider with .get_CGFont().
                let cg_font = native_font.copy_to_CGFont();
                let face = cairo_quartz_font_face_create_for_cgfont(cg_font);
                if face == ptr::null() { fail; }

                let cairo_font = ScaledFont::create_cairo_font(face, size);
                cairo_font_face_destroy(face);

                unsafe {
                    azure_native_font.mFont = cast::transmute(cairo_font);
                }
            }
            NoBackend | Direct2DBackend | RecordingBackend => {
                fail ~"don't know how to make a scaled font for this backend";
            }
        }

        let azure_native_font_ptr = ptr::to_unsafe_ptr(&azure_native_font);
        let azure_scaled_font = AzCreateScaledFontForNativeFont(azure_native_font_ptr, size);
        ScaledFont { azure_scaled_font: move azure_scaled_font }
    }
}

// FIXME: Move this stuff to a rust-skia?
// FIXME: Demangle the names!!!
#[link_args="-lskia"]
extern {
    #[cfg(target_os="macos")]
    pub fn _Z26SkCreateTypefaceFromCTFontPK8__CTFont(font: CTFontRef) -> *SkTypeface;
}

<|endoftext|>


<commit_before>//! FIXME: write short doc here

use std::fmt;

use syntax::{ast, SmolStr};

/// `Name` is a wrapper around string, which is used in hir for both references
/// and declarations. In theory, names should also carry hygiene info, but we are
/// not there yet!
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Name(Repr);

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum Repr {
    Text(SmolStr),
    TupleField(usize),
}

impl fmt::Display for Name {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.0 {
            Repr::Text(text) => fmt::Display::fmt(&text, f),
            Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
        }
    }
}

impl Name {
    /// Note: this is private to make creating name from random string hard.
    /// Hopefully, this should allow us to integrate hygiene cleaner in the
    /// future, and to switch to interned representation of names.
    const fn new_text(text: SmolStr) -> Name {
        Name(Repr::Text(text))
    }

    pub fn new_tuple_field(idx: usize) -> Name {
        Name(Repr::TupleField(idx))
    }

    pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
        Self::new_text(lt.text().into())
    }

    /// Shortcut to create inline plain text name
    const fn new_inline(text: &str) -> Name {
        Name::new_text(SmolStr::new_inline(text))
    }

    /// Resolve a name from the text of token.
    fn resolve(raw_text: &str) -> Name {
        if let Some(text) = raw_text.strip_prefix("r#") {
            Name::new_text(SmolStr::new(text))
        } else {
            Name::new_text(raw_text.into())
        }
    }

    pub fn missing() -> Name {
        Name::new_text("[missing name]".into())
    }

    pub fn as_tuple_index(&self) -> Option<usize> {
        match self.0 {
            Repr::TupleField(idx) => Some(idx),
            _ => None,
        }
    }
}

pub trait AsName {
    fn as_name(&self) -> Name;
}

impl AsName for ast::NameRef {
    fn as_name(&self) -> Name {
        match self.as_tuple_field() {
            Some(idx) => Name::new_tuple_field(idx),
            None => Name::resolve(&self.text()),
        }
    }
}

impl AsName for ast::Name {
    fn as_name(&self) -> Name {
        Name::resolve(&self.text())
    }
}

impl AsName for ast::NameOrNameRef {
    fn as_name(&self) -> Name {
        match self {
            ast::NameOrNameRef::Name(it) => it.as_name(),
            ast::NameOrNameRef::NameRef(it) => it.as_name(),
        }
    }
}

impl AsName for tt::Ident {
    fn as_name(&self) -> Name {
        Name::resolve(&self.text)
    }
}

impl AsName for ast::FieldKind {
    fn as_name(&self) -> Name {
        match self {
            ast::FieldKind::Name(nr) => nr.as_name(),
            ast::FieldKind::Index(idx) => {
                let idx = idx.text().parse::<usize>().unwrap_or(0);
                Name::new_tuple_field(idx)
            }
        }
    }
}

impl AsName for base_db::Dependency {
    fn as_name(&self) -> Name {
        Name::new_text(SmolStr::new(&*self.name))
    }
}

pub mod known {
    macro_rules! known_names {
        ($($ident:ident),* $(,)?) => {
            $(
                #[allow(bad_style)]
                pub const $ident: super::Name =
                    super::Name::new_inline(stringify!($ident));
            )*
        };
    }

    known_names!(
        // Primitives
        isize,
        i8,
        i16,
        i32,
        i64,
        i128,
        usize,
        u8,
        u16,
        u32,
        u64,
        u128,
        f32,
        f64,
        bool,
        char,
        str,
        // Special names
        macro_rules,
        derive,
        doc,
        cfg,
        cfg_attr,
        // Components of known path (value or mod name)
        std,
        core,
        alloc,
        iter,
        ops,
        future,
        result,
        boxed,
        option,
        // Components of known path (type name)
        Iterator,
        IntoIterator,
        Item,
        Try,
        Ok,
        Future,
        Result,
        Option,
        Output,
        Target,
        Box,
        RangeFrom,
        RangeFull,
        RangeInclusive,
        RangeToInclusive,
        RangeTo,
        Range,
        Neg,
        Not,
        Index,
        // Components of known path (function name)
        filter_map,
        next,
        iter_mut,
        len,
        is_empty,
        // Builtin macros
        file,
        column,
        compile_error,
        line,
        module_path,
        assert,
        stringify,
        concat,
        include,
        include_bytes,
        include_str,
        format_args,
        format_args_nl,
        env,
        option_env,
        llvm_asm,
        asm,
        // Builtin derives
        Copy,
        Clone,
        Default,
        Debug,
        Hash,
        Ord,
        PartialOrd,
        Eq,
        PartialEq,
        // Safe intrinsics
        abort,
        size_of,
        min_align_of,
        needs_drop,
        caller_location,
        size_of_val,
        min_align_of_val,
        add_with_overflow,
        sub_with_overflow,
        mul_with_overflow,
        wrapping_add,
        wrapping_sub,
        wrapping_mul,
        saturating_add,
        saturating_sub,
        rotate_left,
        rotate_right,
        ctpop,
        ctlz,
        cttz,
        bswap,
        bitreverse,
        discriminant_value,
        type_id,
        likely,
        unlikely,
        ptr_guaranteed_eq,
        ptr_guaranteed_ne,
        minnumf32,
        minnumf64,
        maxnumf32,
        rustc_peek,
        maxnumf64,
        type_name,
        variant_count,
    );

    // self/Self cannot be used as an identifier
    pub const SELF_PARAM: super::Name = super::Name::new_inline("self");
    pub const SELF_TYPE: super::Name = super::Name::new_inline("Self");

    pub const STATIC_LIFETIME: super::Name = super::Name::new_inline("'static");

    #[macro_export]
    macro_rules! name {
        (self) => {
            $crate::name::known::SELF_PARAM
        };
        (Self) => {
            $crate::name::known::SELF_TYPE
        };
        ('static) => {
            $crate::name::known::STATIC_LIFETIME
        };
        ($ident:ident) => {
            $crate::name::known::$ident
        };
    }
}

pub use crate::name;
<commit_msg>internal: document semantics for missing names<commit_after>//! FIXME: write short doc here

use std::fmt;

use syntax::{ast, SmolStr};

/// `Name` is a wrapper around string, which is used in hir for both references
/// and declarations. In theory, names should also carry hygiene info, but we are
/// not there yet!
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Name(Repr);

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum Repr {
    Text(SmolStr),
    TupleField(usize),
}

impl fmt::Display for Name {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.0 {
            Repr::Text(text) => fmt::Display::fmt(&text, f),
            Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
        }
    }
}

impl Name {
    /// Note: this is private to make creating name from random string hard.
    /// Hopefully, this should allow us to integrate hygiene cleaner in the
    /// future, and to switch to interned representation of names.
    const fn new_text(text: SmolStr) -> Name {
        Name(Repr::Text(text))
    }

    pub fn new_tuple_field(idx: usize) -> Name {
        Name(Repr::TupleField(idx))
    }

    pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
        Self::new_text(lt.text().into())
    }

    /// Shortcut to create inline plain text name
    const fn new_inline(text: &str) -> Name {
        Name::new_text(SmolStr::new_inline(text))
    }

    /// Resolve a name from the text of token.
    fn resolve(raw_text: &str) -> Name {
        if let Some(text) = raw_text.strip_prefix("r#") {
            Name::new_text(SmolStr::new(text))
        } else {
            Name::new_text(raw_text.into())
        }
    }

    /// A fake name for things missing in the source code.
    ///
    /// For example, `impl Foo for {}` should be treated as a trait impl for a
    /// type with a missing name. Similarly, `struct S { : u32 }` should have a
    /// single field with a missing name.
    ///
    /// Ideally, we want a `gensym` semantics for missing names -- each missing
    /// name is equal only to itself. It's not clear how to implement this in
    /// salsa though, so we punt on that bit for a moment.
    pub fn missing() -> Name {
        Name::new_text("[missing name]".into())
    }

    pub fn as_tuple_index(&self) -> Option<usize> {
        match self.0 {
            Repr::TupleField(idx) => Some(idx),
            _ => None,
        }
    }
}

pub trait AsName {
    fn as_name(&self) -> Name;
}

impl AsName for ast::NameRef {
    fn as_name(&self) -> Name {
        match self.as_tuple_field() {
            Some(idx) => Name::new_tuple_field(idx),
            None => Name::resolve(&self.text()),
        }
    }
}

impl AsName for ast::Name {
    fn as_name(&self) -> Name {
        Name::resolve(&self.text())
    }
}

impl AsName for ast::NameOrNameRef {
    fn as_name(&self) -> Name {
        match self {
            ast::NameOrNameRef::Name(it) => it.as_name(),
            ast::NameOrNameRef::NameRef(it) => it.as_name(),
        }
    }
}

impl AsName for tt::Ident {
    fn as_name(&self) -> Name {
        Name::resolve(&self.text)
    }
}

impl AsName for ast::FieldKind {
    fn as_name(&self) -> Name {
        match self {
            ast::FieldKind::Name(nr) => nr.as_name(),
            ast::FieldKind::Index(idx) => {
                let idx = idx.text().parse::<usize>().unwrap_or(0);
                Name::new_tuple_field(idx)
            }
        }
    }
}

impl AsName for base_db::Dependency {
    fn as_name(&self) -> Name {
        Name::new_text(SmolStr::new(&*self.name))
    }
}

pub mod known {
    macro_rules! known_names {
        ($($ident:ident),* $(,)?) => {
            $(
                #[allow(bad_style)]
                pub const $ident: super::Name =
                    super::Name::new_inline(stringify!($ident));
            )*
        };
    }

    known_names!(
        // Primitives
        isize,
        i8,
        i16,
        i32,
        i64,
        i128,
        usize,
        u8,
        u16,
        u32,
        u64,
        u128,
        f32,
        f64,
        bool,
        char,
        str,
        // Special names
        macro_rules,
        derive,
        doc,
        cfg,
        cfg_attr,
        // Components of known path (value or mod name)
        std,
        core,
        alloc,
        iter,
        ops,
        future,
        result,
        boxed,
        option,
        // Components of known path (type name)
        Iterator,
        IntoIterator,
        Item,
        Try,
        Ok,
        Future,
        Result,
        Option,
        Output,
        Target,
        Box,
        RangeFrom,
        RangeFull,
        RangeInclusive,
        RangeToInclusive,
        RangeTo,
        Range,
        Neg,
        Not,
        Index,
        // Components of known path (function name)
        filter_map,
        next,
        iter_mut,
        len,
        is_empty,
        // Builtin macros
        file,
        column,
        compile_error,
        line,
        module_path,
        assert,
        stringify,
        concat,
        include,
        include_bytes,
        include_str,
        format_args,
        format_args_nl,
        env,
        option_env,
        llvm_asm,
        asm,
        // Builtin derives
        Copy,
        Clone,
        Default,
        Debug,
        Hash,
        Ord,
        PartialOrd,
        Eq,
        PartialEq,
        // Safe intrinsics
        abort,
        size_of,
        min_align_of,
        needs_drop,
        caller_location,
        size_of_val,
        min_align_of_val,
        add_with_overflow,
        sub_with_overflow,
        mul_with_overflow,
        wrapping_add,
        wrapping_sub,
        wrapping_mul,
        saturating_add,
        saturating_sub,
        rotate_left,
        rotate_right,
        ctpop,
        ctlz,
        cttz,
        bswap,
        bitreverse,
        discriminant_value,
        type_id,
        likely,
        unlikely,
        ptr_guaranteed_eq,
        ptr_guaranteed_ne,
        minnumf32,
        minnumf64,
        maxnumf32,
        rustc_peek,
        maxnumf64,
        type_name,
        variant_count,
    );

    // self/Self cannot be used as an identifier
    pub const SELF_PARAM: super::Name = super::Name::new_inline("self");
    pub const SELF_TYPE: super::Name = super::Name::new_inline("Self");

    pub const STATIC_LIFETIME: super::Name = super::Name::new_inline("'static");

    #[macro_export]
    macro_rules! name {
        (self) => {
            $crate::name::known::SELF_PARAM
        };
        (Self) => {
            $crate::name::known::SELF_TYPE
        };
        ('static) => {
            $crate::name::known::STATIC_LIFETIME
        };
        ($ident:ident) => {
            $crate::name::known::$ident
        };
    }
}

pub use crate::name;
<|endoftext|>


<commit_before>
#![feature(box_syntax,box_patterns)]
extern crate seax_svm;

use seax_svm::svm::slist::Stack;
use seax_svm::svm::slist::List::{Cons,Nil};
use seax_svm::svm::cell::Atom::*;
use seax_svm::svm::cell::SVMCell::*;
use seax_svm::svm::Inst::*;

macro_rules! list(
    ( $e:expr, $($rest:expr),+ ) => ( Cons($e, Box::new(list!( $( $rest ),+ )) ));
    ( $e:expr ) => ( Cons($e, Box::new(Nil)) );
    () => ( Box::new(Nil) );
);

/// SVM integration tests.
///
/// These are based on the sample programs in Zach Allaun's Clojure SECD
/// [implementation](https://github.com/zachallaun/secd). Each example also
/// provides the source code for the equivalent Lisp program.

/// Test for simple list construction through CONS.
///
/// ```lisp
/// (cons 10 (cons 20 nil))
/// ```
#[test]
fn test_list_creation() {
    let state = seax_svm::svm::eval_program(list!(
        InstCell(NIL),
        InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
        InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS)
        ));
    assert_eq!(state.peek(), Some(&ListCell( box list!(AtomCell(SInt(20)), AtomCell(SInt(10))))));
}<commit_msg>Add more integration tests<commit_after>
#![feature(box_syntax,box_patterns)]
extern crate seax_svm;

use seax_svm::svm::slist::Stack;
use seax_svm::svm::slist::List::{Cons,Nil};
use seax_svm::svm::cell::Atom::*;
use seax_svm::svm::cell::SVMCell::*;
use seax_svm::svm::Inst::*;

macro_rules! list(
    ( $e:expr, $($rest:expr),+ ) => ( Cons($e, Box::new(list!( $( $rest ),+ )) ));
    ( $e:expr ) => ( Cons($e, Box::new(Nil)) );
    () => ( Box::new(Nil) );
);

/// SVM integration tests.
///
/// These are based on the sample programs in Zach Allaun's Clojure SECD
/// [implementation](https://github.com/zachallaun/secd). Each example also
/// provides the source code for the equivalent Lisp program.

/// Test for simple list construction through CONS.
///
/// ```lisp
/// (cons 10 (cons 20 nil))
/// ```
#[test]
fn test_list_creation() {
    let state = seax_svm::svm::eval_program(list!(
        InstCell(NIL),
        InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
        InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS)
        ));
    assert_eq!(state.peek(), Some(&ListCell( box list!(AtomCell(SInt(20)), AtomCell(SInt(10))))));
}

/// Test for simple list construction and destructuring
///
/// ```lisp
/// (car (cons 10 (cons 20 nil)))
/// ```
#[test]
fn test_list_car() {
    let state = seax_svm::svm::eval_program(list!(
        InstCell(NIL),
        InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
        InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS),
        InstCell(CAR)
        ));
    assert_eq!(state.peek(), Some(&AtomCell(SInt(20))));
}
/// Test for simple list construction and destructuring
///
/// ```lisp
/// (cdr (cons 10 (cons 20 nil)))
/// ```
#[test]
fn test_list_cdr() {
    let state = seax_svm::svm::eval_program(list!(
        InstCell(NIL),
        InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
        InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS),
        InstCell(CDR)
        ));
    assert_eq!(state.peek(), Some(&ListCell(box list!(AtomCell(SInt(10))))));
}

/// Test for simple mathematics application
///
/// ```lisp
/// (+ 10 10)
/// ```
#[test]
fn test_simple_add() {
    let state = seax_svm::svm::eval_program(list!(
        InstCell(LDC), AtomCell(SInt(10)),
        InstCell(LDC), AtomCell(SInt(10)),
        InstCell(ADD)
        ));
    assert_eq!(state.peek(), Some(&AtomCell(SInt(20))));
}

/// Test for nested arithmetic
///
/// ```lisp
/// (- 20 (+ 5 5))
/// ```
#[test]
fn test_nested_arith() {
    let state = seax_svm::svm::eval_program(list!(
        InstCell(LDC), AtomCell(SInt(5)),
        InstCell(LDC), AtomCell(SInt(5)),
        InstCell(ADD),
        InstCell(LDC), AtomCell(SInt(20)),
        InstCell(SUB)
        ));
    assert_eq!(state.peek(), Some(&AtomCell(SInt(10))));
}<|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.

struct NoCloneOrEq;

#[deriving(PartialEq)]
struct E {
    x: NoCloneOrEq //~ ERROR does not implement any method in scope named `eq`
         //~^ ERROR does not implement any method in scope named `ne`
}
#[deriving(Clone)]
struct C {
    x: NoCloneOrEq //~ ERROR does not implement any method in scope named `clone`
}

fn main() {}
<commit_msg>Fix error message in compile-fail test<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.

struct NoCloneOrEq;

#[deriving(PartialEq)]
struct E {
    x: NoCloneOrEq //~ ERROR does not implement any method in scope named `eq`
         //~^ ERROR does not implement any method in scope named `ne`
}
#[deriving(Clone)]
struct C {
    x: NoCloneOrEq
    //~^ ERROR the trait `core::clone::Clone` is not implemented for the type `NoCloneOrEq`
}

fn main() {}
<|endoftext|>


<commit_before>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::hash::{Hash, Hasher};
use std::mem;

use dtoa;
use linked_hash_map::LinkedHashMap;
use serde::{self, Serialize, Deserialize};
use yaml_rust::Yaml;

use super::{Error, Deserializer, Serializer};

#[derive(Clone, PartialOrd, Debug)]
pub enum Value {
    Null,
    Bool(bool),
    I64(i64),
    F64(f64),
    String(String),
    Sequence(Sequence),
    Mapping(Mapping),
}

pub type Sequence = Vec<Value>;
pub type Mapping = LinkedHashMap<Value, Value>;

/// Shortcut function to encode a `T` into a YAML `Value`.
///
/// ```rust
/// use serde_yaml::{Value, to_value};
/// let val = to_value("foo");
/// assert_eq!(val, Value::String("foo".to_owned()))
/// ```
pub fn to_value<T: ?Sized>(value: &T) -> Value
    where T: Serialize,
{
    let mut ser = Serializer::new();
    value.serialize(&mut ser).unwrap();
    ser.take().into()
}

/// Shortcut function to decode a YAML `Value` into a `T`.
///
/// ```rust
/// use serde_yaml::{Value, from_value};
/// let val = Value::String("foo".to_owned());
/// assert_eq!("foo", from_value::<String>(val).unwrap());
/// ```
pub fn from_value<T>(value: Value) -> Result<T, Error>
    where T: Deserialize,
{
    let yaml = value.into();
    let mut de = Deserializer::new(&yaml);
    Deserialize::deserialize(&mut de)
}

impl Value {
    pub fn is_null(&self) -> bool {
        if let Value::Null = *self {
            true
        } else {
            false
        }
    }

    pub fn is_bool(&self) -> bool {
        self.as_bool().is_some()
    }

    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Bool(b) => Some(b),
            _ => None,
        }
    }

    pub fn is_i64(&self) -> bool {
        self.as_i64().is_some()
    }

    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::I64(i) => Some(i),
            _ => None,
        }
    }

    pub fn is_f64(&self) -> bool {
        self.as_f64().is_some()
    }

    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::F64(i) => Some(i),
            _ => None,
        }
    }

    pub fn is_string(&self) -> bool {
        self.as_str().is_some()
    }

    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(&s),
            _ => None,
        }
    }

    pub fn is_sequence(&self) -> bool {
        self.as_sequence().is_some()
    }

    pub fn as_sequence(&self) -> Option<&Sequence> {
        match *self {
            Value::Sequence(ref seq) => Some(seq),
            _ => None,
        }
    }

    pub fn as_sequence_mut(&mut self) -> Option<&mut Sequence> {
        match *self {
            Value::Sequence(ref mut seq) => Some(seq),
            _ => None,
        }
    }

    pub fn is_mapping(&self) -> bool {
        self.as_mapping().is_some()
    }

    pub fn as_mapping(&self) -> Option<&Mapping> {
        match *self {
            Value::Mapping(ref map) => Some(map),
            _ => None,
        }
    }

    pub fn as_mapping_mut(&mut self) -> Option<&mut Mapping> {
        match *self {
            Value::Mapping(ref mut map) => Some(map),
            _ => None,
        }
    }
}

impl From<Yaml> for Value {
    fn from(yaml: Yaml) -> Self {
        match yaml {
            Yaml::Real(f) => Value::F64(f.parse().unwrap()),
            Yaml::Integer(i) => Value::I64(i),
            Yaml::String(s) => Value::String(s),
            Yaml::Boolean(b) => Value::Bool(b),
            Yaml::Array(array) =>  {
                Value::Sequence(array.into_iter()
                                     .map(Into::into)
                                     .collect())
            }
            Yaml::Hash(hash) => {
                Value::Mapping(hash.into_iter()
                                   .map(|(k, v)| (k.into(), v.into()))
                                   .collect())
            }
            Yaml::Alias(_) => panic!("alias unsupported"),
            Yaml::Null => Value::Null,
            Yaml::BadValue => panic!("bad value"),
        }
    }
}

impl From<Value> for Yaml {
    fn from(value: Value) -> Self {
        match value {
            Value::Null => Yaml::Null,
            Value::Bool(b) => Yaml::Boolean(b),
            Value::I64(i) => Yaml::Integer(i),
            Value::F64(f) => {
                let mut buf = Vec::new();
                dtoa::write(&mut buf, f).unwrap();
                Yaml::Real(String::from_utf8(buf).unwrap())
            }
            Value::String(s) => Yaml::String(s),
            Value::Sequence(seq) => {
                Yaml::Array(seq.into_iter()
                               .map(Into::into)
                               .collect())
            }
            Value::Mapping(map) => {
                Yaml::Hash(map.into_iter()
                              .map(|(k, v)| (k.into(), v.into()))
                              .collect())
            }
        }
    }
}

impl Serialize for Value {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        match *self {
            Value::Null => serializer.serialize_unit(),
            Value::Bool(b) => serializer.serialize_bool(b),
            Value::I64(i) => serializer.serialize_i64(i),
            Value::F64(f) => serializer.serialize_f64(f),
            Value::String(ref s) => serializer.serialize_str(s),
            Value::Sequence(ref seq) => seq.serialize(serializer),
            Value::Mapping(ref map) => map.serialize(serializer),
        }
    }
}

impl Deserialize for Value {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: serde::Deserializer
    {
        struct ValueVisitor;

        impl serde::de::Visitor for ValueVisitor {
            type Value = Value;

            fn visit_bool<E>(&mut self, b: bool) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::Bool(b))
            }

            fn visit_i64<E>(&mut self, i: i64) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::I64(i))
            }

            fn visit_u64<E>(&mut self, u: u64) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::I64(u as i64))
            }

            fn visit_f64<E>(&mut self, f: f64) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::F64(f))
            }

            fn visit_str<E>(&mut self, s: &str) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::String(s.to_owned()))
            }

            fn visit_string<E>(&mut self, s: String) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::String(s))
            }

            fn visit_unit<E>(&mut self) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::Null)
            }

            fn visit_none<E>(&mut self) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::Null)
            }

            fn visit_some<D>(
                &mut self,
                deserializer: &mut D
            ) -> Result<Value, D::Error>
                where D: serde::Deserializer,
            {
                Deserialize::deserialize(deserializer)
            }

            fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error>
                where V: serde::de::SeqVisitor,
            {
                use serde::de::impls::VecVisitor;
                let values = try!(VecVisitor::new().visit_seq(visitor));
                Ok(Value::Sequence(values))
            }

            fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error>
                where V: serde::de::MapVisitor,
            {
                use linked_hash_map::serde::LinkedHashMapVisitor;
                let values = try!(LinkedHashMapVisitor::new().visit_map(visitor));
                Ok(Value::Mapping(values))
            }
        }

        deserializer.deserialize(ValueVisitor)
    }
}

impl PartialEq for Value {
    fn eq(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::Null, &Value::Null) => true,
            (&Value::Bool(a), &Value::Bool(b)) => a == b,
            (&Value::I64(a), &Value::I64(b)) => a == b,
            (&Value::F64(a), &Value::F64(b)) => {
                if a.is_nan() && b.is_nan() {
                    // compare NaN for bitwise equality
                    let (a, b): (i64, i64) = unsafe {
                        (mem::transmute(a), mem::transmute(b))
                    };
                    a == b
                } else {
                    a == b
                }
            }
            (&Value::String(ref a), &Value::String(ref b)) => a == b,
            (&Value::Sequence(ref a), &Value::Sequence(ref b)) => a == b,
            (&Value::Mapping(ref a), &Value::Mapping(ref b)) => a == b,
            _ => false,
        }
    }
}

impl Eq for Value {}

impl Hash for Value {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match self {
            &Value::Null => 0.hash(state),
            &Value::Bool(b) => (1, b).hash(state),
            &Value::I64(i) => (2, i).hash(state),
            &Value::F64(_) => {
                // you should feel bad for using f64 as a map key
                3.hash(state);
            }
            &Value::String(ref s) => (4, s).hash(state),
            &Value::Sequence(ref seq) => (5, seq).hash(state),
            &Value::Mapping(ref map) => (6, map).hash(state),
        }
    }
}
<commit_msg>Treat reals that don't parse as strings<commit_after>// Copyright 2016 Serde YAML Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::hash::{Hash, Hasher};
use std::mem;

use dtoa;
use linked_hash_map::LinkedHashMap;
use serde::{self, Serialize, Deserialize};
use yaml_rust::Yaml;

use super::{Error, Deserializer, Serializer};

#[derive(Clone, PartialOrd, Debug)]
pub enum Value {
    Null,
    Bool(bool),
    I64(i64),
    F64(f64),
    String(String),
    Sequence(Sequence),
    Mapping(Mapping),
}

pub type Sequence = Vec<Value>;
pub type Mapping = LinkedHashMap<Value, Value>;

/// Shortcut function to encode a `T` into a YAML `Value`.
///
/// ```rust
/// use serde_yaml::{Value, to_value};
/// let val = to_value("foo");
/// assert_eq!(val, Value::String("foo".to_owned()))
/// ```
pub fn to_value<T: ?Sized>(value: &T) -> Value
    where T: Serialize,
{
    let mut ser = Serializer::new();
    value.serialize(&mut ser).unwrap();
    ser.take().into()
}

/// Shortcut function to decode a YAML `Value` into a `T`.
///
/// ```rust
/// use serde_yaml::{Value, from_value};
/// let val = Value::String("foo".to_owned());
/// assert_eq!("foo", from_value::<String>(val).unwrap());
/// ```
pub fn from_value<T>(value: Value) -> Result<T, Error>
    where T: Deserialize,
{
    let yaml = value.into();
    let mut de = Deserializer::new(&yaml);
    Deserialize::deserialize(&mut de)
}

impl Value {
    pub fn is_null(&self) -> bool {
        if let Value::Null = *self {
            true
        } else {
            false
        }
    }

    pub fn is_bool(&self) -> bool {
        self.as_bool().is_some()
    }

    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Bool(b) => Some(b),
            _ => None,
        }
    }

    pub fn is_i64(&self) -> bool {
        self.as_i64().is_some()
    }

    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::I64(i) => Some(i),
            _ => None,
        }
    }

    pub fn is_f64(&self) -> bool {
        self.as_f64().is_some()
    }

    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::F64(i) => Some(i),
            _ => None,
        }
    }

    pub fn is_string(&self) -> bool {
        self.as_str().is_some()
    }

    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(&s),
            _ => None,
        }
    }

    pub fn is_sequence(&self) -> bool {
        self.as_sequence().is_some()
    }

    pub fn as_sequence(&self) -> Option<&Sequence> {
        match *self {
            Value::Sequence(ref seq) => Some(seq),
            _ => None,
        }
    }

    pub fn as_sequence_mut(&mut self) -> Option<&mut Sequence> {
        match *self {
            Value::Sequence(ref mut seq) => Some(seq),
            _ => None,
        }
    }

    pub fn is_mapping(&self) -> bool {
        self.as_mapping().is_some()
    }

    pub fn as_mapping(&self) -> Option<&Mapping> {
        match *self {
            Value::Mapping(ref map) => Some(map),
            _ => None,
        }
    }

    pub fn as_mapping_mut(&mut self) -> Option<&mut Mapping> {
        match *self {
            Value::Mapping(ref mut map) => Some(map),
            _ => None,
        }
    }
}

impl From<Yaml> for Value {
    fn from(yaml: Yaml) -> Self {
        match yaml {
            Yaml::Real(f) => {
                match f.parse() {
                    Ok(f) => Value::F64(f),
                    Err(_) => Value::String(f),
                }
            }
            Yaml::Integer(i) => Value::I64(i),
            Yaml::String(s) => Value::String(s),
            Yaml::Boolean(b) => Value::Bool(b),
            Yaml::Array(array) =>  {
                Value::Sequence(array.into_iter()
                                     .map(Into::into)
                                     .collect())
            }
            Yaml::Hash(hash) => {
                Value::Mapping(hash.into_iter()
                                   .map(|(k, v)| (k.into(), v.into()))
                                   .collect())
            }
            Yaml::Alias(_) => panic!("alias unsupported"),
            Yaml::Null => Value::Null,
            Yaml::BadValue => panic!("bad value"),
        }
    }
}

impl From<Value> for Yaml {
    fn from(value: Value) -> Self {
        match value {
            Value::Null => Yaml::Null,
            Value::Bool(b) => Yaml::Boolean(b),
            Value::I64(i) => Yaml::Integer(i),
            Value::F64(f) => {
                let mut buf = Vec::new();
                dtoa::write(&mut buf, f).unwrap();
                Yaml::Real(String::from_utf8(buf).unwrap())
            }
            Value::String(s) => Yaml::String(s),
            Value::Sequence(seq) => {
                Yaml::Array(seq.into_iter()
                               .map(Into::into)
                               .collect())
            }
            Value::Mapping(map) => {
                Yaml::Hash(map.into_iter()
                              .map(|(k, v)| (k.into(), v.into()))
                              .collect())
            }
        }
    }
}

impl Serialize for Value {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        match *self {
            Value::Null => serializer.serialize_unit(),
            Value::Bool(b) => serializer.serialize_bool(b),
            Value::I64(i) => serializer.serialize_i64(i),
            Value::F64(f) => serializer.serialize_f64(f),
            Value::String(ref s) => serializer.serialize_str(s),
            Value::Sequence(ref seq) => seq.serialize(serializer),
            Value::Mapping(ref map) => map.serialize(serializer),
        }
    }
}

impl Deserialize for Value {
    fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
        where D: serde::Deserializer
    {
        struct ValueVisitor;

        impl serde::de::Visitor for ValueVisitor {
            type Value = Value;

            fn visit_bool<E>(&mut self, b: bool) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::Bool(b))
            }

            fn visit_i64<E>(&mut self, i: i64) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::I64(i))
            }

            fn visit_u64<E>(&mut self, u: u64) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::I64(u as i64))
            }

            fn visit_f64<E>(&mut self, f: f64) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::F64(f))
            }

            fn visit_str<E>(&mut self, s: &str) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::String(s.to_owned()))
            }

            fn visit_string<E>(&mut self, s: String) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::String(s))
            }

            fn visit_unit<E>(&mut self) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::Null)
            }

            fn visit_none<E>(&mut self) -> Result<Value, E>
                where E: serde::de::Error
            {
                Ok(Value::Null)
            }

            fn visit_some<D>(
                &mut self,
                deserializer: &mut D
            ) -> Result<Value, D::Error>
                where D: serde::Deserializer,
            {
                Deserialize::deserialize(deserializer)
            }

            fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error>
                where V: serde::de::SeqVisitor,
            {
                use serde::de::impls::VecVisitor;
                let values = try!(VecVisitor::new().visit_seq(visitor));
                Ok(Value::Sequence(values))
            }

            fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error>
                where V: serde::de::MapVisitor,
            {
                use linked_hash_map::serde::LinkedHashMapVisitor;
                let values = try!(LinkedHashMapVisitor::new().visit_map(visitor));
                Ok(Value::Mapping(values))
            }
        }

        deserializer.deserialize(ValueVisitor)
    }
}

impl PartialEq for Value {
    fn eq(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::Null, &Value::Null) => true,
            (&Value::Bool(a), &Value::Bool(b)) => a == b,
            (&Value::I64(a), &Value::I64(b)) => a == b,
            (&Value::F64(a), &Value::F64(b)) => {
                if a.is_nan() && b.is_nan() {
                    // compare NaN for bitwise equality
                    let (a, b): (i64, i64) = unsafe {
                        (mem::transmute(a), mem::transmute(b))
                    };
                    a == b
                } else {
                    a == b
                }
            }
            (&Value::String(ref a), &Value::String(ref b)) => a == b,
            (&Value::Sequence(ref a), &Value::Sequence(ref b)) => a == b,
            (&Value::Mapping(ref a), &Value::Mapping(ref b)) => a == b,
            _ => false,
        }
    }
}

impl Eq for Value {}

impl Hash for Value {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match self {
            &Value::Null => 0.hash(state),
            &Value::Bool(b) => (1, b).hash(state),
            &Value::I64(i) => (2, i).hash(state),
            &Value::F64(_) => {
                // you should feel bad for using f64 as a map key
                3.hash(state);
            }
            &Value::String(ref s) => (4, s).hash(state),
            &Value::Sequence(ref seq) => (5, seq).hash(state),
            &Value::Mapping(ref map) => (6, map).hash(state),
        }
    }
}
<|endoftext|>


<commit_before>// P_2_3_3_01
//
// Generative Gestaltung – Creative Coding im Web
// ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018
// Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni
// with contributions by Joey Lee and Niels Poldervaart
// Copyright 2018
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * draw tool. shows how to draw with dynamic elements.
 *
 * MOUSE
 * drag                : draw with text
 *
 * KEYS
 * del, backspace      : clear screen
 * arrow up            : angle distortion +
 * arrow down          : angle distortion -
 * s                   : save png
 */
use nannou::prelude::*;

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    x: f32,
    y: f32,
    step_size: f32,
    letters: String,
    font_size: u32,
    font_size_min: u32,
    angle: f32,
    angle_distortion: f32,
    distance: f32,
    counter: usize,
}

fn model(app: &App) -> Model {
    app.new_window()
        .size(1280, 720)
        .view(view)
        .mouse_pressed(mouse_pressed)
        .key_pressed(key_pressed)
        .key_released(key_released)
        .build()
        .unwrap();

    let letters = "All the world's a stage, and all the men and women merely players. They have their exits and their entrances.".to_string();
    Model {
        x: 0.0,
        y: 0.0,
        step_size: 5.0,
        letters,
        font_size: 3,
        font_size_min: 3,
        angle: 0.0,
        angle_distortion: 0.0,
        distance: 0.0,
        counter: 0,
    }
}

fn update(app: &App, model: &mut Model, _update: Update) {

    if app.mouse.buttons.left().is_down() {
        model.distance = pt2(model.x, model.y).distance(pt2(app.mouse.x, app.mouse.y));
        model.font_size = model.font_size_min + model.distance as u32 / 2;

        let win_rect = app.main_window().rect();
        let letter = &model.letters.chars().nth(model.counter).unwrap().to_string();
        model.step_size = text(letter).font_size(model.font_size).build(win_rect).bounding_rect().w();

        if model.distance > model.step_size {
            model.angle = (app.mouse.y - model.y).atan2(app.mouse.x - model.x);
            model.counter += 1;
            if model.counter >= model.letters.len() {
                model.counter = 0;
            }

            model.x = model.x + model.angle.cos() * model.step_size;
            model.y = model.y + model.angle.sin() * model.step_size;
        }
    }
}

fn view(app: &App, model: &Model, frame: Frame) {
    if frame.nth() == 0 {
        frame.clear(WHITE);
    }

    let draw = app.draw();

    if model.distance > model.step_size {
        let draw = app.draw().x_y(model.x, model.y).rotate(model.angle + (random_f32() * model.angle_distortion));

        let letter = &model.letters.chars().nth(model.counter).unwrap().to_string();
        draw.text(letter)
            .font_size(model.font_size)
            .x_y(0.0, 0.0)
            .color(BLACK);
    }

    // Write to the window frame.
    draw.to_frame(app, &frame).unwrap();
}

fn mouse_pressed(app: &App, model: &mut Model, _button: MouseButton) {
    model.x = app.mouse.x;
    model.y = app.mouse.y;
}

fn key_pressed(_app: &App, model: &mut Model, key: Key) {
    if key == Key::Up {
        model.angle_distortion += 0.1;
    }
    if key == Key::Down {
        model.angle_distortion -= 0.1;
    }
}

fn key_released(app: &App, _model: &mut Model, key: Key) {
    if key == Key::S {
        app.main_window()
            .capture_frame(app.exe_name().unwrap() + ".png");
    }
}
<commit_msg>cargo fmt<commit_after>// P_2_3_3_01
//
// Generative Gestaltung – Creative Coding im Web
// ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018
// Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni
// with contributions by Joey Lee and Niels Poldervaart
// Copyright 2018
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * draw tool. shows how to draw with dynamic elements.
 *
 * MOUSE
 * drag                : draw with text
 *
 * KEYS
 * del, backspace      : clear screen
 * arrow up            : angle distortion +
 * arrow down          : angle distortion -
 * s                   : save png
 */
use nannou::prelude::*;

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    x: f32,
    y: f32,
    step_size: f32,
    letters: String,
    font_size: u32,
    font_size_min: u32,
    angle: f32,
    angle_distortion: f32,
    distance: f32,
    counter: usize,
}

fn model(app: &App) -> Model {
    app.new_window()
        .size(1280, 720)
        .view(view)
        .mouse_pressed(mouse_pressed)
        .key_pressed(key_pressed)
        .key_released(key_released)
        .build()
        .unwrap();

    let letters = "All the world's a stage, and all the men and women merely players. They have their exits and their entrances.".to_string();
    Model {
        x: 0.0,
        y: 0.0,
        step_size: 5.0,
        letters,
        font_size: 3,
        font_size_min: 3,
        angle: 0.0,
        angle_distortion: 0.0,
        distance: 0.0,
        counter: 0,
    }
}

fn update(app: &App, model: &mut Model, _update: Update) {
    if app.mouse.buttons.left().is_down() {
        model.distance = pt2(model.x, model.y).distance(pt2(app.mouse.x, app.mouse.y));
        model.font_size = model.font_size_min + model.distance as u32 / 2;

        let win_rect = app.main_window().rect();
        let letter = &model
            .letters
            .chars()
            .nth(model.counter)
            .unwrap()
            .to_string();
        model.step_size = text(letter)
            .font_size(model.font_size)
            .build(win_rect)
            .bounding_rect()
            .w();

        if model.distance > model.step_size {
            model.angle = (app.mouse.y - model.y).atan2(app.mouse.x - model.x);
            model.counter += 1;
            if model.counter >= model.letters.len() {
                model.counter = 0;
            }

            model.x = model.x + model.angle.cos() * model.step_size;
            model.y = model.y + model.angle.sin() * model.step_size;
        }
    }
}

fn view(app: &App, model: &Model, frame: Frame) {
    if frame.nth() == 0 {
        frame.clear(WHITE);
    }

    let draw = app.draw();

    if model.distance > model.step_size {
        let draw = app
            .draw()
            .x_y(model.x, model.y)
            .rotate(model.angle + (random_f32() * model.angle_distortion));

        let letter = &model
            .letters
            .chars()
            .nth(model.counter)
            .unwrap()
            .to_string();
        draw.text(letter)
            .font_size(model.font_size)
            .x_y(0.0, 0.0)
            .color(BLACK);
    }

    // Write to the window frame.
    draw.to_frame(app, &frame).unwrap();
}

fn mouse_pressed(app: &App, model: &mut Model, _button: MouseButton) {
    model.x = app.mouse.x;
    model.y = app.mouse.y;
}

fn key_pressed(_app: &App, model: &mut Model, key: Key) {
    if key == Key::Up {
        model.angle_distortion += 0.1;
    }
    if key == Key::Down {
        model.angle_distortion -= 0.1;
    }
}

fn key_released(app: &App, _model: &mut Model, key: Key) {
    if key == Key::S {
        app.main_window()
            .capture_frame(app.exe_name().unwrap() + ".png");
    }
}
<|endoftext|>


<commit_before><commit_msg>working fully?<commit_after><|endoftext|>


<commit_before>use std::default::Default;
use util::color;
use ecs::{Component};
use entity::{Entity};
use components::{Spawn, Category};
use components::{Desc, MapMemory, Health};
use components::{Brain, BrainState, Alignment};
use components::{Item};
use item::{ItemType};
use stats::{Stats};
use stats::Intrinsic::*;
use ability::Ability;
use Biome::*;
use world;

#[derive(Copy)]
pub struct Prototype {
    pub target: Entity
}

impl Prototype {
    pub fn new(parent: Option<Entity>) -> Prototype {
        Prototype {
            target: world::with_mut(|w| w.ecs.new_entity(parent))
        }
    }
}

impl<C: Component> Fn(C,) -> Prototype for Prototype {
    extern "rust-call" fn call(&self, (comp,): (C,)) -> Prototype {
        comp.add_to(self.target);
        *self
    }
}

/// Only call at world init!
pub fn init() {
    let base_mob = Prototype::new(None)
        (Brain { state: BrainState::Asleep, alignment: Alignment::Evil })
        ({let h: Health = Default::default(); h})
        .target;

    // Init the prototypes

    // Player
    Prototype::new(Some(base_mob))
        (Brain { state: BrainState::PlayerControl, alignment: Alignment::Good })
        (Desc::new("player", 51, color::AZURE))
        (Stats::new(6, &[Hands]))
        (MapMemory::new())
        ;

    // Enemies
    Prototype::new(Some(base_mob))
        (Desc::new("dreg", 72, color::OLIVE))
        (Stats::new(1, &[Hands]))
        (Spawn::new(Category::Mob))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("snake", 71, color::GREEN))
        (Stats::new(1, &[]))
        (Spawn::new(Category::Mob).biome(Overland))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("ooze", 77, color::LIGHTSEAGREEN))
        (Stats::new(3, &[]))
        (Spawn::new(Category::Mob).biome(Dungeon).depth(3))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("ogre", 73, color::DARKSLATEGRAY))
        (Stats::new(6, &[Hands]))
        (Spawn::new(Category::Mob).depth(5))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("wraith", 74, color::HOTPINK))
        (Stats::new(8, &[Hands]))
        (Spawn::new(Category::Mob).biome(Dungeon).depth(6))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("octopus", 63, color::DARKTURQUOISE))
        (Stats::new(10, &[]))
        (Spawn::new(Category::Mob).depth(7))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("efreet", 78, color::ORANGE))
        (Stats::new(12, &[]))
        (Spawn::new(Category::Mob).depth(8))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("serpent", 94, color::CORAL))
        (Stats::new(15, &[]))
        (Spawn::new(Category::Mob).biome(Dungeon).depth(9))
        ;

    // Items
    Prototype::new(None)
        (Desc::new("heart", 89, color::RED))
        (Spawn::new(Category::Consumable))
        (Item { item_type: ItemType::Instant, ability: Ability::HealInstant(2) })
        ;

    Prototype::new(None)
        (Desc::new("sword", 84, color::GAINSBORO))
        (Spawn::new(Category::Equipment).commonness(100))
        (Stats::new(5, &[]))
        (Item { item_type: ItemType::MeleeWeapon, ability: Ability::Multi(vec![]) })
        ;
}
<commit_msg>More compact prototype def<commit_after>use std::default::Default;
use util::color::*;
use ecs::{Component};
use entity::{Entity};
use components::{Spawn, Category};
use components::{Desc, MapMemory, Health};
use components::{Brain, BrainState, Alignment};
use components::{Item};
use item::{ItemType};
use stats::{Stats};
use stats::Intrinsic::*;
use ability::Ability;
use Biome::*;
use world;

#[derive(Copy)]
pub struct Prototype {
    pub target: Entity
}

impl Prototype {
    pub fn new(parent: Option<Entity>) -> Prototype {
        Prototype {
            target: world::with_mut(|w| w.ecs.new_entity(parent))
        }
    }
}

impl<C: Component> Fn(C,) -> Prototype for Prototype {
    extern "rust-call" fn call(&self, (comp,): (C,)) -> Prototype {
        comp.add_to(self.target);
        *self
    }
}

/// Only call at world init!
pub fn init() {
    let base_mob = Prototype::new(None)
        (Brain { state: BrainState::Asleep, alignment: Alignment::Evil })
        ({let h: Health = Default::default(); h})
        .target;

    // Init the prototypes

    // Player
    Prototype::new(Some(base_mob))
        (Brain { state: BrainState::PlayerControl, alignment: Alignment::Good })
        (Desc::new("player", 51, AZURE))
        (Stats::new(6, &[Hands]))
        (MapMemory::new())
        ;

    // Enemies
    Prototype::new(Some(base_mob))
        (Desc::new("dreg", 72, OLIVE))
        (Stats::new(1, &[Hands]))
        (Spawn::new(Category::Mob))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("snake", 71, GREEN))
        (Stats::new(1, &[]))
        (Spawn::new(Category::Mob).biome(Overland))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("ooze", 77, LIGHTSEAGREEN))
        (Stats::new(3, &[]))
        (Spawn::new(Category::Mob).biome(Dungeon).depth(3))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("ogre", 73, DARKSLATEGRAY))
        (Stats::new(6, &[Hands]))
        (Spawn::new(Category::Mob).depth(5))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("wraith", 74, HOTPINK))
        (Stats::new(8, &[Hands]))
        (Spawn::new(Category::Mob).biome(Dungeon).depth(6))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("octopus", 63, DARKTURQUOISE))
        (Stats::new(10, &[]))
        (Spawn::new(Category::Mob).depth(7))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("efreet", 78, ORANGE))
        (Stats::new(12, &[]))
        (Spawn::new(Category::Mob).depth(8))
        ;

    Prototype::new(Some(base_mob))
        (Desc::new("serpent", 94, CORAL))
        (Stats::new(15, &[]))
        (Spawn::new(Category::Mob).biome(Dungeon).depth(9))
        ;

    // Items
    Prototype::new(None)
        (Desc::new("heart", 89, RED))
        (Spawn::new(Category::Consumable))
        (Item { item_type: ItemType::Instant, ability: Ability::HealInstant(2) })
        ;

    Prototype::new(None)
        (Desc::new("sword", 84, GAINSBORO))
        (Spawn::new(Category::Equipment).commonness(100))
        (Stats::new(5, &[]))
        (Item { item_type: ItemType::MeleeWeapon, ability: Ability::Multi(vec![]) })
        ;
}
<|endoftext|>