<commit_before>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

extern crate radeco_lib;

use radeco_lib::utils::{Pipeline, Runner, Pipeout, Analysis};
use radeco_lib::frontend::r2::R2;

#[test]
fn test1() {
	let pipeline = vec![Pipeline::ReadFromR2, Pipeline::ParseEsil,
	                    Pipeline::CFG, Pipeline::SSA];

	let test_name = "test1".to_owned();
	let bin_name = Some("./ex-bins/simple2".to_owned());
	let addr = Some("sym.main".to_owned());
	let mut test = Runner::new(test_name, bin_name, addr, false, pipeline, None);
	test.run();
	test.output(None);
}

#[test]
fn test_analysis1() {
	let esil = vec!["4,5,+".to_owned(), "6,*".to_owned(),
	                "100,>,zf,=".to_owned(),
					"5,rax,=".to_owned(),
					"6,rbx,=".to_owned(),
					"7,rbx,=".to_owned()
	               ];

	let test_name = "test2".to_owned();
	// Get a new r2 instance.
    let mut r2 = R2::new(Some("./ex-bins/simple2".to_owned())).unwrap();
    // Initialize with sane defaults.
    r2.init();
    let r = r2.get_reg_info().unwrap();

	let pipeline = vec![
		Pipeline::ParseEsil,
		Pipeline::CFG,
		Pipeline::SSA,
		Pipeline::Verify,
		Pipeline::AnalyzeSSA(Analysis::ConstProp),
		Pipeline::DCE,
		Pipeline::Verify
	];

	let mut test = Runner::new(test_name, None, None, true, pipeline, None);
	test.state.pipeout = Some(Pipeout::Esil(esil));
	test.state.reg_info = Some(r.clone());
	test.run();
	test.output(None);
}

#[test]
fn test_analysis2() {
	let test_name = "test_analysis".to_owned();
	let bin_name = Some("./ex-bins/constprop.o".to_owned());
	let addr = Some("entry0".to_owned());
	let pipeline = vec![
		Pipeline::ReadFromR2,
		Pipeline::ParseEsil,
		Pipeline::CFG,
		Pipeline::SSA,
		Pipeline::Verify
		//Pipeline::DCE,
		//Pipeline::AnalyzeSSA(Analysis::ConstProp),
		//Pipeline::DCE
	];
	let mut test = Runner::new(test_name, bin_name, addr, true, pipeline, None);
	test.run();
	test.output(None);
}

//#[test]
//fn tachikoma() {
	//let test_name = "tachikoma".to_string();
	//let bin_name = Some("./ex-bins/tachikoma".to_string());
	//let addr = Some("fcn.0002b401".to_string());
	//let pipeline = vec![
		//Pipeline::ReadFromR2,
		//Pipeline::ParseEsil,
		//Pipeline::CFG,
		//Pipeline::SSA,
		//Pipeline::Verify
		////Pipeline::DCE,
		////Pipeline::Verify
		////Pipeline::AnalyzeSSA(Analysis::ConstProp),
		////Pipeline::DCE
	//];
	//let mut test = Runner::new(test_name, bin_name, addr, true, pipeline, None);
	//test.run();
	//test.dump();
//}
<commit_msg>Fixes tests<commit_after>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

extern crate radeco_lib;
extern crate r2pipe;

use radeco_lib::utils::{Pipeline, Runner, Pipeout, Analysis};
use r2pipe::R2;

#[test]
fn test1() {
	let pipeline = vec![Pipeline::ReadFromR2, Pipeline::ParseEsil,
	                    Pipeline::CFG, Pipeline::SSA];

	let test_name = "test1".to_owned();
	let bin_name = Some("./ex-bins/simple2".to_owned());
	let addr = Some("sym.main".to_owned());
	let mut test = Runner::new(test_name, bin_name, addr, false, pipeline, None);
	test.run();
	test.output(None);
}

#[test]
fn test_analysis1() {
	let esil = vec!["4,5,+".to_owned(), "6,*".to_owned(),
	                "100,>,zf,=".to_owned(),
					"5,rax,=".to_owned(),
					"6,rbx,=".to_owned(),
					"7,rbx,=".to_owned()
	               ];

	let test_name = "test2".to_owned();
	// Get a new r2 instance.
    let mut r2 = R2::new(Some("./ex-bins/simple2".to_owned())).unwrap();
    // Initialize with sane defaults.
    r2.init();
    let r = r2.get_reg_info().unwrap();

	let pipeline = vec![
		Pipeline::ParseEsil,
		Pipeline::CFG,
		Pipeline::SSA,
		Pipeline::Verify,
		Pipeline::AnalyzeSSA(Analysis::ConstProp),
		Pipeline::DCE,
		Pipeline::Verify
	];

	let mut test = Runner::new(test_name, None, None, true, pipeline, None);
	test.state.pipeout = Some(Pipeout::Esil(esil));
	test.state.reg_info = Some(r.clone());
	test.run();
	test.output(None);
}

#[test]
fn test_analysis2() {
	let test_name = "test_analysis".to_owned();
	let bin_name = Some("./ex-bins/constprop.o".to_owned());
	let addr = Some("entry0".to_owned());
	let pipeline = vec![
		Pipeline::ReadFromR2,
		Pipeline::ParseEsil,
		Pipeline::CFG,
		Pipeline::SSA
		//Pipeline::Verify
		//Pipeline::DCE,
		//Pipeline::AnalyzeSSA(Analysis::ConstProp),
		//Pipeline::DCE
	];
	let mut test = Runner::new(test_name, bin_name, addr, true, pipeline, None);
	test.run();
	test.output(None);
}

//#[test]
//fn tachikoma() {
	//let test_name = "tachikoma".to_string();
	//let bin_name = Some("./ex-bins/tachikoma".to_string());
	//let addr = Some("fcn.0002b401".to_string());
	//let pipeline = vec![
		//Pipeline::ReadFromR2,
		//Pipeline::ParseEsil,
		//Pipeline::CFG,
		//Pipeline::SSA,
		//Pipeline::Verify
		////Pipeline::DCE,
		////Pipeline::Verify
		////Pipeline::AnalyzeSSA(Analysis::ConstProp),
		////Pipeline::DCE
	//];
	//let mut test = Runner::new(test_name, bin_name, addr, true, pipeline, None);
	//test.run();
	//test.dump();
//}
<|endoftext|>


<commit_before>#[macro_use]
extern crate generic_array;
use generic_array::typenum::{U3, U97};
use generic_array::GenericArray;
use std::ops::Drop;

#[test]
fn test() {
    let mut list97 = [0; 97];
    for i in 0..97 {
        list97[i] = i as i32;
    }
    let l : GenericArray<i32, U97> = GenericArray::from_slice(&list97);
    assert_eq!(l[0], 0);
    assert_eq!(l[1], 1);
    assert_eq!(l[32], 32);
    assert_eq!(l[56], 56);
}

static mut drop_counter: u32 = 0;

#[derive(Clone)]
struct TestDrop(u32);

impl Drop for TestDrop {
    fn drop(&mut self) {
        unsafe {
            drop_counter += 1;
        }
    }
}

#[test]
fn test_drop() {
    unsafe {
        drop_counter = 0;
    }
    {
        // This clones the structs, so we will have 6 drops, not 3
        let _: GenericArray<TestDrop, U3> = arr![TestDrop; TestDrop(1), TestDrop(2), TestDrop(3)];
    }
    unsafe {
        assert_eq!(drop_counter, 6);    // 6 drops, as explained above
    }
}

#[test]
fn test_arr() {
    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
    assert_eq!(test[1], 2);
}

#[test]
fn test_iter_flat_map() {
    assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
}

#[cfg(feature="serde")]
mod impl_serde {
    extern crate serde_json;

    use generic_array::GenericArray;
    use generic_array::typenum::U6;

    #[test]
    fn test_serde_implementation() {
        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
        let string = serde_json::to_string(&array).unwrap();
        assert_eq!(string, "[0,5,3,7.07192,76,-9]");

        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
        assert_eq!(test_array, array);
    }
}
<commit_msg>Added a test checking if Copy implementation works<commit_after>#[macro_use]
extern crate generic_array;
use generic_array::typenum::{U3, U97};
use generic_array::GenericArray;
use std::ops::Drop;

#[test]
fn test() {
    let mut list97 = [0; 97];
    for i in 0..97 {
        list97[i] = i as i32;
    }
    let l : GenericArray<i32, U97> = GenericArray::from_slice(&list97);
    assert_eq!(l[0], 0);
    assert_eq!(l[1], 1);
    assert_eq!(l[32], 32);
    assert_eq!(l[56], 56);
}

static mut drop_counter: u32 = 0;

#[derive(Clone)]
struct TestDrop(u32);

impl Drop for TestDrop {
    fn drop(&mut self) {
        unsafe {
            drop_counter += 1;
        }
    }
}

#[test]
fn test_drop() {
    unsafe {
        drop_counter = 0;
    }
    {
        // This clones the structs, so we will have 6 drops, not 3
        let _: GenericArray<TestDrop, U3> = arr![TestDrop; TestDrop(1), TestDrop(2), TestDrop(3)];
    }
    unsafe {
        assert_eq!(drop_counter, 6);    // 6 drops, as explained above
    }
}

#[test]
fn test_arr() {
    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
    assert_eq!(test[1], 2);
}

#[test]
fn test_copy() {
    let test = arr![u32; 1, 2, 3];
    let test2 = test;
    // if GenericArray is not copy, this should fail as a use of a moved value
    assert_eq!(test[1], 2);
    assert_eq!(test2[0], 1);
}

#[test]
fn test_iter_flat_map() {
    assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
}

#[cfg(feature="serde")]
mod impl_serde {
    extern crate serde_json;

    use generic_array::GenericArray;
    use generic_array::typenum::U6;

    #[test]
    fn test_serde_implementation() {
        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
        let string = serde_json::to_string(&array).unwrap();
        assert_eq!(string, "[0,5,3,7.07192,76,-9]");

        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
        assert_eq!(test_array, array);
    }
}
<|endoftext|>


<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;
mod util;

use rocksdb::{DB, Direction, IteratorMode, MemtableFactory, Options};
use util::DBName;

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

#[test]
pub fn test_iterator() {
    let n = DBName::new("_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(&n.name).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"zz", Direction::Reverse));
            let expected = vec![(cba(&k4), cba(&v4)), (cba(&k3), cba(&v3))];
            assert_eq!(iterator1.take(2).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());
        }
    }
}

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

#[test]
pub fn test_prefix_iterator() {
    let n = DBName::new("_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, &n.name).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)
        }
    }
    let opts = Options::default();
    assert!(DB::destroy(&opts, path).is_ok());
}

#[test]
pub fn test_full_iterator() {
    let path = "_rust_rocksdb_fulliteratortest";
    {
        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 factory = MemtableFactory::HashSkipList {
            bucket_count: 1_000_000,
            height: 4,
            branching_factor: 4,
        };

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);
        opts.set_allow_concurrent_memtable_write(false);
        opts.set_memtable_factory(factory);

        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());

        // A normal iterator won't work here since we're using a HashSkipList for our memtable
        // implementation (which buckets keys based on their prefix):
        let bad_iterator = db.iterator(IteratorMode::Start);
        assert_eq!(bad_iterator.collect::<Vec<_>>(), vec![]);

        let expected = vec![
            (cba(&a1), cba(&a1)),
            (cba(&a2), cba(&a2)),
            (cba(&b1), cba(&b1)),
            (cba(&b2), cba(&b2)),
        ];

        let a_iterator = db.full_iterator(IteratorMode::Start);
        assert_eq!(a_iterator.collect::<Vec<_>>(), expected)
    }
    let opts = Options::default();
    assert!(DB::destroy(&opts, path).is_ok());
}
<commit_msg>Update test_iterator.rs<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;
mod util;

use rocksdb::{DB, Direction, IteratorMode, MemtableFactory, Options};
use util::DBName;

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

#[test]
pub fn test_iterator() {
    let n = DBName::new("_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(&n.name).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"zz", Direction::Reverse));
            let expected = vec![(cba(&k4), cba(&v4)), (cba(&k3), cba(&v3))];
            assert_eq!(iterator1.take(2).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());
        }
    }
}

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

#[test]
pub fn test_prefix_iterator() {
    let n = DBName::new("_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, &n.name).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)
        }
    }
}

#[test]
pub fn test_full_iterator() {
    let path = "_rust_rocksdb_fulliteratortest";
    {
        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 factory = MemtableFactory::HashSkipList {
            bucket_count: 1_000_000,
            height: 4,
            branching_factor: 4,
        };

        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_prefix_extractor(prefix_extractor);
        opts.set_allow_concurrent_memtable_write(false);
        opts.set_memtable_factory(factory);

        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());

        // A normal iterator won't work here since we're using a HashSkipList for our memtable
        // implementation (which buckets keys based on their prefix):
        let bad_iterator = db.iterator(IteratorMode::Start);
        assert_eq!(bad_iterator.collect::<Vec<_>>(), vec![]);

        let expected = vec![
            (cba(&a1), cba(&a1)),
            (cba(&a2), cba(&a2)),
            (cba(&b1), cba(&b1)),
            (cba(&b2), cba(&b2)),
        ];

        let a_iterator = db.full_iterator(IteratorMode::Start);
        assert_eq!(a_iterator.collect::<Vec<_>>(), expected)
    }
    let opts = Options::default();
    assert!(DB::destroy(&opts, path).is_ok());
}
<|endoftext|>


<commit_before>// http://dev.w3.org/csswg/css3-syntax/#tokenization
//
// The output of the tokenization step is a series of zero or more
// of the following tokens:
// ident, function, at-keyword, hash, string, bad-string, url, bad-url,
// delim, number, percentage, dimension, unicode-range, whitespace, comment,
// cdo, cdc, colon, semicolon, [, ], (, ), {, }.
//
// ident, function, at-keyword, hash, string, and url tokens
// have a value composed of zero or more characters.
// Delim tokens have a value composed of a single character.
// Number, percentage, and dimension tokens have a representation
// composed of 1 or more character, a numeric value,
// and a type flag set to either "integer" or "number".
// The type flag defaults to "integer" if not otherwise set.
// Dimension tokens additionally have a unit
// composed of one or more characters.
// Unicode-range tokens have a range of characters.

use cssparser;

#[deriving_eq]
enum NumericValue {
    Integer(int),
    // The spec calls this "number".
    // Use "float" instead to reduce term overloading with "number token".
    Float(float),
}
// TODO: add a NumberValue.as_float() method.

#[deriving_eq]
enum Token {
    Ident(~str),
    Function(~str),
    AtKeyword(~str),
    Hash(~str),
    String(~str),
    BadString,
    URL(~str),
    BadURL,
    Delim(char),
    Number(NumericValue, ~str),  // value, representation
    Percentage(NumericValue, ~str),  // value, representation
    Dimension(NumericValue, ~str, ~str),  // value, representation, unit
    UnicodeRange(char, char),  // start, end. XXX what about empty ranges?
    WhiteSpace,
    Comment,
    CDO,  // <!--
    CDC,  // -->
    Colon,  // ,
    Semicolon,  // ;
    OpenBraket, // [
    OpenParen, // (
    OpenBrace, // {
    CloseBraket, // ]
    CloseParen, // (
    CloseBrace, // }
}

struct State {
    input: ~str,
    length: uint,
    mut position: uint,
    mut errors: ~[~str]
}

fn is_eof(state: &State) -> bool {
    state.position >= state.length
}

fn current_char(state: &State) -> char {
    str::char_at(state.input, state.position)
}

fn consume_char(state: &State) -> char {
    let range = str::char_range_at(state.input, state.position);
    state.position = range.next;
    range.ch
}

// 3.3.9. Comment state
fn consume_comment(state: &State) -> Token {
    state.position += 1;  // consume the * in /*
    match str::find_str_from(state.input, "*/", state.position) {
        Some(end_position) => state.position = end_position + 2,
        None => {
            state.errors.push(~"EOF in comment");
            state.position = state.input.len();
        }
    }
    Comment
}

// http://dev.w3.org/csswg/css3-syntax/#tokenization
fn tokenize(input: &str//, transform_function_whitespace: bool,
//            quirks_mode: bool
            ) -> {tokens: ~[Token], parse_errors: ~[~str]} {
    let input = cssparser::preprocess(input);
    let state = &State {
        input: input, length: input.len(),
        position: 0, errors: ~[] };
    let mut tokens: ~[Token] = ~[];

    // 3.3.4. Data state
    while !is_eof(state) {
        tokens.push(match consume_char(state) {
            '/' if !is_eof(state) && current_char(state) == '*'
                => consume_comment(state),
            c => Delim(c),
        })
    }

    // Work around `error: moving out of mutable field`
    // TODO: find a cleaner way.
    let mut errors: ~[~str] = ~[];
    errors <-> state.errors;
    {tokens: tokens, parse_errors: errors}
}

#[test]
fn test_tokenizer() {
    fn assert_tokens(input: &str, expected_tokens: &[Token],
                     expected_errors: &[~str]) {
        let result = tokenize(input//, false, false
        );
        let tokens: &[Token] = result.tokens;
        let parse_errors: &[~str] = result.parse_errors;
        if tokens != expected_tokens {
            fail fmt!("%? != %?", tokens, expected_tokens);
        }
        if parse_errors != expected_errors {
            fail fmt!("%? != %?", tokens, expected_errors);
        }
    }
    assert_tokens("", [], []);
    assert_tokens(",/", [Delim(','), Delim('/')], []);
    assert_tokens(",/* Li/*psum… */", [Delim(','), Comment], []);
    assert_tokens(",/* Li/*psum… *//", [Delim(','), Comment, Delim('/')], []);
    assert_tokens(",/* Lipsum", [Delim(','), Comment], [~"EOF in comment"]);
    assert_tokens(",/*", [Delim(','), Comment], [~"EOF in comment"]);
}
<commit_msg>Add one-char tokens.<commit_after>// http://dev.w3.org/csswg/css3-syntax/#tokenization
//
// The output of the tokenization step is a series of zero or more
// of the following tokens:
// ident, function, at-keyword, hash, string, bad-string, url, bad-url,
// delim, number, percentage, dimension, unicode-range, whitespace, comment,
// cdo, cdc, colon, semicolon, [, ], (, ), {, }.
//
// ident, function, at-keyword, hash, string, and url tokens
// have a value composed of zero or more characters.
// Delim tokens have a value composed of a single character.
// Number, percentage, and dimension tokens have a representation
// composed of 1 or more character, a numeric value,
// and a type flag set to either "integer" or "number".
// The type flag defaults to "integer" if not otherwise set.
// Dimension tokens additionally have a unit
// composed of one or more characters.
// Unicode-range tokens have a range of characters.

use cssparser;

#[deriving_eq]
enum NumericValue {
    Integer(int),
    // The spec calls this "number".
    // Use "float" instead to reduce term overloading with "number token".
    Float(float),
}
// TODO: add a NumberValue.as_float() method.

#[deriving_eq]
enum Token {
    Ident(~str),
    Function(~str),
    AtKeyword(~str),
    Hash(~str),
    String(~str),
    BadString,
    URL(~str),
    BadURL,
    Delim(char),
    Number(NumericValue, ~str),  // value, representation
    Percentage(NumericValue, ~str),  // value, representation
    Dimension(NumericValue, ~str, ~str),  // value, representation, unit
    UnicodeRange(char, char),  // start, end. XXX what about empty ranges?
    WhiteSpace,
    Comment,
    CDO,  // <!--
    CDC,  // -->
    Colon,  // ,
    Semicolon,  // ;
    OpenBraket, // [
    OpenParen, // (
    OpenBrace, // {
    CloseBraket, // ]
    CloseParen, // )
    CloseBrace, // }
}

struct State {
    input: ~str,
    length: uint,
    mut position: uint,
    mut errors: ~[~str]
}

fn is_eof(state: &State) -> bool {
    state.position >= state.length
}

fn current_char(state: &State) -> char {
    str::char_at(state.input, state.position)
}

fn consume_char(state: &State) -> char {
    let range = str::char_range_at(state.input, state.position);
    state.position = range.next;
    range.ch
}

// 3.3.9. Comment state
fn consume_comment(state: &State) -> Token {
    state.position += 1;  // consume the * in /*
    match str::find_str_from(state.input, "*/", state.position) {
        Some(end_position) => state.position = end_position + 2,
        None => {
            state.errors.push(~"EOF in comment");
            state.position = state.input.len();
        }
    }
    Comment
}

// http://dev.w3.org/csswg/css3-syntax/#tokenization
fn tokenize(input: &str//, transform_function_whitespace: bool,
//            quirks_mode: bool
            ) -> {tokens: ~[Token], parse_errors: ~[~str]} {
    let input = cssparser::preprocess(input);
    let state = &State {
        input: input, length: input.len(),
        position: 0, errors: ~[] };
    let mut tokens: ~[Token] = ~[];

    // 3.3.4. Data state
    while !is_eof(state) {
        tokens.push(match consume_char(state) {
            '/' if !is_eof(state) && current_char(state) == '*'
                => consume_comment(state),
            ',' => Colon,
            ';' => Semicolon,
            '[' => OpenBraket,
            '(' => OpenParen,
            '{' => OpenBrace,
            ']' => CloseBraket,
            ')' => CloseParen,
            '}' => CloseBrace,
            c => Delim(c),
        })
    }

    // Work around `error: moving out of mutable field`
    // TODO: find a cleaner way.
    let mut errors: ~[~str] = ~[];
    errors <-> state.errors;
    {tokens: tokens, parse_errors: errors}
}

#[test]
fn test_tokenizer() {
    fn assert_tokens(input: &str, expected_tokens: &[Token],
                     expected_errors: &[~str]) {
        let result = tokenize(input//, false, false
        );
        let tokens: &[Token] = result.tokens;
        let parse_errors: &[~str] = result.parse_errors;
        if tokens != expected_tokens {
            fail fmt!("%? != %?", tokens, expected_tokens);
        }
        if parse_errors != expected_errors {
            fail fmt!("%? != %?", tokens, expected_errors);
        }
    }
    assert_tokens("", [], []);
    assert_tokens("?/", [Delim('?'), Delim('/')], []);
    assert_tokens("?/* Li/*psum… */", [Delim('?'), Comment], []);
    assert_tokens("?/* Li/*psum… *//", [Delim('?'), Comment, Delim('/')], []);
    assert_tokens("?/* Lipsum", [Delim('?'), Comment], [~"EOF in comment"]);
    assert_tokens("?/*", [Delim('?'), Comment], [~"EOF in comment"]);
    assert_tokens("[?}{)",
        [OpenBraket, Delim('?'), CloseBrace, OpenBrace, CloseParen], []);
}
<|endoftext|>


<commit_before>//! Performes early-stage optimizations on Cranelift IR.

#![deny(
    missing_docs,
    trivial_numeric_casts,
    unused_extern_crates,
    unstable_features
)]
#![warn(unused_import_braces)]
#![cfg_attr(
    feature = "clippy",
    plugin(clippy(conf_file = "../../clippy.toml"))
)]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(new_without_default, new_without_default_derive)
)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        float_arithmetic,
        mut_mut,
        nonminimal_bool,
        option_map_unwrap_or,
        option_map_unwrap_or_else,
        print_stdout,
        unicode_not_nfc,
        use_self
    )
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), alloc)]

#[cfg(not(feature = "std"))]
extern crate alloc;

extern crate cranelift_codegen;
// extern crate rustc_apfloat;

mod constant_folding;

use cranelift_codegen::{isa::TargetIsa, settings::FlagsOrIsa, CodegenResult, Context};

/// Optimize the function with available optimizations.
///
/// Since this can be resource intensive (and code-size inflating),
/// it is separated from `Context::compile` to allow DCE to remove it
/// if it's not used.
pub fn optimize(ctx: &mut Context, isa: &TargetIsa) -> CodegenResult<()> {
    ctx.verify_if(isa)?;
    fold_constants(ctx, isa)?;

    Ok(())
}

/// Fold constants
pub fn fold_constants<'a, FOI>(ctx: &mut Context, fisa: FOI) -> CodegenResult<()>
where
    FOI: Into<FlagsOrIsa<'a>>,
{
    constant_folding::fold_constants(&mut ctx.func);
    ctx.verify_if(fisa)?;
    Ok(())
}

/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
    pub use alloc::{boxed, slice, string, vec};
    pub use core::*;
}
<commit_msg>Update no_std support.<commit_after>//! Performes early-stage optimizations on Cranelift IR.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates,)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "std", deny(unstable_features))]
#![cfg_attr(
    feature = "clippy",
    plugin(clippy(conf_file = "../../clippy.toml"))
)]
#![cfg_attr(
    feature = "cargo-clippy",
    allow(new_without_default, new_without_default_derive)
)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        float_arithmetic,
        mut_mut,
        nonminimal_bool,
        option_map_unwrap_or,
        option_map_unwrap_or_else,
        print_stdout,
        unicode_not_nfc,
        use_self
    )
)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]

#[cfg(not(feature = "std"))]
extern crate alloc;

extern crate cranelift_codegen;
// extern crate rustc_apfloat;

mod constant_folding;

use cranelift_codegen::{isa::TargetIsa, settings::FlagsOrIsa, CodegenResult, Context};

/// Optimize the function with available optimizations.
///
/// Since this can be resource intensive (and code-size inflating),
/// it is separated from `Context::compile` to allow DCE to remove it
/// if it's not used.
pub fn optimize(ctx: &mut Context, isa: &TargetIsa) -> CodegenResult<()> {
    ctx.verify_if(isa)?;
    fold_constants(ctx, isa)?;

    Ok(())
}

/// Fold constants
pub fn fold_constants<'a, FOI>(ctx: &mut Context, fisa: FOI) -> CodegenResult<()>
where
    FOI: Into<FlagsOrIsa<'a>>,
{
    constant_folding::fold_constants(&mut ctx.func);
    ctx.verify_if(fisa)?;
    Ok(())
}

/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
    pub use alloc::{boxed, slice, string, vec};
    pub use core::*;
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::Rng;
use std::fmt::Debug;
use std::collections::{HashMap, HashSet};

#[allow(unused_variables)]

// Because these are passed without & to some functions,
// it will probably be necessary for these two types to be Copy.
pub type CellID = u64;
pub type CallbackID = u64;

enum Cell<'a, T: Debug + Copy + PartialEq> {
    Input(T),
    Compute(Vec<CellID>, Box<Fn(&[T]) -> T>, HashMap<CallbackID, Box<FnMut(T) -> () + 'a>>),
}

pub struct Reactor<'a, T: Debug + Copy + PartialEq> {
    cells: Vec<Cell<'a, T>>,
}

// You are guaranteed that Reactor will only be tested against types that are Copy + PartialEq.
impl<'a, T: 'a + Debug + Copy + PartialEq> Reactor<'a, T> {
    pub fn new() -> Self {
        Reactor { cells: Vec::default() }
    }

    // Creates an input cell with the specified initial value, returning its ID.
    pub fn create_input(&mut self, initial: T) -> CellID {
        self.cells.push(Cell::Input(initial));

        (self.cells.len() - 1) as CellID
    }

    // Creates a compute cell with the specified dependencies and compute function.
    // The compute function is expected to take in its arguments in the same order as specified in
    // `dependencies`.
    // You do not need to reject compute functions that expect more arguments than there are
    // dependencies (how would you check for this, anyway?).
    //
    // Return an Err (and you can change the error type) if any dependency doesn't exist.
    //
    // Notice that there is no way to *remove* a cell.
    // This means that you may assume, without checking, that if the dependencies exist at creation
    // time they will continue to exist as long as the Reactor exists.
    pub fn create_compute<F: 'static + Fn(&[T]) -> T>(&mut self,
                                                      dependencies: &[CellID],
                                                      compute_func: F)
                                                      -> Result<CellID, ()> {
        if !dependencies.iter().all(|v| (*v as usize) < self.cells.len()) {
            return Err(());
        }

        self.cells.push(Cell::Compute(dependencies.to_vec(),
                                      Box::new(compute_func),
                                      HashMap::default()));

        Ok((self.cells.len() - 1) as CellID)

    }

    // Retrieves the current value of the cell, or None if the cell does not exist.
    //
    // You may wonder whether it is possible to implement `get(&self, id: CellID) -> Option<&Cell>`
    // and have a `value(&self)` method on `Cell`.
    //
    // It turns out this introduces a significant amount of extra complexity to this exercise.
    // We chose not to cover this here, since this exercise is probably enough work as-is.
    pub fn value(&self, id: CellID) -> Option<T> {
        if let Some(val) = self.cells.get(id as usize) {
            match val {
                &Cell::Input(v) => return Some(v),
                &Cell::Compute(ref deps, ref f, _) => {
                    return Some(f(deps.iter()
                        .map(|cid| self.value(*cid).unwrap())
                        .collect::<Vec<_>>()
                        .as_slice()));
                }
            }
        }
        None
    }

    fn get_dependencies_for_cell_id(&self, id: CellID, impacted_computed_cells: &mut Vec<CellID>) {
        for (idx, cell) in self.cells.iter().enumerate() {
            match cell {
                &Cell::Compute(ref deps, _, _) => {
                    if deps.contains(&id) {
                        impacted_computed_cells.push(idx as CellID);
                        self.get_dependencies_for_cell_id(idx as CellID, impacted_computed_cells);
                    }
                }
                _ => {}
            }
        }

    }
    // Sets the value of the specified input cell.
    //
    // Return an Err (and you can change the error type) if the cell does not exist, or the
    // specified cell is a compute cell, since compute cells cannot have their values directly set.
    //
    // Similarly, you may wonder about `get_mut(&mut self, id: CellID) -> Option<&mut Cell>`, with
    // a `set_value(&mut self, new_value: T)` method on `Cell`.
    //
    // As before, that turned out to add too much extra complexity.
    pub fn set_value(&mut self, id: CellID, new_value: T) -> Result<(), ()> {
        let mut impacted_computed_cells = Vec::new();
        self.get_dependencies_for_cell_id(id, &mut impacted_computed_cells);

        impacted_computed_cells = impacted_computed_cells.into_iter()
            .collect::<HashSet<_>>()
            .into_iter()
            .collect::<Vec<_>>();

        // callbacks need to be triggered only if the value has been changed
        let computed_cells_old_values = impacted_computed_cells.iter()
            .map(|idx| (idx, self.value(*idx as CellID).unwrap()))
            .collect::<Vec<_>>();

        match self.cells.get_mut(id as usize) {
            Some(&mut Cell::Input(ref mut val)) => {
                *val = new_value;
            }
            _ => return Err(()),
        }

        let computed_cells_new_values = impacted_computed_cells.iter()
            .map(|idx| (idx, self.value(*idx as CellID).unwrap()))
            .collect::<Vec<_>>();

        let changed_computed_cells = computed_cells_old_values.iter()
            .zip(computed_cells_new_values.iter())
            .filter(|&(&(_, old_val), &(idx, new_val))| old_val != new_val)
            .map(|(&(_, _), &(idx, val))| (idx, val))
            .collect::<Vec<_>>();

        for (idx, val) in changed_computed_cells {
            match self.cells.get_mut(*idx as usize) {
                Some(&mut Cell::Compute(ref deps, ref mut f, ref mut callbacks)) => {
                    callbacks.iter_mut().map(|(key, f)| f(val)).all(|_| true);
                }
                _ => (),
            }
        }

        Ok(())

    }

    // Adds a callback to the specified compute cell.
    //
    // Return an Err (and you can change the error type) if the cell does not exist.
    //
    // Callbacks on input cells will not be tested.
    //
    // The semantics of callbacks (as will be tested):
    // For a single set_value call, each compute cell's callbacks should each be called:
    // * Zero times if the compute cell's value did not change as a result of the set_value call.
    // * Exactly once if the compute cell's value changed as a result of the set_value call.
    //   The value passed to the callback should be the final value of the compute cell after the
    //   set_value call.
    pub fn add_callback<F: FnMut(T) -> () + 'a>(&mut self,
                                                id: CellID,
                                                callback: F)
                                                -> Result<CallbackID, ()> {
        if (id as usize) > self.cells.len() {
            return Err(());
        }

        let mut rng = rand::thread_rng();
        let mut clbkid = rng.gen::<CallbackID>();
        match self.cells[id as usize] {
            Cell::Compute(_, _, ref mut callbacks) => {
                while callbacks.contains_key(&clbkid) {
                    clbkid = rng.gen::<CallbackID>();
                }
                callbacks.insert(clbkid, Box::new(callback));
            }
            _ => (),

        }

        Ok(clbkid)
    }

    // Removes the specified callback, using an ID returned from add_callback.
    //
    // Return an Err (and you can change the error type) if either the cell or callback
    // does not exist.
    //
    // A removed callback should no longer be called.
    pub fn remove_callback(&mut self, cell: CellID, callback: CallbackID) -> Result<(), ()> {
        if (cell as usize) > self.cells.len() {
            return Err(());
        }

        match self.cells[cell as usize] {
            Cell::Compute(_, _, ref mut callbacks) => {
                if !callbacks.contains_key(&callback) {
                    return Err(());

                }
                let _ = callbacks.remove(&callback);
            }
            Cell::Input(_) => return Err(()),
        }

        Ok(())
    }
}
<commit_msg>React exercise after clippy cleanup<commit_after>extern crate rand;

use rand::Rng;
use std::fmt::Debug;
use std::collections::{HashMap, HashSet};

#[allow(unused_variables)]

// Because these are passed without & to some functions,
// it will probably be necessary for these two types to be Copy.
pub type CellID = u64;
pub type CallbackID = u64;

enum Cell<'a, T: Debug + Copy + PartialEq> {
    Input(T),
    Compute(Vec<CellID>, Box<Fn(&[T]) -> T>, HashMap<CallbackID, Box<FnMut(T) -> () + 'a>>),
}

pub struct Reactor<'a, T: Debug + Copy + PartialEq> {
    cells: Vec<Cell<'a, T>>,
}

// You are guaranteed that Reactor will only be tested against types that are Copy + PartialEq.
impl<'a, T: 'a + Debug + Copy + PartialEq> Reactor<'a, T> {
    pub fn new() -> Self {
        Reactor { cells: Vec::default() }
    }

    // Creates an input cell with the specified initial value, returning its ID.
    pub fn create_input(&mut self, initial: T) -> CellID {
        self.cells.push(Cell::Input(initial));

        (self.cells.len() - 1) as CellID
    }

    // Creates a compute cell with the specified dependencies and compute function.
    // The compute function is expected to take in its arguments in the same order as specified in
    // `dependencies`.
    // You do not need to reject compute functions that expect more arguments than there are
    // dependencies (how would you check for this, anyway?).
    //
    // Return an Err (and you can change the error type) if any dependency doesn't exist.
    //
    // Notice that there is no way to *remove* a cell.
    // This means that you may assume, without checking, that if the dependencies exist at creation
    // time they will continue to exist as long as the Reactor exists.
    pub fn create_compute<F: 'static + Fn(&[T]) -> T>(&mut self,
                                                      dependencies: &[CellID],
                                                      compute_func: F)
                                                      -> Result<CellID, ()> {
        if !dependencies.iter().all(|v| (*v as usize) < self.cells.len()) {
            return Err(());
        }

        self.cells.push(Cell::Compute(dependencies.to_vec(),
                                      Box::new(compute_func),
                                      HashMap::default()));

        Ok((self.cells.len() - 1) as CellID)

    }

    // Retrieves the current value of the cell, or None if the cell does not exist.
    //
    // You may wonder whether it is possible to implement `get(&self, id: CellID) -> Option<&Cell>`
    // and have a `value(&self)` method on `Cell`.
    //
    // It turns out this introduces a significant amount of extra complexity to this exercise.
    // We chose not to cover this here, since this exercise is probably enough work as-is.
    pub fn value(&self, id: CellID) -> Option<T> {
        if let Some(val) = self.cells.get(id as usize) {
            match *val {
                Cell::Input(v) => return Some(v),
                Cell::Compute(ref deps, ref f, _) => {
                    return Some(f(deps.iter()
                        .map(|cid| self.value(*cid).unwrap())
                        .collect::<Vec<_>>()
                        .as_slice()));
                }
            }
        }
        None
    }

    fn get_dependencies_for_cell_id(&self,
                                    id: CellID,
                                    impacted_computed_cells: &mut HashSet<CellID>) {
        for (idx, cell) in self.cells.iter().enumerate() {
            if let Cell::Compute(ref deps, _, _) = *cell {
                if deps.contains(&id) {
                    impacted_computed_cells.insert(idx as CellID);
                    self.get_dependencies_for_cell_id(idx as CellID, impacted_computed_cells);
                }
            }
        }

    }
    // Sets the value of the specified input cell.
    //
    // Return an Err (and you can change the error type) if the cell does not exist, or the
    // specified cell is a compute cell, since compute cells cannot have their values directly set.
    //
    // Similarly, you may wonder about `get_mut(&mut self, id: CellID) -> Option<&mut Cell>`, with
    // a `set_value(&mut self, new_value: T)` method on `Cell`.
    //
    // As before, that turned out to add too much extra complexity.
    pub fn set_value(&mut self, id: CellID, new_value: T) -> Result<(), ()> {
        let mut impacted_computed_cells = HashSet::new();
        self.get_dependencies_for_cell_id(id, &mut impacted_computed_cells);

        // callbacks need to be triggered only if the value has been changed
        let computed_cells_old_values = impacted_computed_cells.iter()
            .map(|idx| (idx, self.value(*idx as CellID).unwrap()))
            .collect::<Vec<_>>();

        match self.cells.get_mut(id as usize) {
            Some(&mut Cell::Input(ref mut val)) => {
                *val = new_value;
            }
            _ => return Err(()),
        }

        let computed_cells_new_values = impacted_computed_cells.iter()
            .map(|idx| (idx, self.value(*idx as CellID).unwrap()))
            .collect::<Vec<_>>();

        let changed_computed_cells = computed_cells_old_values.iter()
            .zip(computed_cells_new_values.iter())
            .filter(|&(&(_, old_val), &(_, new_val))| old_val != new_val)
            .map(|(&(_, _), &(idx, val))| (idx, val))
            .collect::<Vec<_>>();

        for (idx, val) in changed_computed_cells {
            if let Some(&mut Cell::Compute(_, _, ref mut callbacks)) = self.cells
                .get_mut(*idx as usize) {
                callbacks.iter_mut().map(|(_, f)| f(val)).all(|_| true);
            }
        }

        Ok(())

    }

    // Adds a callback to the specified compute cell.
    //
    // Return an Err (and you can change the error type) if the cell does not exist.
    //
    // Callbacks on input cells will not be tested.
    //
    // The semantics of callbacks (as will be tested):
    // For a single set_value call, each compute cell's callbacks should each be called:
    // * Zero times if the compute cell's value did not change as a result of the set_value call.
    // * Exactly once if the compute cell's value changed as a result of the set_value call.
    //   The value passed to the callback should be the final value of the compute cell after the
    //   set_value call.
    pub fn add_callback<F: FnMut(T) -> () + 'a>(&mut self,
                                                id: CellID,
                                                callback: F)
                                                -> Result<CallbackID, ()> {
        if (id as usize) > self.cells.len() {
            return Err(());
        }

        let mut rng = rand::thread_rng();
        let mut clbkid = rng.gen::<CallbackID>();
        if let Cell::Compute(_, _, ref mut callbacks) = self.cells[id as usize] {
            while callbacks.contains_key(&clbkid) {
                clbkid = rng.gen::<CallbackID>();
            }
            callbacks.insert(clbkid, Box::new(callback));
        }

        Ok(clbkid)
    }

    // Removes the specified callback, using an ID returned from add_callback.
    //
    // Return an Err (and you can change the error type) if either the cell or callback
    // does not exist.
    //
    // A removed callback should no longer be called.
    pub fn remove_callback(&mut self, cell: CellID, callback: CallbackID) -> Result<(), ()> {
        if (cell as usize) > self.cells.len() {
            return Err(());
        }

        match self.cells[cell as usize] {
            Cell::Compute(_, _, ref mut callbacks) => {
                if !callbacks.contains_key(&callback) {
                    return Err(());

                }
                let _ = callbacks.remove(&callback);
            }
            Cell::Input(_) => return Err(()),
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>///! Utilities for universally unique identifiers.
///!
///! The identifiers generated by this module:
///!
///! - are URL safe
///! - contain information on the type of object that they
///!   are identifying
///! - have an extremely low probability of collision
///!
///! Generated identifiers have a fixed length of 32 characters made up
///! of two parts separated by a hyphen:
///!
///! - 2 characters in the range `[a-z]` that identifying the "family" of
///!   identifiers, usually the type of object the identifier is for
///!   e.g. `fi` = file, `re` = request
///!
///! - 20 characters in the range `[0-9A-Za-z]` that are randomly generated
///!
///! For project identifiers (those starting with 'pr') only lowercase
///! letters are used for compatibility with Docker image naming rules.
///!
///! The total size of the generated ids is 23 bytes which allows it to fit
///! inside a [`SmartString`](https://lib.rs/crates/smartstring) for better
///! performance that a plain old `String`.
///!
///! See
///!  - https://segment.com/blog/a-brief-history-of-the-uuid/
///!  - https://zelark.github.io/nano-id-cc/
///!  - https://gist.github.com/fnky/76f533366f75cf75802c8052b577e2a5
use eyre::{bail, Result};
use nanoid::nanoid;
use regex::Regex;
use smartstring::{Compact, SmartString};

pub type Uuid = SmartString<Compact>;

/// The separator between the family and random parts of the identifier
///
/// A hyphen provides for better readability than a dot or colon when used
/// in pubsub topic strings and elsewhere.
const SEPARATOR: &str = "-";

/// The characters used in the random part of the identifier
const CHARACTERS: [char; 62] = [
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
    'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
    'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
    'V', 'W', 'X', 'Y', 'Z',
];

/// Create a family of UUIDs
///
/// ```
/// use uuids::uuid_family;
///
/// uuid_family!(MyId, "my");
/// let id = MyId::new();
/// ```
#[macro_export]
macro_rules! uuid_family {
    ($name:ident, $prefix:literal) => {
        #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
        pub struct $name(uuids::Uuid);

        impl $name {
            pub fn new() -> Self {
                Self(uuids::generate($prefix))
            }
        }

        impl Default for $name {
            fn default() -> Self {
                Self::new()
            }
        }

        impl std::fmt::Display for $name {
            fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(formatter, "{}", self.0.to_string())
            }
        }

        impl std::cmp::PartialEq for $name {
            fn eq(&self, other: &$name) -> bool {
                self.0 == other.0
            }
        }

        impl std::cmp::Eq for $name {}

        impl std::hash::Hash for $name {
            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
                self.0.hash(state);
            }
        }

        impl std::ops::Deref for $name {
            type Target = uuids::Uuid;

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

        impl std::convert::TryFrom<&str> for $name {
            type Error = uuids::InvalidUuid;

            fn try_from(id: &str) -> std::result::Result<Self, Self::Error> {
                match uuids::matches($prefix, id) {
                    true => Ok($name(id.into())),
                    false => Err(uuids::InvalidUuid {}),
                }
            }
        }
    };
}

// Generate a universally unique identifier
pub fn generate(prefix: &str) -> Uuid {
    let chars = nanoid!(20, &CHARACTERS);
    [prefix, SEPARATOR, &chars].concat().into()
}

// Generate a universally unique identifier with only lowercase letters and digits
pub fn generate_lower(prefix: &str) -> Uuid {
    let chars = nanoid!(20, &CHARACTERS[..36]);
    [prefix, SEPARATOR, &chars].concat().into()
}

// Test whether a string is an identifier for a particular prefix
pub fn matches(prefix: &str, id: &str) -> bool {
    let re = ["^", prefix, SEPARATOR, "[0-9a-zA-Z]{20}$"].concat();
    let re = Regex::new(&re).expect("Should be a valid regex");
    re.is_match(id)
}

// Assert that a `Uuid` is an identifer for a particular family
pub fn assert(family: &str, id: Uuid) -> Result<Uuid> {
    match matches(family, &id) {
        true => Ok(id),
        false => bail!(
            "Invalid UUID `{}`, family does not match `{}`",
            family.to_string(),
            id
        ),
    }
}

pub struct InvalidUuid {}

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

    #[test]
    fn normal() {
        let id = generate("no");
        assert_eq!(id.len(), 23);
        assert!(matches("no", &id));
        assert("no", id).unwrap();
    }

    #[test]
    fn lower() {
        let id = generate_lower("pr");
        assert_eq!(id.len(), 23);
        assert!(matches("pr", &id));
        assert("pr", id).unwrap();
    }
}
<commit_msg>fix(UUIDs): Add `PartialOrd` and `Ord` traits to allow sorting and searching<commit_after>///! Utilities for universally unique identifiers.
///!
///! The identifiers generated by this module:
///!
///! - are URL safe
///! - contain information on the type of object that they
///!   are identifying
///! - have an extremely low probability of collision
///!
///! Generated identifiers have a fixed length of 32 characters made up
///! of two parts separated by a hyphen:
///!
///! - 2 characters in the range `[a-z]` that identifying the "family" of
///!   identifiers, usually the type of object the identifier is for
///!   e.g. `fi` = file, `re` = request
///!
///! - 20 characters in the range `[0-9A-Za-z]` that are randomly generated
///!
///! For project identifiers (those starting with 'pr') only lowercase
///! letters are used for compatibility with Docker image naming rules.
///!
///! The total size of the generated ids is 23 bytes which allows it to fit
///! inside a [`SmartString`](https://lib.rs/crates/smartstring) for better
///! performance that a plain old `String`.
///!
///! See
///!  - https://segment.com/blog/a-brief-history-of-the-uuid/
///!  - https://zelark.github.io/nano-id-cc/
///!  - https://gist.github.com/fnky/76f533366f75cf75802c8052b577e2a5
use eyre::{bail, Result};
use nanoid::nanoid;
use regex::Regex;
use smartstring::{Compact, SmartString};

pub type Uuid = SmartString<Compact>;

/// The separator between the family and random parts of the identifier
///
/// A hyphen provides for better readability than a dot or colon when used
/// in pubsub topic strings and elsewhere.
const SEPARATOR: &str = "-";

/// The characters used in the random part of the identifier
const CHARACTERS: [char; 62] = [
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
    'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
    'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
    'V', 'W', 'X', 'Y', 'Z',
];

/// Create a family of UUIDs
///
/// ```
/// use uuids::uuid_family;
///
/// uuid_family!(MyId, "my");
/// let id = MyId::new();
/// ```
#[macro_export]
macro_rules! uuid_family {
    ($name:ident, $prefix:literal) => {
        #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
        pub struct $name(uuids::Uuid);

        impl $name {
            pub fn new() -> Self {
                Self(uuids::generate($prefix))
            }
        }

        impl Default for $name {
            fn default() -> Self {
                Self::new()
            }
        }

        impl std::fmt::Display for $name {
            fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(formatter, "{}", self.0.to_string())
            }
        }

        impl std::cmp::PartialEq for $name {
            fn eq(&self, other: &Self) -> bool {
                self.0 == other.0
            }
        }

        impl std::cmp::Eq for $name {}

        impl std::cmp::PartialOrd for $name {
            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
                self.0.partial_cmp(&other.0)
            }
        }

        impl std::cmp::Ord for $name {
            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
                self.0.cmp(&other.0)
            }
        }

        impl std::hash::Hash for $name {
            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
                self.0.hash(state);
            }
        }

        impl std::ops::Deref for $name {
            type Target = uuids::Uuid;

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

        impl std::convert::TryFrom<&str> for $name {
            type Error = uuids::InvalidUuid;

            fn try_from(id: &str) -> std::result::Result<Self, Self::Error> {
                match uuids::matches($prefix, id) {
                    true => Ok($name(id.into())),
                    false => Err(uuids::InvalidUuid {}),
                }
            }
        }
    };
}

// Generate a universally unique identifier
pub fn generate(prefix: &str) -> Uuid {
    let chars = nanoid!(20, &CHARACTERS);
    [prefix, SEPARATOR, &chars].concat().into()
}

// Generate a universally unique identifier with only lowercase letters and digits
pub fn generate_lower(prefix: &str) -> Uuid {
    let chars = nanoid!(20, &CHARACTERS[..36]);
    [prefix, SEPARATOR, &chars].concat().into()
}

// Test whether a string is an identifier for a particular prefix
pub fn matches(prefix: &str, id: &str) -> bool {
    let re = ["^", prefix, SEPARATOR, "[0-9a-zA-Z]{20}$"].concat();
    let re = Regex::new(&re).expect("Should be a valid regex");
    re.is_match(id)
}

// Assert that a `Uuid` is an identifer for a particular family
pub fn assert(family: &str, id: Uuid) -> Result<Uuid> {
    match matches(family, &id) {
        true => Ok(id),
        false => bail!(
            "Invalid UUID `{}`, family does not match `{}`",
            family.to_string(),
            id
        ),
    }
}

pub struct InvalidUuid {}

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

    #[test]
    fn normal() {
        let id = generate("no");
        assert_eq!(id.len(), 23);
        assert!(matches("no", &id));
        assert("no", id).unwrap();
    }

    #[test]
    fn lower() {
        let id = generate_lower("pr");
        assert_eq!(id.len(), 23);
        assert!(matches("pr", &id));
        assert("pr", id).unwrap();
    }
}
<|endoftext|>


<commit_before>//! This module contains a re-export or vendored version of `core::mem::MaybeUninit` depending
//! on which Rust version it's compiled for.
//!
//! Remove this module and use `core::mem::MaybeUninit` directly when dropping support for <1.36
#![allow(dead_code)]

#[cfg(has_maybe_uninit)]
pub use core::mem::MaybeUninit;

#[cfg(not(has_maybe_uninit))]
use core::mem::ManuallyDrop;

/// Copied from `core::mem::MaybeUninit` to support Rust older than 1.36
#[cfg(not(has_maybe_uninit))]
pub union MaybeUninit<T: Copy> {
    uninit: (),
    value: ManuallyDrop<T>,
}

#[cfg(not(has_maybe_uninit))]
impl<T: Copy> MaybeUninit<T> {
    #[inline(always)]
    pub fn uninit() -> MaybeUninit<T> {
        MaybeUninit { uninit: () }
    }

    #[inline(always)]
    pub fn as_ptr(&self) -> *const T {
        unsafe { &*self.value as *const T }
    }

    #[inline(always)]
    pub fn as_mut_ptr(&mut self) -> *mut T {
        unsafe { &mut *self.value as *mut T }
    }

    #[inline(always)]
    pub unsafe fn assume_init(self) -> T {
        ManuallyDrop::into_inner(self.value)
    }
}
<commit_msg>Use normal #[inline] instead of with (always)<commit_after>//! This module contains a re-export or vendored version of `core::mem::MaybeUninit` depending
//! on which Rust version it's compiled for.
//!
//! Remove this module and use `core::mem::MaybeUninit` directly when dropping support for <1.36
#![allow(dead_code)]

#[cfg(has_maybe_uninit)]
pub use core::mem::MaybeUninit;

#[cfg(not(has_maybe_uninit))]
use core::mem::ManuallyDrop;

/// Copied from `core::mem::MaybeUninit` to support Rust older than 1.36
#[cfg(not(has_maybe_uninit))]
pub union MaybeUninit<T: Copy> {
    uninit: (),
    value: ManuallyDrop<T>,
}

#[cfg(not(has_maybe_uninit))]
impl<T: Copy> MaybeUninit<T> {
    #[inline]
    pub fn uninit() -> MaybeUninit<T> {
        MaybeUninit { uninit: () }
    }

    #[inline]
    pub fn as_ptr(&self) -> *const T {
        unsafe { &*self.value as *const T }
    }

    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut T {
        unsafe { &mut *self.value as *mut T }
    }

    #[inline]
    pub unsafe fn assume_init(self) -> T {
        ManuallyDrop::into_inner(self.value)
    }
}
<|endoftext|>


<commit_before>use crate::{Class, Type, TypeKind};
use std::{
    borrow::Cow,
    collections::BTreeMap,
    io::{Result, Write},
};

fn get_type(ty: &Type) -> Cow<'_, str> {
    let mut name = Cow::Borrowed(match ty.name.as_str() {
        "i8" => "int8_t",
        "i16" => "int16_t",
        "i32" => "int32_t",
        "i64" => "int64_t",
        "u8" => "uint8_t",
        "u16" => "uint16_t",
        "u32" => "uint32_t",
        "u64" => "uint64_t",
        "usize" => "size_t",
        "isize" => "ssize_t",
        "f32" => "float",
        "f64" => "double",
        "bool" => "bool",
        "()" => "void",
        "c_char" => "char",
        "Json" => "char const*",
        x => x,
    });
    match (ty.is_custom, ty.kind) {
        (false, TypeKind::RefMut) => name.to_mut().push_str("*restrict"),
        (false, TypeKind::Ref) => name.to_mut().push_str(" const*"),
        (true, TypeKind::RefMut) => name.to_mut().push_str("RefMut"),
        (true, TypeKind::Ref) => name.to_mut().push_str("Ref"),
        _ => (),
    }
    if name == "uint8_t const*" {
        name = Cow::Borrowed("void const*");
    }
    name
}

pub fn write<W: Write>(mut writer: W, classes: &BTreeMap<String, Class>) -> Result<()> {
    write!(
        writer,
        "{}",
        r#"#ifndef LIVESPLIT_CORE_H
#define LIVESPLIT_CORE_H

#ifdef __cplusplus
#define restrict __restrict
namespace LiveSplit {
extern "C" {
#endif

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

"#
    )?;

    for name in classes.keys() {
        writeln!(
            writer,
            r#"struct {0}_s;
typedef struct {0}_s *restrict {0};
typedef struct {0}_s *restrict {0}RefMut;
typedef struct {0}_s const* {0}Ref;
"#,
            name
        )?;
    }

    for class in classes.values() {
        writeln!(writer, "")?;

        for function in class
            .static_fns
            .iter()
            .chain(class.own_fns.iter())
            .chain(class.shared_fns.iter())
            .chain(class.mut_fns.iter())
        {
            if function.method == "drop" {
                writeln!(
                    writer,
                    r#"/**
Frees the object, allowing it to clean up all of its memory. You need
to call this for every object that you don't use anymore and hasn't
already been freed.
*/"#
                )?;
            } else if !function.comments.is_empty() {
                write!(writer, r#"/**"#)?;

                for comment in &function.comments {
                    write!(
                        writer,
                        r#"
{}"#,
                        comment
                            .replace("<NULL>", "NULL")
                            .replace("<TRUE>", "true")
                            .replace("<FALSE>", "false")
                    )?;
                }

                writeln!(
                    writer,
                    r#"
*/"#
                )?;
            }

            write!(
                writer,
                r#"{} {}("#,
                get_type(&function.output),
                function.name
            )?;

            for (i, (name, typ)) in function.inputs.iter().enumerate() {
                if i != 0 {
                    write!(writer, ", ")?;
                }
                write!(
                    writer,
                    "{} {}",
                    get_type(typ),
                    if name == "this" { "self" } else { name }
                )?;
            }
            if function.inputs.is_empty() {
                write!(writer, "void")?;
            }

            writeln!(writer, ");")?;
        }
    }

    write!(
        writer,
        "{}",
        r#"
#ifdef __cplusplus
}
}
#endif

#endif
"#
    )
}
<commit_msg>Add fallback for the restrict keyword being unavailable to bind_gen<commit_after>use crate::{Class, Type, TypeKind};
use std::{
    borrow::Cow,
    collections::BTreeMap,
    io::{Result, Write},
};

fn get_type(ty: &Type) -> Cow<'_, str> {
    let mut name = Cow::Borrowed(match ty.name.as_str() {
        "i8" => "int8_t",
        "i16" => "int16_t",
        "i32" => "int32_t",
        "i64" => "int64_t",
        "u8" => "uint8_t",
        "u16" => "uint16_t",
        "u32" => "uint32_t",
        "u64" => "uint64_t",
        "usize" => "size_t",
        "isize" => "ssize_t",
        "f32" => "float",
        "f64" => "double",
        "bool" => "bool",
        "()" => "void",
        "c_char" => "char",
        "Json" => "char const*",
        x => x,
    });
    match (ty.is_custom, ty.kind) {
        (false, TypeKind::RefMut) => name.to_mut().push_str("*restrict"),
        (false, TypeKind::Ref) => name.to_mut().push_str(" const*"),
        (true, TypeKind::RefMut) => name.to_mut().push_str("RefMut"),
        (true, TypeKind::Ref) => name.to_mut().push_str("Ref"),
        _ => (),
    }
    if name == "uint8_t const*" {
        name = Cow::Borrowed("void const*");
    }
    name
}

pub fn write<W: Write>(mut writer: W, classes: &BTreeMap<String, Class>) -> Result<()> {
    write!(
        writer,
        "{}",
        r#"#ifndef LIVESPLIT_CORE_H
#define LIVESPLIT_CORE_H

/**
Most C/C++ compilers support __restrict, and it's been standardized in C99 by
adding the restrict keyword.
If not compiled in C99 (or higher) modes, try to use __restrict instead.
*/
#if __STDC_VERSION__ < 199901L
#define restrict __restrict
#endif

#ifdef __cplusplus
namespace LiveSplit {
extern "C" {
#endif

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

"#
    )?;

    for name in classes.keys() {
        writeln!(
            writer,
            r#"struct {0}_s;
typedef struct {0}_s *restrict {0};
typedef struct {0}_s *restrict {0}RefMut;
typedef struct {0}_s const* {0}Ref;
"#,
            name
        )?;
    }

    for class in classes.values() {
        writeln!(writer, "")?;

        for function in class
            .static_fns
            .iter()
            .chain(class.own_fns.iter())
            .chain(class.shared_fns.iter())
            .chain(class.mut_fns.iter())
        {
            if function.method == "drop" {
                writeln!(
                    writer,
                    r#"/**
Frees the object, allowing it to clean up all of its memory. You need
to call this for every object that you don't use anymore and hasn't
already been freed.
*/"#
                )?;
            } else if !function.comments.is_empty() {
                write!(writer, r#"/**"#)?;

                for comment in &function.comments {
                    write!(
                        writer,
                        r#"
{}"#,
                        comment
                            .replace("<NULL>", "NULL")
                            .replace("<TRUE>", "true")
                            .replace("<FALSE>", "false")
                    )?;
                }

                writeln!(
                    writer,
                    r#"
*/"#
                )?;
            }

            write!(
                writer,
                r#"{} {}("#,
                get_type(&function.output),
                function.name
            )?;

            for (i, (name, typ)) in function.inputs.iter().enumerate() {
                if i != 0 {
                    write!(writer, ", ")?;
                }
                write!(
                    writer,
                    "{} {}",
                    get_type(typ),
                    if name == "this" { "self" } else { name }
                )?;
            }
            if function.inputs.is_empty() {
                write!(writer, "void")?;
            }

            writeln!(writer, ");")?;
        }
    }

    write!(
        writer,
        "{}",
        r#"
#ifdef __cplusplus
}
}
#endif

#endif
"#
    )
}
<|endoftext|>


<commit_before>use std::{
    collections::HashMap,
    fs,
    path::{Path, PathBuf},
};

use clap::{App, Arg, SubCommand};
use failure::bail;

use tools::{collect_tests, generate, run, run_rustfmt, Mode, Overwrite, Result, Test, Verify};

const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar";
const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline";

fn main() -> Result<()> {
    let matches = App::new("tasks")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .arg(
            Arg::with_name("verify")
                .long("--verify")
                .help("Verify that generated code is up-to-date")
                .global(true),
        )
        .subcommand(SubCommand::with_name("gen-syntax"))
        .subcommand(SubCommand::with_name("gen-tests"))
        .subcommand(SubCommand::with_name("install-code"))
        .subcommand(SubCommand::with_name("format"))
        .get_matches();
    let mode = if matches.is_present("verify") {
        Verify
    } else {
        Overwrite
    };
    match matches.subcommand() {
        ("install-code", _) => install_code_extension()?,
        ("gen-tests", _) => gen_tests(mode)?,
        ("gen-syntax", _) => generate(Overwrite)?,
        ("format", _) => run_rustfmt(Overwrite)?,
        _ => unreachable!(),
    }
    Ok(())
}

fn gen_tests(mode: Mode) -> Result<()> {
    let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?;

    let inline_tests_dir = Path::new(INLINE_TESTS_DIR);
    if !inline_tests_dir.is_dir() {
        fs::create_dir_all(inline_tests_dir)?;
    }
    let existing = existing_tests(inline_tests_dir)?;

    for t in existing.keys().filter(|&t| !tests.contains_key(t)) {
        panic!("Test is deleted: {}", t);
    }

    let mut new_idx = existing.len() + 2;
    for (name, test) in tests {
        let path = match existing.get(&name) {
            Some((path, _test)) => path.clone(),
            None => {
                let file_name = format!("{:04}_{}.rs", new_idx, name);
                new_idx += 1;
                inline_tests_dir.join(file_name)
            }
        };
        teraron::update(&path, &test.text, mode)?;
    }
    Ok(())
}

fn tests_from_dir(dir: &Path) -> Result<HashMap<String, Test>> {
    let mut res = HashMap::new();
    for entry in ::walkdir::WalkDir::new(dir) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue;
        }
        if entry.path().extension().unwrap_or_default() != "rs" {
            continue;
        }
        let text = fs::read_to_string(entry.path())?;

        for (_, test) in collect_tests(&text) {
            if let Some(old_test) = res.insert(test.name.clone(), test) {
                bail!("Duplicate test: {}", old_test.name)
            }
        }
    }
    Ok(res)
}

fn existing_tests(dir: &Path) -> Result<HashMap<String, (PathBuf, Test)>> {
    let mut res = HashMap::new();
    for file in fs::read_dir(dir)? {
        let file = file?;
        let path = file.path();
        if path.extension().unwrap_or_default() != "rs" {
            continue;
        }
        let name = {
            let file_name = path.file_name().unwrap().to_str().unwrap();
            file_name[5..file_name.len() - 3].to_string()
        };
        let text = fs::read_to_string(&path)?;
        let test = Test {
            name: name.clone(),
            text,
        };
        if let Some(old) = res.insert(name, (path, test)) {
            println!("Duplicate test: {:?}", old);
        }
    }
    Ok(res)
}

fn install_code_extension() -> Result<()> {
    run("cargo install --path crates/ra_lsp_server --force", ".")?;
    if cfg!(windows) {
        run(r"cmd.exe /c npm.cmd install", "./editors/code")?;
    } else {
        run(r"npm install", "./editors/code")?;
    }
    run(
        r"node ./node_modules/vsce/out/vsce package",
        "./editors/code",
    )?;
    if cfg!(windows) {
        run(
            r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix",
            "./editors/code",
        )?;
    } else {
        run(
            r"code --install-extension ./ra-lsp-0.0.1.vsix",
            "./editors/code",
        )?;
    }
    Ok(())
}
<commit_msg>account for new layout when collecting tests<commit_after>use std::{
    collections::HashMap,
    fs,
    path::{Path, PathBuf},
};

use clap::{App, Arg, SubCommand};
use failure::bail;

use tools::{collect_tests, generate, run, run_rustfmt, Mode, Overwrite, Result, Test, Verify};

const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar";
const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline";

fn main() -> Result<()> {
    let matches = App::new("tasks")
        .setting(clap::AppSettings::SubcommandRequiredElseHelp)
        .arg(
            Arg::with_name("verify")
                .long("--verify")
                .help("Verify that generated code is up-to-date")
                .global(true),
        )
        .subcommand(SubCommand::with_name("gen-syntax"))
        .subcommand(SubCommand::with_name("gen-tests"))
        .subcommand(SubCommand::with_name("install-code"))
        .subcommand(SubCommand::with_name("format"))
        .get_matches();
    let mode = if matches.is_present("verify") {
        Verify
    } else {
        Overwrite
    };
    match matches.subcommand() {
        ("install-code", _) => install_code_extension()?,
        ("gen-tests", _) => gen_tests(mode)?,
        ("gen-syntax", _) => generate(Overwrite)?,
        ("format", _) => run_rustfmt(Overwrite)?,
        _ => unreachable!(),
    }
    Ok(())
}

fn gen_tests(mode: Mode) -> Result<()> {
    let tests = tests_from_dir(Path::new(GRAMMAR_DIR))?;

    let inline_tests_dir = Path::new(INLINE_TESTS_DIR);
    if !inline_tests_dir.is_dir() {
        fs::create_dir_all(inline_tests_dir)?;
    }
    let existing = existing_tests(inline_tests_dir)?;

    for t in existing.keys().filter(|&t| !tests.contains_key(t)) {
        panic!("Test is deleted: {}", t);
    }

    let mut new_idx = existing.len() + 2;
    for (name, test) in tests {
        let path = match existing.get(&name) {
            Some((path, _test)) => path.clone(),
            None => {
                let file_name = format!("{:04}_{}.rs", new_idx, name);
                new_idx += 1;
                inline_tests_dir.join(file_name)
            }
        };
        teraron::update(&path, &test.text, mode)?;
    }
    Ok(())
}

fn tests_from_dir(dir: &Path) -> Result<HashMap<String, Test>> {
    let mut res = HashMap::new();
    for entry in ::walkdir::WalkDir::new(dir) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue;
        }
        if entry.path().extension().unwrap_or_default() != "rs" {
            continue;
        }
        process_file(&mut res, entry.path())?;
    }
    let grammar_rs = dir.parent().unwrap().join("grammar.rs");
    process_file(&mut res, &grammar_rs)?;
    return Ok(res);
    fn process_file(res: &mut HashMap<String, Test>, path: &Path) -> Result<()> {
        let text = fs::read_to_string(path)?;

        for (_, test) in collect_tests(&text) {
            if let Some(old_test) = res.insert(test.name.clone(), test) {
                bail!("Duplicate test: {}", old_test.name)
            }
        }
        Ok(())
    }
}

fn existing_tests(dir: &Path) -> Result<HashMap<String, (PathBuf, Test)>> {
    let mut res = HashMap::new();
    for file in fs::read_dir(dir)? {
        let file = file?;
        let path = file.path();
        if path.extension().unwrap_or_default() != "rs" {
            continue;
        }
        let name = {
            let file_name = path.file_name().unwrap().to_str().unwrap();
            file_name[5..file_name.len() - 3].to_string()
        };
        let text = fs::read_to_string(&path)?;
        let test = Test {
            name: name.clone(),
            text,
        };
        if let Some(old) = res.insert(name, (path, test)) {
            println!("Duplicate test: {:?}", old);
        }
    }
    Ok(res)
}

fn install_code_extension() -> Result<()> {
    run("cargo install --path crates/ra_lsp_server --force", ".")?;
    if cfg!(windows) {
        run(r"cmd.exe /c npm.cmd install", "./editors/code")?;
    } else {
        run(r"npm install", "./editors/code")?;
    }
    run(
        r"node ./node_modules/vsce/out/vsce package",
        "./editors/code",
    )?;
    if cfg!(windows) {
        run(
            r"cmd.exe /c code.cmd --install-extension ./ra-lsp-0.0.1.vsix",
            "./editors/code",
        )?;
    } else {
        run(
            r"code --install-extension ./ra-lsp-0.0.1.vsix",
            "./editors/code",
        )?;
    }
    Ok(())
}
<|endoftext|>