<commit_before>//! Handles encoding of a Bitterlemon image

extern crate arrayvec;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Run {
	Set(u8),
	Clear(u8)
}

impl Into<u8> for Run {
	fn into(self) -> u8 {

		use self::Run::*;

		match self {
			Set(n)   => {
				assert!(n <= RLE_MAX_RUN);
				let n_out = if n == RLE_MAX_RUN {0u8} else {n};
				0xc0u8 + n_out
			},
			Clear(n) => {
				assert!(n <= RLE_MAX_RUN);
				let n_out = if n == RLE_MAX_RUN {0u8} else {n};
				0x80u8 + n_out
			},
		}

	}
}

#[derive(Debug)]
pub struct RunIterator<S> {
	state: Option<Run>,
	source: S,
}

fn rle_new_run(pp: bool) -> Run {
	if pp {Run::Set(1)} else {Run::Clear(1)}
}

const RLE_MAX_RUN: u8 = 64;

impl<S: Iterator<Item=bool>> RunIterator<S> {

	pub fn from_pixels(source: S) -> RunIterator<S> {
		RunIterator {
			state: None,
			source: source
		}
	}
}

impl<S: Iterator<Item=bool>> Iterator for RunIterator<S> {
	type Item = Run;

	fn next(&mut self) -> Option<Run> {
		use self::Run::*;
		loop {

			// Grab next bit from source; early return if None upstream
			let pp = match self.source.next() {
				Some(b) => b,
				None    => return match self.state {
					Some(x) => {
						// Push out current state and clear for next time
						let old = x;
						self.state = None;
						Some(old)
					},
					// All done
					None => None
				}
			};

			match self.state {

				// Can't fit any more in this run
				Some(Set(RLE_MAX_RUN)) => {
					self.state = Some(rle_new_run(pp));
					return Some(Set(RLE_MAX_RUN));
				},

				// Can't fit any more in this run
				Some(Clear(RLE_MAX_RUN)) => {
					self.state = Some(rle_new_run(pp));
					return Some(Clear(RLE_MAX_RUN));
				}

				// Increase existing Set run
				Some(Set(count)) if pp => {
					self.state = Some(Set(count + 1));
					continue;
				},

				// Swap from Set to Clear
				Some(Set(_)) if ! pp => {
					let old = self.state;
					self.state = Some(Clear(1));
					return old;
				},

				// Increase existing Clear run
				Some(Clear(count)) if ! pp => {
					self.state = Some(Clear(count + 1));
					continue;
				},

				// Swap from Clear to Set
				Some(Clear(_)) if pp => {
					let old = self.state;
					self.state = Some(Set(1));
					return old;
				},

				// All cases covered, but can't convince rustc
				Some(_) => {
					unreachable!();
				}

				None => {
					self.state = Some(rle_new_run(pp));
					continue;
				}
			}

		}

	}
}

type RunHolding = arrayvec::ArrayVec<[Run; 128]>;

#[derive(Debug, PartialEq, Eq)]
pub struct WithFrames<S> {
	runs: RunHolding,
	source: S
}

impl<S: Iterator<Item=Run>> WithFrames<S> {
	pub fn new(source: S) -> WithFrames<S> {
		WithFrames {
			runs: RunHolding::new(),
			source: source,
		}
	}
}

fn bytes_as_frame(runs: &RunHolding) -> usize {
	let total_bits: usize = runs.iter().map(|&run| match run {
		Run::Set(x) => x as usize,
		Run::Clear(x) => x as usize,
	}).sum();

	(total_bits + 15) >> 3 // round up to next byte, add header
}

fn bytes_as_runs(runs: &RunHolding) -> usize {
	// runs in bytes are next highest multiples of 64
	runs.iter().map(|&run| {
		let found = match run {
			Run::Set(x) => x,
			Run::Clear(x) => x,
		};
		debug_assert!(found > 0);
		(found + 63) >> 6
	} as usize).sum()
}

#[cfg(test)]
mod test_frame_sizer {

	use super::*;
	use super::Run::*;

	fn op(input: &[Run], frame_size: usize, run_size: usize) {
		let mut builder = RunHolding::new();

		for element in input {
			assert_eq!(None, builder.push(element.clone()));
		}

		assert_eq!(frame_size, bytes_as_frame(&builder));
		assert_eq!(run_size, bytes_as_runs(&builder));
	}

	#[test]
	fn empty() {
		op(&[], 1, 0);
	}

	#[test]
	fn single_set() {
		op(&[Set(1)], 2, 1);
	}

	#[test]
	fn single_clear() {
		op(&[Clear(1)], 2, 1);
	}
	#[test]
	fn enough_to_overflow_a_frame_to_2_post_header_bytes() {
		op(&[Set(5), Clear(5)], 3, 2);
	}

	#[test]
	fn can_pack_3_runs_into_a_single_frame_byte() {
		op(&[Clear(3), Set(2), Clear(3)], 2, 3);
	}
}

impl<S> Iterator for WithFrames<S> {
	type Item = u8;

	fn next(&mut self) -> Option<Self::Item> {
		unimplemented!();
	}

}

#[cfg(test)]
mod test_runs {

	use std::iter::Iterator;

	use super::{Run, RunIterator};
	use super::Run::*;

	#[test]
	fn runs() {

		let op = |input: &[u8], output: &[Run]| {

			let bool_stream : Vec<bool> = input.iter().map(|&c| c == b'1').collect();
			let collected : Vec<Run> = RunIterator::from_pixels(bool_stream.iter().map(|&b| b)).collect();

			assert_eq!(output, collected.as_slice());
		};

		// simple single runs
		op(b"1", &[Set(1)]);
		op(b"1111", &[Set(4)]);
		op(b"00", &[Clear(2)]);
		op(b"", &[]);

		// alterations
		op(b"011", &[Clear(1), Set(2)]);
		op(b"110", &[Set(2), Clear(1)]);
		op(b"0101", &[Clear(1), Set(1), Clear(1), Set(1)]);

		// run size limits
		let large_set = [b'1'; (super::RLE_MAX_RUN + 1) as usize];
		op(&large_set, &[Set(super::RLE_MAX_RUN), Set(1)]);

		// clear size limits
		let large_clear = [b'0' ; (super::RLE_MAX_RUN + 1) as usize];
		op(&large_clear, &[Clear(super::RLE_MAX_RUN), Clear(1)]);
	}
}

<commit_msg>Easily extract the size of a Run<commit_after>//! Handles encoding of a Bitterlemon image

extern crate arrayvec;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Run {
	Set(u8),
	Clear(u8)
}

impl Run {
	fn size(&self) -> u8 {
		match *self {
			Run::Set(x) => x,
			Run::Clear(x) => x,
		}
	}

	fn size_mut<'a>(&'a mut self) -> &'a mut u8 {
		match *self {
			Run::Set(ref mut x) => x,
			Run::Clear(ref mut x) => x,
		}
	}
}

#[cfg(test)]
mod run_tests {

	use super::Run::*;

	#[test]
	fn size() {
		assert_eq!(50, Set(50).size());
		assert_eq!(50, Clear(50).size());
		assert_eq!(Set(50).size(), Clear(50).size());
	}

	#[test]
	fn size_mut() {
		macro_rules! implement {
			($e:ident) => (
				let mut run = super::Run::$e(20);
				assert_eq!(20, *run.size_mut());

				*run.size_mut() += 2;
				assert_eq!($e(22), run);
			)
		}

		implement!(Set);
		implement!(Clear);
	}
}

impl Into<u8> for Run {
	fn into(self) -> u8 {

		use self::Run::*;

		match self {
			Set(n)   => {
				assert!(n <= RLE_MAX_RUN);
				let n_out = if n == RLE_MAX_RUN {0u8} else {n};
				0xc0u8 + n_out
			},
			Clear(n) => {
				assert!(n <= RLE_MAX_RUN);
				let n_out = if n == RLE_MAX_RUN {0u8} else {n};
				0x80u8 + n_out
			},
		}

	}
}

#[derive(Debug)]
pub struct RunIterator<S> {
	state: Option<Run>,
	source: S,
}

fn rle_new_run(pp: bool) -> Run {
	if pp {Run::Set(1)} else {Run::Clear(1)}
}

const RLE_MAX_RUN: u8 = 64;

impl<S: Iterator<Item=bool>> RunIterator<S> {

	pub fn from_pixels(source: S) -> RunIterator<S> {
		RunIterator {
			state: None,
			source: source
		}
	}
}

impl<S: Iterator<Item=bool>> Iterator for RunIterator<S> {
	type Item = Run;

	fn next(&mut self) -> Option<Run> {
		use self::Run::*;
		loop {

			// Grab next bit from source; early return if None upstream
			let pp = match self.source.next() {
				Some(b) => b,
				None    => return match self.state {
					Some(x) => {
						// Push out current state and clear for next time
						let old = x;
						self.state = None;
						Some(old)
					},
					// All done
					None => None
				}
			};

			match self.state {

				// Can't fit any more in this run
				Some(Set(RLE_MAX_RUN)) => {
					self.state = Some(rle_new_run(pp));
					return Some(Set(RLE_MAX_RUN));
				},

				// Can't fit any more in this run
				Some(Clear(RLE_MAX_RUN)) => {
					self.state = Some(rle_new_run(pp));
					return Some(Clear(RLE_MAX_RUN));
				}

				// Increase existing Set run
				Some(Set(count)) if pp => {
					self.state = Some(Set(count + 1));
					continue;
				},

				// Swap from Set to Clear
				Some(Set(_)) if ! pp => {
					let old = self.state;
					self.state = Some(Clear(1));
					return old;
				},

				// Increase existing Clear run
				Some(Clear(count)) if ! pp => {
					self.state = Some(Clear(count + 1));
					continue;
				},

				// Swap from Clear to Set
				Some(Clear(_)) if pp => {
					let old = self.state;
					self.state = Some(Set(1));
					return old;
				},

				// All cases covered, but can't convince rustc
				Some(_) => {
					unreachable!();
				}

				None => {
					self.state = Some(rle_new_run(pp));
					continue;
				}
			}

		}

	}
}

type RunHolding = arrayvec::ArrayVec<[Run; 128]>;

#[derive(Debug, PartialEq, Eq)]
pub struct WithFrames<S> {
	runs: RunHolding,
	source: S
}

impl<S: Iterator<Item=Run>> WithFrames<S> {
	pub fn new(source: S) -> WithFrames<S> {
		WithFrames {
			runs: RunHolding::new(),
			source: source,
		}
	}
}

fn bytes_as_frame(runs: &RunHolding) -> usize {
	let total_bits: usize = runs.iter().map(|&run| match run {
		Run::Set(x) => x as usize,
		Run::Clear(x) => x as usize,
	}).sum();

	(total_bits + 15) >> 3 // round up to next byte, add header
}

fn bytes_as_runs(runs: &RunHolding) -> usize {
	// runs in bytes are next highest multiples of 64
	runs.iter().map(|&run| {
		let found = match run {
			Run::Set(x) => x,
			Run::Clear(x) => x,
		};
		debug_assert!(found > 0);
		(found + 63) >> 6
	} as usize).sum()
}

#[cfg(test)]
mod test_frame_sizer {

	use super::*;
	use super::Run::*;

	fn op(input: &[Run], frame_size: usize, run_size: usize) {
		let mut builder = RunHolding::new();

		for element in input {
			assert_eq!(None, builder.push(element.clone()));
		}

		assert_eq!(frame_size, bytes_as_frame(&builder));
		assert_eq!(run_size, bytes_as_runs(&builder));
	}

	#[test]
	fn empty() {
		op(&[], 1, 0);
	}

	#[test]
	fn single_set() {
		op(&[Set(1)], 2, 1);
	}

	#[test]
	fn single_clear() {
		op(&[Clear(1)], 2, 1);
	}
	#[test]
	fn enough_to_overflow_a_frame_to_2_post_header_bytes() {
		op(&[Set(5), Clear(5)], 3, 2);
	}

	#[test]
	fn can_pack_3_runs_into_a_single_frame_byte() {
		op(&[Clear(3), Set(2), Clear(3)], 2, 3);
	}
}

impl<S> Iterator for WithFrames<S> {
	type Item = u8;

	fn next(&mut self) -> Option<Self::Item> {
		unimplemented!();
	}

}

#[cfg(test)]
mod test_runs {

	use std::iter::Iterator;

	use super::{Run, RunIterator};
	use super::Run::*;

	#[test]
	fn runs() {

		let op = |input: &[u8], output: &[Run]| {

			let bool_stream : Vec<bool> = input.iter().map(|&c| c == b'1').collect();
			let collected : Vec<Run> = RunIterator::from_pixels(bool_stream.iter().map(|&b| b)).collect();

			assert_eq!(output, collected.as_slice());
		};

		// simple single runs
		op(b"1", &[Set(1)]);
		op(b"1111", &[Set(4)]);
		op(b"00", &[Clear(2)]);
		op(b"", &[]);

		// alterations
		op(b"011", &[Clear(1), Set(2)]);
		op(b"110", &[Set(2), Clear(1)]);
		op(b"0101", &[Clear(1), Set(1), Clear(1), Set(1)]);

		// run size limits
		let large_set = [b'1'; (super::RLE_MAX_RUN + 1) as usize];
		op(&large_set, &[Set(super::RLE_MAX_RUN), Set(1)]);

		// clear size limits
		let large_clear = [b'0' ; (super::RLE_MAX_RUN + 1) as usize];
		op(&large_clear, &[Clear(super::RLE_MAX_RUN), Clear(1)]);
	}
}

<|endoftext|>


<commit_before>// Rx -- Reactive programming for Rust
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate rx;

use rx::{Never, Observable, Observer, Subject};
use std::cell::RefCell;
use std::rc::Rc;

// Generator tests

#[test]
fn never() {
    let mut never = Never::new();
    let _subscription = never.subscribe_error(
        |_x: u8| panic!("never observable should not produce a value"),
        || panic!("never observable should not complete"),
        |_err: ()| panic!("never observable should not fail")
    );

    // Without something like a message loop, the observable cannot suddenly
    // start pushing values, so if it did not produce anything here, it never
    // will.
}

// Option tests

#[test]
fn option_subscribe_next() {
    let mut received = None;

    // Subscribing to `Some` should push the value.
    Some(19).subscribe_next(|x| received = Some(x));
    assert_eq!(Some(19), received);

    None.subscribe_next(|_x: u32| panic!("none should not push a value"));
}

#[test]
fn option_subscribe_completed() {
    let mut received = None;
    let mut completed = false;

    // Subscribing to `Some` should complete after pushing the value.
    Some(19).subscribe_completed(|x| received = Some(x), || completed = true);
    assert_eq!(Some(19), received);
    assert!(completed);

    // Subscribing to `None` should complete without pushing a value.
    completed = false;
    None.subscribe_completed(
        |_x: u32| panic!("none should not push a value"),
        || completed = true
    );
    assert!(completed);
}

#[test]
fn option_subscribe_error() {
    let mut received = None;
    let mut completed = false;

    Some(23).subscribe_error(
        |x| received = Some(x),
        || completed = true,
        |_err| panic!("some observable should not fail")
    );
    assert_eq!(Some(23), received);
    assert!(completed);

    completed = false;
    None.subscribe_error(
        |_x: u32| panic!("none should not push a value"),
        || completed = true,
        |_err| panic!("none observable should not fail")
    );
    assert!(completed);
}

// Result tests

#[test]
fn result_subscribe_next_ok() {
    let mut result: Result<u32, ()> = Ok(13);
    let mut received = None;
    result.subscribe_next(|x| received = Some(x));
    assert_eq!(Some(13), received);
}

#[test]
#[should_panic]
fn result_subscribe_next_err() {
    let mut result: Result<u32, ()> = Err(());
    let mut received = None;

    // This should panic, because we did not provide an error handler.
    result.subscribe_next(|x| received = Some(x));
}

#[test]
fn result_subscribe_completed_ok() {
    let mut result: Result<u32, ()> = Ok(13);
    let mut received = None;
    let mut completed = false;
    result.subscribe_completed(|x| received = Some(x), || completed = true);
    assert_eq!(Some(13), received);
    assert!(completed);
}

#[test]
fn result_subscribe_error_ok() {
    let mut result: Result<u32, ()> = Ok(13);
    let mut received = None;
    let mut completed = false;
    result.subscribe_error(
        |x| received = Some(x),
        || completed = true,
        |_err| panic!("ok result should not be a failing observable")
    );
    assert_eq!(Some(13), received);
    assert!(completed);
}

#[test]
fn result_subscribe_error_err() {
    let mut result: Result<(), u32> = Err(17);
    let mut error = None;
    result.subscribe_error(
        |_x| panic!("err result should not push a value"),
        || panic!("err result should not complete"),
        |err| error = Some(err)
    );
    assert_eq!(Some(17), error);
}

// Slice tests

#[test]
fn slice_subscribe_next() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    values.subscribe_next(|&x| received.push(x));
    assert_eq!(&values[..], &received[..]);
}

#[test]
fn slice_subscribe_completed() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    let mut completed = false;
    values.subscribe_completed(|&x| received.push(x), || completed = true);
    assert_eq!(&values[..], &received[..]);
    assert!(completed);
}

#[test]
fn slice_subscribe_error() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    let mut completed = false;
    let mut failed = false;
    values.subscribe_error(|&x| received.push(x), || completed = true, |_err| failed = true);
    assert_eq!(&values[..], &received[..]);
    assert!(completed);
    assert!(!failed);
}

#[test]
fn slice_subscribe_option() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let expected = &[Some(2u8), Some(3), Some(5), Some(7), Some(11), Some(13), None];
    let mut received = Vec::new();
    values.subscribe_option(|x| received.push(x.cloned()));
    assert_eq!(&received[..], &expected[..]);
}

#[test]
fn slice_subscribe_result() {
    let mut values = &[2u8, 3, 5, 7];
    let expected = &[Ok(Some(2u8)), Ok(Some(3)), Ok(Some(5)), Ok(Some(7)), Ok(None)];
    let mut received = Vec::new();
    values.subscribe_result(|x| received.push(x.map(|y| y.cloned())));
    assert_eq!(&received[..], &expected[..]);
}

// Subject tests

#[test]
fn subject_on_next() {
    let mut subject = Subject::<u8, ()>::new();
    let mut received = Vec::new();
    let _subscription = subject.observable().subscribe_next(|x| received.push(x));

    // Subject should not push anything upon subscription.
    assert_eq!(0, received.len());

    let values = &[2u8, 3, 5, 7, 11, 13];
    for i in 0..values.len() {
        subject.on_next(values[i]);
        assert_eq!(&values[..i + 1], &received[..]);
    }
}

#[test]
fn subject_on_completed() {
    let mut subject = Subject::<u8, ()>::new();
    let mut completed = false;
    let _subscription = subject.observable().subscribe_completed(
        |_x| panic!("no value should be pushed"),
        || completed = true
    );

    // Subject should not push anything upon subscription.
    assert!(!completed);

    subject.on_completed();
    assert!(completed);
}

#[test]
fn subject_on_error() {
    let mut subject = Subject::<u8, u8>::new();
    let mut error = 0;
    let _subscription = subject.observable().subscribe_error(
        |_x| panic!("no value should be pushed"),
        || panic!("subject should not complete"),
        |err| error = err
    );

    // Subject should not fail upon subscription.
    assert_eq!(0, error);

    subject.on_error(41);
    assert_eq!(41, error);
}

/// Helper for the `subject_clones_once_per_observer()` test.
struct CloneCounter {
    counter: Rc<RefCell<u32>>,
}

impl Clone for CloneCounter {
    fn clone(&self) -> CloneCounter {
        let count: u32 = *self.counter.borrow();
        *self.counter.borrow_mut() = count + 1;
        CloneCounter {
            counter: self.counter.clone(),
        }
    }
}

#[test]
fn subject_clones_once_per_observer() {
    let mut subject = Subject::<CloneCounter, ()>::new();
    let mut first_called = false;
    let mut second_called = false;
    let counter = CloneCounter {
        counter: Rc::new(RefCell::new(0)),
    };

    // Subscribe twice.
    let _s1 = subject.observable().subscribe_next(|_x| first_called = true);
    let _s2 = subject.observable().subscribe_next(|_x| second_called = true);

    // Nothing should have been cloned yet.
    assert_eq!(0, *counter.counter.borrow());

    subject.on_next(counter.clone());

    // We cloned once, and the subject should have cloned once per subscription.
    assert_eq!(3, *counter.counter.borrow());
    assert!(first_called);
    assert!(second_called);
}

#[test]
fn subject_drop_subscription() {
    let mut subject = Subject::<u8, ()>::new();
    let mut received = Vec::new();
    let subscription = subject.observable().subscribe_next(|x| received.push(x));

    subject.on_next(2);
    subject.on_next(3);
    subject.on_next(5);

    assert_eq!(&[2u8, 3, 5], &received[..]);

    drop(subscription);

    subject.on_next(7);
    subject.on_next(11);

    // Values pushed after drop should not have been invoked.
    assert_eq!(&[2u8, 3, 5], &received[..]);
}

#[test]
fn subject_drop_subscription_multi() {
    let mut subject = Subject::<u8, ()>::new();
    let mut received = Vec::new();
    let _s1 = subject.observable().subscribe_next(|x| received.push(x));
    let s2 = subject.observable().subscribe_error(
        |_x| panic!("no value should be pushed after dropping subscription"),
        || panic!("completion should not be signalled after dropping subscription"),
        |_err| panic!("failure should not be signalled after dropping subscription")
    );

    drop(s2);

    subject.on_next(2);
    subject.on_next(3);
    subject.on_next(5);
    subject.on_completed();

    assert_eq!(&[2u8, 3, 5], &received[..]);
}

// TODO: Test multiple subscriptions and combinations of values and completed/error.
// TODO: Add better tests for dropping the subject subscription.

// Transform tests

#[test]
fn map() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let expected = &[4u8, 6, 10, 14, 22, 26];
    let mut received = Vec::new();
    let mut mapped = values.map(|x| x * 2);
    mapped.subscribe_next(|x| received.push(x));
    assert_eq!(&expected[..], &received[..]);
}

#[test]
fn map_err() {
    let mut error = None;
    let mut mapped = Err(23_u32).map_err(|x| x * 2);
    mapped.subscribe_error(
        |_x: u32| panic!("mapped error should not produce a value"),
        || panic!("mapped error should not complete"),
        |err| error = Some(err)
    );
    assert_eq!(Some(46), error);
}
<commit_msg>Add more tests for map and map_err<commit_after>// Rx -- Reactive programming for Rust
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate rx;

use rx::{Never, Observable, Observer, Subject};
use std::cell::RefCell;
use std::rc::Rc;

// Generator tests

#[test]
fn never() {
    let mut never = Never::new();
    let _subscription = never.subscribe_error(
        |_x: u8| panic!("never observable should not produce a value"),
        || panic!("never observable should not complete"),
        |_err: ()| panic!("never observable should not fail")
    );

    // Without something like a message loop, the observable cannot suddenly
    // start pushing values, so if it did not produce anything here, it never
    // will.
}

// Option tests

#[test]
fn option_subscribe_next() {
    let mut received = None;

    // Subscribing to `Some` should push the value.
    Some(19).subscribe_next(|x| received = Some(x));
    assert_eq!(Some(19), received);

    None.subscribe_next(|_x: u32| panic!("none should not push a value"));
}

#[test]
fn option_subscribe_completed() {
    let mut received = None;
    let mut completed = false;

    // Subscribing to `Some` should complete after pushing the value.
    Some(19).subscribe_completed(|x| received = Some(x), || completed = true);
    assert_eq!(Some(19), received);
    assert!(completed);

    // Subscribing to `None` should complete without pushing a value.
    completed = false;
    None.subscribe_completed(
        |_x: u32| panic!("none should not push a value"),
        || completed = true
    );
    assert!(completed);
}

#[test]
fn option_subscribe_error() {
    let mut received = None;
    let mut completed = false;

    Some(23).subscribe_error(
        |x| received = Some(x),
        || completed = true,
        |_err| panic!("some observable should not fail")
    );
    assert_eq!(Some(23), received);
    assert!(completed);

    completed = false;
    None.subscribe_error(
        |_x: u32| panic!("none should not push a value"),
        || completed = true,
        |_err| panic!("none observable should not fail")
    );
    assert!(completed);
}

// Result tests

#[test]
fn result_subscribe_next_ok() {
    let mut result: Result<u32, ()> = Ok(13);
    let mut received = None;
    result.subscribe_next(|x| received = Some(x));
    assert_eq!(Some(13), received);
}

#[test]
#[should_panic]
fn result_subscribe_next_err() {
    let mut result: Result<u32, ()> = Err(());
    let mut received = None;

    // This should panic, because we did not provide an error handler.
    result.subscribe_next(|x| received = Some(x));
}

#[test]
fn result_subscribe_completed_ok() {
    let mut result: Result<u32, ()> = Ok(13);
    let mut received = None;
    let mut completed = false;
    result.subscribe_completed(|x| received = Some(x), || completed = true);
    assert_eq!(Some(13), received);
    assert!(completed);
}

#[test]
fn result_subscribe_error_ok() {
    let mut result: Result<u32, ()> = Ok(13);
    let mut received = None;
    let mut completed = false;
    result.subscribe_error(
        |x| received = Some(x),
        || completed = true,
        |_err| panic!("ok result should not be a failing observable")
    );
    assert_eq!(Some(13), received);
    assert!(completed);
}

#[test]
fn result_subscribe_error_err() {
    let mut result: Result<(), u32> = Err(17);
    let mut error = None;
    result.subscribe_error(
        |_x| panic!("err result should not push a value"),
        || panic!("err result should not complete"),
        |err| error = Some(err)
    );
    assert_eq!(Some(17), error);
}

// Slice tests

#[test]
fn slice_subscribe_next() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    values.subscribe_next(|&x| received.push(x));
    assert_eq!(&values[..], &received[..]);
}

#[test]
fn slice_subscribe_completed() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    let mut completed = false;
    values.subscribe_completed(|&x| received.push(x), || completed = true);
    assert_eq!(&values[..], &received[..]);
    assert!(completed);
}

#[test]
fn slice_subscribe_error() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    let mut completed = false;
    let mut failed = false;
    values.subscribe_error(|&x| received.push(x), || completed = true, |_err| failed = true);
    assert_eq!(&values[..], &received[..]);
    assert!(completed);
    assert!(!failed);
}

#[test]
fn slice_subscribe_option() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let expected = &[Some(2u8), Some(3), Some(5), Some(7), Some(11), Some(13), None];
    let mut received = Vec::new();
    values.subscribe_option(|x| received.push(x.cloned()));
    assert_eq!(&received[..], &expected[..]);
}

#[test]
fn slice_subscribe_result() {
    let mut values = &[2u8, 3, 5, 7];
    let expected = &[Ok(Some(2u8)), Ok(Some(3)), Ok(Some(5)), Ok(Some(7)), Ok(None)];
    let mut received = Vec::new();
    values.subscribe_result(|x| received.push(x.map(|y| y.cloned())));
    assert_eq!(&received[..], &expected[..]);
}

// Subject tests

#[test]
fn subject_on_next() {
    let mut subject = Subject::<u8, ()>::new();
    let mut received = Vec::new();
    let _subscription = subject.observable().subscribe_next(|x| received.push(x));

    // Subject should not push anything upon subscription.
    assert_eq!(0, received.len());

    let values = &[2u8, 3, 5, 7, 11, 13];
    for i in 0..values.len() {
        subject.on_next(values[i]);
        assert_eq!(&values[..i + 1], &received[..]);
    }
}

#[test]
fn subject_on_completed() {
    let mut subject = Subject::<u8, ()>::new();
    let mut completed = false;
    let _subscription = subject.observable().subscribe_completed(
        |_x| panic!("no value should be pushed"),
        || completed = true
    );

    // Subject should not push anything upon subscription.
    assert!(!completed);

    subject.on_completed();
    assert!(completed);
}

#[test]
fn subject_on_error() {
    let mut subject = Subject::<u8, u8>::new();
    let mut error = 0;
    let _subscription = subject.observable().subscribe_error(
        |_x| panic!("no value should be pushed"),
        || panic!("subject should not complete"),
        |err| error = err
    );

    // Subject should not fail upon subscription.
    assert_eq!(0, error);

    subject.on_error(41);
    assert_eq!(41, error);
}

/// Helper for the `subject_clones_once_per_observer()` test.
struct CloneCounter {
    counter: Rc<RefCell<u32>>,
}

impl Clone for CloneCounter {
    fn clone(&self) -> CloneCounter {
        let count: u32 = *self.counter.borrow();
        *self.counter.borrow_mut() = count + 1;
        CloneCounter {
            counter: self.counter.clone(),
        }
    }
}

#[test]
fn subject_clones_once_per_observer() {
    let mut subject = Subject::<CloneCounter, ()>::new();
    let mut first_called = false;
    let mut second_called = false;
    let counter = CloneCounter {
        counter: Rc::new(RefCell::new(0)),
    };

    // Subscribe twice.
    let _s1 = subject.observable().subscribe_next(|_x| first_called = true);
    let _s2 = subject.observable().subscribe_next(|_x| second_called = true);

    // Nothing should have been cloned yet.
    assert_eq!(0, *counter.counter.borrow());

    subject.on_next(counter.clone());

    // We cloned once, and the subject should have cloned once per subscription.
    assert_eq!(3, *counter.counter.borrow());
    assert!(first_called);
    assert!(second_called);
}

#[test]
fn subject_drop_subscription() {
    let mut subject = Subject::<u8, ()>::new();
    let mut received = Vec::new();
    let subscription = subject.observable().subscribe_next(|x| received.push(x));

    subject.on_next(2);
    subject.on_next(3);
    subject.on_next(5);

    assert_eq!(&[2u8, 3, 5], &received[..]);

    drop(subscription);

    subject.on_next(7);
    subject.on_next(11);

    // Values pushed after drop should not have been invoked.
    assert_eq!(&[2u8, 3, 5], &received[..]);
}

#[test]
fn subject_drop_subscription_multi() {
    let mut subject = Subject::<u8, ()>::new();
    let mut received = Vec::new();
    let _s1 = subject.observable().subscribe_next(|x| received.push(x));
    let s2 = subject.observable().subscribe_error(
        |_x| panic!("no value should be pushed after dropping subscription"),
        || panic!("completion should not be signalled after dropping subscription"),
        |_err| panic!("failure should not be signalled after dropping subscription")
    );

    drop(s2);

    subject.on_next(2);
    subject.on_next(3);
    subject.on_next(5);
    subject.on_completed();

    assert_eq!(&[2u8, 3, 5], &received[..]);
}

// TODO: Test multiple subscriptions and combinations of values and completed/error.
// TODO: Add better tests for dropping the subject subscription.

// Transform tests

#[test]
fn map() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let expected = &[4u8, 6, 10, 14, 22, 26];
    let mut received = Vec::new();
    let mut mapped = values.map(|x| x * 2);
    mapped.subscribe_next(|x| received.push(x));
    assert_eq!(&expected[..], &received[..]);
}

#[test]
fn map_does_not_change_error() {
    let mut error = None;
    let mut mapped = Err(23_u32).map(|x: u32| format!("{}", x));
    mapped.subscribe_error(
        |_x: String| panic!("mapped error should not produce a value"),
        || panic!("mapped error should not complete"),
        |err| error = Some(err)
    );
    assert_eq!(Some(23), error);
}

#[test]
fn map_err() {
    let mut error = None;
    let mut mapped = Err(23_u32).map_err(|x| x * 2);
    mapped.subscribe_error(
        |_x: u32| panic!("mapped error should not produce a value"),
        || panic!("mapped error should not complete"),
        |err| error = Some(err)
    );
    assert_eq!(Some(46), error);
}

#[test]
fn map_err_does_not_change_values() {
    let mut values = &[2u8, 3, 5, 7, 11, 13];
    let mut received = Vec::new();
    let mut mapped = values.map_err(|_unit| 17u8);
    mapped.subscribe_next(|&x| received.push(x));
    assert_eq!(&values[..], &received[..]);
}
<|endoftext|>


<commit_before>// Copyright 2019 The Grin Developers
//
// 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.

use self::chain::types::NoopAdapter;
use self::chain::ErrorKind;
use self::core::core::verifier_cache::LruVerifierCache;
use self::core::core::KernelFeatures;
use self::core::global::{self, ChainTypes};
use self::core::libtx::{self, build, ProofBuilder};
use self::core::pow::Difficulty;
use self::core::{consensus, pow};
use self::keychain::{ExtKeychain, ExtKeychainPath, Keychain};
use self::util::RwLock;
use chrono::Duration;
use env_logger;
use grin_chain as chain;
use grin_core as core;
use grin_keychain as keychain;
use grin_util as util;
use std::fs;
use std::sync::Arc;

fn clean_output_dir(dir_name: &str) {
	let _ = fs::remove_dir_all(dir_name);
}

#[test]
fn test_coinbase_maturity() {
	let _ = env_logger::init();
	let chain_dir = ".grin_coinbase";
	clean_output_dir(chain_dir);
	global::set_mining_mode(ChainTypes::AutomatedTesting);

	let genesis_block = pow::mine_genesis_block().unwrap();

	let verifier_cache = Arc::new(RwLock::new(LruVerifierCache::new()));

	{
		let chain = chain::Chain::init(
			".grin".to_string(),
			Arc::new(NoopAdapter {}),
			genesis_block,
			pow::verify_size,
			verifier_cache,
			false,
		)
		.unwrap();

		let prev = chain.head_header().unwrap();

		let keychain = ExtKeychain::from_random_seed(false).unwrap();
		let builder = ProofBuilder::new(&keychain);
		let key_id1 = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();
		let key_id2 = ExtKeychainPath::new(1, 2, 0, 0, 0).to_identifier();
		let key_id3 = ExtKeychainPath::new(1, 3, 0, 0, 0).to_identifier();
		let key_id4 = ExtKeychainPath::new(1, 4, 0, 0, 0).to_identifier();

		let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
		let reward = libtx::reward::output(&keychain, &builder, &key_id1, 0, false).unwrap();
		let mut block = core::core::Block::new(&prev, vec![], Difficulty::min(), reward).unwrap();
		block.header.timestamp = prev.timestamp + Duration::seconds(60);
		block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

		chain.set_txhashset_roots(&mut block).unwrap();

		pow::pow_size(
			&mut block.header,
			next_header_info.difficulty,
			global::proofsize(),
			global::min_edge_bits(),
		)
		.unwrap();

		assert_eq!(block.outputs().len(), 1);
		let coinbase_output = block.outputs()[0];
		assert!(coinbase_output.is_coinbase());

		chain
			.process_block(block.clone(), chain::Options::MINE)
			.unwrap();

		let prev = chain.head_header().unwrap();

		let amount = consensus::REWARD;

		let lock_height = 1 + global::coinbase_maturity();
		assert_eq!(lock_height, 4);

		// here we build a tx that attempts to spend the earlier coinbase output
		// this is not a valid tx as the coinbase output cannot be spent yet
		let coinbase_txn = build::transaction(
			KernelFeatures::Plain { fee: 2 },
			vec![
				build::coinbase_input(amount, key_id1.clone()),
				build::output(amount - 2, key_id2.clone()),
			],
			&keychain,
			&builder,
		)
		.unwrap();

		let txs = vec![coinbase_txn.clone()];
		let fees = txs.iter().map(|tx| tx.fee()).sum();
		let reward = libtx::reward::output(&keychain, &builder, &key_id3, fees, false).unwrap();
		let mut block = core::core::Block::new(&prev, txs, Difficulty::min(), reward).unwrap();
		let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
		block.header.timestamp = prev.timestamp + Duration::seconds(60);
		block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

		chain.set_txhashset_roots(&mut block).unwrap();

		// Confirm the tx attempting to spend the coinbase output
		// is not valid at the current block height given the current chain state.
		match chain.verify_coinbase_maturity(&coinbase_txn) {
			Ok(_) => {}
			Err(e) => match e.kind() {
				ErrorKind::ImmatureCoinbase => {}
				_ => panic!("Expected transaction error with immature coinbase."),
			},
		}

		pow::pow_size(
			&mut block.header,
			next_header_info.difficulty,
			global::proofsize(),
			global::min_edge_bits(),
		)
		.unwrap();

		// mine enough blocks to increase the height sufficiently for
		// coinbase to reach maturity and be spendable in the next block
		for _ in 0..3 {
			let prev = chain.head_header().unwrap();

			let keychain = ExtKeychain::from_random_seed(false).unwrap();
			let builder = ProofBuilder::new(&keychain);
			let key_id1 = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();

			let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
			let reward = libtx::reward::output(&keychain, &builder, &key_id1, 0, false).unwrap();
			let mut block =
				core::core::Block::new(&prev, vec![], Difficulty::min(), reward).unwrap();

			block.header.timestamp = prev.timestamp + Duration::seconds(60);
			block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

			chain.set_txhashset_roots(&mut block).unwrap();

			pow::pow_size(
				&mut block.header,
				next_header_info.difficulty,
				global::proofsize(),
				global::min_edge_bits(),
			)
			.unwrap();

			assert_eq!(block.outputs().len(), 1);
			let coinbase_output = block.outputs()[0];
			assert!(coinbase_output.is_coinbase());

			chain
				.process_block(block.clone(), chain::Options::MINE)
				.unwrap();

			let prev = chain.head_header().unwrap();

			let amount = consensus::REWARD;

			let lock_height = 1 + global::coinbase_maturity();
			assert_eq!(lock_height, 4);

			// here we build a tx that attempts to spend the earlier coinbase output
			// this is not a valid tx as the coinbase output cannot be spent yet
			let coinbase_txn = build::transaction(
				KernelFeatures::Plain { fee: 2 },
				vec![
					build::coinbase_input(amount, key_id1.clone()),
					build::output(amount - 2, key_id2.clone()),
				],
				&keychain,
				&builder,
			)
			.unwrap();

			let txs = vec![coinbase_txn.clone()];
			let fees = txs.iter().map(|tx| tx.fee()).sum();
			let reward = libtx::reward::output(&keychain, &builder, &key_id3, fees, false).unwrap();
			let mut block = core::core::Block::new(&prev, txs, Difficulty::min(), reward).unwrap();
			let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
			block.header.timestamp = prev.timestamp + Duration::seconds(60);
			block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

			chain.set_txhashset_roots(&mut block).unwrap();

			// Confirm the tx attempting to spend the coinbase output
			// is not valid at the current block height given the current chain state.
			match chain.verify_coinbase_maturity(&coinbase_txn) {
				Ok(_) => {}
				Err(e) => match e.kind() {
					ErrorKind::ImmatureCoinbase => {}
					_ => panic!("Expected transaction error with immature coinbase."),
				},
			}

			pow::pow_size(
				&mut block.header,
				next_header_info.difficulty,
				global::proofsize(),
				global::min_edge_bits(),
			)
			.unwrap();

			// mine enough blocks to increase the height sufficiently for
			// coinbase to reach maturity and be spendable in the next block
			for _ in 0..3 {
				let prev = chain.head_header().unwrap();

				let keychain = ExtKeychain::from_random_seed(false).unwrap();
				let builder = ProofBuilder::new(&keychain);
				let pk = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();

				let reward = libtx::reward::output(&keychain, &builder, &pk, 0, false).unwrap();
				let mut block =
					core::core::Block::new(&prev, vec![], Difficulty::min(), reward).unwrap();
				let next_header_info =
					consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
				block.header.timestamp = prev.timestamp + Duration::seconds(60);
				block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

				chain.set_txhashset_roots(&mut block).unwrap();

				pow::pow_size(
					&mut block.header,
					next_header_info.difficulty,
					global::proofsize(),
					global::min_edge_bits(),
				)
				.unwrap();

				chain.process_block(block, chain::Options::MINE).unwrap();
			}

			let prev = chain.head_header().unwrap();

			// Confirm the tx spending the coinbase output is now valid.
			// The coinbase output has matured sufficiently based on current chain state.
			chain.verify_coinbase_maturity(&coinbase_txn).unwrap();

			let txs = vec![coinbase_txn];
			let fees = txs.iter().map(|tx| tx.fee()).sum();
			let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
			let reward = libtx::reward::output(&keychain, &builder, &key_id4, fees, false).unwrap();
			let mut block = core::core::Block::new(&prev, txs, Difficulty::min(), reward).unwrap();

			block.header.timestamp = prev.timestamp + Duration::seconds(60);
			block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

			chain.set_txhashset_roots(&mut block).unwrap();

			pow::pow_size(
				&mut block.header,
				next_header_info.difficulty,
				global::proofsize(),
				global::min_edge_bits(),
			)
			.unwrap();

			let result = chain.process_block(block, chain::Options::MINE);
			match result {
				Ok(_) => (),
				Err(_) => panic!("we did not expect an error here"),
			};
		}
	}
	// Cleanup chain directory
	clean_output_dir(chain_dir);
}
<commit_msg>mismatch between the test dir used and the test dir cleaned up... (#3133)<commit_after>// Copyright 2019 The Grin Developers
//
// 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.

use self::chain::types::NoopAdapter;
use self::chain::ErrorKind;
use self::core::core::verifier_cache::LruVerifierCache;
use self::core::core::KernelFeatures;
use self::core::global::{self, ChainTypes};
use self::core::libtx::{self, build, ProofBuilder};
use self::core::pow::Difficulty;
use self::core::{consensus, pow};
use self::keychain::{ExtKeychain, ExtKeychainPath, Keychain};
use self::util::RwLock;
use chrono::Duration;
use env_logger;
use grin_chain as chain;
use grin_core as core;
use grin_keychain as keychain;
use grin_util as util;
use std::fs;
use std::sync::Arc;

fn clean_output_dir(dir_name: &str) {
	let _ = fs::remove_dir_all(dir_name);
}

#[test]
fn test_coinbase_maturity() {
	let _ = env_logger::init();
	let chain_dir = ".grin_coinbase";
	clean_output_dir(chain_dir);
	global::set_mining_mode(ChainTypes::AutomatedTesting);

	let genesis_block = pow::mine_genesis_block().unwrap();

	let verifier_cache = Arc::new(RwLock::new(LruVerifierCache::new()));

	{
		let chain = chain::Chain::init(
			chain_dir.to_string(),
			Arc::new(NoopAdapter {}),
			genesis_block,
			pow::verify_size,
			verifier_cache,
			false,
		)
		.unwrap();

		let prev = chain.head_header().unwrap();

		let keychain = ExtKeychain::from_random_seed(false).unwrap();
		let builder = ProofBuilder::new(&keychain);
		let key_id1 = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();
		let key_id2 = ExtKeychainPath::new(1, 2, 0, 0, 0).to_identifier();
		let key_id3 = ExtKeychainPath::new(1, 3, 0, 0, 0).to_identifier();
		let key_id4 = ExtKeychainPath::new(1, 4, 0, 0, 0).to_identifier();

		let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
		let reward = libtx::reward::output(&keychain, &builder, &key_id1, 0, false).unwrap();
		let mut block = core::core::Block::new(&prev, vec![], Difficulty::min(), reward).unwrap();
		block.header.timestamp = prev.timestamp + Duration::seconds(60);
		block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

		chain.set_txhashset_roots(&mut block).unwrap();

		pow::pow_size(
			&mut block.header,
			next_header_info.difficulty,
			global::proofsize(),
			global::min_edge_bits(),
		)
		.unwrap();

		assert_eq!(block.outputs().len(), 1);
		let coinbase_output = block.outputs()[0];
		assert!(coinbase_output.is_coinbase());

		chain
			.process_block(block.clone(), chain::Options::MINE)
			.unwrap();

		let prev = chain.head_header().unwrap();

		let amount = consensus::REWARD;

		let lock_height = 1 + global::coinbase_maturity();
		assert_eq!(lock_height, 4);

		// here we build a tx that attempts to spend the earlier coinbase output
		// this is not a valid tx as the coinbase output cannot be spent yet
		let coinbase_txn = build::transaction(
			KernelFeatures::Plain { fee: 2 },
			vec![
				build::coinbase_input(amount, key_id1.clone()),
				build::output(amount - 2, key_id2.clone()),
			],
			&keychain,
			&builder,
		)
		.unwrap();

		let txs = vec![coinbase_txn.clone()];
		let fees = txs.iter().map(|tx| tx.fee()).sum();
		let reward = libtx::reward::output(&keychain, &builder, &key_id3, fees, false).unwrap();
		let mut block = core::core::Block::new(&prev, txs, Difficulty::min(), reward).unwrap();
		let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
		block.header.timestamp = prev.timestamp + Duration::seconds(60);
		block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

		chain.set_txhashset_roots(&mut block).unwrap();

		// Confirm the tx attempting to spend the coinbase output
		// is not valid at the current block height given the current chain state.
		match chain.verify_coinbase_maturity(&coinbase_txn) {
			Ok(_) => {}
			Err(e) => match e.kind() {
				ErrorKind::ImmatureCoinbase => {}
				_ => panic!("Expected transaction error with immature coinbase."),
			},
		}

		pow::pow_size(
			&mut block.header,
			next_header_info.difficulty,
			global::proofsize(),
			global::min_edge_bits(),
		)
		.unwrap();

		// mine enough blocks to increase the height sufficiently for
		// coinbase to reach maturity and be spendable in the next block
		for _ in 0..3 {
			let prev = chain.head_header().unwrap();

			let keychain = ExtKeychain::from_random_seed(false).unwrap();
			let builder = ProofBuilder::new(&keychain);
			let key_id1 = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();

			let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
			let reward = libtx::reward::output(&keychain, &builder, &key_id1, 0, false).unwrap();
			let mut block =
				core::core::Block::new(&prev, vec![], Difficulty::min(), reward).unwrap();

			block.header.timestamp = prev.timestamp + Duration::seconds(60);
			block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

			chain.set_txhashset_roots(&mut block).unwrap();

			pow::pow_size(
				&mut block.header,
				next_header_info.difficulty,
				global::proofsize(),
				global::min_edge_bits(),
			)
			.unwrap();

			assert_eq!(block.outputs().len(), 1);
			let coinbase_output = block.outputs()[0];
			assert!(coinbase_output.is_coinbase());

			chain
				.process_block(block.clone(), chain::Options::MINE)
				.unwrap();

			let prev = chain.head_header().unwrap();

			let amount = consensus::REWARD;

			let lock_height = 1 + global::coinbase_maturity();
			assert_eq!(lock_height, 4);

			// here we build a tx that attempts to spend the earlier coinbase output
			// this is not a valid tx as the coinbase output cannot be spent yet
			let coinbase_txn = build::transaction(
				KernelFeatures::Plain { fee: 2 },
				vec![
					build::coinbase_input(amount, key_id1.clone()),
					build::output(amount - 2, key_id2.clone()),
				],
				&keychain,
				&builder,
			)
			.unwrap();

			let txs = vec![coinbase_txn.clone()];
			let fees = txs.iter().map(|tx| tx.fee()).sum();
			let reward = libtx::reward::output(&keychain, &builder, &key_id3, fees, false).unwrap();
			let mut block = core::core::Block::new(&prev, txs, Difficulty::min(), reward).unwrap();
			let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
			block.header.timestamp = prev.timestamp + Duration::seconds(60);
			block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

			chain.set_txhashset_roots(&mut block).unwrap();

			// Confirm the tx attempting to spend the coinbase output
			// is not valid at the current block height given the current chain state.
			match chain.verify_coinbase_maturity(&coinbase_txn) {
				Ok(_) => {}
				Err(e) => match e.kind() {
					ErrorKind::ImmatureCoinbase => {}
					_ => panic!("Expected transaction error with immature coinbase."),
				},
			}

			pow::pow_size(
				&mut block.header,
				next_header_info.difficulty,
				global::proofsize(),
				global::min_edge_bits(),
			)
			.unwrap();

			// mine enough blocks to increase the height sufficiently for
			// coinbase to reach maturity and be spendable in the next block
			for _ in 0..3 {
				let prev = chain.head_header().unwrap();

				let keychain = ExtKeychain::from_random_seed(false).unwrap();
				let builder = ProofBuilder::new(&keychain);
				let pk = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();

				let reward = libtx::reward::output(&keychain, &builder, &pk, 0, false).unwrap();
				let mut block =
					core::core::Block::new(&prev, vec![], Difficulty::min(), reward).unwrap();
				let next_header_info =
					consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
				block.header.timestamp = prev.timestamp + Duration::seconds(60);
				block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

				chain.set_txhashset_roots(&mut block).unwrap();

				pow::pow_size(
					&mut block.header,
					next_header_info.difficulty,
					global::proofsize(),
					global::min_edge_bits(),
				)
				.unwrap();

				chain.process_block(block, chain::Options::MINE).unwrap();
			}

			let prev = chain.head_header().unwrap();

			// Confirm the tx spending the coinbase output is now valid.
			// The coinbase output has matured sufficiently based on current chain state.
			chain.verify_coinbase_maturity(&coinbase_txn).unwrap();

			let txs = vec![coinbase_txn];
			let fees = txs.iter().map(|tx| tx.fee()).sum();
			let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
			let reward = libtx::reward::output(&keychain, &builder, &key_id4, fees, false).unwrap();
			let mut block = core::core::Block::new(&prev, txs, Difficulty::min(), reward).unwrap();

			block.header.timestamp = prev.timestamp + Duration::seconds(60);
			block.header.pow.secondary_scaling = next_header_info.secondary_scaling;

			chain.set_txhashset_roots(&mut block).unwrap();

			pow::pow_size(
				&mut block.header,
				next_header_info.difficulty,
				global::proofsize(),
				global::min_edge_bits(),
			)
			.unwrap();

			let result = chain.process_block(block, chain::Options::MINE);
			match result {
				Ok(_) => (),
				Err(_) => panic!("we did not expect an error here"),
			};
		}
	}
	// Cleanup chain directory
	clean_output_dir(chain_dir);
}
<|endoftext|>


<commit_before>#[doc(hidden)]
pub mod global_expression_methods;
#[doc(hidden)]
pub mod bool_expression_methods;
#[doc(hidden)]
pub mod text_expression_methods;

pub use self::global_expression_methods::ExpressionMethods;
pub use self::bool_expression_methods::BoolExpressionMethods;
pub use self::text_expression_methods::{TextExpressionMethods, VarCharExpressionMethods};
<commit_msg>We can't have the expression_modules submodules be hidden<commit_after>pub mod global_expression_methods;
pub mod bool_expression_methods;
pub mod text_expression_methods;

pub use self::global_expression_methods::ExpressionMethods;
pub use self::bool_expression_methods::BoolExpressionMethods;
pub use self::text_expression_methods::{TextExpressionMethods, VarCharExpressionMethods};
<|endoftext|>


<commit_before>pub struct NoColorFormatter {

}

pub struct ZshColorFormatter {

}

pub trait CanFormat {
    fn format(&self, f: FormatEntry) -> String;
}

pub struct FormatEntry {
    pub text: String,
    pub color: String,
}

impl Clone for FormatEntry {
    fn clone(&self) -> Self {
        FormatEntry{text: self.text.clone(), color: self.color.clone()}
    }
}

impl CanFormat for ZshColorFormatter {
    fn format(&self, f: FormatEntry) -> String {
        // {% ... %} correct word wrap with zsh
        if f.color.is_empty() {
            f.text
        } else {
            format!("%{{%F{{{color}}}%}}{s}%{{%f%}}", color=f.color, s=f.text)
        }
    }
}

impl CanFormat for NoColorFormatter {
    fn format(&self, f: FormatEntry) -> String {
        f.text
    }
}

<commit_msg>add tests for formatting<commit_after>pub struct NoColorFormatter {

}

pub struct ZshColorFormatter {

}

pub trait CanFormat {
    fn format(&self, f: FormatEntry) -> String;
}

pub struct FormatEntry {
    pub text: String,
    pub color: String,
}

impl Clone for FormatEntry {
    fn clone(&self) -> Self {
        FormatEntry{text: self.text.clone(), color: self.color.clone()}
    }
}

impl CanFormat for ZshColorFormatter {
    fn format(&self, f: FormatEntry) -> String {
        // {% ... %} correct word wrap with zsh
        if f.text.is_empty() || f.color.is_empty() {
            f.text
        } else {
            format!("%{{%F{{{color}}}%}}{s}%{{%f%}}", color=f.color, s=f.text)
        }
    }
}

impl CanFormat for NoColorFormatter {
    fn format(&self, f: FormatEntry) -> String {
        f.text
    }
}

#[test]
fn test_zsh_color() {
    let z = ZshColorFormatter{};
    let f = FormatEntry{text: String::from("asd"), color: String::from("white")};
    let result = z.format(f);
    assert_eq!(result, "%{%F{white}%}asd%{%f%}");
}

#[test]
fn test_zsh_color_blank_color() {
    let z = ZshColorFormatter{};
    let f = FormatEntry{text: String::from("asd"), color: String::from("")};
    let result = z.format(f);
    assert_eq!(result, "asd");
}

#[test]
fn test_zsh_color_blank_str() {
    let z = ZshColorFormatter{};
    let f = FormatEntry{text: String::from(""), color: String::from("white")};
    let result = z.format(f);
    assert_eq!(result, "");
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;

use collections::String;
use collections::Vec;

use common::event::{self, Event, EventOption};

use core::{cmp, mem};

use drivers::io::{Io, Pio};

use graphics::color::Color;
use graphics::display::Display;

use sync::WaitQueue;

fn ansi_color(value: u8) -> Color {
    match value {
        0 => Color::new(0x00, 0x00, 0x00),
        1 => Color::new(0x80, 0x00, 0x00),
        2 => Color::new(0x00, 0x80, 0x00),
        3 => Color::new(0x80, 0x80, 0x00),
        4 => Color::new(0x00, 0x00, 0x80),
        5 => Color::new(0x80, 0x00, 0x80),
        6 => Color::new(0x00, 0x80, 0x80),
        7 => Color::new(0xc0, 0xc0, 0xc0),
        8 => Color::new(0x80, 0x80, 0x80),
        9 => Color::new(0xff, 0x00, 0x00),
        10 => Color::new(0x00, 0xff, 0x00),
        11 => Color::new(0xff, 0xff, 0x00),
        12 => Color::new(0x00, 0x00, 0xff),
        13 => Color::new(0xff, 0x00, 0xff),
        14 => Color::new(0x00, 0xff, 0xff),
        15 => Color::new(0xff, 0xff, 0xff),
        16 ... 231 => {
            let convert = |value: u8| -> u8 {
                match value {
                    0 => 0,
                    _ => value * 0x28 + 0x28
                }
            };

            let r = convert((value - 16)/36 % 6);
            let g = convert((value - 16)/6 % 6);
            let b = convert((value - 16) % 6);
            Color::new(r, g, b)
        },
        232 ... 255 => {
            let gray = (value - 232) * 10 + 8;
            Color::new(gray, gray, gray)
        },
        _ => Color::new(0, 0, 0)
    }
}

pub struct Console {
    pub display: Option<Box<Display>>,
    pub point_x: usize,
    pub point_y: usize,
    pub foreground: Color,
    pub background: Color,
    pub draw: bool,
    pub redraw: bool,
    pub command: String,
    pub commands: WaitQueue<String>,
    pub escape: bool,
    pub escape_sequence: bool,
    pub sequence: Vec<String>,
    pub raw_mode: bool,
}

impl Console {
    pub fn new() -> Console {
        Console {
            display: Display::root(),
            point_x: 0,
            point_y: 0,
            foreground: ansi_color(7),
            background: ansi_color(0),
            draw: false,
            redraw: true,
            command: String::new(),
            commands: WaitQueue::new(),
            escape: false,
            escape_sequence: false,
            sequence: Vec::new(),
            raw_mode: false,
        }
    }

    pub fn code(&mut self, c: char) {
        if self.escape_sequence {
            match c {
                '0' ... '9' => {
                    // Add a number to the sequence list
                    if let Some(mut value) = self.sequence.last_mut() {
                        value.push(c);
                    }
                },
                ';' => {
                    // Split sequence into list
                    self.sequence.push(String::new());
                },
                'm' => {
                    // Display attributes
                    let mut value_iter = self.sequence.iter();
                    while let Some(value_str) = value_iter.next() {
                        let value = value_str.parse::<u8>().unwrap_or(0);
                        match value {
                            0 => {
                                self.foreground = ansi_color(7);
                                self.background = ansi_color(0);
                            },
                            30 ... 37 => self.foreground = ansi_color(value - 30),
                            38 => match value_iter.next().map_or("", |s| &s).parse::<usize>().unwrap_or(0) {
                                2 => {
                                    //True color
                                    let r = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    let g = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    let b = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    self.foreground = Color::new(r, g, b);
                                },
                                5 => {
                                    //256 color
                                    let color_value = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    self.foreground = ansi_color(color_value);
                                },
                                _ => {}
                            },
                            40 ... 47 => self.background = ansi_color(value - 40),
                            48 => match value_iter.next().map_or("", |s| &s).parse::<usize>().unwrap_or(0) {
                                2 => {
                                    //True color
                                    let r = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    let g = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    let b = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    self.background = Color::new(r, g, b);
                                },
                                5 => {
                                    //256 color
                                    let color_value = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    self.background = ansi_color(color_value);
                                },
                                _ => {}
                            },
                            _ => {},
                        }
                    }

                    self.escape_sequence = false;
                },
                'J' => {
                    match self.sequence.get(0).map_or("", |p| &p).parse::<usize>().unwrap_or(0) {
                        0 => {
                            //TODO: Erase down
                        },
                        1 => {
                            //TODO: Erase up
                        },
                        2 => {
                            // Erase all
                            self.point_x = 0;
                            self.point_y = 0;
                            if let Some(ref mut display) = self.display {
                                display.set(self.background);
                            }
                            if ! self.raw_mode {
                                self.redraw = true;
                            }
                        },
                        _ => {}
                    }

                    self.escape_sequence = false;
                },
                'H' | 'f' => {
                    if let Some(ref mut display) = self.display {
                        display.rect(self.point_x, self.point_y, 8, 16, self.background);
                    }

                    let row = self.sequence.get(0).map_or("", |p| &p).parse::<isize>().unwrap_or(1);
                    self.point_y = cmp::max(0, row - 1) as usize * 16;

                    let col = self.sequence.get(1).map_or("", |p| &p).parse::<isize>().unwrap_or(1);
                    self.point_x = cmp::max(0, col - 1) as usize * 8;

                    if let Some(ref mut display) = self.display {
                        display.rect(self.point_x, self.point_y, 8, 16, self.foreground);
                    }

                    self.escape_sequence = false;
                },
/*
@MANSTART{terminal-raw-mode}
INTRODUCTION
    Since Redox has no ioctl syscall, it uses escape codes for switching to raw mode.

ENTERING AND EXITING RAW MODE
    Entering raw mode is done using CSI-r (^[r). Unsetting raw mode is done by CSI-R (^[R).

RAW MODE
    Raw mode means that the stdin must be handled solely by the program itself. It will not automatically be printed nor will it be modified in any way (modulo escape codes).

    This means that:
        - stdin is not printed.
        - newlines are interpreted as carriage returns in stdin.
        - stdin is not buffered, meaning that the stream of bytes goes directly to the program, without the user having to press enter.
@MANEND
*/
                'r' => {
                    self.raw_mode = true;
                    self.escape_sequence = false;
                },
                'R' => {
                    self.raw_mode = false;
                    self.escape_sequence = false;
                },
                _ => self.escape_sequence = false,
            }

            if !self.escape_sequence {
                self.sequence.clear();
                self.escape = false;
            }
        } else {
            match c {
                '[' => {
                    // Control sequence initiator

                    self.escape_sequence = true;
                    self.sequence.push(String::new());
                },
                'c' => {
                    // Reset
                    self.point_x = 0;
                    self.point_y = 0;
                    self.raw_mode = false;
                    self.foreground = ansi_color(7);
                    self.background = ansi_color(0);
                    if let Some(ref mut display) = self.display {
                        display.set(self.background);
                    }
                    self.redraw = true;

                    self.escape = false;
                }
                _ => self.escape = false,
            }
        }
    }

    pub fn character(&mut self, c: char) {
        let (width, height) = if let Some(ref mut display) = self.display {
            (display.width, display.height)
        } else {
            (80, 30)
        };

        if let Some(ref mut display) = self.display {
            display.rect(self.point_x, self.point_y, 8, 16, self.background);
        }

        match c {
            '\0' => {},
            '\x1B' => self.escape = true,
            '\n' => {
                self.point_x = 0;
                self.point_y += 16;
                if ! self.raw_mode {
                    self.redraw = true;
                }
            },
            '\t' => self.point_x = ((self.point_x / 64) + 1) * 64,
            '\r' => self.point_x = 0,
            '\x08' => {
                if self.point_x >= 8 {
                    self.point_x -= 8;
                }

                if let Some(ref mut display) = self.display {
                    display.rect(self.point_x, self.point_y, 8, 16, self.background);
                }
            },
            _ => {
                if let Some(ref mut display) = self.display {
                    display.char(self.point_x, self.point_y, c, self.foreground);
                }

                self.point_x += 8;
            }
        }

        if self.point_x >= width {
            self.point_x = 0;
            self.point_y += 16;
        }

        while self.point_y + 16 > height {
            if let Some(ref mut display) = self.display {
                display.scroll(16, self.background);
            }
            self.point_y -= 16;
        }

        if let Some(ref mut display) = self.display {
            display.rect(self.point_x, self.point_y, 8, 16, self.foreground);
        }
    }

    pub fn event(&mut self, event: Event) {
        match event.to_option() {
            EventOption::Key(key_event) => {
                if key_event.pressed {
                    if self.raw_mode {
                        match key_event.scancode {
                            event::K_BKSP => self.command.push_str("\x08"),
                            event::K_UP => self.command.push_str("\x1B[A"),
                            event::K_DOWN => self.command.push_str("\x1B[B"),
                            event::K_RIGHT => self.command.push_str("\x1B[C"),
                            event::K_LEFT => self.command.push_str("\x1B[D"),
                            _ => match key_event.character {
                                '\0' => {},
                                c => {
                                    self.command.push(c);
                                }
                            },
                        }

                        if ! self.command.is_empty() {
                            let mut command = String::new();
                            mem::swap(&mut self.command, &mut command);
                            self.commands.send(command);
                        }
                    } else {
                        match key_event.scancode {
                            event::K_BKSP => if ! self.command.is_empty() {
                                self.redraw = true;

                                self.write(&[8]);
                                self.command.pop();
                            },
                            _ => match key_event.character {
                                '\0' => (),
                                c => {
                                    self.redraw = true;

                                    self.write(&[c as u8]);
                                    self.command.push(c);

                                    if c == '\n' {
                                        let mut command = String::new();
                                        mem::swap(&mut self.command, &mut command);
                                        self.commands.send(command);
                                    }
                                }
                            },
                        }
                    }
                }
            }
            _ => (),
        }
    }

    pub fn write(&mut self, bytes: &[u8]) {
        for byte in bytes.iter() {
            let c = *byte as char;

            if self.escape {
                self.code(c);
            } else {
                self.character(c);
            }

            if self.display.is_none() || ! self.draw {
                let serial_status = Pio::<u8>::new(0x3F8 + 5);
                let mut serial_data = Pio::<u8>::new(0x3F8);

                while !serial_status.readf(0x20) {}
                serial_data.write(*byte);

                if *byte == 8 {
                    while !serial_status.readf(0x20) {}
                    serial_data.write(0x20);

                    while !serial_status.readf(0x20) {}
                    serial_data.write(8);
                }
            }
        }

        if self.draw && self.redraw {
            self.redraw = false;
            if let Some(ref mut display) = self.display {
                display.flip();
            }
        }
    }
}
<commit_msg>Fix issue in console: returning 8 instead of 7F for backspace in raw mode<commit_after>use alloc::boxed::Box;

use collections::String;
use collections::Vec;

use common::event::{self, Event, EventOption};

use core::{cmp, mem};

use drivers::io::{Io, Pio};

use graphics::color::Color;
use graphics::display::Display;

use sync::WaitQueue;

fn ansi_color(value: u8) -> Color {
    match value {
        0 => Color::new(0x00, 0x00, 0x00),
        1 => Color::new(0x80, 0x00, 0x00),
        2 => Color::new(0x00, 0x80, 0x00),
        3 => Color::new(0x80, 0x80, 0x00),
        4 => Color::new(0x00, 0x00, 0x80),
        5 => Color::new(0x80, 0x00, 0x80),
        6 => Color::new(0x00, 0x80, 0x80),
        7 => Color::new(0xc0, 0xc0, 0xc0),
        8 => Color::new(0x80, 0x80, 0x80),
        9 => Color::new(0xff, 0x00, 0x00),
        10 => Color::new(0x00, 0xff, 0x00),
        11 => Color::new(0xff, 0xff, 0x00),
        12 => Color::new(0x00, 0x00, 0xff),
        13 => Color::new(0xff, 0x00, 0xff),
        14 => Color::new(0x00, 0xff, 0xff),
        15 => Color::new(0xff, 0xff, 0xff),
        16 ... 231 => {
            let convert = |value: u8| -> u8 {
                match value {
                    0 => 0,
                    _ => value * 0x28 + 0x28
                }
            };

            let r = convert((value - 16)/36 % 6);
            let g = convert((value - 16)/6 % 6);
            let b = convert((value - 16) % 6);
            Color::new(r, g, b)
        },
        232 ... 255 => {
            let gray = (value - 232) * 10 + 8;
            Color::new(gray, gray, gray)
        },
        _ => Color::new(0, 0, 0)
    }
}

pub struct Console {
    pub display: Option<Box<Display>>,
    pub point_x: usize,
    pub point_y: usize,
    pub foreground: Color,
    pub background: Color,
    pub draw: bool,
    pub redraw: bool,
    pub command: String,
    pub commands: WaitQueue<String>,
    pub escape: bool,
    pub escape_sequence: bool,
    pub sequence: Vec<String>,
    pub raw_mode: bool,
}

impl Console {
    pub fn new() -> Console {
        Console {
            display: Display::root(),
            point_x: 0,
            point_y: 0,
            foreground: ansi_color(7),
            background: ansi_color(0),
            draw: false,
            redraw: true,
            command: String::new(),
            commands: WaitQueue::new(),
            escape: false,
            escape_sequence: false,
            sequence: Vec::new(),
            raw_mode: false,
        }
    }

    pub fn code(&mut self, c: char) {
        if self.escape_sequence {
            match c {
                '0' ... '9' => {
                    // Add a number to the sequence list
                    if let Some(mut value) = self.sequence.last_mut() {
                        value.push(c);
                    }
                },
                ';' => {
                    // Split sequence into list
                    self.sequence.push(String::new());
                },
                'm' => {
                    // Display attributes
                    let mut value_iter = self.sequence.iter();
                    while let Some(value_str) = value_iter.next() {
                        let value = value_str.parse::<u8>().unwrap_or(0);
                        match value {
                            0 => {
                                self.foreground = ansi_color(7);
                                self.background = ansi_color(0);
                            },
                            30 ... 37 => self.foreground = ansi_color(value - 30),
                            38 => match value_iter.next().map_or("", |s| &s).parse::<usize>().unwrap_or(0) {
                                2 => {
                                    //True color
                                    let r = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    let g = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    let b = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    self.foreground = Color::new(r, g, b);
                                },
                                5 => {
                                    //256 color
                                    let color_value = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    self.foreground = ansi_color(color_value);
                                },
                                _ => {}
                            },
                            40 ... 47 => self.background = ansi_color(value - 40),
                            48 => match value_iter.next().map_or("", |s| &s).parse::<usize>().unwrap_or(0) {
                                2 => {
                                    //True color
                                    let r = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    let g = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    let b = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    self.background = Color::new(r, g, b);
                                },
                                5 => {
                                    //256 color
                                    let color_value = value_iter.next().map_or("", |s| &s).parse::<u8>().unwrap_or(0);
                                    self.background = ansi_color(color_value);
                                },
                                _ => {}
                            },
                            _ => {},
                        }
                    }

                    self.escape_sequence = false;
                },
                'J' => {
                    match self.sequence.get(0).map_or("", |p| &p).parse::<usize>().unwrap_or(0) {
                        0 => {
                            //TODO: Erase down
                        },
                        1 => {
                            //TODO: Erase up
                        },
                        2 => {
                            // Erase all
                            self.point_x = 0;
                            self.point_y = 0;
                            if let Some(ref mut display) = self.display {
                                display.set(self.background);
                            }
                            if ! self.raw_mode {
                                self.redraw = true;
                            }
                        },
                        _ => {}
                    }

                    self.escape_sequence = false;
                },
                'H' | 'f' => {
                    if let Some(ref mut display) = self.display {
                        display.rect(self.point_x, self.point_y, 8, 16, self.background);
                    }

                    let row = self.sequence.get(0).map_or("", |p| &p).parse::<isize>().unwrap_or(1);
                    self.point_y = cmp::max(0, row - 1) as usize * 16;

                    let col = self.sequence.get(1).map_or("", |p| &p).parse::<isize>().unwrap_or(1);
                    self.point_x = cmp::max(0, col - 1) as usize * 8;

                    if let Some(ref mut display) = self.display {
                        display.rect(self.point_x, self.point_y, 8, 16, self.foreground);
                    }

                    self.escape_sequence = false;
                },
/*
@MANSTART{terminal-raw-mode}
INTRODUCTION
    Since Redox has no ioctl syscall, it uses escape codes for switching to raw mode.

ENTERING AND EXITING RAW MODE
    Entering raw mode is done using CSI-r (^[r). Unsetting raw mode is done by CSI-R (^[R).

RAW MODE
    Raw mode means that the stdin must be handled solely by the program itself. It will not automatically be printed nor will it be modified in any way (modulo escape codes).

    This means that:
        - stdin is not printed.
        - newlines are interpreted as carriage returns in stdin.
        - stdin is not buffered, meaning that the stream of bytes goes directly to the program, without the user having to press enter.
@MANEND
*/
                'r' => {
                    self.raw_mode = true;
                    self.escape_sequence = false;
                },
                'R' => {
                    self.raw_mode = false;
                    self.escape_sequence = false;
                },
                _ => self.escape_sequence = false,
            }

            if !self.escape_sequence {
                self.sequence.clear();
                self.escape = false;
            }
        } else {
            match c {
                '[' => {
                    // Control sequence initiator

                    self.escape_sequence = true;
                    self.sequence.push(String::new());
                },
                'c' => {
                    // Reset
                    self.point_x = 0;
                    self.point_y = 0;
                    self.raw_mode = false;
                    self.foreground = ansi_color(7);
                    self.background = ansi_color(0);
                    if let Some(ref mut display) = self.display {
                        display.set(self.background);
                    }
                    self.redraw = true;

                    self.escape = false;
                }
                _ => self.escape = false,
            }
        }
    }

    pub fn character(&mut self, c: char) {
        let (width, height) = if let Some(ref mut display) = self.display {
            (display.width, display.height)
        } else {
            (80, 30)
        };

        if let Some(ref mut display) = self.display {
            display.rect(self.point_x, self.point_y, 8, 16, self.background);
        }

        match c {
            '\0' => {},
            '\x1B' => self.escape = true,
            '\n' => {
                self.point_x = 0;
                self.point_y += 16;
                if ! self.raw_mode {
                    self.redraw = true;
                }
            },
            '\t' => self.point_x = ((self.point_x / 64) + 1) * 64,
            '\r' => self.point_x = 0,
            '\x08' => {
                if self.point_x >= 8 {
                    self.point_x -= 8;
                }

                if let Some(ref mut display) = self.display {
                    display.rect(self.point_x, self.point_y, 8, 16, self.background);
                }
            },
            _ => {
                if let Some(ref mut display) = self.display {
                    display.char(self.point_x, self.point_y, c, self.foreground);
                }

                self.point_x += 8;
            }
        }

        if self.point_x >= width {
            self.point_x = 0;
            self.point_y += 16;
        }

        while self.point_y + 16 > height {
            if let Some(ref mut display) = self.display {
                display.scroll(16, self.background);
            }
            self.point_y -= 16;
        }

        if let Some(ref mut display) = self.display {
            display.rect(self.point_x, self.point_y, 8, 16, self.foreground);
        }
    }

    pub fn event(&mut self, event: Event) {
        match event.to_option() {
            EventOption::Key(key_event) => {
                if key_event.pressed {
                    if self.raw_mode {
                        match key_event.scancode {
                            event::K_BKSP => self.command.push_str("\x7F"),
                            event::K_UP => self.command.push_str("\x1B[A"),
                            event::K_DOWN => self.command.push_str("\x1B[B"),
                            event::K_RIGHT => self.command.push_str("\x1B[C"),
                            event::K_LEFT => self.command.push_str("\x1B[D"),
                            _ => match key_event.character {
                                '\0' => {},
                                c => {
                                    self.command.push(c);
                                }
                            },
                        }

                        if ! self.command.is_empty() {
                            let mut command = String::new();
                            mem::swap(&mut self.command, &mut command);
                            self.commands.send(command);
                        }
                    } else {
                        match key_event.scancode {
                            event::K_BKSP => if ! self.command.is_empty() {
                                self.redraw = true;

                                self.write(&[8]);
                                self.command.pop();
                            },
                            _ => match key_event.character {
                                '\0' => (),
                                c => {
                                    self.redraw = true;

                                    self.write(&[c as u8]);
                                    self.command.push(c);

                                    if c == '\n' {
                                        let mut command = String::new();
                                        mem::swap(&mut self.command, &mut command);
                                        self.commands.send(command);
                                    }
                                }
                            },
                        }
                    }
                }
            }
            _ => (),
        }
    }

    pub fn write(&mut self, bytes: &[u8]) {
        for byte in bytes.iter() {
            let c = *byte as char;

            if self.escape {
                self.code(c);
            } else {
                self.character(c);
            }

            if self.display.is_none() || ! self.draw {
                let serial_status = Pio::<u8>::new(0x3F8 + 5);
                let mut serial_data = Pio::<u8>::new(0x3F8);

                while !serial_status.readf(0x20) {}
                serial_data.write(*byte);

                if *byte == 8 {
                    while !serial_status.readf(0x20) {}
                    serial_data.write(0x20);

                    while !serial_status.readf(0x20) {}
                    serial_data.write(8);
                }
            }
        }

        if self.draw && self.redraw {
            self.redraw = false;
            if let Some(ref mut display) = self.display {
                display.flip();
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::config::SafetyRulesConfig;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ConsensusConfig {
    pub max_block_size: u64,
    pub max_pruned_blocks_in_mem: usize,
    // Timeout for consensus to get an ack from mempool for executed transactions (in milliseconds)
    pub mempool_executed_txn_timeout_ms: u64,
    // Timeout for consensus to pull transactions from mempool and get a response (in milliseconds)
    pub mempool_txn_pull_timeout_ms: u64,
    pub round_initial_timeout_ms: u64,
    pub safety_rules: SafetyRulesConfig,
    // Only sync committed transactions but not vote for any pending blocks. This is useful when
    // validators coordinate on the latest version to apply a manual transaction.
    pub sync_only: bool,
    pub channel_size: usize,
    // When false, use the Direct Mempool Quorum Store
    pub use_quorum_store: bool,
    pub quorum_store_pull_timeout_ms: u64,
    // Decides how long the leader waits before proposing empty block if there's no txns in mempool
    // the period = (poll_count - 1) * 30ms
    pub quorum_store_poll_count: u64,
    pub intra_consensus_channel_buffer_size: usize,
}

impl Default for ConsensusConfig {
    fn default() -> ConsensusConfig {
        ConsensusConfig {
            max_block_size: 6000,
            max_pruned_blocks_in_mem: 100,
            mempool_executed_txn_timeout_ms: 1000,
            mempool_txn_pull_timeout_ms: 1000,
            round_initial_timeout_ms: 1000,
            safety_rules: SafetyRulesConfig::default(),
            sync_only: false,
            channel_size: 30, // hard-coded
            use_quorum_store: false,
            quorum_store_pull_timeout_ms: 1000,
            quorum_store_poll_count: 20,
            intra_consensus_channel_buffer_size: 10,
        }
    }
}

impl ConsensusConfig {
    pub fn set_data_dir(&mut self, data_dir: PathBuf) {
        self.safety_rules.set_data_dir(data_dir);
    }
}

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

    #[test]
    fn test_config_serialization() {
        let config = ConsensusConfig::default();
        let s = serde_yaml::to_string(&config).unwrap();

        serde_yaml::from_str::<ConsensusConfig>(&s).unwrap();
    }
}
<commit_msg>[Consensus] Configure round timeout from 1s -> 1.5s (#2078)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::config::SafetyRulesConfig;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(default, deny_unknown_fields)]
pub struct ConsensusConfig {
    pub max_block_size: u64,
    pub max_pruned_blocks_in_mem: usize,
    // Timeout for consensus to get an ack from mempool for executed transactions (in milliseconds)
    pub mempool_executed_txn_timeout_ms: u64,
    // Timeout for consensus to pull transactions from mempool and get a response (in milliseconds)
    pub mempool_txn_pull_timeout_ms: u64,
    pub round_initial_timeout_ms: u64,
    pub safety_rules: SafetyRulesConfig,
    // Only sync committed transactions but not vote for any pending blocks. This is useful when
    // validators coordinate on the latest version to apply a manual transaction.
    pub sync_only: bool,
    pub channel_size: usize,
    // When false, use the Direct Mempool Quorum Store
    pub use_quorum_store: bool,
    pub quorum_store_pull_timeout_ms: u64,
    // Decides how long the leader waits before proposing empty block if there's no txns in mempool
    // the period = (poll_count - 1) * 30ms
    pub quorum_store_poll_count: u64,
    pub intra_consensus_channel_buffer_size: usize,
}

impl Default for ConsensusConfig {
    fn default() -> ConsensusConfig {
        ConsensusConfig {
            max_block_size: 6000,
            max_pruned_blocks_in_mem: 100,
            mempool_executed_txn_timeout_ms: 1000,
            mempool_txn_pull_timeout_ms: 1000,
            round_initial_timeout_ms: 1500,
            safety_rules: SafetyRulesConfig::default(),
            sync_only: false,
            channel_size: 30, // hard-coded
            use_quorum_store: false,

            quorum_store_pull_timeout_ms: 1000,
            quorum_store_poll_count: 20,
            intra_consensus_channel_buffer_size: 10,
        }
    }
}

impl ConsensusConfig {
    pub fn set_data_dir(&mut self, data_dir: PathBuf) {
        self.safety_rules.set_data_dir(data_dir);
    }
}

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

    #[test]
    fn test_config_serialization() {
        let config = ConsensusConfig::default();
        let s = serde_yaml::to_string(&config).unwrap();

        serde_yaml::from_str::<ConsensusConfig>(&s).unwrap();
    }
}
<|endoftext|>


<commit_before>

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
}

impl GitLab {
    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }
    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
        }
    }

    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token)
    }
}
<commit_msg>Change order of new()<commit_after>

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        let gl = GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
        };

        // FIXME: Connect to GitLab

        gl
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token)
    }
}
<|endoftext|>