<commit_before>// Copyright 2021 Google LLC
//
// 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
//
//    https://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.

// This example shows some Rust subclasses of C++ classes.

mod uwu;

use autocxx::include_cpp;
use autocxx::subclass::{is_subclass, CppSubclass, CppSubclassDefault};
use cxx::CxxString;
use std::cell::RefCell;
use std::rc::Rc;

include_cpp! {
    #include "messages.h"
    safety!(unsafe) // unsafety policy; see docs
}

static SHAKESPEARE_QUOTES: [&str; 10] = [
    "All that glitters is not gold",
    "Hell is empty and all the devils are here.",
    "Good night, good night! parting is such sweet sorrow, That I shall say good night till it be morrow.",
    "These violent delights have violent ends...",
    "Something is rotten in the state of Denmark.",
    "Love all, trust a few, do wrong to none.",
    "The lady doth protest too much, methinks.",
    "Brevity is the soul of wit.",
    "Uneasy lies the head that wears a crown.",
    "Now is the winter of our discontent.",
];

// Here's the definition of MessageDisplayer from src/messages.h:
// ```cpp
// class MessageDisplayer {
// public:
//     virtual void display_message(const std::string& message) const = 0;
//     virtual ~MessageDisplayer() {};
// };
// ```
// The following lines define a subclass of MessageDisplayer,
// together with the "subclass!" directive above in the include_cpp!
// macro. See the main function at the bottom for how this subclass
// is instantiated.

#[is_subclass(superclass("MessageDisplayer"))]
#[derive(Default)]
pub struct UwuDisplayer {}

// As this type derives from Default, this makes some
// default constructors available (used later). This might later
// move into syntactic sugar like `#[derive(DefaultCppSubclass)]`.
impl CppSubclassDefault<ffi::UwuDisplayerCpp> for UwuDisplayer {}

impl ffi::MessageDisplayer_methods for UwuDisplayer {
    fn display_message(&self, msg: &CxxString) {
        let uwu = uwu::uwu(msg.to_str().unwrap());
        println!("{}", uwu);
    }
}

// And here's a different pure virtual class.
// Here's its definition from src/messages.h:
// ```cpp
// class MessageProducer {
// public:
//     virtual std::string get_message() const = 0;
//     virtual ~MessageProducer() {};
// };
// ```
// This one is notable only in that the interface of the C++ class
// involves std::string, yet in Rust the subclass uses
// std::unique_ptr<std::string> (for all the normal reasons in autocxx -
// for now, at least, we can't hold non-trivial C++ objects on the Rust stack.)
// All the boxing and unboxing is done automatically by autocxx layers.

#[is_subclass(superclass("MessageProducer"))]
#[derive(Default)]
pub struct QuoteProducer {}

// This does the same as the `impl CppSubclassDefault` for the previous example;
// either could be used. This is just a bit more explicit.
impl QuoteProducer {
    fn new() -> Rc<RefCell<Self>> {
        Self::new_rust_owned(Self::default())
    }
}

impl ffi::MessageProducer_methods for QuoteProducer {
    fn get_message(&self) -> cxx::UniquePtr<CxxString> {
        use ffi::ToCppString;
        SHAKESPEARE_QUOTES[fastrand::usize(0..SHAKESPEARE_QUOTES.len())].into_cpp()
    }
}

// Here's another subclass of the same 'displayer' class.
// This one is more complex in two ways.
//
// First, we actually want to store some data here in our subclass.
// That means we can't just allocate ourselves with Default::default().
// And that means we need to be aware of the cpp_peer field which is
// added by the #[subclass] macro.
//
// Second, we're going to simulate the observer/listener type pattern
// in C++ where a const* is used to send messages around a codebase yet
// recipients need to react by mutating themselves or otherwise actively
// doing stuff. In C++ you'd probably need a const_cast. Here we use
// interior mutability.

#[is_subclass(superclass("MessageDisplayer"))]
pub struct BoxDisplayer {
    message_count: RefCell<usize>,
}

impl BoxDisplayer {
    fn new() -> Rc<RefCell<Self>> {
        Self::new_rust_owned(Self {
            // As we're allocating this class ourselves instead of using [`Default`]
            // we need to initialize the `cpp_peer` member ourselves. This member is
            // inserted by the `#[is_subclass]` annotation. autocxx will
            // later use this to store a pointer back to the C++ peer.
            cpp_peer: Default::default(),
            message_count: RefCell::new(1usize),
        })
    }
}

impl ffi::MessageDisplayer_methods for BoxDisplayer {
    fn display_message(&self, msg: &CxxString) {
        let msg = textwrap::fill(msg.to_str().unwrap(), 70);
        let horz_line = std::iter::repeat("#").take(74).collect::<String>();
        println!("{}", horz_line);
        let msgmsg = format!("Message {}", self.message_count.borrow());
        self.message_count.replace_with(|old| *old + 1usize);
        println!("# {:^70} #", msgmsg);
        println!("{}", horz_line);
        for l in msg.lines() {
            println!("# {:^70} #", l);
        }
        println!("{}", horz_line);
    }
}

fn main() {
    ffi::register_cpp_thingies();
    // Construct a Rust-owned UwuDisplayer. We can also construct
    // a C++-owned or self-owned subclass - see docs for `CppSubclass`.
    let uwu = UwuDisplayer::default_rust_owned();
    // The next line casts the &UwuDisplayerCpp to a &MessageDisplayer.
    ffi::register_displayer(uwu.as_ref().borrow().as_ref());
    // Constructs in just the same way as the first one, but using
    // our explicit constructor.
    let boxd = BoxDisplayer::new();
    ffi::register_displayer(boxd.as_ref().borrow().as_ref());
    let shakespeare = QuoteProducer::new();
    ffi::register_producer(shakespeare.as_ref().borrow().as_ref());
    ffi::run_demo();
    ffi::run_demo();
}
<commit_msg>Adjust example suitably.<commit_after>// Copyright 2021 Google LLC
//
// 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
//
//    https://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.

// This example shows some Rust subclasses of C++ classes.

mod uwu;

use autocxx::include_cpp;
use autocxx::subclass::{is_subclass, CppSubclass, CppSubclassDefault, CppSubclassDefaultImpl};
use cxx::CxxString;
use std::cell::RefCell;
use std::rc::Rc;

include_cpp! {
    #include "messages.h"
    safety!(unsafe) // unsafety policy; see docs
}

static SHAKESPEARE_QUOTES: [&str; 10] = [
    "All that glitters is not gold",
    "Hell is empty and all the devils are here.",
    "Good night, good night! parting is such sweet sorrow, That I shall say good night till it be morrow.",
    "These violent delights have violent ends...",
    "Something is rotten in the state of Denmark.",
    "Love all, trust a few, do wrong to none.",
    "The lady doth protest too much, methinks.",
    "Brevity is the soul of wit.",
    "Uneasy lies the head that wears a crown.",
    "Now is the winter of our discontent.",
];

// Here's the definition of MessageDisplayer from src/messages.h:
// ```cpp
// class MessageDisplayer {
// public:
//     virtual void display_message(const std::string& message) const = 0;
//     virtual ~MessageDisplayer() {};
// };
// ```
// The following lines define a subclass of MessageDisplayer,
// together with the "subclass!" directive above in the include_cpp!
// macro. See the main function at the bottom for how this subclass
// is instantiated.

#[is_subclass(superclass("MessageDisplayer"))]
#[derive(CppSubclassDefault, Default)]
pub struct UwuDisplayer {}

impl ffi::MessageDisplayer_methods for UwuDisplayer {
    fn display_message(&self, msg: &CxxString) {
        let uwu = uwu::uwu(msg.to_str().unwrap());
        println!("{}", uwu);
    }
}

// And here's a different pure virtual class.
// Here's its definition from src/messages.h:
// ```cpp
// class MessageProducer {
// public:
//     virtual std::string get_message() const = 0;
//     virtual ~MessageProducer() {};
// };
// ```
// This one is notable only in that the interface of the C++ class
// involves std::string, yet in Rust the subclass uses
// std::unique_ptr<std::string> (for all the normal reasons in autocxx -
// for now, at least, we can't hold non-trivial C++ objects on the Rust stack.)
// All the boxing and unboxing is done automatically by autocxx layers.

#[is_subclass(superclass("MessageProducer"))]
#[derive(Default)]
pub struct QuoteProducer {}

// This does the same as the `impl CppSubclassDefault` for the previous example;
// either could be used. This is just a bit more explicit.
impl QuoteProducer {
    fn new() -> Rc<RefCell<Self>> {
        Self::new_rust_owned(Self::default())
    }
}

impl ffi::MessageProducer_methods for QuoteProducer {
    fn get_message(&self) -> cxx::UniquePtr<CxxString> {
        use ffi::ToCppString;
        SHAKESPEARE_QUOTES[fastrand::usize(0..SHAKESPEARE_QUOTES.len())].into_cpp()
    }
}

// Here's another subclass of the same 'displayer' class.
// This one is more complex in two ways.
//
// First, we actually want to store some data here in our subclass.
// That means we can't just allocate ourselves with Default::default().
// And that means we need to be aware of the cpp_peer field which is
// added by the #[subclass] macro.
//
// Second, we're going to simulate the observer/listener type pattern
// in C++ where a const* is used to send messages around a codebase yet
// recipients need to react by mutating themselves or otherwise actively
// doing stuff. In C++ you'd probably need a const_cast. Here we use
// interior mutability.

#[is_subclass(superclass("MessageDisplayer"))]
pub struct BoxDisplayer {
    message_count: RefCell<usize>,
}

impl BoxDisplayer {
    fn new() -> Rc<RefCell<Self>> {
        Self::new_rust_owned(Self {
            // As we're allocating this class ourselves instead of using [`Default`]
            // we need to initialize the `cpp_peer` member ourselves. This member is
            // inserted by the `#[is_subclass]` annotation. autocxx will
            // later use this to store a pointer back to the C++ peer.
            cpp_peer: Default::default(),
            message_count: RefCell::new(1usize),
        })
    }
}

impl ffi::MessageDisplayer_methods for BoxDisplayer {
    fn display_message(&self, msg: &CxxString) {
        let msg = textwrap::fill(msg.to_str().unwrap(), 70);
        let horz_line = std::iter::repeat("#").take(74).collect::<String>();
        println!("{}", horz_line);
        let msgmsg = format!("Message {}", self.message_count.borrow());
        self.message_count.replace_with(|old| *old + 1usize);
        println!("# {:^70} #", msgmsg);
        println!("{}", horz_line);
        for l in msg.lines() {
            println!("# {:^70} #", l);
        }
        println!("{}", horz_line);
    }
}

fn main() {
    ffi::register_cpp_thingies();
    // Construct a Rust-owned UwuDisplayer. We can also construct
    // a C++-owned or self-owned subclass - see docs for `CppSubclass`.
    let uwu = UwuDisplayer::default_rust_owned();
    // The next line casts the &UwuDisplayerCpp to a &MessageDisplayer.
    ffi::register_displayer(uwu.as_ref().borrow().as_ref());
    // Constructs in just the same way as the first one, but using
    // our explicit constructor.
    let boxd = BoxDisplayer::new();
    ffi::register_displayer(boxd.as_ref().borrow().as_ref());
    let shakespeare = QuoteProducer::new();
    ffi::register_producer(shakespeare.as_ref().borrow().as_ref());
    ffi::run_demo();
    ffi::run_demo();
}
<|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.

//! An implementation of `RocksDB` database.

use exonum_profiler::ProfilerSpan;
use rocksdb::{self, WriteBatch, DBIterator};
use rocksdb::utils::get_cf_names;

use std::mem;
use std::sync::Arc;
use std::path::Path;
use std::fmt;
use std::error::Error;
use std::iter::Peekable;

use storage::{self, Database, Iterator, Iter, Snapshot, Patch};
use storage::db::Change;

pub use rocksdb::{Options as RocksDBOptions, WriteOptions as RocksDBWriteOptions};
pub use rocksdb::BlockBasedOptions as RocksBlockOptions;

impl From<rocksdb::Error> for storage::Error {
    fn from(err: rocksdb::Error) -> storage::Error {
        storage::Error::new(err.description())
    }
}

/// Database implementation on the top of `RocksDB` backend.
pub struct RocksDB {
    db: Arc<rocksdb::DB>,
}

/// A snapshot of a `RocksDB`.
pub struct RocksDBSnapshot {
    snapshot: rocksdb::Snapshot<'static>,
    _db: Arc<rocksdb::DB>,
}

/// An iterator over the entries of a `RocksDB`.
struct RocksDBIterator {
    iter: Peekable<DBIterator>,
    key: Option<Box<[u8]>>,
    value: Option<Box<[u8]>>,
}

impl RocksDB {
    /// Open a database stored in the specified path with the specified options.
    pub fn open<P: AsRef<Path>>(path: P, options: &RocksDBOptions) -> storage::Result<RocksDB> {
        let db = {
            if let Ok(names) = get_cf_names(&path) {
                let cf_names = names.iter().map(|name| name.as_str()).collect::<Vec<_>>();
                rocksdb::DB::open_cf(options, path, cf_names.as_ref())?
            } else {
                rocksdb::DB::open(options, path)?
            }
        };
        Ok(RocksDB { db: Arc::new(db) })
    }

    fn do_merge(&self, patch: Patch, w_opts: &RocksDBWriteOptions) -> storage::Result<()> {
        let _p = ProfilerSpan::new("RocksDB::merge");
        let mut batch = WriteBatch::default();
        for (cf_name, changes) in patch {
            let cf = match self.db.cf_handle(&cf_name) {
                Some(cf) => cf,
                None => {
                    self.db
                        .create_cf(&cf_name, &RocksDBOptions::default())
                        .unwrap()
                }
            };
            for (key, change) in changes {
                match change {
                    Change::Put(ref value) => batch.put_cf(cf, key.as_ref(), value)?,
                    Change::Delete => batch.delete_cf(cf, &key)?,
                }
            }
        }
        self.db.write_opt(batch, w_opts).map_err(Into::into)
    }
}

impl Database for RocksDB {
    fn snapshot(&self) -> Box<Snapshot> {
        let _p = ProfilerSpan::new("RocksDB::snapshot");
        Box::new(RocksDBSnapshot {
            snapshot: unsafe { mem::transmute(self.db.snapshot()) },
            _db: Arc::clone(&self.db),
        })
    }

    fn merge(&self, patch: Patch) -> storage::Result<()> {
        let w_opts = RocksDBWriteOptions::default();
        self.do_merge(patch, &w_opts)
    }

    fn merge_sync(&self, patch: Patch) -> storage::Result<()> {
        let mut w_opts = RocksDBWriteOptions::default();
        w_opts.set_sync(true);
        self.do_merge(patch, &w_opts)
    }
}

impl Snapshot for RocksDBSnapshot {
    fn get(&self, name: &str, key: &[u8]) -> Option<Vec<u8>> {
        let _p = ProfilerSpan::new("RocksDBSnapshot::get");
        if let Some(cf) = self._db.cf_handle(name) {
            match self.snapshot.get_cf(cf, key) {
                Ok(value) => value.map(|v| v.to_vec()),
                Err(e) => panic!(e),
            }
        } else {
            None
        }
    }

    fn iter<'a>(&'a self, name: &str, from: &[u8]) -> Iter<'a> {
        use rocksdb::{IteratorMode, Direction};
        let _p = ProfilerSpan::new("RocksDBSnapshot::iter");
        let iter = match self._db.cf_handle(name) {
            Some(cf) => {
                self.snapshot
                    .iterator_cf(cf, IteratorMode::From(from, Direction::Forward))
                    .unwrap()
            }
            None => self.snapshot.iterator(IteratorMode::Start),
        };
        Box::new(RocksDBIterator {
            iter: iter.peekable(),
            key: None,
            value: None,
        })
    }
}

impl<'a> Iterator for RocksDBIterator {
    fn next(&mut self) -> Option<(&[u8], &[u8])> {
        let _p = ProfilerSpan::new("RocksDBIterator::next");
        if let Some((key, value)) = self.iter.next() {
            self.key = Some(key);
            self.value = Some(value);
            Some((self.key.as_ref().unwrap(), self.value.as_ref().unwrap()))
        } else {
            None
        }
    }

    fn peek(&mut self) -> Option<(&[u8], &[u8])> {
        let _p = ProfilerSpan::new("RocksDBIterator::peek");
        if let Some(&(ref key, ref value)) = self.iter.peek() {
            Some((key, value))
        } else {
            None
        }
    }
}

impl fmt::Debug for RocksDB {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RocksDB(..)")
    }
}

impl fmt::Debug for RocksDBSnapshot {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RocksDBSnapshot(..)")
    }
}
<commit_msg>Remove unused lifetime parameter<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.

//! An implementation of `RocksDB` database.

use exonum_profiler::ProfilerSpan;
use rocksdb::{self, WriteBatch, DBIterator};
use rocksdb::utils::get_cf_names;

use std::mem;
use std::sync::Arc;
use std::path::Path;
use std::fmt;
use std::error::Error;
use std::iter::Peekable;

use storage::{self, Database, Iterator, Iter, Snapshot, Patch};
use storage::db::Change;

pub use rocksdb::{Options as RocksDBOptions, WriteOptions as RocksDBWriteOptions};
pub use rocksdb::BlockBasedOptions as RocksBlockOptions;

impl From<rocksdb::Error> for storage::Error {
    fn from(err: rocksdb::Error) -> storage::Error {
        storage::Error::new(err.description())
    }
}

/// Database implementation on the top of `RocksDB` backend.
pub struct RocksDB {
    db: Arc<rocksdb::DB>,
}

/// A snapshot of a `RocksDB`.
pub struct RocksDBSnapshot {
    snapshot: rocksdb::Snapshot<'static>,
    _db: Arc<rocksdb::DB>,
}

/// An iterator over the entries of a `RocksDB`.
struct RocksDBIterator {
    iter: Peekable<DBIterator>,
    key: Option<Box<[u8]>>,
    value: Option<Box<[u8]>>,
}

impl RocksDB {
    /// Open a database stored in the specified path with the specified options.
    pub fn open<P: AsRef<Path>>(path: P, options: &RocksDBOptions) -> storage::Result<RocksDB> {
        let db = {
            if let Ok(names) = get_cf_names(&path) {
                let cf_names = names.iter().map(|name| name.as_str()).collect::<Vec<_>>();
                rocksdb::DB::open_cf(options, path, cf_names.as_ref())?
            } else {
                rocksdb::DB::open(options, path)?
            }
        };
        Ok(RocksDB { db: Arc::new(db) })
    }

    fn do_merge(&self, patch: Patch, w_opts: &RocksDBWriteOptions) -> storage::Result<()> {
        let _p = ProfilerSpan::new("RocksDB::merge");
        let mut batch = WriteBatch::default();
        for (cf_name, changes) in patch {
            let cf = match self.db.cf_handle(&cf_name) {
                Some(cf) => cf,
                None => {
                    self.db
                        .create_cf(&cf_name, &RocksDBOptions::default())
                        .unwrap()
                }
            };
            for (key, change) in changes {
                match change {
                    Change::Put(ref value) => batch.put_cf(cf, key.as_ref(), value)?,
                    Change::Delete => batch.delete_cf(cf, &key)?,
                }
            }
        }
        self.db.write_opt(batch, w_opts).map_err(Into::into)
    }
}

impl Database for RocksDB {
    fn snapshot(&self) -> Box<Snapshot> {
        let _p = ProfilerSpan::new("RocksDB::snapshot");
        Box::new(RocksDBSnapshot {
            snapshot: unsafe { mem::transmute(self.db.snapshot()) },
            _db: Arc::clone(&self.db),
        })
    }

    fn merge(&self, patch: Patch) -> storage::Result<()> {
        let w_opts = RocksDBWriteOptions::default();
        self.do_merge(patch, &w_opts)
    }

    fn merge_sync(&self, patch: Patch) -> storage::Result<()> {
        let mut w_opts = RocksDBWriteOptions::default();
        w_opts.set_sync(true);
        self.do_merge(patch, &w_opts)
    }
}

impl Snapshot for RocksDBSnapshot {
    fn get(&self, name: &str, key: &[u8]) -> Option<Vec<u8>> {
        let _p = ProfilerSpan::new("RocksDBSnapshot::get");
        if let Some(cf) = self._db.cf_handle(name) {
            match self.snapshot.get_cf(cf, key) {
                Ok(value) => value.map(|v| v.to_vec()),
                Err(e) => panic!(e),
            }
        } else {
            None
        }
    }

    fn iter<'a>(&'a self, name: &str, from: &[u8]) -> Iter<'a> {
        use rocksdb::{IteratorMode, Direction};
        let _p = ProfilerSpan::new("RocksDBSnapshot::iter");
        let iter = match self._db.cf_handle(name) {
            Some(cf) => {
                self.snapshot
                    .iterator_cf(cf, IteratorMode::From(from, Direction::Forward))
                    .unwrap()
            }
            None => self.snapshot.iterator(IteratorMode::Start),
        };
        Box::new(RocksDBIterator {
            iter: iter.peekable(),
            key: None,
            value: None,
        })
    }
}

impl Iterator for RocksDBIterator {
    fn next(&mut self) -> Option<(&[u8], &[u8])> {
        let _p = ProfilerSpan::new("RocksDBIterator::next");
        if let Some((key, value)) = self.iter.next() {
            self.key = Some(key);
            self.value = Some(value);
            Some((self.key.as_ref().unwrap(), self.value.as_ref().unwrap()))
        } else {
            None
        }
    }

    fn peek(&mut self) -> Option<(&[u8], &[u8])> {
        let _p = ProfilerSpan::new("RocksDBIterator::peek");
        if let Some(&(ref key, ref value)) = self.iter.peek() {
            Some((key, value))
        } else {
            None
        }
    }
}

impl fmt::Debug for RocksDB {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RocksDB(..)")
    }
}

impl fmt::Debug for RocksDBSnapshot {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RocksDBSnapshot(..)")
    }
}
<|endoftext|>


<commit_before>mod changelog;

use xshell::{cmd, Shell};

use crate::{date_iso, flags, is_release_tag, project_root};

impl flags::Release {
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
        if !self.dry_run {
            cmd!(sh, "git switch release").run()?;
            cmd!(sh, "git fetch upstream --tags --force").run()?;
            cmd!(sh, "git reset --hard tags/nightly").run()?;
            // The `release` branch sometimes has a couple of cherry-picked
            // commits for patch releases. If that's the case, just overwrite
            // it. As we are setting `release` branch to an up-to-date `nightly`
            // tag, this shouldn't be problematic in general.
            //
            // Note that, as we tag releases, we don't worry about "losing"
            // commits -- they'll be kept alive by the tag. More generally, we
            // don't care about historic releases all that much, it's fine even
            // to delete old tags.
            cmd!(sh, "git push --force").run()?;
        }

        // Generates bits of manual.adoc.
        cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_")
            .run()?;

        let website_root = project_root().join("../rust-analyzer.github.io");
        {
            let _dir = sh.push_dir(&website_root);
            cmd!(sh, "git switch src").run()?;
            cmd!(sh, "git pull").run()?;
        }
        let changelog_dir = website_root.join("./thisweek/_posts");

        let today = date_iso(sh)?;
        let commit = cmd!(sh, "git rev-parse HEAD").read()?;
        let changelog_n = sh
            .read_dir(changelog_dir.as_path())?
            .into_iter()
            .filter_map(|p| p.file_stem().map(|s| s.to_string_lossy().to_string()))
            .filter_map(|s| s.splitn(5, '-').last().map(|n| n.replace('-', ".")))
            .filter_map(|s| s.parse::<f32>().ok())
            .map(|n| 1 + n.floor() as usize)
            .max()
            .unwrap_or_default();

        for adoc in [
            "manual.adoc",
            "generated_assists.adoc",
            "generated_config.adoc",
            "generated_diagnostic.adoc",
            "generated_features.adoc",
        ] {
            let src = project_root().join("./docs/user/").join(adoc);
            let dst = website_root.join(adoc);

            let contents = sh.read_file(src)?;
            sh.write_file(dst, contents)?;
        }

        let tags = cmd!(sh, "git tag --list").read()?;
        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();

        let contents = changelog::get_changelog(sh, changelog_n, &commit, prev_tag, &today)?;
        let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
        sh.write_file(&path, &contents)?;

        Ok(())
    }
}

impl flags::Promote {
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
        let _dir = sh.push_dir("../rust-rust-analyzer");
        cmd!(sh, "git switch master").run()?;
        cmd!(sh, "git fetch upstream").run()?;
        cmd!(sh, "git reset --hard upstream/master").run()?;

        let date = date_iso(sh)?;
        let branch = format!("rust-analyzer-{date}");
        cmd!(sh, "git switch -c {branch}").run()?;
        cmd!(sh, "git subtree pull -P src/tools/rust-analyzer rust-analyzer master").run()?;

        if !self.dry_run {
            cmd!(sh, "git push -u origin {branch}").run()?;
            cmd!(
                sh,
                "xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost"
            )
            .run()?;
        }
        Ok(())
    }
}
<commit_msg>Auto merge of #12930 - lnicola:subtree-branch, r=lnicola<commit_after>mod changelog;

use xshell::{cmd, Shell};

use crate::{date_iso, flags, is_release_tag, project_root};

impl flags::Release {
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
        if !self.dry_run {
            cmd!(sh, "git switch release").run()?;
            cmd!(sh, "git fetch upstream --tags --force").run()?;
            cmd!(sh, "git reset --hard tags/nightly").run()?;
            // The `release` branch sometimes has a couple of cherry-picked
            // commits for patch releases. If that's the case, just overwrite
            // it. As we are setting `release` branch to an up-to-date `nightly`
            // tag, this shouldn't be problematic in general.
            //
            // Note that, as we tag releases, we don't worry about "losing"
            // commits -- they'll be kept alive by the tag. More generally, we
            // don't care about historic releases all that much, it's fine even
            // to delete old tags.
            cmd!(sh, "git push --force").run()?;
        }

        // Generates bits of manual.adoc.
        cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_")
            .run()?;

        let website_root = project_root().join("../rust-analyzer.github.io");
        {
            let _dir = sh.push_dir(&website_root);
            cmd!(sh, "git switch src").run()?;
            cmd!(sh, "git pull").run()?;
        }
        let changelog_dir = website_root.join("./thisweek/_posts");

        let today = date_iso(sh)?;
        let commit = cmd!(sh, "git rev-parse HEAD").read()?;
        let changelog_n = sh
            .read_dir(changelog_dir.as_path())?
            .into_iter()
            .filter_map(|p| p.file_stem().map(|s| s.to_string_lossy().to_string()))
            .filter_map(|s| s.splitn(5, '-').last().map(|n| n.replace('-', ".")))
            .filter_map(|s| s.parse::<f32>().ok())
            .map(|n| 1 + n.floor() as usize)
            .max()
            .unwrap_or_default();

        for adoc in [
            "manual.adoc",
            "generated_assists.adoc",
            "generated_config.adoc",
            "generated_diagnostic.adoc",
            "generated_features.adoc",
        ] {
            let src = project_root().join("./docs/user/").join(adoc);
            let dst = website_root.join(adoc);

            let contents = sh.read_file(src)?;
            sh.write_file(dst, contents)?;
        }

        let tags = cmd!(sh, "git tag --list").read()?;
        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();

        let contents = changelog::get_changelog(sh, changelog_n, &commit, prev_tag, &today)?;
        let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
        sh.write_file(&path, &contents)?;

        Ok(())
    }
}

impl flags::Promote {
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
        let _dir = sh.push_dir("../rust-rust-analyzer");
        cmd!(sh, "git switch master").run()?;
        cmd!(sh, "git fetch upstream").run()?;
        cmd!(sh, "git reset --hard upstream/master").run()?;

        let date = date_iso(sh)?;
        let branch = format!("rust-analyzer-{date}");
        cmd!(sh, "git switch -c {branch}").run()?;
        cmd!(sh, "git subtree pull -m ':arrow_up: rust-analyzer' -P src/tools/rust-analyzer rust-analyzer release").run()?;

        if !self.dry_run {
            cmd!(sh, "git push -u origin {branch}").run()?;
            cmd!(
                sh,
                "xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost"
            )
            .run()?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

pub mod highlight {
    pub static CSS: &'static str = include_str!("../../templates/highlight/default.css");
    pub static JS: &'static str = include_str!("../../templates/highlight/highlight.pack.js");
}

pub mod html {
    pub static CSS: &'static str = concat!(include_str!("../../templates/epub/stylesheet.css"),
                                           include_str!("../../templates/html/template.css"));
    pub static CSS_COLOURS: &'static str = include_str!("../../templates/html/colours.css");
    pub static PRINT_CSS: &'static str = include_str!("../../templates/html/print.css");
    pub static JS: &'static str = include_str!("../../templates/html/script.js");

}

pub mod img {
    pub static MENU_SVG: &'static [u8] = include_bytes!("../../templates/img/menu.svg");
    pub static BOOK_SVG: &'static [u8] = include_bytes!("../../templates/img/book.svg");
    pub static PAGES_SVG: &'static [u8] = include_bytes!("../../templates/img/pages.svg");
}

pub mod html_single {
    pub static HTML: &'static str = include_str!("../../templates/html_single/template.html");
    pub static JS: &'static str = include_str!("../../templates/html_single/script.js");
}

pub mod html_dir {
    pub static TEMPLATE: &'static str = include_str!("../../templates/html_dir/template.html");
}

pub mod latex {
    pub static TEMPLATE: &'static str = include_str!("../../templates/latex/template.tex");
}

pub mod epub {
    pub static TEMPLATE: &'static str = include_str!("../../templates/epub/template.xhtml");
    pub static CSS: &'static str = include_str!("../../templates/epub/stylesheet.css");
    pub static COVER: &'static str = include_str!("../../templates/epub/cover.xhtml");
    pub static TITLE: &'static str = include_str!("../../templates/epub/titlepage.xhtml");
}

pub mod epub3 {
    pub static TEMPLATE: &'static str = include_str!("../../templates/epub3/template.xhtml");
    pub static COVER: &'static str = include_str!("../../templates/epub3/cover.xhtml");
    pub static TITLE: &'static str = include_str!("../../templates/epub3/titlepage.xhtml");
}

pub mod odt {
    pub static CONTENT: &'static str = include_str!("../../templates/odt/content.xml");
    pub static ODT: &'static [u8] = include_bytes!("../../templates/odt/template.odt");
}
<commit_msg>Remove lifetime annotation (no longer needed in rustc 1.17.0)<commit_after>// Copyright (C) 2016, 2017 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

pub mod highlight {
    pub static CSS: &str = include_str!("../../templates/highlight/default.css");
    pub static JS: &str = include_str!("../../templates/highlight/highlight.pack.js");
}

pub mod html {
    pub static CSS: &str = concat!(include_str!("../../templates/epub/stylesheet.css"),
                                           include_str!("../../templates/html/template.css"));
    pub static CSS_COLOURS: &str = include_str!("../../templates/html/colours.css");
    pub static PRINT_CSS: &str = include_str!("../../templates/html/print.css");
    pub static JS: &str = include_str!("../../templates/html/script.js");

}

pub mod img {
    pub static MENU_SVG: &[u8] = include_bytes!("../../templates/img/menu.svg");
    pub static BOOK_SVG: &[u8] = include_bytes!("../../templates/img/book.svg");
    pub static PAGES_SVG: &[u8] = include_bytes!("../../templates/img/pages.svg");
}

pub mod html_single {
    pub static HTML: &str = include_str!("../../templates/html_single/template.html");
    pub static JS: &str = include_str!("../../templates/html_single/script.js");
}

pub mod html_dir {
    pub static TEMPLATE: &str = include_str!("../../templates/html_dir/template.html");
}

pub mod latex {
    pub static TEMPLATE: &str = include_str!("../../templates/latex/template.tex");
}

pub mod epub {
    pub static TEMPLATE: &str = include_str!("../../templates/epub/template.xhtml");
    pub static CSS: &str = include_str!("../../templates/epub/stylesheet.css");
    pub static COVER: &str = include_str!("../../templates/epub/cover.xhtml");
    pub static TITLE: &str = include_str!("../../templates/epub/titlepage.xhtml");
}

pub mod epub3 {
    pub static TEMPLATE: &str = include_str!("../../templates/epub3/template.xhtml");
    pub static COVER: &str = include_str!("../../templates/epub3/cover.xhtml");
    pub static TITLE: &str = include_str!("../../templates/epub3/titlepage.xhtml");
}

pub mod odt {
    pub static CONTENT: &str = include_str!("../../templates/odt/content.xml");
    pub static ODT: &[u8] = include_bytes!("../../templates/odt/template.odt");
}
<|endoftext|>


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

//! The `Clone` trait for types that cannot be 'implicitly copied'
//!
//! In Rust, some simple types are "implicitly copyable" and when you
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e. they do not
//! contain owned boxes or implement `Drop`), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the `Clone` trait and calling
//! the `clone` method.

#![stable(feature = "rust1", since = "1.0.0")]

use marker::Sized;

/// A common trait for cloning an object.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Clone : Sized {
    /// Returns a copy of the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone(&self) -> Self;

    /// Perform copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overridden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline(always)]
    #[unstable(feature = "core",
               reason = "this function is rarely used")]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Clone for &'a T {
    /// Return a shallow copy of the reference.
    #[inline]
    fn clone(&self) -> &'a T { *self }
}

macro_rules! clone_impl {
    ($t:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Clone for $t {
            /// Return a deep copy of the value.
            #[inline]
            fn clone(&self) -> $t { *self }
        }
    }
}

clone_impl! { isize }
clone_impl! { i8 }
clone_impl! { i16 }
clone_impl! { i32 }
clone_impl! { i64 }

clone_impl! { usize }
clone_impl! { u8 }
clone_impl! { u16 }
clone_impl! { u32 }
clone_impl! { u64 }

clone_impl! { f32 }
clone_impl! { f64 }

clone_impl! { () }
clone_impl! { bool }
clone_impl! { char }

macro_rules! extern_fn_clone {
    ($($A:ident),*) => (
        #[unstable(feature = "core",
                   reason = "this may not be sufficient for fns with region parameters")]
        impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType {
            /// Return a copy of a function pointer
            #[inline]
            fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
        }
    )
}

extern_fn_clone! {}
extern_fn_clone! { A }
extern_fn_clone! { A, B }
extern_fn_clone! { A, B, C }
extern_fn_clone! { A, B, C, D }
extern_fn_clone! { A, B, C, D, E }
extern_fn_clone! { A, B, C, D, E, F }
extern_fn_clone! { A, B, C, D, E, F, G }
extern_fn_clone! { A, B, C, D, E, F, G, H }
<commit_msg>An example for clone<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The `Clone` trait for types that cannot be 'implicitly copied'
//!
//! In Rust, some simple types are "implicitly copyable" and when you
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e. they do not
//! contain owned boxes or implement `Drop`), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the `Clone` trait and calling
//! the `clone` method.

#![stable(feature = "rust1", since = "1.0.0")]

use marker::Sized;

/// A common trait for cloning an object.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Clone : Sized {
    /// Returns a copy of the value.
    ///
    /// # Examples
    ///
    /// ```
    /// let hello = "Hello"; // &str implements Clone
    ///
    /// assert_eq!("Hello", hello.clone());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn clone(&self) -> Self;

    /// Perform copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overridden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline(always)]
    #[unstable(feature = "core",
               reason = "this function is rarely used")]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Clone for &'a T {
    /// Return a shallow copy of the reference.
    #[inline]
    fn clone(&self) -> &'a T { *self }
}

macro_rules! clone_impl {
    ($t:ty) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Clone for $t {
            /// Return a deep copy of the value.
            #[inline]
            fn clone(&self) -> $t { *self }
        }
    }
}

clone_impl! { isize }
clone_impl! { i8 }
clone_impl! { i16 }
clone_impl! { i32 }
clone_impl! { i64 }

clone_impl! { usize }
clone_impl! { u8 }
clone_impl! { u16 }
clone_impl! { u32 }
clone_impl! { u64 }

clone_impl! { f32 }
clone_impl! { f64 }

clone_impl! { () }
clone_impl! { bool }
clone_impl! { char }

macro_rules! extern_fn_clone {
    ($($A:ident),*) => (
        #[unstable(feature = "core",
                   reason = "this may not be sufficient for fns with region parameters")]
        impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType {
            /// Return a copy of a function pointer
            #[inline]
            fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
        }
    )
}

extern_fn_clone! {}
extern_fn_clone! { A }
extern_fn_clone! { A, B }
extern_fn_clone! { A, B, C }
extern_fn_clone! { A, B, C, D }
extern_fn_clone! { A, B, C, D, E }
extern_fn_clone! { A, B, C, D, E, F }
extern_fn_clone! { A, B, C, D, E, F, G }
extern_fn_clone! { A, B, C, D, E, F, G, H }
<|endoftext|>


<commit_before>use ast::{Expr, BinOp, UnOp, Dec};
use parser::lexer::Lexer;
use parser::token::Token;
use parser::parser_error::ParserError;
use std::result;

pub type Result<T> = result::Result<T, ParserError>;

struct Parser {
  lexer: Lexer,
  current_token: Token,
}

impl Parser {
  pub fn new(lexer: Lexer, token: Token) -> Parser {
    Parser {
      lexer: lexer,
      current_token: token,
    }
  }

  fn current_token(&self) -> Token {
    self.current_token.clone()
  }

  fn eat(&mut self, expected: Token) -> Result<()> {
    let actual = self.current_token();

    if expected != actual {
      return Err(ParserError::UnexpectedToken(expected, actual))
    }

    self.current_token = try!(self.lexer.get_next_token());
    debug!("new current token: {:?}", self.current_token);
    Ok(())
  }

  fn ternary(&mut self, e1: Expr, e2: Expr, e3: Expr) -> Expr {
    Expr::Ternary(to_box(e1), to_box(e2), to_box(e3))
  }

  fn binop(&mut self, bop: BinOp, e1: Expr, e2: Expr) -> Expr {
    Expr::Bop(bop, to_box(e1), to_box(e2))
  }

  fn parse_fn_params(&mut self) -> Result<Vec<Expr>> {
    let mut params = Vec::new();
    let mut token = self.current_token();

    while token != Token::RParen {
      debug!("getting fn params");
      let term = try!(self.binop_expr());

      params.push(term);

      if self.current_token == Token::Comma {
        try!(self.eat(Token::Comma));
      }

      token = self.current_token();
    }

    Ok(params)
  }

  fn parse_fn_decl_params(&mut self) -> Result<Vec<Expr>> {
    let mut params = Vec::new();
    let mut token = self.current_token();

    while token != Token::RParen {
      debug!("getting fn decl params");
      match token.clone() {
        Token::Var(s) => {
          try!(self.eat(Token::Var(s.clone())));
          params.push(Expr::Var(s));
        },
        Token::Comma => try!(self.eat(Token::Comma)),
        _ => return Err(ParserError::InvalidToken(token, String::from("parsing fn decl params")))
      }

      token = self.current_token();
    }

    Ok(params)
  }

  fn parse_fn(&mut self) -> Result<Expr> {
    debug!("parsing named fn...");
    try!(self.eat(Token::FnDecl));

    let var = match self.current_token() {
      Token::Var(s) => {
        try!(self.eat(Token::Var(s.clone())));
        Some(Expr::Var(s))
      },
      _ => None,
    };

    try!(self.eat(Token::LParen));
    let params = try!(self.parse_fn_decl_params());
    try!(self.eat(Token::RParen));

    try!(self.eat(Token::LBracket));
    let body = try!(self.block());
    try!(self.eat(Token::RBracket));

    match var {
      Some(v) => {
        try!(self.eat(Token::Seq));
        let e3 = try!(self.block());

        let func = Expr::Func(Some(to_box(v.clone())), to_box(body.clone()), params);

        Ok(Expr::Decl(Dec::DConst, to_box(v), to_box(func), to_box(e3)))
      },
      None => {
        let func = Expr::Func(None, to_box(body.clone()), params);

        // fn call rule
        if self.current_token == Token::LParen {
          try!(self.eat(Token::LParen));
          let params = try!(self.parse_fn_params());
          try!(self.eat(Token::RParen));

          Ok(Expr::FnCall(to_box(func), params))
        } else {
          Ok(func)
        }
      }
    }
  }

  fn parse_while(&mut self) -> Result<Expr> {
    try!(self.eat(Token::While));
    try!(self.eat(Token::LParen));
    let e1 = try!(self.statement());
    try!(self.eat(Token::RParen));
    let e2 = try!(self.factor());
    try!(self.eat(Token::Seq));
    let e3 = try!(self.block());

    return Ok(Expr::While(
      to_box(e1.clone()),
      to_box(e1),
      to_box(e2.clone()),
      to_box(e2),
      to_box(e3)
    ));
  }

  fn parse_if(&mut self) -> Result<Expr> {
    try!(self.eat(Token::If));
    let e1 = try!(self.binop_expr());
    let e2 = try!(self.block());
    let e3 = try!(self.statement());

    return Ok(self.ternary(e1, e2, e3));
  }

  fn factor(&mut self) -> Result<Expr> {
    let e = match self.current_token() {
      Token::Int(n) => {
        try!(self.eat(Token::Int(n.clone())));
        Expr::Int(n)
      },
      Token::Bool(b) => {
        try!(self.eat(Token::Bool(b.clone())));
        Expr::Bool(b)
      },
      Token::Var(s) => {
        try!(self.eat(Token::Var(s.clone())));

        // fn call rule
        if self.current_token == Token::LParen {
          try!(self.eat(Token::LParen));
          let params = try!(self.parse_fn_params());
          try!(self.eat(Token::RParen));

          Expr::FnCall(to_box(Expr::Var(s)), params)
        } else {
          Expr::Var(s)
        }
      },
      Token::FnDecl => {
        try!(self.parse_fn())
      },
      Token::VarDecl => {
        try!(self.eat(Token::VarDecl));
        let var = try!(self.term());
        try!(self.eat(Token::Assign));
        let e2 = try!(self.statement());
        try!(self.eat(Token::Seq));
        let e3 = try!(self.block());

        Expr::Decl(Dec::DVar, to_box(var), to_box(e2), to_box(e3))
      },
      Token::Let => {
        try!(self.eat(Token::Let));
        let var = try!(self.term());
        try!(self.eat(Token::Assign));
        let e2 = try!(self.statement());
        try!(self.eat(Token::Seq));
        let e3 = try!(self.block());

        Expr::Decl(Dec::DConst, to_box(var), to_box(e2), to_box(e3))
      },
      Token::If => {
        try!(self.parse_if())
      },
      Token::Else => {
        try!(self.eat(Token::Else));
        try!(self.statement())
      },
      Token::While => {
        try!(self.parse_while())
      },
      Token::LParen => {
        try!(self.eat(Token::LParen));
        let node = try!(self.statement());
        try!(self.eat(Token::RParen));
        node
      },
      Token::LBracket => {
        try!(self.eat(Token::LBracket));
        let node = try!(self.block());
        try!(self.eat(Token::RBracket));
        node
      },
      Token::Not => {
        try!(self.eat(Token::Not));
        Expr::Uop(UnOp::Not, to_box(try!(self.factor())))
      },
      Token::Minus => {
        try!(self.eat(Token::Minus));
        Expr::Uop(UnOp::Neg, to_box(try!(self.factor())))
      },
      Token::EOF => {
        try!(self.eat(Token::EOF));
        Expr::Undefined
      },
      _ => {
        return Err(ParserError::InvalidToken(self.current_token(), String::from("parsing factor")))
      }
    };

    Ok(e)
  }

  pub fn term(&mut self) -> Result<Expr> {
    let mut node = try!(self.factor());

    let mut op = self.current_token();

    while op.is_term_op() {
      try!(self.eat(op.clone()));
      let right_node = try!(self.term());

      node = match op {
        Token::Times => self.binop(BinOp::Times, node, right_node),
        Token::Div => self.binop(BinOp::Div, node, right_node),
        _ => return Err(ParserError::InvalidToken(op, String::from("parsing term")))
      };

      op = self.current_token();
    }

    Ok(node)
  }

  pub fn binop_expr(&mut self) -> Result<Expr> {
    let mut node = try!(self.term());

    let mut op = self.current_token();

    while op.is_expr_op() {
      debug!("expr looping on op {:?}", op);
      try!(self.eat(op.clone()));

      let right_node = try!(self.term());

      node = match op {
        Token::Plus => self.binop(BinOp::Plus, node, right_node),
        Token::Minus => self.binop(BinOp::Minus, node, right_node),
        Token::Eq => self.binop(BinOp::Eq, node, right_node),
        Token::Ne => self.binop(BinOp::Ne, node, right_node),
        Token::Leq => self.binop(BinOp::Leq, node, right_node),
        Token::Geq => self.binop(BinOp::Geq, node, right_node),
        Token::Lt => self.binop(BinOp::Lt, node, right_node),
        Token::Gt => self.binop(BinOp::Gt, node, right_node),
        Token::And => self.binop(BinOp::And, node, right_node),
        Token::Or => self.binop(BinOp::Or, node, right_node),
        Token::Mod => self.binop(BinOp::Mod, node, right_node),
        _ => return Err(ParserError::InvalidToken(op, String::from("parsing binop expression")))
      };

      op = self.current_token();
    }

    Ok(node)
  }

  pub fn statement(&mut self) -> Result<Expr> {
    let mut node = try!(self.binop_expr());
    let mut op = self.current_token();

    while op.is_statement_op() {
      try!(self.eat(op.clone()));

      node = match op {
        Token::Ternary => {
          let e2 = try!(self.block());
          try!(self.eat(Token::Else));
          let e3 = try!(self.statement());
          self.ternary(node, e2, e3)
        },
        Token::Assign => {
          let e2 = try!(self.statement());
          self.binop(BinOp::Assign, node, e2)
        },
        _ => return Err(ParserError::InvalidToken(op, String::from("parsing statement")))
      };

      op = self.current_token();
    }

    Ok(node)
  }

  pub fn block(&mut self) -> Result<Expr> {
    let mut node = try!(self.statement());
    let mut op = self.current_token();

    while op.is_block_op() {
      try!(self.eat(op.clone()));

      node = match op {
        Token::Seq => {
          let e2 = match self.current_token() {
            Token::RBracket => Expr::Undefined,
            _ => try!(self.statement()),
          };

          self.binop(BinOp::Seq, node, e2)
        },
        _ => return Err(ParserError::InvalidToken(op, String::from("parsing block")))
      };

      op = self.current_token();
    }

    Ok(node)
  }

  pub fn program(&mut self) -> Result<Expr> {
    self.block()
  }
}

fn to_box(e: Expr) -> Box<Expr> {
  Box::new(e)
}

pub fn parse(input: &str) -> Result<Expr> {
  let mut lexer = Lexer::new(input.to_string());

  let token = try!(lexer.get_next_token());

  let mut parser = Parser::new(lexer, token);
  let expr = parser.program();

  debug!("parsed expr: {:#?}", expr);
  debug!("original: {:#?}", input);

  expr
}
<commit_msg>remove try! from parser<commit_after>use ast::{Expr, BinOp, UnOp, Dec};
use parser::lexer::Lexer;
use parser::token::Token;
use parser::parser_error::ParserError;
use std::result;

pub type Result<T> = result::Result<T, ParserError>;

struct Parser {
  lexer: Lexer,
  current_token: Token,
}

impl Parser {
  pub fn new(lexer: Lexer, token: Token) -> Parser {
    Parser {
      lexer: lexer,
      current_token: token,
    }
  }

  fn current_token(&self) -> Token {
    self.current_token.clone()
  }

  fn eat(&mut self, expected: Token) -> Result<()> {
    let actual = self.current_token();

    if expected != actual {
      return Err(ParserError::UnexpectedToken(expected, actual))
    }

    self.current_token = self.lexer.get_next_token()?;
    debug!("new current token: {:?}", self.current_token);
    Ok(())
  }

  fn ternary(&mut self, e1: Expr, e2: Expr, e3: Expr) -> Expr {
    Expr::Ternary(to_box(e1), to_box(e2), to_box(e3))
  }

  fn binop(&mut self, bop: BinOp, e1: Expr, e2: Expr) -> Expr {
    Expr::Bop(bop, to_box(e1), to_box(e2))
  }

  fn parse_fn_params(&mut self) -> Result<Vec<Expr>> {
    let mut params = Vec::new();
    let mut token = self.current_token();

    while token != Token::RParen {
      debug!("getting fn params");
      let term = self.binop_expr()?;

      params.push(term);

      if self.current_token == Token::Comma {
        self.eat(Token::Comma)?;
      }

      token = self.current_token();
    }

    Ok(params)
  }

  fn parse_fn_decl_params(&mut self) -> Result<Vec<Expr>> {
    let mut params = Vec::new();
    let mut token = self.current_token();

    while token != Token::RParen {
      debug!("getting fn decl params");
      match token.clone() {
        Token::Var(s) => {
          self.eat(Token::Var(s.clone()))?;
          params.push(Expr::Var(s));
        },
        Token::Comma => self.eat(Token::Comma)?,
        _ => return Err(ParserError::InvalidToken(token, String::from("parsing fn decl params")))
      }

      token = self.current_token();
    }

    Ok(params)
  }

  fn parse_fn(&mut self) -> Result<Expr> {
    debug!("parsing named fn...");
    self.eat(Token::FnDecl)?;

    let var = match self.current_token() {
      Token::Var(s) => {
        self.eat(Token::Var(s.clone()))?;
        Some(Expr::Var(s))
      },
      _ => None,
    };

    self.eat(Token::LParen)?;
    let params = self.parse_fn_decl_params()?;
    self.eat(Token::RParen)?;

    self.eat(Token::LBracket)?;
    let body = self.block()?;
    self.eat(Token::RBracket)?;

    match var {
      Some(v) => {
        self.eat(Token::Seq)?;
        let e3 = self.block()?;

        let func = Expr::Func(Some(to_box(v.clone())), to_box(body.clone()), params);

        Ok(Expr::Decl(Dec::DConst, to_box(v), to_box(func), to_box(e3)))
      },
      None => {
        let func = Expr::Func(None, to_box(body.clone()), params);

        // fn call rule
        if self.current_token == Token::LParen {
          self.eat(Token::LParen)?;
          let params = self.parse_fn_params()?;
          self.eat(Token::RParen)?;

          Ok(Expr::FnCall(to_box(func), params))
        } else {
          Ok(func)
        }
      }
    }
  }

  fn parse_while(&mut self) -> Result<Expr> {
    self.eat(Token::While)?;
    self.eat(Token::LParen)?;
    let e1 = self.statement()?;
    self.eat(Token::RParen)?;
    let e2 = self.factor()?;
    self.eat(Token::Seq)?;
    let e3 = self.block()?;

    return Ok(Expr::While(
      to_box(e1.clone()),
      to_box(e1),
      to_box(e2.clone()),
      to_box(e2),
      to_box(e3)
    ));
  }

  fn parse_if(&mut self) -> Result<Expr> {
    self.eat(Token::If)?;
    let e1 = self.binop_expr()?;
    let e2 = self.block()?;
    let e3 = self.statement()?;

    return Ok(self.ternary(e1, e2, e3));
  }

  fn factor(&mut self) -> Result<Expr> {
    let e = match self.current_token() {
      Token::Int(n) => {
        self.eat(Token::Int(n.clone()))?;
        Expr::Int(n)
      },
      Token::Bool(b) => {
        self.eat(Token::Bool(b.clone()))?;
        Expr::Bool(b)
      },
      Token::Var(s) => {
        self.eat(Token::Var(s.clone()))?;

        // fn call rule
        if self.current_token == Token::LParen {
          self.eat(Token::LParen)?;
          let params = self.parse_fn_params()?;
          self.eat(Token::RParen)?;

          Expr::FnCall(to_box(Expr::Var(s)), params)
        } else {
          Expr::Var(s)
        }
      },
      Token::FnDecl => {
        self.parse_fn()?
      },
      Token::VarDecl => {
        self.eat(Token::VarDecl)?;
        let var = self.term()?;
        self.eat(Token::Assign)?;
        let e2 = self.statement()?;
        self.eat(Token::Seq)?;
        let e3 = self.block()?;

        Expr::Decl(Dec::DVar, to_box(var), to_box(e2), to_box(e3))
      },
      Token::Let => {
        self.eat(Token::Let)?;
        let var = self.term()?;
        self.eat(Token::Assign)?;
        let e2 = self.statement()?;
        self.eat(Token::Seq)?;
        let e3 = self.block()?;

        Expr::Decl(Dec::DConst, to_box(var), to_box(e2), to_box(e3))
      },
      Token::If => {
        self.parse_if()?
      },
      Token::Else => {
        self.eat(Token::Else)?;
        self.statement()?
      },
      Token::While => {
        self.parse_while()?
      },
      Token::LParen => {
        self.eat(Token::LParen)?;
        let node = self.statement()?;
        self.eat(Token::RParen)?;
        node
      },
      Token::LBracket => {
        self.eat(Token::LBracket)?;
        let node = self.block()?;
        self.eat(Token::RBracket)?;
        node
      },
      Token::Not => {
        self.eat(Token::Not)?;
        Expr::Uop(UnOp::Not, to_box(self.factor()?))
      },
      Token::Minus => {
        self.eat(Token::Minus)?;
        Expr::Uop(UnOp::Neg, to_box(self.factor()?))
      },
      Token::EOF => {
        self.eat(Token::EOF)?;
        Expr::Undefined
      },
      _ => {
        return Err(ParserError::InvalidToken(self.current_token(), String::from("parsing factor")))
      }
    };

    Ok(e)
  }

  pub fn term(&mut self) -> Result<Expr> {
    let mut node = self.factor()?;

    let mut op = self.current_token();

    while op.is_term_op() {
      self.eat(op.clone())?;
      let right_node = self.term()?;

      node = match op {
        Token::Times => self.binop(BinOp::Times, node, right_node),
        Token::Div => self.binop(BinOp::Div, node, right_node),
        _ => return Err(ParserError::InvalidToken(op, String::from("parsing term")))
      };

      op = self.current_token();
    }

    Ok(node)
  }

  pub fn binop_expr(&mut self) -> Result<Expr> {
    let mut node = self.term()?;

    let mut op = self.current_token();

    while op.is_expr_op() {
      debug!("expr looping on op {:?}", op);
      self.eat(op.clone())?;

      let right_node = self.term()?;

      node = match op {
        Token::Plus => self.binop(BinOp::Plus, node, right_node),
        Token::Minus => self.binop(BinOp::Minus, node, right_node),
        Token::Eq => self.binop(BinOp::Eq, node, right_node),
        Token::Ne => self.binop(BinOp::Ne, node, right_node),
        Token::Leq => self.binop(BinOp::Leq, node, right_node),
        Token::Geq => self.binop(BinOp::Geq, node, right_node),
        Token::Lt => self.binop(BinOp::Lt, node, right_node),
        Token::Gt => self.binop(BinOp::Gt, node, right_node),
        Token::And => self.binop(BinOp::And, node, right_node),
        Token::Or => self.binop(BinOp::Or, node, right_node),
        Token::Mod => self.binop(BinOp::Mod, node, right_node),
        _ => return Err(ParserError::InvalidToken(op, String::from("parsing binop expression")))
      };

      op = self.current_token();
    }

    Ok(node)
  }

  pub fn statement(&mut self) -> Result<Expr> {
    let mut node = self.binop_expr()?;
    let mut op = self.current_token();

    while op.is_statement_op() {
      self.eat(op.clone())?;

      node = match op {
        Token::Ternary => {
          let e2 = self.block()?;
          self.eat(Token::Else)?;
          let e3 = self.statement()?;
          self.ternary(node, e2, e3)
        },
        Token::Assign => {
          let e2 = self.statement()?;
          self.binop(BinOp::Assign, node, e2)
        },
        _ => return Err(ParserError::InvalidToken(op, String::from("parsing statement")))
      };

      op = self.current_token();
    }

    Ok(node)
  }

  pub fn block(&mut self) -> Result<Expr> {
    let mut node = self.statement()?;
    let mut op = self.current_token();

    while op.is_block_op() {
      self.eat(op.clone())?;

      node = match op {
        Token::Seq => {
          let e2 = match self.current_token() {
            Token::RBracket => Expr::Undefined,
            _ => self.statement()?,
          };

          self.binop(BinOp::Seq, node, e2)
        },
        _ => return Err(ParserError::InvalidToken(op, String::from("parsing block")))
      };

      op = self.current_token();
    }

    Ok(node)
  }

  pub fn program(&mut self) -> Result<Expr> {
    self.block()
  }
}

fn to_box(e: Expr) -> Box<Expr> {
  Box::new(e)
}

pub fn parse(input: &str) -> Result<Expr> {
  let mut lexer = Lexer::new(input.to_string());

  let token = lexer.get_next_token()?;

  let mut parser = Parser::new(lexer, token);
  let expr = parser.program();

  debug!("parsed expr: {:#?}", expr);
  debug!("original: {:#?}", input);

  expr
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::{bail, Result};
use regex::Regex;
use std::matches;
use std::ops::Drop;
use std::time::Duration;
use structopt::StructOpt;

use opentitanlib::app::TransportWrapper;
use opentitanlib::execute_test;
use opentitanlib::io::spi::Transfer;
use opentitanlib::spiflash::{
    sfdp, BlockEraseSize, SpiFlash, SupportedAddressModes, WriteGranularity,
};
use opentitanlib::test_utils::init::InitializeTest;
use opentitanlib::uart::console::{ExitStatus, UartConsole};
use opentitanlib::util::parse_int::ParseInt;

#[derive(Debug, StructOpt)]
struct Opts {
    #[structopt(flatten)]
    init: InitializeTest,

    #[structopt(
        long, parse(try_from_str=humantime::parse_duration),
        default_value = "5s",
        help = "Bootstrap detection timeout",
    )]
    timeout: Duration,

    #[structopt(
        long, parse(try_from_str=usize::from_str),
        default_value = "12",
        help = "JEDEC page of manufacturer",
    )]
    jedec_page: usize,

    #[structopt(
        long, parse(try_from_str=u8::from_str),
        default_value = "0xEF",
        help = "JEDEC ID of manufacturer",
    )]
    jedec_id: u8,

    #[structopt(
        long, parse(try_from_str=u8::from_str),
        default_value = "0x08",
        help = "JEDEC manufacturer product ID",
    )]
    jedec_product: u8,

    #[structopt(
        long, parse(try_from_str=u32::from_str),
        default_value = "0x100000",
        help = "Size of the internal flash",
    )]
    flash_size: u32,
}

/// A struct for isolating individual test points.
///
/// This is basically an example of the RAII technique.
/// Calling `BootstrapTest::start()` resets the chip and puts it in bootstrap mode (assuming it's
/// enabled). Strapping pins are released and the chip is reset when the returned struct is
/// dropped, typically at the end of the test point.
struct BootstrapTest<'a> {
    transport: &'a TransportWrapper,
    reset_delay: Duration,
}

impl<'a> BootstrapTest<'a> {
    pub fn start(transport: &'a TransportWrapper, reset_delay: Duration) -> Result<Self> {
        let b = BootstrapTest {
            transport,
            reset_delay,
        };
        transport.apply_pin_strapping("ROM_BOOTSTRAP")?;
        transport.reset_target(b.reset_delay, true)?;
        Ok(b)
    }
}

impl<'a> Drop for BootstrapTest<'a> {
    fn drop(&mut self) {
        self.transport
            .remove_pin_strapping("ROM_BOOTSTRAP")
            .unwrap();
        self.transport.reset_target(self.reset_delay, true).unwrap();
    }
}

fn test_bootstrap_enabled_requested(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    // TODO: Should really `opts.init.uart_params.create()` here, but we need to refactor
    // BootstrapOptions first.
    //let uart = opts.init.uart_params.create(&transport)?;
    let uart = transport.uart("0")?;
    let mut console = UartConsole {
        timeout: Some(opts.timeout),
        exit_success: Some(Regex::new(r"bootstrap:1\r\n")?),
        exit_failure: Some(Regex::new(r"BFV:")?),
        ..Default::default()
    };

    transport.apply_pin_strapping("ROM_BOOTSTRAP")?;
    transport.reset_target(opts.init.bootstrap.options.reset_delay, true)?;

    // Now watch the console for the exit conditions.
    let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
    if result != ExitStatus::ExitSuccess {
        bail!("FAIL: {:?}", result);
    };
    // Now check whether the SPI device is responding to status messages
    let spi = transport.spi("0")?;
    assert_eq!(SpiFlash::read_status(&*spi)?, 0x00);

    Ok(())
}

fn test_bootstrap_enabled_not_requested(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    // TODO: Should really `opts.init.uart_params.create()` here, but we need to refactor
    // BootstrapOptions first.
    //let uart = opts.init.uart_params.create(&transport)?;
    let uart = transport.uart("0")?;
    let mut console = UartConsole {
        timeout: Some(opts.timeout),
        exit_success: Some(Regex::new(r"BFV:")?),
        exit_failure: Some(Regex::new(r"bootstrap:1\r\n")?),
        ..Default::default()
    };

    transport.reset_target(opts.init.bootstrap.options.reset_delay, true)?;

    // Now watch the console for the exit conditions.
    let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
    if result != ExitStatus::ExitSuccess {
        bail!("FAIL: {:?}", result);
    };

    // Now check whether the SPI device is responding to commands.
    // Note: CIPO line is in high-z state when CMD_INFO registers are not configured.
    // Use READ_SFDP instead of READ_STATUS to avoid false negatives when bootstrap is not
    // requested
    let spi = transport.spi("0")?;
    assert!(matches!(
        SpiFlash::read_sfdp(&*spi)
            .unwrap_err()
            .downcast::<sfdp::Error>()
            .unwrap(),
        sfdp::Error::WrongHeaderSignature(..)
    ));
    Ok(())
}

fn test_jedec_id(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    let spi = transport.spi("0")?;
    let id = SpiFlash::read_jedec_id(&*spi, 16)?;
    log::info!("Read jedec id: {:x?}", id);
    let mut index = 0;
    while id[index] == 0x7f {
        index += 1;
    }
    let page = index;
    let manufacturer = id[index];
    let product = id[index + 1];
    let density = id[index + 2];

    assert_eq!(page, opts.jedec_page);
    assert_eq!(manufacturer, opts.jedec_id);
    assert_eq!(product, opts.jedec_product);
    assert_eq!(1u32 << density, opts.flash_size);
    Ok(())
}

fn test_write_enable_disable(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    let spi = transport.spi("0")?;

    assert_eq!(SpiFlash::read_status(&*spi)?, 0x0);

    SpiFlash::set_write_enable(&*spi)?;
    assert_eq!(SpiFlash::read_status(&*spi)?, 0x2);

    SpiFlash::set_write_disable(&*spi)?;
    assert_eq!(SpiFlash::read_status(&*spi)?, 0x0);

    Ok(())
}

fn test_sfdp(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    let spi = transport.spi("0")?;
    let sfdp = SpiFlash::read_sfdp(&*spi)?;
    log::info!("SFDP: {:#x?}", sfdp);

    // We expect a SFDP header of version 1.10 with no additional phdrs
    // except the mandatory JDEC phdr.
    assert_eq!(sfdp.header.signature, 0x50444653);
    assert_eq!(sfdp.header.minor, 0xa);
    assert_eq!(sfdp.header.major, 0x1);
    assert_eq!(sfdp.header.nph, 0x0);
    assert_eq!(sfdp.header.reserved, 0xff);

    // Check the parameters of the mandatory phdr.
    assert_eq!(sfdp.phdr[0].id, 0x0);
    assert_eq!(sfdp.phdr[0].minor, 0x7);
    assert_eq!(sfdp.phdr[0].major, 0x1);
    assert_eq!(sfdp.phdr[0].dwords, 0x17);
    assert_eq!(sfdp.phdr[0].offset, 0x10);

    // Check the values of the JEDEC parameters.
    // TODO(lowRISC/opentitan#14457): Update these checks after updating the
    // SFDP parser in opentitanlib.
    assert_eq!(sfdp.jedec.block_erase_size, BlockEraseSize::Block4KiB);
    assert_eq!(
        sfdp.jedec.write_granularity,
        WriteGranularity::Granularity64Bytes
    );
    assert_eq!(sfdp.jedec.write_en_required, true);
    assert_eq!(sfdp.jedec.write_en_opcode, 0x50);
    assert_eq!(sfdp.jedec.erase_opcode_4kib, 0x20);
    assert_eq!(sfdp.jedec.support_fast_read_112, false);
    assert_eq!(sfdp.jedec.address_modes, SupportedAddressModes::Mode3b);
    assert_eq!(sfdp.jedec.support_double_rate_clocking, false);
    assert_eq!(sfdp.jedec.support_fast_read_122, false);
    assert_eq!(sfdp.jedec.support_fast_read_144, false);
    assert_eq!(sfdp.jedec.support_fast_read_114, false);
    assert_eq!(sfdp.jedec.support_fast_read_222, false);
    assert_eq!(sfdp.jedec.support_fast_read_444, false);
    assert_eq!(sfdp.jedec.density, opts.flash_size);
    Ok(())
}

fn test_bootstrap_shutdown(
    opts: &Opts,
    transport: &TransportWrapper,
    cmd: u8,
    bfv: &str,
) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    let spi = transport.spi("0")?;
    let uart = transport.uart("0")?;
    let mut console = UartConsole {
        timeout: Some(Duration::new(2, 0)),
        // `kErrorBootPolicyBadIdentifier` (0142500d) is defined in `error.h`.
        exit_success: Some(Regex::new(
            format!("(?s)BFV:{bfv}\r\n.*BFV:0142500d\r\n").as_str(),
        )?),
        ..Default::default()
    };
    // Send CHIP_ERASE to transition to phase 2.
    SpiFlash::from_spi(&*spi)?.chip_erase(&*spi)?;
    // Remove strapping so that chip fails to boot instead of going into bootstrap.
    transport.remove_pin_strapping("ROM_BOOTSTRAP")?;
    // SECTOR_ERASE with invalid address to trigger a shutdown.
    SpiFlash::set_write_enable(&*spi)?;
    let bad_erase = [cmd, 0xff, 0xff, 0xff];
    spi.run_transaction(&mut [Transfer::Write(&bad_erase)])?;
    // We should see the expected BFVs.
    let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
    if result != ExitStatus::ExitSuccess {
        bail!("FAIL: {:?}", result);
    }
    // Also verify that the chip is no longer in bootstrap mode.
    assert!(matches!(
        SpiFlash::read_sfdp(&*spi)
            .unwrap_err()
            .downcast::<sfdp::Error>()
            .unwrap(),
        sfdp::Error::WrongHeaderSignature(..)
    ));

    Ok(())
}

fn main() -> Result<()> {
    let opts = Opts::from_args();
    opts.init.init_logging();
    let transport = opts.init.init_target()?;

    execute_test!(test_bootstrap_enabled_not_requested, &opts, &transport);
    execute_test!(test_bootstrap_enabled_requested, &opts, &transport);
    execute_test!(test_jedec_id, &opts, &transport);
    execute_test!(test_sfdp, &opts, &transport);
    execute_test!(test_write_enable_disable, &opts, &transport);
    for (cmd, bfv) in [
        // `kErrorBootstrapEraseAddress` (01425303) is defined in `error.h`.
        (SpiFlash::SECTOR_ERASE, "01425303"),
        // `kErrorBootstrapProgramAddress` (02425303) is defined in `error.h`.
        (SpiFlash::PAGE_PROGRAM, "02425303"),
    ] {
        execute_test!(test_bootstrap_shutdown, &opts, &transport, cmd, bfv);
    }

    Ok(())
}
<commit_msg>[test] Erase chip in BootstrapTest::drop()<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::{bail, Result};
use regex::Regex;
use std::matches;
use std::ops::Drop;
use std::time::Duration;
use structopt::StructOpt;

use opentitanlib::app::TransportWrapper;
use opentitanlib::execute_test;
use opentitanlib::io::spi::Transfer;
use opentitanlib::spiflash::{
    sfdp, BlockEraseSize, SpiFlash, SupportedAddressModes, WriteGranularity,
};
use opentitanlib::test_utils::init::InitializeTest;
use opentitanlib::uart::console::{ExitStatus, UartConsole};
use opentitanlib::util::parse_int::ParseInt;

#[derive(Debug, StructOpt)]
struct Opts {
    #[structopt(flatten)]
    init: InitializeTest,

    #[structopt(
        long, parse(try_from_str=humantime::parse_duration),
        default_value = "5s",
        help = "Bootstrap detection timeout",
    )]
    timeout: Duration,

    #[structopt(
        long, parse(try_from_str=usize::from_str),
        default_value = "12",
        help = "JEDEC page of manufacturer",
    )]
    jedec_page: usize,

    #[structopt(
        long, parse(try_from_str=u8::from_str),
        default_value = "0xEF",
        help = "JEDEC ID of manufacturer",
    )]
    jedec_id: u8,

    #[structopt(
        long, parse(try_from_str=u8::from_str),
        default_value = "0x08",
        help = "JEDEC manufacturer product ID",
    )]
    jedec_product: u8,

    #[structopt(
        long, parse(try_from_str=u32::from_str),
        default_value = "0x100000",
        help = "Size of the internal flash",
    )]
    flash_size: u32,
}

/// A struct for isolating individual test points.
///
/// This is basically an example of the RAII technique.
/// Calling `BootstrapTest::start()` resets the chip and puts it in bootstrap mode (assuming it's
/// enabled). Strapping pins are released and the chip is reset when the returned struct is
/// dropped, typically at the end of the test point.
struct BootstrapTest<'a> {
    transport: &'a TransportWrapper,
    reset_delay: Duration,
}

impl<'a> BootstrapTest<'a> {
    pub fn start(transport: &'a TransportWrapper, reset_delay: Duration) -> Result<Self> {
        let b = BootstrapTest {
            transport,
            reset_delay,
        };
        transport.apply_pin_strapping("ROM_BOOTSTRAP")?;
        transport.reset_target(b.reset_delay, true)?;
        Ok(b)
    }
}

impl<'a> Drop for BootstrapTest<'a> {
    fn drop(&mut self) {
        self.transport.apply_pin_strapping("ROM_BOOTSTRAP").unwrap();
        self.transport.reset_target(self.reset_delay, true).unwrap();
        let spi = self.transport.spi("0").unwrap();
        SpiFlash::from_spi(&*spi)
            .unwrap()
            .chip_erase(&*spi)
            .unwrap();
        self.transport
            .remove_pin_strapping("ROM_BOOTSTRAP")
            .unwrap();
        self.transport.reset_target(self.reset_delay, true).unwrap();
    }
}

fn test_bootstrap_enabled_requested(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    // TODO: Should really `opts.init.uart_params.create()` here, but we need to refactor
    // BootstrapOptions first.
    //let uart = opts.init.uart_params.create(&transport)?;
    let uart = transport.uart("0")?;
    let mut console = UartConsole {
        timeout: Some(opts.timeout),
        exit_success: Some(Regex::new(r"bootstrap:1\r\n")?),
        exit_failure: Some(Regex::new(r"BFV:")?),
        ..Default::default()
    };

    transport.apply_pin_strapping("ROM_BOOTSTRAP")?;
    transport.reset_target(opts.init.bootstrap.options.reset_delay, true)?;

    // Now watch the console for the exit conditions.
    let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
    if result != ExitStatus::ExitSuccess {
        bail!("FAIL: {:?}", result);
    };
    // Now check whether the SPI device is responding to status messages
    let spi = transport.spi("0")?;
    assert_eq!(SpiFlash::read_status(&*spi)?, 0x00);

    Ok(())
}

fn test_bootstrap_enabled_not_requested(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    // TODO: Should really `opts.init.uart_params.create()` here, but we need to refactor
    // BootstrapOptions first.
    //let uart = opts.init.uart_params.create(&transport)?;
    let uart = transport.uart("0")?;
    let mut console = UartConsole {
        timeout: Some(opts.timeout),
        exit_success: Some(Regex::new(r"BFV:")?),
        exit_failure: Some(Regex::new(r"bootstrap:1\r\n")?),
        ..Default::default()
    };

    transport.reset_target(opts.init.bootstrap.options.reset_delay, true)?;

    // Now watch the console for the exit conditions.
    let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
    if result != ExitStatus::ExitSuccess {
        bail!("FAIL: {:?}", result);
    };

    // Now check whether the SPI device is responding to commands.
    // Note: CIPO line is in high-z state when CMD_INFO registers are not configured.
    // Use READ_SFDP instead of READ_STATUS to avoid false negatives when bootstrap is not
    // requested
    let spi = transport.spi("0")?;
    assert!(matches!(
        SpiFlash::read_sfdp(&*spi)
            .unwrap_err()
            .downcast::<sfdp::Error>()
            .unwrap(),
        sfdp::Error::WrongHeaderSignature(..)
    ));
    Ok(())
}

fn test_jedec_id(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    let spi = transport.spi("0")?;
    let id = SpiFlash::read_jedec_id(&*spi, 16)?;
    log::info!("Read jedec id: {:x?}", id);
    let mut index = 0;
    while id[index] == 0x7f {
        index += 1;
    }
    let page = index;
    let manufacturer = id[index];
    let product = id[index + 1];
    let density = id[index + 2];

    assert_eq!(page, opts.jedec_page);
    assert_eq!(manufacturer, opts.jedec_id);
    assert_eq!(product, opts.jedec_product);
    assert_eq!(1u32 << density, opts.flash_size);
    Ok(())
}

fn test_write_enable_disable(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    let spi = transport.spi("0")?;

    assert_eq!(SpiFlash::read_status(&*spi)?, 0x0);

    SpiFlash::set_write_enable(&*spi)?;
    assert_eq!(SpiFlash::read_status(&*spi)?, 0x2);

    SpiFlash::set_write_disable(&*spi)?;
    assert_eq!(SpiFlash::read_status(&*spi)?, 0x0);

    Ok(())
}

fn test_sfdp(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    let spi = transport.spi("0")?;
    let sfdp = SpiFlash::read_sfdp(&*spi)?;
    log::info!("SFDP: {:#x?}", sfdp);

    // We expect a SFDP header of version 1.10 with no additional phdrs
    // except the mandatory JDEC phdr.
    assert_eq!(sfdp.header.signature, 0x50444653);
    assert_eq!(sfdp.header.minor, 0xa);
    assert_eq!(sfdp.header.major, 0x1);
    assert_eq!(sfdp.header.nph, 0x0);
    assert_eq!(sfdp.header.reserved, 0xff);

    // Check the parameters of the mandatory phdr.
    assert_eq!(sfdp.phdr[0].id, 0x0);
    assert_eq!(sfdp.phdr[0].minor, 0x7);
    assert_eq!(sfdp.phdr[0].major, 0x1);
    assert_eq!(sfdp.phdr[0].dwords, 0x17);
    assert_eq!(sfdp.phdr[0].offset, 0x10);

    // Check the values of the JEDEC parameters.
    // TODO(lowRISC/opentitan#14457): Update these checks after updating the
    // SFDP parser in opentitanlib.
    assert_eq!(sfdp.jedec.block_erase_size, BlockEraseSize::Block4KiB);
    assert_eq!(
        sfdp.jedec.write_granularity,
        WriteGranularity::Granularity64Bytes
    );
    assert_eq!(sfdp.jedec.write_en_required, true);
    assert_eq!(sfdp.jedec.write_en_opcode, 0x50);
    assert_eq!(sfdp.jedec.erase_opcode_4kib, 0x20);
    assert_eq!(sfdp.jedec.support_fast_read_112, false);
    assert_eq!(sfdp.jedec.address_modes, SupportedAddressModes::Mode3b);
    assert_eq!(sfdp.jedec.support_double_rate_clocking, false);
    assert_eq!(sfdp.jedec.support_fast_read_122, false);
    assert_eq!(sfdp.jedec.support_fast_read_144, false);
    assert_eq!(sfdp.jedec.support_fast_read_114, false);
    assert_eq!(sfdp.jedec.support_fast_read_222, false);
    assert_eq!(sfdp.jedec.support_fast_read_444, false);
    assert_eq!(sfdp.jedec.density, opts.flash_size);
    Ok(())
}

fn test_bootstrap_shutdown(
    opts: &Opts,
    transport: &TransportWrapper,
    cmd: u8,
    bfv: &str,
) -> Result<()> {
    let _bs = BootstrapTest::start(transport, opts.init.bootstrap.options.reset_delay)?;

    let spi = transport.spi("0")?;
    let uart = transport.uart("0")?;
    let mut console = UartConsole {
        timeout: Some(Duration::new(2, 0)),
        // `kErrorBootPolicyBadIdentifier` (0142500d) is defined in `error.h`.
        exit_success: Some(Regex::new(
            format!("(?s)BFV:{bfv}\r\n.*BFV:0142500d\r\n").as_str(),
        )?),
        ..Default::default()
    };
    // Send CHIP_ERASE to transition to phase 2.
    SpiFlash::from_spi(&*spi)?.chip_erase(&*spi)?;
    // Remove strapping so that chip fails to boot instead of going into bootstrap.
    transport.remove_pin_strapping("ROM_BOOTSTRAP")?;
    // SECTOR_ERASE with invalid address to trigger a shutdown.
    SpiFlash::set_write_enable(&*spi)?;
    let bad_erase = [cmd, 0xff, 0xff, 0xff];
    spi.run_transaction(&mut [Transfer::Write(&bad_erase)])?;
    // We should see the expected BFVs.
    let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
    if result != ExitStatus::ExitSuccess {
        bail!("FAIL: {:?}", result);
    }
    // Also verify that the chip is no longer in bootstrap mode.
    assert!(matches!(
        SpiFlash::read_sfdp(&*spi)
            .unwrap_err()
            .downcast::<sfdp::Error>()
            .unwrap(),
        sfdp::Error::WrongHeaderSignature(..)
    ));

    Ok(())
}

fn main() -> Result<()> {
    let opts = Opts::from_args();
    opts.init.init_logging();
    let transport = opts.init.init_target()?;

    execute_test!(test_bootstrap_enabled_not_requested, &opts, &transport);
    execute_test!(test_bootstrap_enabled_requested, &opts, &transport);
    execute_test!(test_jedec_id, &opts, &transport);
    execute_test!(test_sfdp, &opts, &transport);
    execute_test!(test_write_enable_disable, &opts, &transport);
    for (cmd, bfv) in [
        // `kErrorBootstrapEraseAddress` (01425303) is defined in `error.h`.
        (SpiFlash::SECTOR_ERASE, "01425303"),
        // `kErrorBootstrapProgramAddress` (02425303) is defined in `error.h`.
        (SpiFlash::PAGE_PROGRAM, "02425303"),
    ] {
        execute_test!(test_bootstrap_shutdown, &opts, &transport, cmd, bfv);
    }

    Ok(())
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// 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.

/*!
# Rust-PortAudio

__Portaudio__ bindings for Rust

PortAudio provides a uniform application programming interface (API) across all supported platforms.
You can think of the PortAudio library as a wrapper that converts calls to the PortAudio API into calls to platform-specific native audio APIs.
Operating systems often offer more than one native audio API and some APIs (such as JACK) may be available on multiple target operating systems.
PortAudio supports all the major native audio APIs on each supported platform.

# Installation

You must install on your computer the Portaudio libraries who is used for the binding.

Portaudio is available with package management tools on Linux, or brew on Mac OS.

You can download it directly from the website : [portaudio](http://www.portaudio.com/download.html)

Then clone the repo and build the library with the following command at the root of the __rust-portaudio__ repository.

__rust-portaudio__ is build with the rustpkg tool :

```Shell
> rustpkg build portaudio
```

*/

#[link(name = "portaudio",
       vers = "0.0.1",
       package_id = "portaudio",
       author = "letang.jeremy@gmail.com",
       uuid = "57224177-873F-43C2-8F44-A41D501C1A63",
       url = "http://https://github.com/JeremyLetang/rust-portaudio")];

#[comment = "Portaudio binding for Rust"];
// #[license = "Zlib/png"];
#[crate_type = "lib"];

#[feature(globs, managed_boxes)];
#[warn(missing_doc)];
#[allow(dead_code)];

extern mod extra;

#[cfg(target_os="macos")]
#[cfg(target_os="linux")]
#[cfg(target_os="win32")]
mod c_library {
    #[link(name = "portaudio")]
    extern {}
}

pub mod types;
pub mod pa;

#[doc(hidden)]
pub mod user_traits;
#[doc(hidden)]
#[cfg(target_os="macos")]
pub mod mac_core;
//pub mod asio;
#[doc(hidden)]
pub mod ffi;
<commit_msg>remove link attribute<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// 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.

/*!
# Rust-PortAudio

__Portaudio__ bindings for Rust

PortAudio provides a uniform application programming interface (API) across all supported platforms.
You can think of the PortAudio library as a wrapper that converts calls to the PortAudio API into calls to platform-specific native audio APIs.
Operating systems often offer more than one native audio API and some APIs (such as JACK) may be available on multiple target operating systems.
PortAudio supports all the major native audio APIs on each supported platform.

# Installation

You must install on your computer the Portaudio libraries who is used for the binding.

Portaudio is available with package management tools on Linux, or brew on Mac OS.

You can download it directly from the website : [portaudio](http://www.portaudio.com/download.html)

Then clone the repo and build the library with the following command at the root of the __rust-portaudio__ repository.

__rust-portaudio__ is build with the rustpkg tool :

```Shell
> rustpkg build portaudio
```

*/

#[crate_id = "portaudio#0.1"];

#[comment = "Portaudio binding for Rust"];
// #[license = "Zlib/png"];
#[crate_type = "lib"];

#[feature(globs, managed_boxes)];
#[warn(missing_doc)];
#[allow(dead_code)];

extern mod extra;

#[cfg(target_os="macos")]
#[cfg(target_os="linux")]
#[cfg(target_os="win32")]
mod c_library {
    #[link(name = "portaudio")]
    extern {}
}

pub mod types;
pub mod pa;

#[doc(hidden)]
pub mod user_traits;
#[doc(hidden)]
#[cfg(target_os="macos")]
pub mod mac_core;
//pub mod asio;
#[doc(hidden)]
pub mod ffi;
<|endoftext|>


<commit_before>use rustc_serialize::json::{ToJson, Json};
use std::collections::BTreeMap;
use super::Name;

impl ToJson for Name {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("surname".to_string(), self.surname().to_json());
        d.insert("first_initial".to_string(), format!("{}", self.first_initial()).to_json());
        if self.given_name().is_some() {
            d.insert("given_name".to_string(), self.given_name().unwrap().to_json());
        }
        if self.middle_initials().is_some() {
            d.insert("middle_initial".to_string(), self.middle_initials().unwrap().to_json());
        }
        if self.middle_names().is_some() {
            d.insert("middle_names".to_string(), self.middle_name().unwrap().to_json());
        }
        if self.suffix().is_some() {
            d.insert("suffix".to_string(), self.suffix().unwrap().to_json());
        }
        Json::Object(d)
    }
}
<commit_msg>Add docs for to_json<commit_after>use rustc_serialize::json::{ToJson, Json};
use std::collections::BTreeMap;
use super::Name;

impl ToJson for Name {

    /// Serializes a name into parsed components.
    ///
    /// ```
    /// # extern crate rustc_serialize;
    /// # extern crate human_name;
    /// #
    /// use human_name::Name;
    /// use rustc_serialize::json::ToJson;
    ///
    /// # fn main() {
    /// let name = Name::parse("JOHN ALLEN Q MACDONALD JR").unwrap();
    /// assert_eq!(
    ///   r#"{"first_initial":"J","given_name":"John","middle_initial":"AQ","middle_names":"Allen","suffix":"Jr.","surname":"MacDonald"}"#,
    ///   name.to_json().to_string()
    /// );
    /// # }
    /// ```
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("surname".to_string(), self.surname().to_json());
        d.insert("first_initial".to_string(), format!("{}", self.first_initial()).to_json());
        if self.given_name().is_some() {
            d.insert("given_name".to_string(), self.given_name().unwrap().to_json());
        }
        if self.middle_initials().is_some() {
            d.insert("middle_initial".to_string(), self.middle_initials().unwrap().to_json());
        }
        if self.middle_names().is_some() {
            d.insert("middle_names".to_string(), self.middle_name().unwrap().to_json());
        }
        if self.suffix().is_some() {
            d.insert("suffix".to_string(), self.suffix().unwrap().to_json());
        }
        Json::Object(d)
    }
}
<|endoftext|>