<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use test_capnp::{test_all_types, TestEnum};

pub fn init_test_message(mut builder : test_all_types::Builder) {
    builder.set_void_field(());
    builder.set_bool_field(true);
    builder.set_int8_field(-123);
    builder.set_int16_field(-12345);
    builder.set_int32_field(-12345678);
    builder.set_int64_field(-123456789012345);
    builder.set_u_int8_field(234);
    builder.set_u_int16_field(45678);
    builder.set_u_int32_field(3456789012);
    builder.set_u_int64_field(12345678901234567890);
    builder.set_float32_field(1234.5);
    builder.set_float64_field(-123e45);
    builder.set_text_field("foo");
    builder.set_data_field(b"bar");
    {
        let mut sub_builder = builder.borrow().init_struct_field();
        sub_builder.set_void_field(());
        sub_builder.set_bool_field(true);
        sub_builder.set_int8_field(-12);
        sub_builder.set_int16_field(3456);
        sub_builder.set_int32_field(-78901234);
        sub_builder.set_int64_field(56789012345678);
        sub_builder.set_u_int8_field(90);
        sub_builder.set_u_int16_field(1234);
        sub_builder.set_u_int32_field(56789012);
        sub_builder.set_u_int64_field(345678901234567890);
        sub_builder.set_float32_field(-1.25e-10);
        sub_builder.set_float64_field(345f64);
        sub_builder.set_text_field("baz");
        sub_builder.set_data_field(b"qux");
        {
            let mut sub_sub_builder = sub_builder.borrow().init_struct_field();
            sub_sub_builder.set_text_field("nested");
            sub_sub_builder.init_struct_field().set_text_field("really nested");
        }
        sub_builder.set_enum_field(TestEnum::Baz);

        sub_builder.borrow().init_void_list(3);
        {
            let mut bool_list = sub_builder.borrow().init_bool_list(5);
            bool_list.set(0, false);
            bool_list.set(1, true);
            bool_list.set(2, false);
            bool_list.set(3, true);
            bool_list.set(4, true);
        }
        {
            let mut int8_list = sub_builder.borrow().init_int8_list(4);
            int8_list.set(0, 12);
            int8_list.set(1, -34);
            int8_list.set(2, -0x80);
            int8_list.set(3, 0x7f);
        }
        {
            let mut int16_list = sub_builder.borrow().init_int16_list(4);
            int16_list.set(0, 1234);
            int16_list.set(1, -5678);
            int16_list.set(2, -0x8000);
            int16_list.set(3, 0x7fff);
        }
        {
            let mut int32_list = sub_builder.borrow().init_int32_list(4);
            int32_list.set(0, 12345678);
            int32_list.set(1, -90123456);
            int32_list.set(2, -0x80000000);
            int32_list.set(3, 0x7fffffff);
        }
        {
            let mut int64_list = sub_builder.borrow().init_int64_list(4);
            int64_list.set(0, 123456789012345);
            int64_list.set(1, -678901234567890);
            int64_list.set(2, -0x8000000000000000);
            int64_list.set(3, 0x7fffffffffffffff);
        }

        // ...
        {
            let mut struct_list = sub_builder.borrow().init_struct_list(3);
            struct_list.borrow().get(0).set_text_field("x structlist 1");
            struct_list.borrow().get(1).set_text_field("x structlist 2");
            struct_list.borrow().get(2).set_text_field("x structlist 3");
        }

        let mut enum_list = sub_builder.borrow().init_enum_list(3);
        enum_list.set(0, TestEnum::Qux);
        enum_list.set(1, TestEnum::Bar);
        enum_list.set(2, TestEnum::Grault);
    }
    builder.set_enum_field(TestEnum::Corge);

    builder.init_void_list(6);

    // ...
}

pub trait CheckTestMessage {
    fn check_test_message(Self);
}

macro_rules!
check_test_message_impl(($typ:ident) => (
    impl <'a> CheckTestMessage for test_all_types::$typ<'a> {
        fn check_test_message(mut reader : test_all_types::$typ<'a>) {
            #![allow(unused_mut)]
            reader.borrow().get_void_field();
            assert_eq!(true, reader.borrow().get_bool_field());
            assert_eq!(-123, reader.borrow().get_int8_field());
            assert_eq!(-12345, reader.borrow().get_int16_field());
            assert_eq!(-12345678, reader.borrow().get_int32_field());
            assert_eq!(-123456789012345, reader.borrow().get_int64_field());
            assert_eq!(234, reader.borrow().get_u_int8_field());
            assert_eq!(45678, reader.borrow().get_u_int16_field());
            assert_eq!(3456789012, reader.borrow().get_u_int32_field());
            assert_eq!(12345678901234567890, reader.borrow().get_u_int64_field());
            assert_eq!(1234.5, reader.borrow().get_float32_field());
            assert_eq!(-123e45, reader.borrow().get_float64_field());
            assert_eq!("foo", reader.borrow().get_text_field().as_slice());
            assert_eq!(b"bar", &*reader.borrow().get_data_field());
            {
                let mut sub_reader = reader.get_struct_field();
                assert_eq!((), sub_reader.borrow().get_void_field());
                assert_eq!(true, sub_reader.borrow().get_bool_field());
                assert_eq!(-12, sub_reader.borrow().get_int8_field());
                assert_eq!(3456, sub_reader.borrow().get_int16_field());
                assert_eq!(-78901234, sub_reader.borrow().get_int32_field());
                assert_eq!(56789012345678, sub_reader.borrow().get_int64_field());
                assert_eq!(90, sub_reader.borrow().get_u_int8_field());
                assert_eq!(1234, sub_reader.borrow().get_u_int16_field());
                assert_eq!(56789012, sub_reader.borrow().get_u_int32_field());
                assert_eq!(345678901234567890, sub_reader.borrow().get_u_int64_field());
                assert_eq!(-1.25e-10, sub_reader.borrow().get_float32_field());
                assert_eq!(345f64, sub_reader.borrow().get_float64_field());
                assert_eq!("baz", sub_reader.borrow().get_text_field().as_slice());
                assert_eq!(b"qux", &*sub_reader.borrow().get_data_field());
                {
                    let mut sub_sub_reader = sub_reader.borrow().get_struct_field();
                    assert_eq!("nested", sub_sub_reader.borrow().get_text_field().as_slice());
                    assert_eq!("really nested", sub_sub_reader.get_struct_field().get_text_field().as_slice());
                }
                assert!(Some(TestEnum::Baz) == sub_reader.borrow().get_enum_field());
                assert_eq!(3, sub_reader.borrow().get_void_list().len());

                {
                    let bool_list = sub_reader.borrow().get_bool_list();
                    assert_eq!(5, bool_list.len());
                    assert_eq!(false, bool_list.get(0));
                    assert_eq!(true, bool_list.get(1));
                    assert_eq!(false, bool_list.get(2));
                    assert_eq!(true, bool_list.get(3));
                    assert_eq!(true, bool_list.get(4));
                }

                {
                    let int8_list = sub_reader.borrow().get_int8_list();
                    assert_eq!(4, int8_list.len());
                    assert_eq!(12, int8_list.get(0));
                    assert_eq!(-34, int8_list.get(1));
                    assert_eq!(-0x80, int8_list.get(2));
                    assert_eq!(0x7f, int8_list.get(3));
                }

                {
                    let int16_list = sub_reader.borrow().get_int16_list();
                    assert_eq!(4, int16_list.len());
                    assert_eq!(1234, int16_list.get(0));
                    assert_eq!(-5678, int16_list.get(1));
                    assert_eq!(-0x8000, int16_list.get(2));
                    assert_eq!(0x7fff, int16_list.get(3));
                }

                {
                    let int32_list = sub_reader.borrow().get_int32_list();
                    assert_eq!(4, int32_list.len());
                    assert_eq!(12345678, int32_list.get(0));
                    assert_eq!(-90123456, int32_list.get(1));
                    assert_eq!(-0x80000000, int32_list.get(2));
                    assert_eq!(0x7fffffff, int32_list.get(3));
                }

                // ...

                {
                    let mut struct_list = sub_reader.borrow().get_struct_list();
                    assert_eq!(3, struct_list.len());
                    assert_eq!("x structlist 1", struct_list.borrow().get(0).get_text_field().as_slice());
                    assert_eq!("x structlist 2", struct_list.borrow().get(1).get_text_field().as_slice());
                    assert_eq!("x structlist 3", struct_list.borrow().get(2).get_text_field().as_slice());
                }

                {
                    let enum_list = sub_reader.get_enum_list();
                    assert_eq!(3, enum_list.len());
                    assert!(Some(TestEnum::Qux) == enum_list.get(0));
                    assert!(Some(TestEnum::Bar) == enum_list.get(1));
                    assert!(Some(TestEnum::Grault) == enum_list.get(2));
                }
            }
        }
    }
));

check_test_message_impl!(Reader);

check_test_message_impl!(Builder);
<commit_msg>Deref is now implemented for text::Builder<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use test_capnp::{test_all_types, TestEnum};

pub fn init_test_message(mut builder : test_all_types::Builder) {
    builder.set_void_field(());
    builder.set_bool_field(true);
    builder.set_int8_field(-123);
    builder.set_int16_field(-12345);
    builder.set_int32_field(-12345678);
    builder.set_int64_field(-123456789012345);
    builder.set_u_int8_field(234);
    builder.set_u_int16_field(45678);
    builder.set_u_int32_field(3456789012);
    builder.set_u_int64_field(12345678901234567890);
    builder.set_float32_field(1234.5);
    builder.set_float64_field(-123e45);
    builder.set_text_field("foo");
    builder.set_data_field(b"bar");
    {
        let mut sub_builder = builder.borrow().init_struct_field();
        sub_builder.set_void_field(());
        sub_builder.set_bool_field(true);
        sub_builder.set_int8_field(-12);
        sub_builder.set_int16_field(3456);
        sub_builder.set_int32_field(-78901234);
        sub_builder.set_int64_field(56789012345678);
        sub_builder.set_u_int8_field(90);
        sub_builder.set_u_int16_field(1234);
        sub_builder.set_u_int32_field(56789012);
        sub_builder.set_u_int64_field(345678901234567890);
        sub_builder.set_float32_field(-1.25e-10);
        sub_builder.set_float64_field(345f64);
        sub_builder.set_text_field("baz");
        sub_builder.set_data_field(b"qux");
        {
            let mut sub_sub_builder = sub_builder.borrow().init_struct_field();
            sub_sub_builder.set_text_field("nested");
            sub_sub_builder.init_struct_field().set_text_field("really nested");
        }
        sub_builder.set_enum_field(TestEnum::Baz);

        sub_builder.borrow().init_void_list(3);
        {
            let mut bool_list = sub_builder.borrow().init_bool_list(5);
            bool_list.set(0, false);
            bool_list.set(1, true);
            bool_list.set(2, false);
            bool_list.set(3, true);
            bool_list.set(4, true);
        }
        {
            let mut int8_list = sub_builder.borrow().init_int8_list(4);
            int8_list.set(0, 12);
            int8_list.set(1, -34);
            int8_list.set(2, -0x80);
            int8_list.set(3, 0x7f);
        }
        {
            let mut int16_list = sub_builder.borrow().init_int16_list(4);
            int16_list.set(0, 1234);
            int16_list.set(1, -5678);
            int16_list.set(2, -0x8000);
            int16_list.set(3, 0x7fff);
        }
        {
            let mut int32_list = sub_builder.borrow().init_int32_list(4);
            int32_list.set(0, 12345678);
            int32_list.set(1, -90123456);
            int32_list.set(2, -0x80000000);
            int32_list.set(3, 0x7fffffff);
        }
        {
            let mut int64_list = sub_builder.borrow().init_int64_list(4);
            int64_list.set(0, 123456789012345);
            int64_list.set(1, -678901234567890);
            int64_list.set(2, -0x8000000000000000);
            int64_list.set(3, 0x7fffffffffffffff);
        }

        // ...
        {
            let mut struct_list = sub_builder.borrow().init_struct_list(3);
            struct_list.borrow().get(0).set_text_field("x structlist 1");
            struct_list.borrow().get(1).set_text_field("x structlist 2");
            struct_list.borrow().get(2).set_text_field("x structlist 3");
        }

        let mut enum_list = sub_builder.borrow().init_enum_list(3);
        enum_list.set(0, TestEnum::Qux);
        enum_list.set(1, TestEnum::Bar);
        enum_list.set(2, TestEnum::Grault);
    }
    builder.set_enum_field(TestEnum::Corge);

    builder.init_void_list(6);

    // ...
}

pub trait CheckTestMessage {
    fn check_test_message(Self);
}

macro_rules!
check_test_message_impl(($typ:ident) => (
    impl <'a> CheckTestMessage for test_all_types::$typ<'a> {
        fn check_test_message(mut reader : test_all_types::$typ<'a>) {
            #![allow(unused_mut)]
            reader.borrow().get_void_field();
            assert_eq!(true, reader.borrow().get_bool_field());
            assert_eq!(-123, reader.borrow().get_int8_field());
            assert_eq!(-12345, reader.borrow().get_int16_field());
            assert_eq!(-12345678, reader.borrow().get_int32_field());
            assert_eq!(-123456789012345, reader.borrow().get_int64_field());
            assert_eq!(234, reader.borrow().get_u_int8_field());
            assert_eq!(45678, reader.borrow().get_u_int16_field());
            assert_eq!(3456789012, reader.borrow().get_u_int32_field());
            assert_eq!(12345678901234567890, reader.borrow().get_u_int64_field());
            assert_eq!(1234.5, reader.borrow().get_float32_field());
            assert_eq!(-123e45, reader.borrow().get_float64_field());
            assert_eq!("foo", &*reader.borrow().get_text_field());
            assert_eq!(b"bar", &*reader.borrow().get_data_field());
            {
                let mut sub_reader = reader.get_struct_field();
                assert_eq!((), sub_reader.borrow().get_void_field());
                assert_eq!(true, sub_reader.borrow().get_bool_field());
                assert_eq!(-12, sub_reader.borrow().get_int8_field());
                assert_eq!(3456, sub_reader.borrow().get_int16_field());
                assert_eq!(-78901234, sub_reader.borrow().get_int32_field());
                assert_eq!(56789012345678, sub_reader.borrow().get_int64_field());
                assert_eq!(90, sub_reader.borrow().get_u_int8_field());
                assert_eq!(1234, sub_reader.borrow().get_u_int16_field());
                assert_eq!(56789012, sub_reader.borrow().get_u_int32_field());
                assert_eq!(345678901234567890, sub_reader.borrow().get_u_int64_field());
                assert_eq!(-1.25e-10, sub_reader.borrow().get_float32_field());
                assert_eq!(345f64, sub_reader.borrow().get_float64_field());
                assert_eq!("baz", sub_reader.borrow().get_text_field().as_slice());
                assert_eq!(b"qux", &*sub_reader.borrow().get_data_field());
                {
                    let mut sub_sub_reader = sub_reader.borrow().get_struct_field();
                    assert_eq!("nested", sub_sub_reader.borrow().get_text_field().as_slice());
                    assert_eq!("really nested", sub_sub_reader.get_struct_field().get_text_field().as_slice());
                }
                assert!(Some(TestEnum::Baz) == sub_reader.borrow().get_enum_field());
                assert_eq!(3, sub_reader.borrow().get_void_list().len());

                {
                    let bool_list = sub_reader.borrow().get_bool_list();
                    assert_eq!(5, bool_list.len());
                    assert_eq!(false, bool_list.get(0));
                    assert_eq!(true, bool_list.get(1));
                    assert_eq!(false, bool_list.get(2));
                    assert_eq!(true, bool_list.get(3));
                    assert_eq!(true, bool_list.get(4));
                }

                {
                    let int8_list = sub_reader.borrow().get_int8_list();
                    assert_eq!(4, int8_list.len());
                    assert_eq!(12, int8_list.get(0));
                    assert_eq!(-34, int8_list.get(1));
                    assert_eq!(-0x80, int8_list.get(2));
                    assert_eq!(0x7f, int8_list.get(3));
                }

                {
                    let int16_list = sub_reader.borrow().get_int16_list();
                    assert_eq!(4, int16_list.len());
                    assert_eq!(1234, int16_list.get(0));
                    assert_eq!(-5678, int16_list.get(1));
                    assert_eq!(-0x8000, int16_list.get(2));
                    assert_eq!(0x7fff, int16_list.get(3));
                }

                {
                    let int32_list = sub_reader.borrow().get_int32_list();
                    assert_eq!(4, int32_list.len());
                    assert_eq!(12345678, int32_list.get(0));
                    assert_eq!(-90123456, int32_list.get(1));
                    assert_eq!(-0x80000000, int32_list.get(2));
                    assert_eq!(0x7fffffff, int32_list.get(3));
                }

                // ...

                {
                    let mut struct_list = sub_reader.borrow().get_struct_list();
                    assert_eq!(3, struct_list.len());
                    assert_eq!("x structlist 1", struct_list.borrow().get(0).get_text_field().as_slice());
                    assert_eq!("x structlist 2", struct_list.borrow().get(1).get_text_field().as_slice());
                    assert_eq!("x structlist 3", struct_list.borrow().get(2).get_text_field().as_slice());
                }

                {
                    let enum_list = sub_reader.get_enum_list();
                    assert_eq!(3, enum_list.len());
                    assert!(Some(TestEnum::Qux) == enum_list.get(0));
                    assert!(Some(TestEnum::Bar) == enum_list.get(1));
                    assert!(Some(TestEnum::Grault) == enum_list.get(2));
                }
            }
        }
    }
));

check_test_message_impl!(Reader);

check_test_message_impl!(Builder);
<|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};
use std::{char, convert::From, marker::PhantomData, ops::Deref, u32};

use crate::{
    ast::{InputValue, Selection, ToInputValue},
    executor::{ExecutionResult, Executor, Registry},
    parser::{LexerError, ParseError, ScalarToken, Token},
    schema::meta::MetaType,
    types::base::GraphQLType,
    value::{ParseScalarResult, ScalarValue, Value},
};

/// An ID as defined by the GraphQL specification
///
/// Represented as a string, but can be converted _to_ from an integer as well.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct ID(String);

impl From<String> for ID {
    fn from(s: String) -> ID {
        ID(s)
    }
}

impl ID {
    /// Construct a new ID from anything implementing `Into<String>`
    pub fn new<S: Into<String>>(value: S) -> Self {
        ID(value.into())
    }
}

impl Deref for ID {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

#[crate::graphql_scalar_internal(name = "ID")]
impl<S> GraphQLScalar for ID
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(self.0.clone())
    }

    fn from_input_value(v: &InputValue) -> Option<ID> {
        match *v {
            InputValue::Scalar(ref s) => s
                .as_string()
                .or_else(|| s.as_int().map(|i| i.to_string()))
                .map(ID),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        match value {
            ScalarToken::String(value) | ScalarToken::Int(value) => Ok(S::from(value.to_owned())),
            _ => Err(ParseError::UnexpectedToken(Token::Scalar(value))),
        }
    }
}

#[crate::graphql_scalar_internal(name = "String")]
impl<S> GraphQLScalar for String
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(self.clone())
    }

    fn from_input_value(v: &InputValue) -> Option<String> {
        match *v {
            InputValue::Scalar(ref s) => s.as_string(),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        if let ScalarToken::String(value) = value {
            let mut ret = String::with_capacity(value.len());
            let mut char_iter = value.chars();
            while let Some(ch) = char_iter.next() {
                match ch {
                    '\\' => match char_iter.next() {
                        Some('"') => {
                            ret.push('"');
                        }
                        Some('/') => {
                            ret.push('/');
                        }
                        Some('n') => {
                            ret.push('\n');
                        }
                        Some('r') => {
                            ret.push('\r');
                        }
                        Some('t') => {
                            ret.push('\t');
                        }
                        Some('\\') => {
                            ret.push('\\');
                        }
                        Some('f') => {
                            ret.push('\u{000c}');
                        }
                        Some('b') => {
                            ret.push('\u{0008}');
                        }
                        Some('u') => {
                            ret.push(parse_unicode_codepoint(&mut char_iter)?);
                        }
                        Some(s) => {
                            return Err(ParseError::LexerError(LexerError::UnknownEscapeSequence(
                                format!("\\{}", s),
                            )))
                        }
                        None => return Err(ParseError::LexerError(LexerError::UnterminatedString)),
                    },
                    ch => {
                        ret.push(ch);
                    }
                }
            }
            Ok(ret.into())
        } else {
            Err(ParseError::UnexpectedToken(Token::Scalar(value)))
        }
    }
}

fn parse_unicode_codepoint<'a, I>(char_iter: &mut I) -> Result<char, ParseError<'a>>
where
    I: Iterator<Item = char>,
{
    let escaped_code_point = char_iter
        .next()
        .ok_or_else(|| {
            ParseError::LexerError(LexerError::UnknownEscapeSequence(String::from("\\u")))
        })
        .and_then(|c1| {
            char_iter
                .next()
                .map(|c2| format!("{}{}", c1, c2))
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\u{}", c1)))
                })
        })
        .and_then(|mut s| {
            char_iter
                .next()
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
                        "\\u{}",
                        s.clone()
                    )))
                })
                .map(|c2| {
                    s.push(c2);
                    s
                })
        })
        .and_then(|mut s| {
            char_iter
                .next()
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
                        "\\u{}",
                        s.clone()
                    )))
                })
                .map(|c2| {
                    s.push(c2);
                    s
                })
        })?;
    let code_point = u32::from_str_radix(&escaped_code_point, 16).map_err(|_| {
        ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
            "\\u{}",
            escaped_code_point
        )))
    })?;
    char::from_u32(code_point).ok_or_else(|| {
        ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
            "\\u{}",
            escaped_code_point
        )))
    })
}

impl<'a, S> GraphQLType<S> for &'a str
where
    S: ScalarValue,
{
    type Context = ();
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("String")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        registry.build_scalar_type::<String>(&()).into_meta()
    }

    fn resolve(
        &self,
        _: &(),
        _: Option<&[Selection<S>]>,
        _: &Executor<Self::Context, S>,
    ) -> ExecutionResult<S> {
        Ok(Value::scalar(String::from(*self)))
    }
}

impl<'e, S> crate::GraphQLTypeAsync<S> for &'e str
where
    S: ScalarValue + Send + Sync,
{
    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, crate::ExecutionResult<S>> {
        use futures::future;
        future::FutureExt::boxed(future::ready(self.resolve(info, selection_set, executor)))
    }
}

impl<'a, S> ToInputValue<S> for &'a str
where
    S: ScalarValue,
{
    fn to_input_value(&self) -> InputValue<S> {
        InputValue::scalar(String::from(*self))
    }
}

#[crate::graphql_scalar_internal(name = "Boolean")]
impl<S> GraphQLScalar for bool
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(*self)
    }

    fn from_input_value(v: &InputValue) -> Option<bool> {
        match *v {
            InputValue::Scalar(ref b) => b.as_boolean(),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        // Bools are parsed on it's own. This should not hit this code path
        Err(ParseError::UnexpectedToken(Token::Scalar(value)))
    }
}

#[crate::graphql_scalar_internal(name = "Int")]
impl<S> GraphQLScalar for i32
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(*self)
    }

    fn from_input_value(v: &InputValue) -> Option<i32> {
        match *v {
            InputValue::Scalar(ref i) => i.as_int(),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        if let ScalarToken::Int(v) = value {
            v.parse()
                .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
                .map(|s: i32| s.into())
        } else {
            Err(ParseError::UnexpectedToken(Token::Scalar(value)))
        }
    }
}

#[crate::graphql_scalar_internal(name = "Float")]
impl<S> GraphQLScalar for f64
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(*self)
    }

    fn from_input_value(v: &InputValue) -> Option<f64> {
        match *v {
            InputValue::Scalar(ref s) => s.as_float(),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        match value {
            ScalarToken::Int(v) | ScalarToken::Float(v) => v
                .parse()
                .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
                .map(|s: f64| s.into()),
            ScalarToken::String(_) => Err(ParseError::UnexpectedToken(Token::Scalar(value))),
        }
    }
}

/// Utillity type to define read-only schemas
///
/// If you instantiate `RootNode` with this as the mutation, no mutation will be
/// generated for the schema.
#[derive(Debug)]
pub struct EmptyMutation<T> {
    phantom: PhantomData<T>,
}

impl<T> EmptyMutation<T> {
    /// Construct a new empty mutation
    pub fn new() -> EmptyMutation<T> {
        EmptyMutation {
            phantom: PhantomData,
        }
    }
}

// This is safe due to never using `T`.
unsafe impl<T> Send for EmptyMutation<T> {}

impl<S, T> GraphQLType<S> for EmptyMutation<T>
where
    S: ScalarValue,
{
    type Context = T;
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("_EmptyMutation")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        registry.build_object_type::<Self>(&(), &[]).into_meta()
    }
}

impl<S, T> crate::GraphQLTypeAsync<S> for EmptyMutation<T>
where
    S: ScalarValue + Send + Sync,
    Self: GraphQLType<S> + Send + Sync,
    Self::TypeInfo: Send + Sync,
    Self::Context: Send + Sync,
    T: Send + Sync,
{
}

impl<T> Default for EmptyMutation<T> {
    fn default() -> Self {
        Self {
            phantom: PhantomData,
        }
    }
}

/// Utillity type to define read-only schemas
///
/// If you instantiate `RootNode` with this as the subscription,
/// no subscriptions will be generated for the schema.
pub struct EmptySubscription<T> {
    phantom: PhantomData<T>,
}

// This is safe due to never using `T`.
unsafe impl<T> Send for EmptySubscription<T> {}

impl<T> EmptySubscription<T> {
    /// Construct a new empty subscription
    pub fn new() -> Self {
        EmptySubscription {
            phantom: PhantomData,
        }
    }
}

impl<S, T> GraphQLType<S> for EmptySubscription<T>
where
    S: ScalarValue,
{
    type Context = T;
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("_EmptySubscription")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        registry.build_object_type::<Self>(&(), &[]).into_meta()
    }
}

impl<T, S> crate::GraphQLSubscriptionType<S> for EmptySubscription<T>
where
    S: ScalarValue + Send + Sync + 'static,
    Self: GraphQLType<S> + Send + Sync,
    Self::TypeInfo: Send + Sync,
    Self::Context: Send + Sync,
    T: Send + Sync,
{
}

impl<T> Default for EmptySubscription<T> {
    fn default() -> Self {
        Self {
            phantom: PhantomData,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{EmptyMutation, EmptySubscription, ID};
    use crate::{
        parser::ScalarToken,
        value::{DefaultScalarValue, ParseScalarValue},
    };

    #[test]
    fn test_id_from_string() {
        let actual = ID::from(String::from("foo"));
        let expected = ID(String::from("foo"));
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_id_new() {
        let actual = ID::new("foo");
        let expected = ID(String::from("foo"));
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_id_deref() {
        let id = ID(String::from("foo"));
        assert_eq!(id.len(), 3);
    }

    #[test]
    fn parse_strings() {
        fn parse_string(s: &str, expected: &str) {
            let s =
                <String as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::String(s));
            assert!(s.is_ok(), "A parsing error occurred: {:?}", s);
            let s: Option<String> = s.unwrap().into();
            assert!(s.is_some(), "No string returned");
            assert_eq!(s.unwrap(), expected);
        }

        parse_string("simple", "simple");
        parse_string(" white space ", " white space ");
        parse_string(r#"quote \""#, "quote \"");
        parse_string(r#"escaped \n\r\b\t\f"#, "escaped \n\r\u{0008}\t\u{000c}");
        parse_string(r#"slashes \\ \/"#, "slashes \\ /");
        parse_string(
            r#"unicode \u1234\u5678\u90AB\uCDEF"#,
            "unicode \u{1234}\u{5678}\u{90ab}\u{cdef}",
        );
    }

    #[test]
    fn empty_mutation_is_send() {
        fn check_if_send<T: Send>() {}
        check_if_send::<EmptyMutation<()>>();
    }

    #[test]
    fn empty_subscription_is_send() {
        fn check_if_send<T: Send>() {}
        check_if_send::<EmptySubscription<()>>();
    }

    #[test]
    fn default_is_invariant_over_type() {
        struct Bar;
        let _ = EmptySubscription::<Bar>::default();
        let _ = EmptyMutation::<Bar>::default();
    }
}
<commit_msg>Make some comments clearer. (#665)<commit_after>use serde::{Deserialize, Serialize};
use std::{char, convert::From, marker::PhantomData, ops::Deref, u32};

use crate::{
    ast::{InputValue, Selection, ToInputValue},
    executor::{ExecutionResult, Executor, Registry},
    parser::{LexerError, ParseError, ScalarToken, Token},
    schema::meta::MetaType,
    types::base::GraphQLType,
    value::{ParseScalarResult, ScalarValue, Value},
};

/// An ID as defined by the GraphQL specification
///
/// Represented as a string, but can be converted _to_ from an integer as well.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct ID(String);

impl From<String> for ID {
    fn from(s: String) -> ID {
        ID(s)
    }
}

impl ID {
    /// Construct a new ID from anything implementing `Into<String>`
    pub fn new<S: Into<String>>(value: S) -> Self {
        ID(value.into())
    }
}

impl Deref for ID {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

#[crate::graphql_scalar_internal(name = "ID")]
impl<S> GraphQLScalar for ID
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(self.0.clone())
    }

    fn from_input_value(v: &InputValue) -> Option<ID> {
        match *v {
            InputValue::Scalar(ref s) => s
                .as_string()
                .or_else(|| s.as_int().map(|i| i.to_string()))
                .map(ID),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        match value {
            ScalarToken::String(value) | ScalarToken::Int(value) => Ok(S::from(value.to_owned())),
            _ => Err(ParseError::UnexpectedToken(Token::Scalar(value))),
        }
    }
}

#[crate::graphql_scalar_internal(name = "String")]
impl<S> GraphQLScalar for String
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(self.clone())
    }

    fn from_input_value(v: &InputValue) -> Option<String> {
        match *v {
            InputValue::Scalar(ref s) => s.as_string(),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        if let ScalarToken::String(value) = value {
            let mut ret = String::with_capacity(value.len());
            let mut char_iter = value.chars();
            while let Some(ch) = char_iter.next() {
                match ch {
                    '\\' => match char_iter.next() {
                        Some('"') => {
                            ret.push('"');
                        }
                        Some('/') => {
                            ret.push('/');
                        }
                        Some('n') => {
                            ret.push('\n');
                        }
                        Some('r') => {
                            ret.push('\r');
                        }
                        Some('t') => {
                            ret.push('\t');
                        }
                        Some('\\') => {
                            ret.push('\\');
                        }
                        Some('f') => {
                            ret.push('\u{000c}');
                        }
                        Some('b') => {
                            ret.push('\u{0008}');
                        }
                        Some('u') => {
                            ret.push(parse_unicode_codepoint(&mut char_iter)?);
                        }
                        Some(s) => {
                            return Err(ParseError::LexerError(LexerError::UnknownEscapeSequence(
                                format!("\\{}", s),
                            )))
                        }
                        None => return Err(ParseError::LexerError(LexerError::UnterminatedString)),
                    },
                    ch => {
                        ret.push(ch);
                    }
                }
            }
            Ok(ret.into())
        } else {
            Err(ParseError::UnexpectedToken(Token::Scalar(value)))
        }
    }
}

fn parse_unicode_codepoint<'a, I>(char_iter: &mut I) -> Result<char, ParseError<'a>>
where
    I: Iterator<Item = char>,
{
    let escaped_code_point = char_iter
        .next()
        .ok_or_else(|| {
            ParseError::LexerError(LexerError::UnknownEscapeSequence(String::from("\\u")))
        })
        .and_then(|c1| {
            char_iter
                .next()
                .map(|c2| format!("{}{}", c1, c2))
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!("\\u{}", c1)))
                })
        })
        .and_then(|mut s| {
            char_iter
                .next()
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
                        "\\u{}",
                        s.clone()
                    )))
                })
                .map(|c2| {
                    s.push(c2);
                    s
                })
        })
        .and_then(|mut s| {
            char_iter
                .next()
                .ok_or_else(|| {
                    ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
                        "\\u{}",
                        s.clone()
                    )))
                })
                .map(|c2| {
                    s.push(c2);
                    s
                })
        })?;
    let code_point = u32::from_str_radix(&escaped_code_point, 16).map_err(|_| {
        ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
            "\\u{}",
            escaped_code_point
        )))
    })?;
    char::from_u32(code_point).ok_or_else(|| {
        ParseError::LexerError(LexerError::UnknownEscapeSequence(format!(
            "\\u{}",
            escaped_code_point
        )))
    })
}

impl<'a, S> GraphQLType<S> for &'a str
where
    S: ScalarValue,
{
    type Context = ();
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("String")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        registry.build_scalar_type::<String>(&()).into_meta()
    }

    fn resolve(
        &self,
        _: &(),
        _: Option<&[Selection<S>]>,
        _: &Executor<Self::Context, S>,
    ) -> ExecutionResult<S> {
        Ok(Value::scalar(String::from(*self)))
    }
}

impl<'e, S> crate::GraphQLTypeAsync<S> for &'e str
where
    S: ScalarValue + Send + Sync,
{
    fn resolve_async<'a>(
        &'a self,
        info: &'a Self::TypeInfo,
        selection_set: Option<&'a [Selection<S>]>,
        executor: &'a Executor<Self::Context, S>,
    ) -> crate::BoxFuture<'a, crate::ExecutionResult<S>> {
        use futures::future;
        future::FutureExt::boxed(future::ready(self.resolve(info, selection_set, executor)))
    }
}

impl<'a, S> ToInputValue<S> for &'a str
where
    S: ScalarValue,
{
    fn to_input_value(&self) -> InputValue<S> {
        InputValue::scalar(String::from(*self))
    }
}

#[crate::graphql_scalar_internal(name = "Boolean")]
impl<S> GraphQLScalar for bool
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(*self)
    }

    fn from_input_value(v: &InputValue) -> Option<bool> {
        match *v {
            InputValue::Scalar(ref b) => b.as_boolean(),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        // Bools are parsed separately - they shouldn't reach this code path
        Err(ParseError::UnexpectedToken(Token::Scalar(value)))
    }
}

#[crate::graphql_scalar_internal(name = "Int")]
impl<S> GraphQLScalar for i32
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(*self)
    }

    fn from_input_value(v: &InputValue) -> Option<i32> {
        match *v {
            InputValue::Scalar(ref i) => i.as_int(),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        if let ScalarToken::Int(v) = value {
            v.parse()
                .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
                .map(|s: i32| s.into())
        } else {
            Err(ParseError::UnexpectedToken(Token::Scalar(value)))
        }
    }
}

#[crate::graphql_scalar_internal(name = "Float")]
impl<S> GraphQLScalar for f64
where
    S: ScalarValue,
{
    fn resolve(&self) -> Value {
        Value::scalar(*self)
    }

    fn from_input_value(v: &InputValue) -> Option<f64> {
        match *v {
            InputValue::Scalar(ref s) => s.as_float(),
            _ => None,
        }
    }

    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
        match value {
            ScalarToken::Int(v) | ScalarToken::Float(v) => v
                .parse()
                .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
                .map(|s: f64| s.into()),
            ScalarToken::String(_) => Err(ParseError::UnexpectedToken(Token::Scalar(value))),
        }
    }
}

/// Utillity type to define read-only schemas
///
/// If you instantiate `RootNode` with this as the mutation, no mutation will be
/// generated for the schema.
#[derive(Debug)]
pub struct EmptyMutation<T> {
    phantom: PhantomData<T>,
}

impl<T> EmptyMutation<T> {
    /// Construct a new empty mutation
    pub fn new() -> EmptyMutation<T> {
        EmptyMutation {
            phantom: PhantomData,
        }
    }
}

// This is safe because `T` is never used.
unsafe impl<T> Send for EmptyMutation<T> {}

impl<S, T> GraphQLType<S> for EmptyMutation<T>
where
    S: ScalarValue,
{
    type Context = T;
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("_EmptyMutation")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        registry.build_object_type::<Self>(&(), &[]).into_meta()
    }
}

impl<S, T> crate::GraphQLTypeAsync<S> for EmptyMutation<T>
where
    S: ScalarValue + Send + Sync,
    Self: GraphQLType<S> + Send + Sync,
    Self::TypeInfo: Send + Sync,
    Self::Context: Send + Sync,
    T: Send + Sync,
{
}

impl<T> Default for EmptyMutation<T> {
    fn default() -> Self {
        Self {
            phantom: PhantomData,
        }
    }
}

/// Utillity type to define read-only schemas
///
/// If you instantiate `RootNode` with this as the subscription,
/// no subscriptions will be generated for the schema.
pub struct EmptySubscription<T> {
    phantom: PhantomData<T>,
}

// This is safe due to never using `T`.
unsafe impl<T> Send for EmptySubscription<T> {}

impl<T> EmptySubscription<T> {
    /// Construct a new empty subscription
    pub fn new() -> Self {
        EmptySubscription {
            phantom: PhantomData,
        }
    }
}

impl<S, T> GraphQLType<S> for EmptySubscription<T>
where
    S: ScalarValue,
{
    type Context = T;
    type TypeInfo = ();

    fn name(_: &()) -> Option<&str> {
        Some("_EmptySubscription")
    }

    fn meta<'r>(_: &(), registry: &mut Registry<'r, S>) -> MetaType<'r, S>
    where
        S: 'r,
    {
        registry.build_object_type::<Self>(&(), &[]).into_meta()
    }
}

impl<T, S> crate::GraphQLSubscriptionType<S> for EmptySubscription<T>
where
    S: ScalarValue + Send + Sync + 'static,
    Self: GraphQLType<S> + Send + Sync,
    Self::TypeInfo: Send + Sync,
    Self::Context: Send + Sync,
    T: Send + Sync,
{
}

impl<T> Default for EmptySubscription<T> {
    fn default() -> Self {
        Self {
            phantom: PhantomData,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{EmptyMutation, EmptySubscription, ID};
    use crate::{
        parser::ScalarToken,
        value::{DefaultScalarValue, ParseScalarValue},
    };

    #[test]
    fn test_id_from_string() {
        let actual = ID::from(String::from("foo"));
        let expected = ID(String::from("foo"));
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_id_new() {
        let actual = ID::new("foo");
        let expected = ID(String::from("foo"));
        assert_eq!(actual, expected);
    }

    #[test]
    fn test_id_deref() {
        let id = ID(String::from("foo"));
        assert_eq!(id.len(), 3);
    }

    #[test]
    fn parse_strings() {
        fn parse_string(s: &str, expected: &str) {
            let s =
                <String as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::String(s));
            assert!(s.is_ok(), "A parsing error occurred: {:?}", s);
            let s: Option<String> = s.unwrap().into();
            assert!(s.is_some(), "No string returned");
            assert_eq!(s.unwrap(), expected);
        }

        parse_string("simple", "simple");
        parse_string(" white space ", " white space ");
        parse_string(r#"quote \""#, "quote \"");
        parse_string(r#"escaped \n\r\b\t\f"#, "escaped \n\r\u{0008}\t\u{000c}");
        parse_string(r#"slashes \\ \/"#, "slashes \\ /");
        parse_string(
            r#"unicode \u1234\u5678\u90AB\uCDEF"#,
            "unicode \u{1234}\u{5678}\u{90ab}\u{cdef}",
        );
    }

    #[test]
    fn empty_mutation_is_send() {
        fn check_if_send<T: Send>() {}
        check_if_send::<EmptyMutation<()>>();
    }

    #[test]
    fn empty_subscription_is_send() {
        fn check_if_send<T: Send>() {}
        check_if_send::<EmptySubscription<()>>();
    }

    #[test]
    fn default_is_invariant_over_type() {
        struct Bar;
        let _ = EmptySubscription::<Bar>::default();
        let _ = EmptyMutation::<Bar>::default();
    }
}
<|endoftext|>


<commit_before>//! The GameBoy ROM that gets mapped at address 0 at startup. It's not
//! accessible during normal game execution.

/// Original GameBoy bootrom. It scrolls the NINTENDO logo down the
/// screen and emits the signature two notes when it reaches the
/// middle. It also checks that the cartridge ROM header is correct
/// and deadlocks if that check fails.
pub static BOOTROM: [u8, ..0x100] = [
    // init_stack:
    0x31, 0xFE, 0xFF, // LD     SP 0xfffe
    0xAF,             // XOR    A A
    0x21, 0xFF, 0x9F, // LD     HL #VRAM_END

    // clear_vram:
    0x32,             // LDD    [HL] A
    0xCB, 0x7C,       // BIT    H 7
    0x20, 0xFB,       // JR NZ  clear_vram

    // init_sound:
    0x21, 0x26, 0xFF, // LD     HL 0xff26
    0x0E, 0x11,       // LD     C 0x11
    0x3E, 0x80,       // LD     A 0x80
    0x32,             // LDD    [HL] A
    0xE2,             // LD     [0xff00 + C] A
    0x0C,             // INC    C
    0x3E, 0xF3,       // LD     A 0xf3
    0xE2,             // LD     [0xff00 + C] A
    0x32,             // LDD    [HL] A
    0x3E, 0x77,       // LD     A 0x77
    0x77,             // LD     [HL] A

    // init_palette:
    0x3E, 0xFC,       // LD     A 0xfc
    0xE0, 0x47,       // LD     [0xff00 + #BGP] A

    // init_crc:
    0x11, 0x04, 0x01, // LD     DE 0x0104
    0x21, 0x10, 0x80, // LD     HL 0x8010
    // crc_loop:
    0x1A,             // LD     A [DE]
    0xCD, 0x95, 0x00, // CALL   crc_0
    0xCD, 0x96, 0x00, // CALL   crc_1

    0x13,             // INC    DE
    0x7B,             // LD     A E
    0xFE, 0x34,       // CP     A 0x34
    0x20, 0xF3,       // JR NZ  do_crc

    0x11, 0xD8, 0x00, // LD     DE #tile_data
    0x06, 0x08,       // LD     B 8
    // copy_tile_map:
    0x1A,             // LD     A [DE]
    0x13,             // INC    DE
    0x22,             // LDI    [HL] A
    0x23,             // INC    HL
    0x05,             // DEC    B
    0x20, 0xF9,       // JR NZ  copy_tile_map

    // init_tile
    0x3E, 0x19,       // LD     A 0x19
    0xEA, 0x10, 0x99, // LD     [0x9910] A
    0x21, 0x2F, 0x99, // LD     HL 0x992f
    // init_tiles_loop
    0x0E, 0x0C,       // LD     C 0x0c
    // init_tiles_inner:
    0x3D,             // DEC    A
    0x28, 0x08,       // JR Z   init_scroll
    0x32,             // LDD    [HL] A
    0x0D,             // DEC    C
    0x20, 0xF9,       // JR NZ  init_tiles_inner
    0x2E, 0x0F,       // LD     L 0x0f
    0x18, 0xF3,       // JR     init_tiles_loop

    // init_scroll:
    0x67,             // LD     H A
    0x3E, 0x64,       // LD     A 0x64
    0x57,             // LD     D A
    0xE0, 0x42,       // LD     [0xff00 + #SCY] A
    0x3E, 0x91,       // LD     A 0x91
    0xE0, 0x40,       // LD     [0xff00 + #LCDC] A
    0x04,             // INC    B

    // scroll_loop:
    0x1E, 0x02,       // LD     E 0x02

    // wait_next_vblank:
    0x0E, 0x0C,       // LD     C 0x0c

    // wait_vblank:
    0xF0, 0x44,       // LD     A [0xff00 + #LY]
    0xFE, 0x90,       // CP     A 0x90
    0x20, 0xFA,       // JR NZ  wait_vblank

    0x0D,             // DEC    C
    0x20, 0xF7,       // JR NZ  wait_vblank
    0x1D,             // DEC    E
    0x20, 0xF2,       // JR NZ  wait_next_vblank

    0x0E, 0x13,       // LD     C 0x13
    0x24,             // INC    H
    0x7C,             // LD     A H
    0x1E, 0x83,       // LD     E 0x83
    0xFE, 0x62,       // CP     A 0x62
    0x28, 0x06,       // JR Z   play_sound
    0x1E, 0xC1,       // LD     E 0xc1
    0xFE, 0x64,       // CP     A 0x64
    0x20, 0x06,       // JR NZ  skip_sound
    // play_sound:
    0x7B,             // LD     A E
    0xE2,             // LD     [0xff00 + C] A
    0x0C,             // INC    C
    0x3E, 0x87,       // LD     A 0x87
    0xE2,             // LD     [0xff00 + C] A
    // skip_sound:
    0xF0, 0x42,       // LD     A [0xff00 + #SCY]
    0x90,             // SUB    A B
    0xE0, 0x42,       // LD     [0xff00 + #SCY] A
    0x15,             // DEC    D
    0x20, 0xD2,       // JR NZ  scroll_loop
    0x05,             // DEC    B
    0x20, 0x4F,       // JN NZ  validate_cart
    0x16, 0x20,       // LD     D 0x20
    0x18, 0xCB,       // JR     scroll_loop

    // crc_0:
    0x4F,             // LD     C A
    // crc_1:
    0x06, 0x04,       // LD     B 0x04
    // crc_round:
    0xC5,             // PUSH   BC
    0xCB, 0x11,       // RL     C
    0x17,             // RL     A
    0xC1,             // POP    BC
    0xCB, 0x11,       // RL     C
    0x17,             // RL     A
    0x05,             // DEC    B
    0x20, 0xF5,       // JR NZ  crc_round

    0x22,             // LDI    [HL] A
    0x23,             // INC    HL
    0x22,             // LDI    [HL] A
    0x23,             // INC    HL
    0xC9,             // RET

    // expected_csum: bytes
    0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B,
    0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D,
    0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E,
    0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99,
    0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC,
    0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E,

    // tile_data: bytes
    0x3C, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x3C,

    // validate_cart:
    0x21, 0x04, 0x01, // LD     HL, 0x0104
    0x11, 0xA8, 0x00, // LD     DE, #expected_csum
    // checksum_check:
    0x1A,             // LD     A, [DE]
    0x13,             // INC    DE
    0xBE,             // CP     A, [HL]
    // This is an infinite loop when the checksum fails. Replacing
    // it with 0x00 0x00 (NOP NOP) will allow invalid ROMs to run.
    0x20, 0xFE,       // JR NZ  .
    0x23,             // INC    HL
    0x7D,             // LD     A L
    0xFE, 0x34,       // CP     A 0x32
    0x20, 0xF5,       // JR NZ  checksum_check
    0x06, 0x19,       // LD     B 0x19
    0x78,             // LD     A B
    // header_sum
    0x86,             // ADD    A [HL]
    0x23,             // INC    HL
    0x05,             // DEC    B
    0x20, 0xFB,       // JR NZ  header_sum
    0x86,             // ADD    A [HL]
    // same as above, infinite loop if the sum is bad, replace with
    // NOPs to run anyway.
    0x20, 0xFE,       // JR NZ  .
    0x3E, 0x01,       // LD A   0x1
    // There shouldn't be anything at that address, I assume that's
    // how you tell the hardware to unmap the bootrom
    0xE0, 0x50,       // LD [0xff00 + 0x50] A
    ];
<commit_msg>Fix typo in bootrom disassembly<commit_after>//! The GameBoy ROM that gets mapped at address 0 at startup. It's not
//! accessible during normal game execution.

/// Original GameBoy bootrom. It scrolls the NINTENDO logo down the
/// screen and emits the signature two notes when it reaches the
/// middle. It also checks that the cartridge ROM header is correct
/// and deadlocks if that check fails.
pub static BOOTROM: [u8, ..0x100] = [
    // init_stack:
    0x31, 0xFE, 0xFF, // LD     SP 0xfffe
    0xAF,             // XOR    A A
    0x21, 0xFF, 0x9F, // LD     HL #VRAM_END

    // clear_vram:
    0x32,             // LDD    [HL] A
    0xCB, 0x7C,       // BIT    H 7
    0x20, 0xFB,       // JR NZ  clear_vram

    // init_sound:
    0x21, 0x26, 0xFF, // LD     HL 0xff26
    0x0E, 0x11,       // LD     C 0x11
    0x3E, 0x80,       // LD     A 0x80
    0x32,             // LDD    [HL] A
    0xE2,             // LD     [0xff00 + C] A
    0x0C,             // INC    C
    0x3E, 0xF3,       // LD     A 0xf3
    0xE2,             // LD     [0xff00 + C] A
    0x32,             // LDD    [HL] A
    0x3E, 0x77,       // LD     A 0x77
    0x77,             // LD     [HL] A

    // init_palette:
    0x3E, 0xFC,       // LD     A 0xfc
    0xE0, 0x47,       // LD     [0xff00 + #BGP] A

    // init_crc:
    0x11, 0x04, 0x01, // LD     DE 0x0104
    0x21, 0x10, 0x80, // LD     HL 0x8010
    // crc_loop:
    0x1A,             // LD     A [DE]
    0xCD, 0x95, 0x00, // CALL   crc_0
    0xCD, 0x96, 0x00, // CALL   crc_1

    0x13,             // INC    DE
    0x7B,             // LD     A E
    0xFE, 0x34,       // CP     A 0x34
    0x20, 0xF3,       // JR NZ  do_crc

    0x11, 0xD8, 0x00, // LD     DE #tile_data
    0x06, 0x08,       // LD     B 8
    // copy_tile_map:
    0x1A,             // LD     A [DE]
    0x13,             // INC    DE
    0x22,             // LDI    [HL] A
    0x23,             // INC    HL
    0x05,             // DEC    B
    0x20, 0xF9,       // JR NZ  copy_tile_map

    // init_tile
    0x3E, 0x19,       // LD     A 0x19
    0xEA, 0x10, 0x99, // LD     [0x9910] A
    0x21, 0x2F, 0x99, // LD     HL 0x992f
    // init_tiles_loop
    0x0E, 0x0C,       // LD     C 0x0c
    // init_tiles_inner:
    0x3D,             // DEC    A
    0x28, 0x08,       // JR Z   init_scroll
    0x32,             // LDD    [HL] A
    0x0D,             // DEC    C
    0x20, 0xF9,       // JR NZ  init_tiles_inner
    0x2E, 0x0F,       // LD     L 0x0f
    0x18, 0xF3,       // JR     init_tiles_loop

    // init_scroll:
    0x67,             // LD     H A
    // Changing the following value to from 0x64 to 0x01 skips the
    // whole scrolling logo by displaying it directly in the middle of
    // the screen which makes the intro much shorter while having no
    // side effect that I know of.
    0x3E, 0x64,       // LD     A 0x64
    0x57,             // LD     D A
    0xE0, 0x42,       // LD     [0xff00 + #SCY] A
    0x3E, 0x91,       // LD     A 0x91
    0xE0, 0x40,       // LD     [0xff00 + #LCDC] A
    0x04,             // INC    B

    // scroll_loop:
    0x1E, 0x02,       // LD     E 0x02

    // wait_next_vblank:
    0x0E, 0x0C,       // LD     C 0x0c

    // wait_vblank:
    0xF0, 0x44,       // LD     A [0xff00 + #LY]
    0xFE, 0x90,       // CP     A 0x90
    0x20, 0xFA,       // JR NZ  wait_vblank

    0x0D,             // DEC    C
    0x20, 0xF7,       // JR NZ  wait_vblank
    0x1D,             // DEC    E
    0x20, 0xF2,       // JR NZ  wait_next_vblank

    0x0E, 0x13,       // LD     C 0x13
    0x24,             // INC    H
    0x7C,             // LD     A H
    0x1E, 0x83,       // LD     E 0x83
    0xFE, 0x62,       // CP     A 0x62
    0x28, 0x06,       // JR Z   play_sound
    0x1E, 0xC1,       // LD     E 0xc1
    0xFE, 0x64,       // CP     A 0x64
    0x20, 0x06,       // JR NZ  skip_sound
    // play_sound:
    0x7B,             // LD     A E
    0xE2,             // LD     [0xff00 + C] A
    0x0C,             // INC    C
    0x3E, 0x87,       // LD     A 0x87
    0xE2,             // LD     [0xff00 + C] A
    // skip_sound:
    0xF0, 0x42,       // LD     A [0xff00 + #SCY]
    0x90,             // SUB    A B
    0xE0, 0x42,       // LD     [0xff00 + #SCY] A
    0x15,             // DEC    D
    0x20, 0xD2,       // JR NZ  scroll_loop
    0x05,             // DEC    B
    0x20, 0x4F,       // JR NZ  validate_cart
    0x16, 0x20,       // LD     D 0x20
    0x18, 0xCB,       // JR     scroll_loop

    // crc_0:
    0x4F,             // LD     C A
    // crc_1:
    0x06, 0x04,       // LD     B 0x04
    // crc_round:
    0xC5,             // PUSH   BC
    0xCB, 0x11,       // RL     C
    0x17,             // RL     A
    0xC1,             // POP    BC
    0xCB, 0x11,       // RL     C
    0x17,             // RL     A
    0x05,             // DEC    B
    0x20, 0xF5,       // JR NZ  crc_round

    0x22,             // LDI    [HL] A
    0x23,             // INC    HL
    0x22,             // LDI    [HL] A
    0x23,             // INC    HL
    0xC9,             // RET

    // expected_csum: bytes
    0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B,
    0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D,
    0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E,
    0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99,
    0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC,
    0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E,

    // tile_data: bytes
    0x3C, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x3C,

    // validate_cart:
    0x21, 0x04, 0x01, // LD     HL, 0x0104
    0x11, 0xA8, 0x00, // LD     DE, #expected_csum
    // checksum_check:
    0x1A,             // LD     A, [DE]
    0x13,             // INC    DE
    0xBE,             // CP     A, [HL]
    // This is an infinite loop when the checksum fails. Replacing
    // it with 0x00 0x00 (NOP NOP) will allow invalid ROMs to run.
    0x20, 0xFE,       // JR NZ  .
    0x23,             // INC    HL
    0x7D,             // LD     A L
    0xFE, 0x34,       // CP     A 0x32
    0x20, 0xF5,       // JR NZ  checksum_check
    0x06, 0x19,       // LD     B 0x19
    0x78,             // LD     A B
    // header_sum
    0x86,             // ADD    A [HL]
    0x23,             // INC    HL
    0x05,             // DEC    B
    0x20, 0xFB,       // JR NZ  header_sum
    0x86,             // ADD    A [HL]
    // same as above, infinite loop if the sum is bad, replace with
    // NOPs to run anyway.
    0x20, 0xFE,       // JR NZ  .
    0x3E, 0x01,       // LD A   0x1
    // There shouldn't be anything at that address, I assume that's
    // how you tell the hardware to unmap the bootrom
    0xE0, 0x50,       // LD [0xff00 + 0x50] A
    ];
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// 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.

#![allow(missing_debug_implementations)]

//! This module implement all core commands.
use toml::Value;

use std::fs;
use std::path::Path;
use std::net::SocketAddr;
use std::collections::BTreeMap;

use blockchain::GenesisConfig;
use helpers::generate_testnet_config;
use helpers::config::ConfigFile;
use node::NodeConfig;
use storage::Database;
use crypto;

use blockchain::config::ValidatorKeys;

use super::internal::{Command, Feedback};
use super::{Argument, Context, CommandName};

use super::shared::{AbstractConfig, NodePublicConfig, SharedConfig, NodePrivateConfig,
                    CommonConfigTemplate};
use super::DEFAULT_EXONUM_LISTEN_PORT;

/// Run command.
pub struct Run;

impl Run {
    /// Returns the name of the `Run` command.
    pub fn name() -> CommandName {
        "run"
    }

    /// Returns created database instance.
    #[cfg(not(feature = "memorydb"))]
    pub fn db_helper(ctx: &Context) -> Box<Database> {
        use storage::{LevelDB, LevelDBOptions};

        let path = ctx.arg::<String>("LEVELDB_PATH").expect(
            "LEVELDB_PATH not found.",
        );
        let mut options = LevelDBOptions::new();
        options.create_if_missing = true;
        Box::new(LevelDB::open(Path::new(&path), options).unwrap())
    }

    /// Returns created database instance.
    #[cfg(feature = "memorydb")]
    pub fn db_helper(_: &Context) -> Box<Database> {
        use storage::MemoryDB;
        Box::new(MemoryDB::new())
    }

    fn node_config(ctx: &Context) -> NodeConfig {
        let path = ctx.arg::<String>("NODE_CONFIG_PATH").expect(
            "NODE_CONFIG_PATH not found.",
        );
        ConfigFile::load(path).unwrap()
    }

    fn public_api_address(ctx: &Context) -> Option<SocketAddr> {
        ctx.arg("PUBLIC_API_ADDRESS").ok()
    }

    fn private_api_address(ctx: &Context) -> Option<SocketAddr> {
        ctx.arg("PRIVATE_API_ADDRESS").ok()
    }
}

impl Command for Run {
    fn args(&self) -> Vec<Argument> {
        vec![
            Argument::new_named(
                "NODE_CONFIG_PATH",
                true,
                "Path to node configuration file.",
                "c",
                "node-config",
                false
            ),
            Argument::new_named(
                "LEVELDB_PATH",
                true,
                "Use leveldb database with the given path.",
                "d",
                "leveldb",
                false
            ),
            Argument::new_named(
                "PUBLIC_API_ADDRESS",
                false,
                "Listen address for public api.",
                None,
                "public-api-address",
                false
            ),
            Argument::new_named(
                "PRIVATE_API_ADDRESS",
                false,
                "Listen address for private api.",
                None,
                "private-api-address",
                false
            ),
        ]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Run application"
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {
        let config = Self::node_config(&context);
        let public_addr = Self::public_api_address(&context);
        let private_addr = Self::private_api_address(&context);

        context.set("node_config", config);
        let mut new_context = exts(context);
        let mut config: NodeConfig = new_context.get("node_config").expect(
            "cant load node_config",
        );
        // Override api options
        if let Some(addr) = public_addr {
            config.api.public_api_address = Some(addr);
        }
        if let Some(addr) = private_addr {
            config.api.private_api_address = Some(addr);
        }
        new_context.set("node_config", config);

        Feedback::RunNode(new_context)
    }
}

/// Command for the template generation.
pub struct GenerateCommonConfig;

impl GenerateCommonConfig {
    /// Returns the name of the `GenerateCommonConfig` command.
    pub fn name() -> CommandName {
        "generate-template"
    }
}

impl Command for GenerateCommonConfig {
    fn args(&self) -> Vec<Argument> {
        vec![Argument::new_positional("COMMON_CONFIG", true, "Path to common config.")]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Generate basic config template."
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {
        let template_path = context.arg::<String>("COMMON_CONFIG").expect(
            "COMMON_CONFIG not found",
        );

        context.set("services_config", AbstractConfig::default());
        let new_context = exts(context);
        let services_config = new_context.get("services_config").unwrap_or_default();

        let template = CommonConfigTemplate {
            services_config,
            ..CommonConfigTemplate::default()
        };

        ConfigFile::save(&template, template_path).expect("Could not write template file.");
        Feedback::None
    }
}

/// Command for the node configuration generation.
pub struct GenerateNodeConfig;

impl GenerateNodeConfig {
    /// Returns the name of the `GenerateNodeConfig` command.
    pub fn name() -> CommandName {
        "generate-config"
    }

    fn addr(context: &Context) -> (SocketAddr, SocketAddr) {
        let addr = context.arg::<String>("PEER_ADDR").unwrap_or_default();

        let mut addr_parts = addr.split(':');
        let ip = addr_parts.next().expect("Expected ip address");
        if ip.len() < 8 {
            panic!("Expected ip address in PEER_ADDR.")
        }
        let port = addr_parts.next().map_or(DEFAULT_EXONUM_LISTEN_PORT, |s| {
            s.parse().expect("could not parse port")
        });
        let external_addr = format!("{}:{}", ip, port);
        let listen_addr = format!("0.0.0.0:{}", port);
        (external_addr.parse().unwrap(), listen_addr.parse().unwrap())
    }
}

impl Command for GenerateNodeConfig {
    fn args(&self) -> Vec<Argument> {
        vec![
            Argument::new_positional("COMMON_CONFIG", true, "Path to common config."),
            Argument::new_positional("PUB_CONFIG", true, "Path where save public config."),
            Argument::new_positional("SEC_CONFIG", true, "Path where save private config."),
            Argument::new_named(
                "PEER_ADDR",
                true,
                "Remote peer address",
                "a",
                "peer-addr",
                false
            ),
        ]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Generate node secret and public configs."
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {
        let common_config_path = context.arg::<String>("COMMON_CONFIG").expect(
            "expected common config path",
        );
        let pub_config_path = context.arg::<String>("PUB_CONFIG").expect(
            "expected public config path",
        );
        let priv_config_path = context.arg::<String>("SEC_CONFIG").expect(
            "expected secret config path",
        );

        let addr = Self::addr(&context);
        let common: CommonConfigTemplate =
            ConfigFile::load(&common_config_path).expect("Could not load common config");
        context.set("common_config", common.clone());
        context.set(
            "services_public_configs",
            BTreeMap::<String, Value>::default(),
        );
        context.set(
            "services_secret_configs",
            BTreeMap::<String, Value>::default(),
        );
        let new_context = exts(context);
        let services_public_configs = new_context.get("services_public_configs").unwrap();
        let services_secret_configs = new_context.get("services_secret_configs");

        let (consensus_public_key, consensus_secret_key) = crypto::gen_keypair();
        let (service_public_key, service_secret_key) = crypto::gen_keypair();

        let validator_keys = ValidatorKeys {
            consensus_key: consensus_public_key,
            service_key: service_public_key,
        };
        let node_pub_config = NodePublicConfig {
            addr: addr.0,
            validator_keys,
            services_public_configs,
        };
        let shared_config = SharedConfig {
            node: node_pub_config,
            common: common,
        };
        // save public config seperately
        ConfigFile::save(&shared_config, &pub_config_path).expect(
            "Could not write public config file.",
        );

        let priv_config = NodePrivateConfig {
            listen_addr: addr.1,
            consensus_public_key,
            consensus_secret_key,
            service_public_key,
            service_secret_key,
            services_secret_configs: services_secret_configs.expect(
                "services_secret_configs not found after exts call",
            ),
        };

        ConfigFile::save(&priv_config, priv_config_path).expect(
            "Could not write secret config file.",
        );
        Feedback::None
    }
}

/// Finalize command.
pub struct Finalize;

impl Finalize {
    /// Returns the name of the `Finalize` command.
    pub fn name() -> CommandName {
        "finalize"
    }

    /// Returns `GenesisConfig` from the template.
    fn genesis_from_template(
        template: CommonConfigTemplate,
        configs: Vec<NodePublicConfig>,
    ) -> GenesisConfig {
        GenesisConfig::new_with_consensus(
            template.consensus_config,
            configs.iter().map(|c| c.validator_keys),
        )
    }

    fn reduce_configs(
        public_configs: Vec<SharedConfig>,
        our_config: &NodePrivateConfig,
    ) -> (CommonConfigTemplate, Vec<NodePublicConfig>, NodePublicConfig) {
        let mut map = BTreeMap::new();
        let mut config_iter = public_configs.into_iter();
        let first = config_iter.next().expect(
            "Expected at least one config in PUBLIC_CONFIGS",
        );
        let common = first.common;
        map.insert(first.node.validator_keys.consensus_key, first.node);

        for config in config_iter {
            if common != config.common {
                panic!("Found config with different common part.");
            };
            if map.insert(config.node.validator_keys.consensus_key, config.node)
                .is_some()
            {
                panic!("Found duplicate consenus keys in PUBLIC_CONFIGS");
            }

        }
        (
            common,
            map.iter().map(|(_, &ref c)| c.clone()).collect(),
            map.get(&our_config.consensus_public_key)
                .expect("our key not found in config")
                .clone(),
        )
    }
}

impl Command for Finalize {
    fn args(&self) -> Vec<Argument> {
        vec![
            Argument::new_named(
                "PUBLIC_CONFIGS",
                true,
                "Path to validators public configs",
                "p",
                "public-configs",
                true
            ),
            Argument::new_positional("SECRET_CONFIG", true, "Path to our secret config."),
            Argument::new_positional("OUTPUT_CONFIG_PATH", true, "Path to output node config."),
        ]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Collect public and secret configs into node config."
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {
        let public_configs_path = context.arg_multiple::<String>("PUBLIC_CONFIGS").expect(
            "keychain path not found",
        );
        let secret_config_path = context.arg::<String>("SECRET_CONFIG").expect(
            "config path not found",
        );
        let output_config_path = context.arg::<String>("OUTPUT_CONFIG_PATH").expect(
            "config path not found",
        );

        let secret_config: NodePrivateConfig =
            ConfigFile::load(secret_config_path).expect("Failed to load key config.");
        let public_configs: Vec<SharedConfig> = public_configs_path
            .into_iter()
            .map(|path| {
                ConfigFile::load(path).expect("Failed to load validator public config.")
            })
            .collect();
        let (common, list, our) = Self::reduce_configs(public_configs, &secret_config);
        let peers = list.iter().map(|c| c.addr).collect();

        let genesis = Self::genesis_from_template(common.clone(), list.clone());

        let config = {
            NodeConfig {
                listen_address: secret_config.listen_addr,
                external_address: Some(our.addr),
                network: Default::default(),
                whitelist: Default::default(),
                peers: peers,
                consensus_public_key: secret_config.consensus_public_key,
                consensus_secret_key: secret_config.consensus_secret_key,
                service_public_key: secret_config.service_public_key,
                service_secret_key: secret_config.service_secret_key,
                genesis: genesis,
                api: Default::default(),
                mempool: Default::default(),
                services_configs: Default::default(),
            }
        };

        context.set("public_config_list", list);
        context.set("node_config", config);
        context.set("common_config", common);
        context.set(
            "services_secret_configs",
            secret_config.services_secret_configs,
        );

        let new_context = exts(context);

        let config: NodeConfig = new_context.get("node_config").expect(
            "Could not create config from template, services return error",
        );
        ConfigFile::save(&config, output_config_path).expect("Could not write config file.");

        Feedback::None
    }
}

/// Command for the testnet generation.
pub struct GenerateTestnet;

impl GenerateTestnet {
    /// Returns the name of the `GenerateTestnet` command.
    pub fn name() -> CommandName {
        "generate-testnet"
    }
}

impl Command for GenerateTestnet {
    fn args(&self) -> Vec<Argument> {
        vec![
            Argument::new_named(
                "OUTPUT_DIR",
                true,
                "Path to directory where save configs.",
                "o",
                "output_dir",
                false
            ),
            Argument::new_named(
                "START_PORT",
                false,
                "Port number started from which should validators listen.",
                "p",
                "start",
                false
            ),
            Argument::new_positional("COUNT", true, "Count of validators in testnet."),
        ]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Generates genesis configuration for testnet"
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {

        let dir = context.arg::<String>("OUTPUT_DIR").expect("output dir");
        let count: u8 = context.arg("COUNT").expect("count as int");
        let start_port = context.arg::<u16>("START_PORT").unwrap_or(
            DEFAULT_EXONUM_LISTEN_PORT,
        );

        let dir = Path::new(&dir);
        let dir = dir.join("validators");
        if !dir.exists() {
            fs::create_dir_all(&dir).unwrap();
        }

        let configs = generate_testnet_config(count, start_port);
        context.set("configs", configs);
        let new_context = exts(context);
        let configs: Vec<NodeConfig> = new_context.get("configs").expect(
            "Couldn't read testnet configs after exts call.",
        );

        for (idx, cfg) in configs.into_iter().enumerate() {
            let file_name = format!("{}.toml", idx);
            ConfigFile::save(&cfg, &dir.join(file_name)).unwrap();
        }

        Feedback::None
    }
}
<commit_msg>Dissalow generate-testnet with 0 nodes.<commit_after>// Copyright 2017 The Exonum Team
//
// 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.

#![allow(missing_debug_implementations)]

//! This module implement all core commands.
use toml::Value;

use std::fs;
use std::path::Path;
use std::net::SocketAddr;
use std::collections::BTreeMap;

use blockchain::GenesisConfig;
use helpers::generate_testnet_config;
use helpers::config::ConfigFile;
use node::NodeConfig;
use storage::Database;
use crypto;

use blockchain::config::ValidatorKeys;

use super::internal::{Command, Feedback};
use super::{Argument, Context, CommandName};

use super::shared::{AbstractConfig, NodePublicConfig, SharedConfig, NodePrivateConfig,
                    CommonConfigTemplate};
use super::DEFAULT_EXONUM_LISTEN_PORT;

/// Run command.
pub struct Run;

impl Run {
    /// Returns the name of the `Run` command.
    pub fn name() -> CommandName {
        "run"
    }

    /// Returns created database instance.
    #[cfg(not(feature = "memorydb"))]
    pub fn db_helper(ctx: &Context) -> Box<Database> {
        use storage::{LevelDB, LevelDBOptions};

        let path = ctx.arg::<String>("LEVELDB_PATH").expect(
            "LEVELDB_PATH not found.",
        );
        let mut options = LevelDBOptions::new();
        options.create_if_missing = true;
        Box::new(LevelDB::open(Path::new(&path), options).unwrap())
    }

    /// Returns created database instance.
    #[cfg(feature = "memorydb")]
    pub fn db_helper(_: &Context) -> Box<Database> {
        use storage::MemoryDB;
        Box::new(MemoryDB::new())
    }

    fn node_config(ctx: &Context) -> NodeConfig {
        let path = ctx.arg::<String>("NODE_CONFIG_PATH").expect(
            "NODE_CONFIG_PATH not found.",
        );
        ConfigFile::load(path).unwrap()
    }

    fn public_api_address(ctx: &Context) -> Option<SocketAddr> {
        ctx.arg("PUBLIC_API_ADDRESS").ok()
    }

    fn private_api_address(ctx: &Context) -> Option<SocketAddr> {
        ctx.arg("PRIVATE_API_ADDRESS").ok()
    }
}

impl Command for Run {
    fn args(&self) -> Vec<Argument> {
        vec![
            Argument::new_named(
                "NODE_CONFIG_PATH",
                true,
                "Path to node configuration file.",
                "c",
                "node-config",
                false
            ),
            Argument::new_named(
                "LEVELDB_PATH",
                true,
                "Use leveldb database with the given path.",
                "d",
                "leveldb",
                false
            ),
            Argument::new_named(
                "PUBLIC_API_ADDRESS",
                false,
                "Listen address for public api.",
                None,
                "public-api-address",
                false
            ),
            Argument::new_named(
                "PRIVATE_API_ADDRESS",
                false,
                "Listen address for private api.",
                None,
                "private-api-address",
                false
            ),
        ]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Run application"
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {
        let config = Self::node_config(&context);
        let public_addr = Self::public_api_address(&context);
        let private_addr = Self::private_api_address(&context);

        context.set("node_config", config);
        let mut new_context = exts(context);
        let mut config: NodeConfig = new_context.get("node_config").expect(
            "cant load node_config",
        );
        // Override api options
        if let Some(addr) = public_addr {
            config.api.public_api_address = Some(addr);
        }
        if let Some(addr) = private_addr {
            config.api.private_api_address = Some(addr);
        }
        new_context.set("node_config", config);

        Feedback::RunNode(new_context)
    }
}

/// Command for the template generation.
pub struct GenerateCommonConfig;

impl GenerateCommonConfig {
    /// Returns the name of the `GenerateCommonConfig` command.
    pub fn name() -> CommandName {
        "generate-template"
    }
}

impl Command for GenerateCommonConfig {
    fn args(&self) -> Vec<Argument> {
        vec![Argument::new_positional("COMMON_CONFIG", true, "Path to common config.")]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Generate basic config template."
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {
        let template_path = context.arg::<String>("COMMON_CONFIG").expect(
            "COMMON_CONFIG not found",
        );

        context.set("services_config", AbstractConfig::default());
        let new_context = exts(context);
        let services_config = new_context.get("services_config").unwrap_or_default();

        let template = CommonConfigTemplate {
            services_config,
            ..CommonConfigTemplate::default()
        };

        ConfigFile::save(&template, template_path).expect("Could not write template file.");
        Feedback::None
    }
}

/// Command for the node configuration generation.
pub struct GenerateNodeConfig;

impl GenerateNodeConfig {
    /// Returns the name of the `GenerateNodeConfig` command.
    pub fn name() -> CommandName {
        "generate-config"
    }

    fn addr(context: &Context) -> (SocketAddr, SocketAddr) {
        let addr = context.arg::<String>("PEER_ADDR").unwrap_or_default();

        let mut addr_parts = addr.split(':');
        let ip = addr_parts.next().expect("Expected ip address");
        if ip.len() < 8 {
            panic!("Expected ip address in PEER_ADDR.")
        }
        let port = addr_parts.next().map_or(DEFAULT_EXONUM_LISTEN_PORT, |s| {
            s.parse().expect("could not parse port")
        });
        let external_addr = format!("{}:{}", ip, port);
        let listen_addr = format!("0.0.0.0:{}", port);
        (external_addr.parse().unwrap(), listen_addr.parse().unwrap())
    }
}

impl Command for GenerateNodeConfig {
    fn args(&self) -> Vec<Argument> {
        vec![
            Argument::new_positional("COMMON_CONFIG", true, "Path to common config."),
            Argument::new_positional("PUB_CONFIG", true, "Path where save public config."),
            Argument::new_positional("SEC_CONFIG", true, "Path where save private config."),
            Argument::new_named(
                "PEER_ADDR",
                true,
                "Remote peer address",
                "a",
                "peer-addr",
                false
            ),
        ]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Generate node secret and public configs."
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {
        let common_config_path = context.arg::<String>("COMMON_CONFIG").expect(
            "expected common config path",
        );
        let pub_config_path = context.arg::<String>("PUB_CONFIG").expect(
            "expected public config path",
        );
        let priv_config_path = context.arg::<String>("SEC_CONFIG").expect(
            "expected secret config path",
        );

        let addr = Self::addr(&context);
        let common: CommonConfigTemplate =
            ConfigFile::load(&common_config_path).expect("Could not load common config");
        context.set("common_config", common.clone());
        context.set(
            "services_public_configs",
            BTreeMap::<String, Value>::default(),
        );
        context.set(
            "services_secret_configs",
            BTreeMap::<String, Value>::default(),
        );
        let new_context = exts(context);
        let services_public_configs = new_context.get("services_public_configs").unwrap();
        let services_secret_configs = new_context.get("services_secret_configs");

        let (consensus_public_key, consensus_secret_key) = crypto::gen_keypair();
        let (service_public_key, service_secret_key) = crypto::gen_keypair();

        let validator_keys = ValidatorKeys {
            consensus_key: consensus_public_key,
            service_key: service_public_key,
        };
        let node_pub_config = NodePublicConfig {
            addr: addr.0,
            validator_keys,
            services_public_configs,
        };
        let shared_config = SharedConfig {
            node: node_pub_config,
            common: common,
        };
        // save public config seperately
        ConfigFile::save(&shared_config, &pub_config_path).expect(
            "Could not write public config file.",
        );

        let priv_config = NodePrivateConfig {
            listen_addr: addr.1,
            consensus_public_key,
            consensus_secret_key,
            service_public_key,
            service_secret_key,
            services_secret_configs: services_secret_configs.expect(
                "services_secret_configs not found after exts call",
            ),
        };

        ConfigFile::save(&priv_config, priv_config_path).expect(
            "Could not write secret config file.",
        );
        Feedback::None
    }
}

/// Finalize command.
pub struct Finalize;

impl Finalize {
    /// Returns the name of the `Finalize` command.
    pub fn name() -> CommandName {
        "finalize"
    }

    /// Returns `GenesisConfig` from the template.
    fn genesis_from_template(
        template: CommonConfigTemplate,
        configs: Vec<NodePublicConfig>,
    ) -> GenesisConfig {
        GenesisConfig::new_with_consensus(
            template.consensus_config,
            configs.iter().map(|c| c.validator_keys),
        )
    }

    fn reduce_configs(
        public_configs: Vec<SharedConfig>,
        our_config: &NodePrivateConfig,
    ) -> (CommonConfigTemplate, Vec<NodePublicConfig>, NodePublicConfig) {
        let mut map = BTreeMap::new();
        let mut config_iter = public_configs.into_iter();
        let first = config_iter.next().expect(
            "Expected at least one config in PUBLIC_CONFIGS",
        );
        let common = first.common;
        map.insert(first.node.validator_keys.consensus_key, first.node);

        for config in config_iter {
            if common != config.common {
                panic!("Found config with different common part.");
            };
            if map.insert(config.node.validator_keys.consensus_key, config.node)
                .is_some()
            {
                panic!("Found duplicate consenus keys in PUBLIC_CONFIGS");
            }

        }
        (
            common,
            map.iter().map(|(_, &ref c)| c.clone()).collect(),
            map.get(&our_config.consensus_public_key)
                .expect("our key not found in config")
                .clone(),
        )
    }
}

impl Command for Finalize {
    fn args(&self) -> Vec<Argument> {
        vec![
            Argument::new_named(
                "PUBLIC_CONFIGS",
                true,
                "Path to validators public configs",
                "p",
                "public-configs",
                true
            ),
            Argument::new_positional("SECRET_CONFIG", true, "Path to our secret config."),
            Argument::new_positional("OUTPUT_CONFIG_PATH", true, "Path to output node config."),
        ]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Collect public and secret configs into node config."
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {
        let public_configs_path = context.arg_multiple::<String>("PUBLIC_CONFIGS").expect(
            "keychain path not found",
        );
        let secret_config_path = context.arg::<String>("SECRET_CONFIG").expect(
            "config path not found",
        );
        let output_config_path = context.arg::<String>("OUTPUT_CONFIG_PATH").expect(
            "config path not found",
        );

        let secret_config: NodePrivateConfig =
            ConfigFile::load(secret_config_path).expect("Failed to load key config.");
        let public_configs: Vec<SharedConfig> = public_configs_path
            .into_iter()
            .map(|path| {
                ConfigFile::load(path).expect("Failed to load validator public config.")
            })
            .collect();
        let (common, list, our) = Self::reduce_configs(public_configs, &secret_config);
        let peers = list.iter().map(|c| c.addr).collect();

        let genesis = Self::genesis_from_template(common.clone(), list.clone());

        let config = {
            NodeConfig {
                listen_address: secret_config.listen_addr,
                external_address: Some(our.addr),
                network: Default::default(),
                whitelist: Default::default(),
                peers: peers,
                consensus_public_key: secret_config.consensus_public_key,
                consensus_secret_key: secret_config.consensus_secret_key,
                service_public_key: secret_config.service_public_key,
                service_secret_key: secret_config.service_secret_key,
                genesis: genesis,
                api: Default::default(),
                mempool: Default::default(),
                services_configs: Default::default(),
            }
        };

        context.set("public_config_list", list);
        context.set("node_config", config);
        context.set("common_config", common);
        context.set(
            "services_secret_configs",
            secret_config.services_secret_configs,
        );

        let new_context = exts(context);

        let config: NodeConfig = new_context.get("node_config").expect(
            "Could not create config from template, services return error",
        );
        ConfigFile::save(&config, output_config_path).expect("Could not write config file.");

        Feedback::None
    }
}

/// Command for the testnet generation.
pub struct GenerateTestnet;

impl GenerateTestnet {
    /// Returns the name of the `GenerateTestnet` command.
    pub fn name() -> CommandName {
        "generate-testnet"
    }
}

impl Command for GenerateTestnet {
    fn args(&self) -> Vec<Argument> {
        vec![
            Argument::new_named(
                "OUTPUT_DIR",
                true,
                "Path to directory where save configs.",
                "o",
                "output_dir",
                false
            ),
            Argument::new_named(
                "START_PORT",
                false,
                "Port number started from which should validators listen.",
                "p",
                "start",
                false
            ),
            Argument::new_positional("COUNT", true, "Count of validators in testnet."),
        ]
    }

    fn name(&self) -> CommandName {
        Self::name()
    }

    fn about(&self) -> &str {
        "Generates genesis configuration for testnet"
    }

    fn execute(&self, mut context: Context, exts: &Fn(Context) -> Context) -> Feedback {

        let dir = context.arg::<String>("OUTPUT_DIR").expect("output dir");
        let count: u8 = context.arg("COUNT").expect("count as int");
        let start_port = context.arg::<u16>("START_PORT").unwrap_or(
            DEFAULT_EXONUM_LISTEN_PORT,
        );

        if count == 0 {
            panic!("Can't generate testnet with zero nodes count.");
        }

        let dir = Path::new(&dir);
        let dir = dir.join("validators");
        if !dir.exists() {
            fs::create_dir_all(&dir).unwrap();
        }

        let configs = generate_testnet_config(count, start_port);
        context.set("configs", configs);
        let new_context = exts(context);
        let configs: Vec<NodeConfig> = new_context.get("configs").expect(
            "Couldn't read testnet configs after exts call.",
        );

        for (idx, cfg) in configs.into_iter().enumerate() {
            let file_name = format!("{}.toml", idx);
            ConfigFile::save(&cfg, &dir.join(file_name)).unwrap();
        }

        Feedback::None
    }
}
<|endoftext|>