<commit_before>//! A helper class for dealing with static archives

use std::ffi::{CString, CStr};
use std::io;
use std::mem;
use std::path::{Path, PathBuf};
use std::ptr;
use std::str;

use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind};
use rustc_codegen_ssa::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, find_library};
use rustc::session::Session;

struct ArchiveConfig<'a> {
    pub sess: &'a Session,
    pub dst: PathBuf,
    pub src: Option<PathBuf>,
    pub lib_search_paths: Vec<PathBuf>,
}

/// Helper for adding many files to an archive.
#[must_use = "must call build() to finish building the archive"]
pub struct LlvmArchiveBuilder<'a> {
    config: ArchiveConfig<'a>,
    removals: Vec<String>,
    additions: Vec<Addition>,
    should_update_symbols: bool,
    src_archive: Option<Option<ArchiveRO>>,
}

enum Addition {
    File {
        path: PathBuf,
        name_in_archive: String,
    },
    Archive {
        archive: ArchiveRO,
        skip: Box<dyn FnMut(&str) -> bool>,
    },
}

fn is_relevant_child(c: &Child<'_>) -> bool {
    match c.name() {
        Some(name) => !name.contains("SYMDEF"),
        None => false,
    }
}

fn archive_config<'a>(sess: &'a Session,
                      output: &Path,
                      input: Option<&Path>) -> ArchiveConfig<'a> {
    use rustc_codegen_ssa::back::link::archive_search_paths;
    ArchiveConfig {
        sess,
        dst: output.to_path_buf(),
        src: input.map(|p| p.to_path_buf()),
        lib_search_paths: archive_search_paths(sess),
    }
}

impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
    /// Creates a new static archive, ready for modifying the archive specified
    /// by `config`.
    fn new(sess: &'a Session,
            output: &Path,
            input: Option<&Path>) -> LlvmArchiveBuilder<'a> {
        let config = archive_config(sess, output, input);
        LlvmArchiveBuilder {
            config,
            removals: Vec::new(),
            additions: Vec::new(),
            should_update_symbols: false,
            src_archive: None,
        }
    }

    /// Removes a file from this archive
    fn remove_file(&mut self, file: &str) {
        self.removals.push(file.to_string());
    }

    /// Lists all files in an archive
    fn src_files(&mut self) -> Vec<String> {
        if self.src_archive().is_none() {
            return Vec::new()
        }

        let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();

        archive.iter()
               .filter_map(|child| child.ok())
               .filter(is_relevant_child)
               .filter_map(|child| child.name())
               .filter(|name| !self.removals.iter().any(|x| x == name))
               .map(|name| name.to_owned())
               .collect()
    }

    /// Adds all of the contents of a native library to this archive. This will
    /// search in the relevant locations for a library named `name`.
    fn add_native_library(&mut self, name: &str) {
        let location = find_library(name, &self.config.lib_search_paths,
                                    self.config.sess);
        self.add_archive(&location, |_| false).unwrap_or_else(|e| {
            self.config.sess.fatal(&format!("failed to add native library {}: {}",
                                            location.to_string_lossy(), e));
        });
    }

    /// Adds all of the contents of the rlib at the specified path to this
    /// archive.
    ///
    /// This ignores adding the bytecode from the rlib, and if LTO is enabled
    /// then the object file also isn't added.
    fn add_rlib(&mut self,
                    rlib: &Path,
                    name: &str,
                    lto: bool,
                    skip_objects: bool) -> io::Result<()> {
        // Ignoring obj file starting with the crate name
        // as simple comparison is not enough - there
        // might be also an extra name suffix
        let obj_start = name.to_owned();

        self.add_archive(rlib, move |fname: &str| {
            // Ignore bytecode/metadata files, no matter the name.
            if fname.ends_with(RLIB_BYTECODE_EXTENSION) || fname == METADATA_FILENAME {
                return true
            }

            // Don't include Rust objects if LTO is enabled
            if lto && fname.starts_with(&obj_start) && fname.ends_with(".o") {
                return true
            }

            // Otherwise if this is *not* a rust object and we're skipping
            // objects then skip this file
            if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
                return true
            }

            // ok, don't skip this
            return false
        })
    }

    /// Adds an arbitrary file to this archive
    fn add_file(&mut self, file: &Path) {
        let name = file.file_name().unwrap().to_str().unwrap();
        self.additions.push(Addition::File {
            path: file.to_path_buf(),
            name_in_archive: name.to_owned(),
        });
    }

    /// Indicate that the next call to `build` should update all symbols in
    /// the archive (equivalent to running 'ar s' over it).
    fn update_symbols(&mut self) {
        self.should_update_symbols = true;
    }

    /// Combine the provided files, rlibs, and native libraries into a single
    /// `Archive`.
    fn build(mut self) {
        let kind = self.llvm_archive_kind().unwrap_or_else(|kind|
            self.config.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)));

        if let Err(e) = self.build_with_llvm(kind) {
            self.config.sess.fatal(&format!("failed to build archive: {}", e));
        }

    }
}

impl<'a> LlvmArchiveBuilder<'a> {
    fn src_archive(&mut self) -> Option<&ArchiveRO> {
        if let Some(ref a) = self.src_archive {
            return a.as_ref()
        }
        let src = self.config.src.as_ref()?;
        self.src_archive = Some(ArchiveRO::open(src).ok());
        self.src_archive.as_ref().unwrap().as_ref()
    }

    fn add_archive<F>(&mut self, archive: &Path, skip: F)
                      -> io::Result<()>
        where F: FnMut(&str) -> bool + 'static
    {
        let archive = match ArchiveRO::open(archive) {
            Ok(ar) => ar,
            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
        };
        self.additions.push(Addition::Archive {
            archive,
            skip: Box::new(skip),
        });
        Ok(())
    }

    fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
        let kind = &*self.config.sess.target.target.options.archive_format;
        kind.parse().map_err(|_| kind)
    }

    fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
        let removals = mem::take(&mut self.removals);
        let mut additions = mem::take(&mut self.additions);
        let mut strings = Vec::new();
        let mut members = Vec::new();

        let dst = CString::new(self.config.dst.to_str().unwrap())?;
        let should_update_symbols = self.should_update_symbols;

        unsafe {
            if let Some(archive) = self.src_archive() {
                for child in archive.iter() {
                    let child = child.map_err(string_to_io_error)?;
                    let child_name = match child.name() {
                        Some(s) => s,
                        None => continue,
                    };
                    if removals.iter().any(|r| r == child_name) {
                        continue
                    }

                    let name = CString::new(child_name)?;
                    members.push(llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                name.as_ptr(),
                                                                Some(child.raw)));
                    strings.push(name);
                }
            }
            for addition in &mut additions {
                match addition {
                    Addition::File { path, name_in_archive } => {
                        let path = CString::new(path.to_str().unwrap())?;
                        let name = CString::new(name_in_archive.clone())?;
                        members.push(llvm::LLVMRustArchiveMemberNew(path.as_ptr(),
                                                                    name.as_ptr(),
                                                                    None));
                        strings.push(path);
                        strings.push(name);
                    }
                    Addition::Archive { archive, skip } => {
                        for child in archive.iter() {
                            let child = child.map_err(string_to_io_error)?;
                            if !is_relevant_child(&child) {
                                continue
                            }
                            let child_name = child.name().unwrap();
                            if skip(child_name) {
                                continue
                            }

                            // It appears that LLVM's archive writer is a little
                            // buggy if the name we pass down isn't just the
                            // filename component, so chop that off here and
                            // pass it in.
                            //
                            // See LLVM bug 25877 for more info.
                            let child_name = Path::new(child_name)
                                                  .file_name().unwrap()
                                                  .to_str().unwrap();
                            let name = CString::new(child_name)?;
                            let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                   name.as_ptr(),
                                                                   Some(child.raw));
                            members.push(m);
                            strings.push(name);
                        }
                    }
                }
            }

            let r = llvm::LLVMRustWriteArchive(dst.as_ptr(),
                                               members.len() as libc::size_t,
                                               members.as_ptr() as *const &_,
                                               should_update_symbols,
                                               kind);
            let ret = if r.into_result().is_err() {
                let err = llvm::LLVMRustGetLastError();
                let msg = if err.is_null() {
                    "failed to write archive".into()
                } else {
                    String::from_utf8_lossy(CStr::from_ptr(err).to_bytes())
                };
                Err(io::Error::new(io::ErrorKind::Other, msg))
            } else {
                Ok(())
            };
            for member in members {
                llvm::LLVMRustArchiveMemberFree(member);
            }
            ret
        }
    }
}

fn string_to_io_error(s: String) -> io::Error {
    io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
}
<commit_msg>Rollup merge of #62286 - petrhosek:rustc-no-duplicate-archives, r=cramertj<commit_after>//! A helper class for dealing with static archives

use std::ffi::{CString, CStr};
use std::io;
use std::mem;
use std::path::{Path, PathBuf};
use std::ptr;
use std::str;

use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind};
use rustc_codegen_ssa::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, find_library};
use rustc::session::Session;

struct ArchiveConfig<'a> {
    pub sess: &'a Session,
    pub dst: PathBuf,
    pub src: Option<PathBuf>,
    pub lib_search_paths: Vec<PathBuf>,
}

/// Helper for adding many files to an archive.
#[must_use = "must call build() to finish building the archive"]
pub struct LlvmArchiveBuilder<'a> {
    config: ArchiveConfig<'a>,
    removals: Vec<String>,
    additions: Vec<Addition>,
    should_update_symbols: bool,
    src_archive: Option<Option<ArchiveRO>>,
}

enum Addition {
    File {
        path: PathBuf,
        name_in_archive: String,
    },
    Archive {
        path: PathBuf,
        archive: ArchiveRO,
        skip: Box<dyn FnMut(&str) -> bool>,
    },
}

impl Addition {
    fn path(&self) -> &Path {
        match self {
            Addition::File { path, .. } | Addition::Archive { path, .. } => path,
        }
    }
}

fn is_relevant_child(c: &Child<'_>) -> bool {
    match c.name() {
        Some(name) => !name.contains("SYMDEF"),
        None => false,
    }
}

fn archive_config<'a>(sess: &'a Session,
                      output: &Path,
                      input: Option<&Path>) -> ArchiveConfig<'a> {
    use rustc_codegen_ssa::back::link::archive_search_paths;
    ArchiveConfig {
        sess,
        dst: output.to_path_buf(),
        src: input.map(|p| p.to_path_buf()),
        lib_search_paths: archive_search_paths(sess),
    }
}

impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
    /// Creates a new static archive, ready for modifying the archive specified
    /// by `config`.
    fn new(sess: &'a Session,
            output: &Path,
            input: Option<&Path>) -> LlvmArchiveBuilder<'a> {
        let config = archive_config(sess, output, input);
        LlvmArchiveBuilder {
            config,
            removals: Vec::new(),
            additions: Vec::new(),
            should_update_symbols: false,
            src_archive: None,
        }
    }

    /// Removes a file from this archive
    fn remove_file(&mut self, file: &str) {
        self.removals.push(file.to_string());
    }

    /// Lists all files in an archive
    fn src_files(&mut self) -> Vec<String> {
        if self.src_archive().is_none() {
            return Vec::new()
        }

        let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();

        archive.iter()
               .filter_map(|child| child.ok())
               .filter(is_relevant_child)
               .filter_map(|child| child.name())
               .filter(|name| !self.removals.iter().any(|x| x == name))
               .map(|name| name.to_owned())
               .collect()
    }

    /// Adds all of the contents of a native library to this archive. This will
    /// search in the relevant locations for a library named `name`.
    fn add_native_library(&mut self, name: &str) {
        let location = find_library(name, &self.config.lib_search_paths,
                                    self.config.sess);
        self.add_archive(&location, |_| false).unwrap_or_else(|e| {
            self.config.sess.fatal(&format!("failed to add native library {}: {}",
                                            location.to_string_lossy(), e));
        });
    }

    /// Adds all of the contents of the rlib at the specified path to this
    /// archive.
    ///
    /// This ignores adding the bytecode from the rlib, and if LTO is enabled
    /// then the object file also isn't added.
    fn add_rlib(&mut self,
                    rlib: &Path,
                    name: &str,
                    lto: bool,
                    skip_objects: bool) -> io::Result<()> {
        // Ignoring obj file starting with the crate name
        // as simple comparison is not enough - there
        // might be also an extra name suffix
        let obj_start = name.to_owned();

        self.add_archive(rlib, move |fname: &str| {
            // Ignore bytecode/metadata files, no matter the name.
            if fname.ends_with(RLIB_BYTECODE_EXTENSION) || fname == METADATA_FILENAME {
                return true
            }

            // Don't include Rust objects if LTO is enabled
            if lto && fname.starts_with(&obj_start) && fname.ends_with(".o") {
                return true
            }

            // Otherwise if this is *not* a rust object and we're skipping
            // objects then skip this file
            if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
                return true
            }

            // ok, don't skip this
            return false
        })
    }

    /// Adds an arbitrary file to this archive
    fn add_file(&mut self, file: &Path) {
        let name = file.file_name().unwrap().to_str().unwrap();
        self.additions.push(Addition::File {
            path: file.to_path_buf(),
            name_in_archive: name.to_owned(),
        });
    }

    /// Indicate that the next call to `build` should update all symbols in
    /// the archive (equivalent to running 'ar s' over it).
    fn update_symbols(&mut self) {
        self.should_update_symbols = true;
    }

    /// Combine the provided files, rlibs, and native libraries into a single
    /// `Archive`.
    fn build(mut self) {
        let kind = self.llvm_archive_kind().unwrap_or_else(|kind|
            self.config.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)));

        if let Err(e) = self.build_with_llvm(kind) {
            self.config.sess.fatal(&format!("failed to build archive: {}", e));
        }

    }
}

impl<'a> LlvmArchiveBuilder<'a> {
    fn src_archive(&mut self) -> Option<&ArchiveRO> {
        if let Some(ref a) = self.src_archive {
            return a.as_ref()
        }
        let src = self.config.src.as_ref()?;
        self.src_archive = Some(ArchiveRO::open(src).ok());
        self.src_archive.as_ref().unwrap().as_ref()
    }

    fn add_archive<F>(&mut self, archive: &Path, skip: F)
                      -> io::Result<()>
        where F: FnMut(&str) -> bool + 'static
    {
        let archive_ro = match ArchiveRO::open(archive) {
            Ok(ar) => ar,
            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
        };
        if self.additions.iter().any(|ar| ar.path() == archive) {
            return Ok(())
        }
        self.additions.push(Addition::Archive {
            path: archive.to_path_buf(),
            archive: archive_ro,
            skip: Box::new(skip),
        });
        Ok(())
    }

    fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
        let kind = &*self.config.sess.target.target.options.archive_format;
        kind.parse().map_err(|_| kind)
    }

    fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
        let removals = mem::take(&mut self.removals);
        let mut additions = mem::take(&mut self.additions);
        let mut strings = Vec::new();
        let mut members = Vec::new();

        let dst = CString::new(self.config.dst.to_str().unwrap())?;
        let should_update_symbols = self.should_update_symbols;

        unsafe {
            if let Some(archive) = self.src_archive() {
                for child in archive.iter() {
                    let child = child.map_err(string_to_io_error)?;
                    let child_name = match child.name() {
                        Some(s) => s,
                        None => continue,
                    };
                    if removals.iter().any(|r| r == child_name) {
                        continue
                    }

                    let name = CString::new(child_name)?;
                    members.push(llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                name.as_ptr(),
                                                                Some(child.raw)));
                    strings.push(name);
                }
            }
            for addition in &mut additions {
                match addition {
                    Addition::File { path, name_in_archive } => {
                        let path = CString::new(path.to_str().unwrap())?;
                        let name = CString::new(name_in_archive.clone())?;
                        members.push(llvm::LLVMRustArchiveMemberNew(path.as_ptr(),
                                                                    name.as_ptr(),
                                                                    None));
                        strings.push(path);
                        strings.push(name);
                    }
                    Addition::Archive { archive, skip, .. } => {
                        for child in archive.iter() {
                            let child = child.map_err(string_to_io_error)?;
                            if !is_relevant_child(&child) {
                                continue
                            }
                            let child_name = child.name().unwrap();
                            if skip(child_name) {
                                continue
                            }

                            // It appears that LLVM's archive writer is a little
                            // buggy if the name we pass down isn't just the
                            // filename component, so chop that off here and
                            // pass it in.
                            //
                            // See LLVM bug 25877 for more info.
                            let child_name = Path::new(child_name)
                                                  .file_name().unwrap()
                                                  .to_str().unwrap();
                            let name = CString::new(child_name)?;
                            let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
                                                                   name.as_ptr(),
                                                                   Some(child.raw));
                            members.push(m);
                            strings.push(name);
                        }
                    }
                }
            }

            let r = llvm::LLVMRustWriteArchive(dst.as_ptr(),
                                               members.len() as libc::size_t,
                                               members.as_ptr() as *const &_,
                                               should_update_symbols,
                                               kind);
            let ret = if r.into_result().is_err() {
                let err = llvm::LLVMRustGetLastError();
                let msg = if err.is_null() {
                    "failed to write archive".into()
                } else {
                    String::from_utf8_lossy(CStr::from_ptr(err).to_bytes())
                };
                Err(io::Error::new(io::ErrorKind::Other, msg))
            } else {
                Ok(())
            };
            for member in members {
                llvm::LLVMRustArchiveMemberFree(member);
            }
            ret
        }
    }
}

fn string_to_io_error(s: String) -> io::Error {
    io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
}
<|endoftext|>


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

//! A graph module for use in dataflow, region resolution, and elsewhere.
//!
//! # Interface details
//!
//! You customize the graph by specifying a "node data" type `N` and an
//! "edge data" type `E`. You can then later gain access (mutable or
//! immutable) to these "user-data" bits. Currently, you can only add
//! nodes or edges to the graph. You cannot remove or modify them once
//! added. This could be changed if we have a need.
//!
//! # Implementation details
//!
//! The main tricky thing about this code is the way that edges are
//! stored. The edges are stored in a central array, but they are also
//! threaded onto two linked lists for each node, one for incoming edges
//! and one for outgoing edges. Note that every edge is a member of some
//! incoming list and some outgoing list.  Basically you can load the
//! first index of the linked list from the node data structures (the
//! field `first_edge`) and then, for each edge, load the next index from
//! the field `next_edge`). Each of those fields is an array that should
//! be indexed by the direction (see the type `Direction`).

use bitvec::BitVector;
use std::fmt::{Formatter, Error, Debug};
use std::usize;
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};

#[cfg(test)]
mod tests;

pub struct Graph<N, E> {
    nodes: SnapshotVec<Node<N>>,
    edges: SnapshotVec<Edge<E>>,
}

pub struct Node<N> {
    first_edge: [EdgeIndex; 2], // see module comment
    pub data: N,
}

pub struct Edge<E> {
    next_edge: [EdgeIndex; 2], // see module comment
    source: NodeIndex,
    target: NodeIndex,
    pub data: E,
}

impl<N> SnapshotVecDelegate for Node<N> {
    type Value = Node<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Node<N>>, _: ()) {}
}

impl<N> SnapshotVecDelegate for Edge<N> {
    type Value = Edge<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Edge<N>>, _: ()) {}
}

impl<E: Debug> Debug for Edge<E> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f,
               "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}",
               self.next_edge[0],
               self.next_edge[1],
               self.source,
               self.target,
               self.data)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct NodeIndex(pub usize);

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct EdgeIndex(pub usize);

pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);

// Use a private field here to guarantee no more instances are created:
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Direction {
    repr: usize,
}

pub const OUTGOING: Direction = Direction { repr: 0 };

pub const INCOMING: Direction = Direction { repr: 1 };

impl NodeIndex {
    /// Returns unique id (unique with respect to the graph holding associated node).
    pub fn node_id(&self) -> usize {
        self.0
    }
}

impl EdgeIndex {
    /// Returns unique id (unique with respect to the graph holding associated edge).
    pub fn edge_id(&self) -> usize {
        self.0
    }
}

impl<N: Debug, E: Debug> Graph<N, E> {
    pub fn new() -> Graph<N, E> {
        Graph {
            nodes: SnapshotVec::new(),
            edges: SnapshotVec::new(),
        }
    }

    // # Simple accessors

    #[inline]
    pub fn all_nodes(&self) -> &[Node<N>] {
        &self.nodes
    }

    #[inline]
    pub fn len_nodes(&self) -> usize {
        self.nodes.len()
    }

    #[inline]
    pub fn all_edges(&self) -> &[Edge<E>] {
        &self.edges
    }

    #[inline]
    pub fn len_edges(&self) -> usize {
        self.edges.len()
    }

    // # Node construction

    pub fn next_node_index(&self) -> NodeIndex {
        NodeIndex(self.nodes.len())
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex {
        let idx = self.next_node_index();
        self.nodes.push(Node {
            first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
            data: data,
        });
        idx
    }

    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
        &mut self.nodes[idx.0].data
    }

    pub fn node_data(&self, idx: NodeIndex) -> &N {
        &self.nodes[idx.0].data
    }

    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
        &self.nodes[idx.0]
    }

    // # Edge construction and queries

    pub fn next_edge_index(&self) -> EdgeIndex {
        EdgeIndex(self.edges.len())
    }

    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
        debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);

        let idx = self.next_edge_index();

        // read current first of the list of edges from each node
        let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
        let target_first = self.nodes[target.0].first_edge[INCOMING.repr];

        // create the new edge, with the previous firsts from each node
        // as the next pointers
        self.edges.push(Edge {
            next_edge: [source_first, target_first],
            source: source,
            target: target,
            data: data,
        });

        // adjust the firsts for each node target be the next object.
        self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
        self.nodes[target.0].first_edge[INCOMING.repr] = idx;

        return idx;
    }

    pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E {
        &mut self.edges[idx.0].data
    }

    pub fn edge_data(&self, idx: EdgeIndex) -> &E {
        &self.edges[idx.0].data
    }

    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
        &self.edges[idx.0]
    }

    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the index of the first edge adjacent to `node`.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.nodes[node.0].first_edge[dir.repr]
    }

    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the next edge in a given direction.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.edges[edge.0].next_edge[dir.repr]
    }

    // # Iterating over nodes, edges

    pub fn each_node<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(NodeIndex, &'a Node<N>) -> bool
    {
        //! Iterates over all edges defined in the graph.
        self.nodes.iter().enumerate().all(|(i, node)| f(NodeIndex(i), node))
    }

    pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(EdgeIndex, &'a Edge<E>) -> bool
    {
        //! Iterates over all edges defined in the graph
        self.edges.iter().enumerate().all(|(i, edge)| f(EdgeIndex(i), edge))
    }

    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, OUTGOING)
    }

    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, INCOMING)
    }

    pub fn adjacent_edges(&self, source: NodeIndex, direction: Direction) -> AdjacentEdges<N, E> {
        let first_edge = self.node(source).first_edge[direction.repr];
        AdjacentEdges {
            graph: self,
            direction: direction,
            next: first_edge,
        }
    }

    pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N, E> {
        self.outgoing_edges(source).targets()
    }

    pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N, E> {
        self.incoming_edges(target).sources()
    }

    // # Fixed-point iteration
    //
    // A common use for graphs in our compiler is to perform
    // fixed-point iteration. In this case, each edge represents a
    // constraint, and the nodes themselves are associated with
    // variables or other bitsets. This method facilitates such a
    // computation.

    pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F)
        where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool
    {
        let mut iteration = 0;
        let mut changed = true;
        while changed {
            changed = false;
            iteration += 1;
            for (i, edge) in self.edges.iter().enumerate() {
                changed |= op(iteration, EdgeIndex(i), edge);
            }
        }
    }

    pub fn depth_traverse<'a>(&'a self,
                              start: NodeIndex,
                              direction: Direction)
                              -> DepthFirstTraversal<'a, N, E> {
        DepthFirstTraversal::with_start_node(self, start, direction)
    }
}

// # Iterators

pub struct AdjacentEdges<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    direction: Direction,
    next: EdgeIndex,
}

impl<'g, N, E> AdjacentEdges<'g, N, E> {
    fn targets(self) -> AdjacentTargets<'g, N, E> {
        AdjacentTargets { edges: self }
    }

    fn sources(self) -> AdjacentSources<'g, N, E> {
        AdjacentSources { edges: self }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
    type Item = (EdgeIndex, &'g Edge<E>);

    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
        let edge_index = self.next;
        if edge_index == INVALID_EDGE_INDEX {
            return None;
        }

        let edge = self.graph.edge(edge_index);
        self.next = edge.next_edge[self.direction.repr];
        Some((edge_index, edge))
    }
}

pub struct AdjacentTargets<'g, N: 'g, E: 'g>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.target)
    }
}

pub struct AdjacentSources<'g, N: 'g, E: 'g>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.source)
    }
}

pub struct DepthFirstTraversal<'g, N: 'g, E: 'g> {
    graph: &'g Graph<N, E>,
    stack: Vec<NodeIndex>,
    visited: BitVector,
    direction: Direction,
}

impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
    pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
        let visited = BitVector::new(graph.len_nodes());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![],
            visited: visited,
            direction: direction,
        }
    }

    pub fn with_start_node(graph: &'g Graph<N, E>,
                           start_node: NodeIndex,
                           direction: Direction)
                           -> Self {
        let mut visited = BitVector::new(graph.len_nodes());
        visited.insert(start_node.node_id());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![start_node],
            visited: visited,
            direction: direction,
        }
    }

    pub fn reset(&mut self, start_node: NodeIndex) {
        self.stack.truncate(0);
        self.stack.push(start_node);
        self.visited.clear();
        self.visited.insert(start_node.node_id());
    }

    fn visit(&mut self, node: NodeIndex) {
        if self.visited.insert(node.node_id()) {
            self.stack.push(node);
        }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        let next = self.stack.pop();
        if let Some(idx) = next {
            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
                let target = edge.source_or_target(self.direction);
                self.visit(target);
            }
        }
        next
    }
}

pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F)
    where F: FnMut(EdgeIndex) -> bool
{
    let mut i = 0;
    let n = max_edge_index.0;
    while i < n {
        if !f(EdgeIndex(i)) {
            return;
        }
        i += 1;
    }
}

impl<E> Edge<E> {
    pub fn source(&self) -> NodeIndex {
        self.source
    }

    pub fn target(&self) -> NodeIndex {
        self.target
    }

    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
        if direction == OUTGOING {
            self.target
        } else {
            self.source
        }
    }
}
<commit_msg>Normalize generic bounds in graph iterators<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A graph module for use in dataflow, region resolution, and elsewhere.
//!
//! # Interface details
//!
//! You customize the graph by specifying a "node data" type `N` and an
//! "edge data" type `E`. You can then later gain access (mutable or
//! immutable) to these "user-data" bits. Currently, you can only add
//! nodes or edges to the graph. You cannot remove or modify them once
//! added. This could be changed if we have a need.
//!
//! # Implementation details
//!
//! The main tricky thing about this code is the way that edges are
//! stored. The edges are stored in a central array, but they are also
//! threaded onto two linked lists for each node, one for incoming edges
//! and one for outgoing edges. Note that every edge is a member of some
//! incoming list and some outgoing list.  Basically you can load the
//! first index of the linked list from the node data structures (the
//! field `first_edge`) and then, for each edge, load the next index from
//! the field `next_edge`). Each of those fields is an array that should
//! be indexed by the direction (see the type `Direction`).

use bitvec::BitVector;
use std::fmt::{Formatter, Error, Debug};
use std::usize;
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};

#[cfg(test)]
mod tests;

pub struct Graph<N, E> {
    nodes: SnapshotVec<Node<N>>,
    edges: SnapshotVec<Edge<E>>,
}

pub struct Node<N> {
    first_edge: [EdgeIndex; 2], // see module comment
    pub data: N,
}

pub struct Edge<E> {
    next_edge: [EdgeIndex; 2], // see module comment
    source: NodeIndex,
    target: NodeIndex,
    pub data: E,
}

impl<N> SnapshotVecDelegate for Node<N> {
    type Value = Node<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Node<N>>, _: ()) {}
}

impl<N> SnapshotVecDelegate for Edge<N> {
    type Value = Edge<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Edge<N>>, _: ()) {}
}

impl<E: Debug> Debug for Edge<E> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f,
               "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}",
               self.next_edge[0],
               self.next_edge[1],
               self.source,
               self.target,
               self.data)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct NodeIndex(pub usize);

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct EdgeIndex(pub usize);

pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);

// Use a private field here to guarantee no more instances are created:
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Direction {
    repr: usize,
}

pub const OUTGOING: Direction = Direction { repr: 0 };

pub const INCOMING: Direction = Direction { repr: 1 };

impl NodeIndex {
    /// Returns unique id (unique with respect to the graph holding associated node).
    pub fn node_id(&self) -> usize {
        self.0
    }
}

impl EdgeIndex {
    /// Returns unique id (unique with respect to the graph holding associated edge).
    pub fn edge_id(&self) -> usize {
        self.0
    }
}

impl<N: Debug, E: Debug> Graph<N, E> {
    pub fn new() -> Graph<N, E> {
        Graph {
            nodes: SnapshotVec::new(),
            edges: SnapshotVec::new(),
        }
    }

    // # Simple accessors

    #[inline]
    pub fn all_nodes(&self) -> &[Node<N>] {
        &self.nodes
    }

    #[inline]
    pub fn len_nodes(&self) -> usize {
        self.nodes.len()
    }

    #[inline]
    pub fn all_edges(&self) -> &[Edge<E>] {
        &self.edges
    }

    #[inline]
    pub fn len_edges(&self) -> usize {
        self.edges.len()
    }

    // # Node construction

    pub fn next_node_index(&self) -> NodeIndex {
        NodeIndex(self.nodes.len())
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex {
        let idx = self.next_node_index();
        self.nodes.push(Node {
            first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
            data: data,
        });
        idx
    }

    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
        &mut self.nodes[idx.0].data
    }

    pub fn node_data(&self, idx: NodeIndex) -> &N {
        &self.nodes[idx.0].data
    }

    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
        &self.nodes[idx.0]
    }

    // # Edge construction and queries

    pub fn next_edge_index(&self) -> EdgeIndex {
        EdgeIndex(self.edges.len())
    }

    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
        debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);

        let idx = self.next_edge_index();

        // read current first of the list of edges from each node
        let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
        let target_first = self.nodes[target.0].first_edge[INCOMING.repr];

        // create the new edge, with the previous firsts from each node
        // as the next pointers
        self.edges.push(Edge {
            next_edge: [source_first, target_first],
            source: source,
            target: target,
            data: data,
        });

        // adjust the firsts for each node target be the next object.
        self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
        self.nodes[target.0].first_edge[INCOMING.repr] = idx;

        return idx;
    }

    pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E {
        &mut self.edges[idx.0].data
    }

    pub fn edge_data(&self, idx: EdgeIndex) -> &E {
        &self.edges[idx.0].data
    }

    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
        &self.edges[idx.0]
    }

    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the index of the first edge adjacent to `node`.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.nodes[node.0].first_edge[dir.repr]
    }

    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the next edge in a given direction.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.edges[edge.0].next_edge[dir.repr]
    }

    // # Iterating over nodes, edges

    pub fn each_node<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(NodeIndex, &'a Node<N>) -> bool
    {
        //! Iterates over all edges defined in the graph.
        self.nodes.iter().enumerate().all(|(i, node)| f(NodeIndex(i), node))
    }

    pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(EdgeIndex, &'a Edge<E>) -> bool
    {
        //! Iterates over all edges defined in the graph
        self.edges.iter().enumerate().all(|(i, edge)| f(EdgeIndex(i), edge))
    }

    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, OUTGOING)
    }

    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, INCOMING)
    }

    pub fn adjacent_edges(&self, source: NodeIndex, direction: Direction) -> AdjacentEdges<N, E> {
        let first_edge = self.node(source).first_edge[direction.repr];
        AdjacentEdges {
            graph: self,
            direction: direction,
            next: first_edge,
        }
    }

    pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N, E> {
        self.outgoing_edges(source).targets()
    }

    pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N, E> {
        self.incoming_edges(target).sources()
    }

    // # Fixed-point iteration
    //
    // A common use for graphs in our compiler is to perform
    // fixed-point iteration. In this case, each edge represents a
    // constraint, and the nodes themselves are associated with
    // variables or other bitsets. This method facilitates such a
    // computation.

    pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F)
        where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool
    {
        let mut iteration = 0;
        let mut changed = true;
        while changed {
            changed = false;
            iteration += 1;
            for (i, edge) in self.edges.iter().enumerate() {
                changed |= op(iteration, EdgeIndex(i), edge);
            }
        }
    }

    pub fn depth_traverse<'a>(&'a self,
                              start: NodeIndex,
                              direction: Direction)
                              -> DepthFirstTraversal<'a, N, E> {
        DepthFirstTraversal::with_start_node(self, start, direction)
    }
}

// # Iterators

pub struct AdjacentEdges<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    direction: Direction,
    next: EdgeIndex,
}

impl<'g, N, E> AdjacentEdges<'g, N, E> {
    fn targets(self) -> AdjacentTargets<'g, N, E> {
        AdjacentTargets { edges: self }
    }

    fn sources(self) -> AdjacentSources<'g, N, E> {
        AdjacentSources { edges: self }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
    type Item = (EdgeIndex, &'g Edge<E>);

    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
        let edge_index = self.next;
        if edge_index == INVALID_EDGE_INDEX {
            return None;
        }

        let edge = self.graph.edge(edge_index);
        self.next = edge.next_edge[self.direction.repr];
        Some((edge_index, edge))
    }
}

pub struct AdjacentTargets<'g, N, E>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.target)
    }
}

pub struct AdjacentSources<'g, N, E>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.source)
    }
}

pub struct DepthFirstTraversal<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    stack: Vec<NodeIndex>,
    visited: BitVector,
    direction: Direction,
}

impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
    pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
        let visited = BitVector::new(graph.len_nodes());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![],
            visited: visited,
            direction: direction,
        }
    }

    pub fn with_start_node(graph: &'g Graph<N, E>,
                           start_node: NodeIndex,
                           direction: Direction)
                           -> Self {
        let mut visited = BitVector::new(graph.len_nodes());
        visited.insert(start_node.node_id());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![start_node],
            visited: visited,
            direction: direction,
        }
    }

    pub fn reset(&mut self, start_node: NodeIndex) {
        self.stack.truncate(0);
        self.stack.push(start_node);
        self.visited.clear();
        self.visited.insert(start_node.node_id());
    }

    fn visit(&mut self, node: NodeIndex) {
        if self.visited.insert(node.node_id()) {
            self.stack.push(node);
        }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        let next = self.stack.pop();
        if let Some(idx) = next {
            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
                let target = edge.source_or_target(self.direction);
                self.visit(target);
            }
        }
        next
    }
}

pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F)
    where F: FnMut(EdgeIndex) -> bool
{
    let mut i = 0;
    let n = max_edge_index.0;
    while i < n {
        if !f(EdgeIndex(i)) {
            return;
        }
        i += 1;
    }
}

impl<E> Edge<E> {
    pub fn source(&self) -> NodeIndex {
        self.source
    }

    pub fn target(&self) -> NodeIndex {
        self.target
    }

    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
        if direction == OUTGOING {
            self.target
        } else {
            self.source
        }
    }
}
<|endoftext|>


<commit_before>use crate::nodes::Node;
use anyhow::Result;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct GenericRequest<P> {
    /// A string specifying the version of the JSON-RPC protocol.
    pub jsonrpc: Option<String>,

    /// An identifier for the request established by the client
    /// The standard allows this to be a number or a string but here we use
    /// `u64` because it proved to require less code and is probably more efficient.
    /// May be `None` for notifications from the server
    pub id: Option<u64>,

    /// Parameters of the method call
    pub params: P,
}

/// A JSON-RPC 2.0 request
///
/// @see {@link https://www.jsonrpc.org/specification#request_object}
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "method", rename_all = "lowercase")]
pub enum Request {
    Decode(GenericRequest<crate::decode::rpc::Params>),
    Execute(GenericRequest<crate::execute::rpc::Params>),
}

impl Request {
    pub fn id(&self) -> Option<u64> {
        match self {
            Request::Decode(request) => request.id,
            Request::Execute(request) => request.id,
        }
    }

    pub fn dispatch(self) -> Result<Node> {
        match self {
            Request::Decode(request) => crate::decode::rpc::decode(request.params),
            Request::Execute(request) => crate::execute::rpc::execute(request.params),
        }
    }
}

/// A JSON-RPC 2.0 response
///
/// @see {@link https://www.jsonrpc.org/specification#response_object}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Response {
    /// A string specifying the version of the JSON-RPC protocol.
    pub jsonrpc: Option<String>,

    /// The id of the request that this response is for
    /// May be `None` for notifications from the server
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<u64>,

    /// The result of the method call
    #[serde(skip_serializing_if = "Option::is_none")]
    pub result: Option<Node>,

    /// Any error that may have occurred
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<Error>,
}

impl Response {
    pub fn new(id: Option<u64>, result: Option<Node>, error: Option<anyhow::Error>) -> Self {
        Response {
            id,
            result,
            error: match error {
                Some(error) => Some(Error::server_error(&error.to_string())),
                None => None,
            },
            ..Default::default()
        }
    }
}

impl Default for Response {
    fn default() -> Self {
        Self {
            jsonrpc: Some("2.0".to_string()),
            id: None,
            result: None,
            error: None,
        }
    }
}

/// A JSON-RPC 2.0 error
///
/// @see {@link https://www.jsonrpc.org/specification#error_object}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Error {
    /// A number that indicates the error type that ocurred
    pub code: i16,

    /// A string providing a short description of the error
    pub message: String,

    /// A value that contains additional information about the error
    pub data: Option<serde_json::Value>,
}

impl Error {
    /// Create an error
    pub fn new(code: i16, message: &str, data: Option<serde_json::Value>) -> Self {
        Self {
            code,
            message: message.to_string(),
            data,
        }
    }

    /// A parse error
    pub fn parse_error(details: &str) -> Self {
        Self {
            code: -32700,
            message: format!("Error while parsing request: {}", details),
            data: Some(serde_json::json!({ "details": details })),
        }
    }

    /// An error when a client sends an invalid request
    pub fn invalid_request_error(message: &str) -> Self {
        Self {
            code: -32600,
            message: format!("Request is invalid: {}", message),
            data: None,
        }
    }

    /// An error when the requested method does not exist
    pub fn method_not_found_error(method: &str) -> Self {
        Self {
            code: -32601,
            message: format!("Method '{}' does not exist", method),
            data: None,
        }
    }

    /// An error when one of more parameters are invalid
    pub fn invalid_param_error(message: &str) -> Self {
        Self {
            code: -32000,
            message: message.to_string(),
            data: None,
        }
    }

    /// A generic internal server error
    pub fn server_error(message: &str) -> Self {
        Self {
            code: -32000,
            message: message.to_string(),
            data: None,
        }
    }

    /// An error to indicate the server lacks the requested capability
    pub fn capability_error(capability: &str, method: &str, params: &serde_json::Value) -> Self {
        Self {
            code: -32001,
            message: format!("Incapable of {}", capability),
            data: Some(serde_json::json!({
                "method": method,
                "params": params
            })),
        }
    }
}
<commit_msg>fix(JSON-RPC): Use correct code for invalid params error<commit_after>use crate::nodes::Node;
use anyhow::Result;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct GenericRequest<P> {
    /// A string specifying the version of the JSON-RPC protocol.
    pub jsonrpc: Option<String>,

    /// An identifier for the request established by the client
    /// The standard allows this to be a number or a string but here we use
    /// `u64` because it proved to require less code and is probably more efficient.
    /// May be `None` for notifications from the server
    pub id: Option<u64>,

    /// Parameters of the method call
    pub params: P,
}

/// A JSON-RPC 2.0 request
///
/// @see {@link https://www.jsonrpc.org/specification#request_object}
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "method", rename_all = "lowercase")]
pub enum Request {
    Decode(GenericRequest<crate::decode::rpc::Params>),
    Execute(GenericRequest<crate::execute::rpc::Params>),
}

impl Request {
    pub fn id(&self) -> Option<u64> {
        match self {
            Request::Decode(request) => request.id,
            Request::Execute(request) => request.id,
        }
    }

    pub fn dispatch(self) -> Result<Node> {
        match self {
            Request::Decode(request) => crate::decode::rpc::decode(request.params),
            Request::Execute(request) => crate::execute::rpc::execute(request.params),
        }
    }
}

/// A JSON-RPC 2.0 response
///
/// @see {@link https://www.jsonrpc.org/specification#response_object}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Response {
    /// A string specifying the version of the JSON-RPC protocol.
    pub jsonrpc: Option<String>,

    /// The id of the request that this response is for
    /// May be `None` for notifications from the server
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<u64>,

    /// The result of the method call
    #[serde(skip_serializing_if = "Option::is_none")]
    pub result: Option<Node>,

    /// Any error that may have occurred
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<Error>,
}

impl Response {
    pub fn new(id: Option<u64>, result: Option<Node>, error: Option<anyhow::Error>) -> Self {
        Response {
            id,
            result,
            error: match error {
                Some(error) => Some(Error::server_error(&error.to_string())),
                None => None,
            },
            ..Default::default()
        }
    }
}

impl Default for Response {
    fn default() -> Self {
        Self {
            jsonrpc: Some("2.0".to_string()),
            id: None,
            result: None,
            error: None,
        }
    }
}

/// A JSON-RPC 2.0 error
///
/// @see {@link https://www.jsonrpc.org/specification#error_object}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Error {
    /// A number that indicates the error type that ocurred
    pub code: i16,

    /// A string providing a short description of the error
    pub message: String,

    /// A value that contains additional information about the error
    pub data: Option<serde_json::Value>,
}

impl Error {
    /// Create an error
    pub fn new(code: i16, message: &str, data: Option<serde_json::Value>) -> Self {
        Self {
            code,
            message: message.to_string(),
            data,
        }
    }

    /// A parse error
    pub fn parse_error(details: &str) -> Self {
        Self {
            code: -32700,
            message: format!("Error while parsing request: {}", details),
            data: Some(serde_json::json!({ "details": details })),
        }
    }

    /// An error when a client sends an invalid request
    pub fn invalid_request_error(message: &str) -> Self {
        Self {
            code: -32600,
            message: format!("Request is invalid: {}", message),
            data: None,
        }
    }

    /// An error when the requested method does not exist
    pub fn method_not_found_error(method: &str) -> Self {
        Self {
            code: -32601,
            message: format!("Method '{}' does not exist", method),
            data: None,
        }
    }

    /// An error when one of more parameters are invalid
    pub fn invalid_param_error(message: &str) -> Self {
        Self {
            code: -32602,
            message: message.to_string(),
            data: None,
        }
    }

    /// A generic internal server error
    pub fn server_error(message: &str) -> Self {
        Self {
            code: -32000,
            message: message.to_string(),
            data: None,
        }
    }

    /// An error to indicate the server lacks the requested capability
    pub fn capability_error(capability: &str, method: &str, params: &serde_json::Value) -> Self {
        Self {
            code: -32001,
            message: format!("Incapable of {}", capability),
            data: Some(serde_json::json!({
                "method": method,
                "params": params
            })),
        }
    }
}
<|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.

/*!
 * Atomic types
 *
 * Basic atomic types supporting atomic operations. Each method takes an `Ordering` which
 * represents the strength of the memory barrier for that operation. These orderings are the same
 * as C++11 atomic orderings [http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync]
 *
 * All atomic types are a single word in size.
 */

use unstable::intrinsics;
use cast;
use option::{Option,Some,None};
use libc::c_void;
use ops::Drop;

/**
 * A simple atomic flag, that can be set and cleared. The most basic atomic type.
 */
pub struct AtomicFlag {
    priv v: int
}

/**
 * An atomic boolean type.
 */
pub struct AtomicBool {
    priv v: uint
}

/**
 * A signed atomic integer type, supporting basic atomic aritmetic operations
 */
pub struct AtomicInt {
    priv v: int
}

/**
 * An unsigned atomic integer type, supporting basic atomic aritmetic operations
 */
pub struct AtomicUint {
    priv v: uint
}

/**
 * An unsafe atomic pointer. Only supports basic atomic operations
 */
pub struct AtomicPtr<T> {
    priv p: *mut T
}

/**
 * An owned atomic pointer. Ensures that only a single reference to the data is held at any time.
 */
#[unsafe_no_drop_flag]
pub struct AtomicOption<T> {
    priv p: *mut c_void
}

pub enum Ordering {
    Release,
    Acquire,
    SeqCst
}

impl AtomicFlag {

    pub fn new() -> AtomicFlag {
        AtomicFlag { v: 0 }
    }

    /**
     * Clears the atomic flag
     */
    #[inline]
    pub fn clear(&mut self, order: Ordering) {
        unsafe {atomic_store(&mut self.v, 0, order)}
    }

    /**
     * Sets the flag if it was previously unset, returns the previous value of the
     * flag.
     */
    #[inline]
    pub fn test_and_set(&mut self, order: Ordering) -> bool {
        unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0}
    }
}

impl AtomicBool {
    pub fn new(v: bool) -> AtomicBool {
        AtomicBool { v: if v { 1 } else { 0 } }
    }

    #[inline]
    pub fn load(&self, order: Ordering) -> bool {
        unsafe { atomic_load(&self.v, order) > 0 }
    }

    #[inline]
    pub fn store(&mut self, val: bool, order: Ordering) {
        let val = if val { 1 } else { 0 };

        unsafe { atomic_store(&mut self.v, val, order); }
    }

    #[inline]
    pub fn swap(&mut self, val: bool, order: Ordering) -> bool {
        let val = if val { 1 } else { 0 };

        unsafe { atomic_swap(&mut self.v, val, order) > 0}
    }

    #[inline]
    pub fn compare_and_swap(&mut self, old: bool, new: bool, order: Ordering) -> bool {
        let old = if old { 1 } else { 0 };
        let new = if new { 1 } else { 0 };

        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) > 0 }
    }
}

impl AtomicInt {
    pub fn new(v: int) -> AtomicInt {
        AtomicInt { v:v }
    }

    #[inline]
    pub fn load(&self, order: Ordering) -> int {
        unsafe { atomic_load(&self.v, order) }
    }

    #[inline]
    pub fn store(&mut self, val: int, order: Ordering) {
        unsafe { atomic_store(&mut self.v, val, order); }
    }

    #[inline]
    pub fn swap(&mut self, val: int, order: Ordering) -> int {
        unsafe { atomic_swap(&mut self.v, val, order) }
    }

    #[inline]
    pub fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int {
        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
    }

    /// Returns the old value (like __sync_fetch_and_add).
    #[inline]
    pub fn fetch_add(&mut self, val: int, order: Ordering) -> int {
        unsafe { atomic_add(&mut self.v, val, order) }
    }

    /// Returns the old value (like __sync_fetch_and_sub).
    #[inline]
    pub fn fetch_sub(&mut self, val: int, order: Ordering) -> int {
        unsafe { atomic_sub(&mut self.v, val, order) }
    }
}

impl AtomicUint {
    pub fn new(v: uint) -> AtomicUint {
        AtomicUint { v:v }
    }

    #[inline]
    pub fn load(&self, order: Ordering) -> uint {
        unsafe { atomic_load(&self.v, order) }
    }

    #[inline]
    pub fn store(&mut self, val: uint, order: Ordering) {
        unsafe { atomic_store(&mut self.v, val, order); }
    }

    #[inline]
    pub fn swap(&mut self, val: uint, order: Ordering) -> uint {
        unsafe { atomic_swap(&mut self.v, val, order) }
    }

    #[inline]
    pub fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint {
        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
    }

    /// Returns the old value (like __sync_fetch_and_add).
    #[inline]
    pub fn fetch_add(&mut self, val: uint, order: Ordering) -> uint {
        unsafe { atomic_add(&mut self.v, val, order) }
    }

    /// Returns the old value (like __sync_fetch_and_sub)..
    #[inline]
    pub fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint {
        unsafe { atomic_sub(&mut self.v, val, order) }
    }
}

impl<T> AtomicPtr<T> {
    pub fn new(p: *mut T) -> AtomicPtr<T> {
        AtomicPtr { p:p }
    }

    #[inline]
    pub fn load(&self, order: Ordering) -> *mut T {
        unsafe { atomic_load(&self.p, order) }
    }

    #[inline]
    pub fn store(&mut self, ptr: *mut T, order: Ordering) {
        unsafe { atomic_store(&mut self.p, ptr, order); }
    }

    #[inline]
    pub fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T {
        unsafe { atomic_swap(&mut self.p, ptr, order) }
    }

    #[inline]
    pub fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
        unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) }
    }
}

impl<T> AtomicOption<T> {
    pub fn new(p: ~T) -> AtomicOption<T> {
        unsafe {
            AtomicOption {
                p: cast::transmute(p)
            }
        }
    }

    pub fn empty() -> AtomicOption<T> {
        unsafe {
            AtomicOption {
                p: cast::transmute(0)
            }
        }
    }

    #[inline]
    pub fn swap(&mut self, val: ~T, order: Ordering) -> Option<~T> {
        unsafe {
            let val = cast::transmute(val);

            let p = atomic_swap(&mut self.p, val, order);
            let pv : &uint = cast::transmute(&p);

            if *pv == 0 {
                None
            } else {
                Some(cast::transmute(p))
            }
        }
    }

    #[inline]
    pub fn take(&mut self, order: Ordering) -> Option<~T> {
        unsafe {
            self.swap(cast::transmute(0), order)
        }
    }

    /// A compare-and-swap. Succeeds if the option is 'None' and returns 'None'
    /// if so. If the option was already 'Some', returns 'Some' of the rejected
    /// value.
    #[inline]
    pub fn fill(&mut self, val: ~T, order: Ordering) -> Option<~T> {
        unsafe {
            let val = cast::transmute(val);
            let expected = cast::transmute(0);
            let oldval = atomic_compare_and_swap(&mut self.p, expected, val, order);
            if oldval == expected {
                None
            } else {
                Some(cast::transmute(val))
            }
        }
    }

    /// Be careful: The caller must have some external method of ensuring the
    /// result does not get invalidated by another task after this returns.
    #[inline]
    pub fn is_empty(&mut self, order: Ordering) -> bool {
        unsafe { atomic_load(&self.p, order) == cast::transmute(0) }
    }
}

#[unsafe_destructor]
impl<T> Drop for AtomicOption<T> {
    fn drop(&self) {
        // This will ensure that the contained data is
        // destroyed, unless it's null.
        unsafe {
            // FIXME(#4330) Need self by value to get mutability.
            let this : &mut AtomicOption<T> = cast::transmute(self);
            let _ = this.take(SeqCst);
        }
    }
}

#[inline]
pub unsafe fn atomic_store<T>(dst: &mut T, val: T, order:Ordering) {
    let dst = cast::transmute(dst);
    let val = cast::transmute(val);

    match order {
        Release => intrinsics::atomic_store_rel(dst, val),
        _       => intrinsics::atomic_store(dst, val)
    }
}

#[inline]
pub unsafe fn atomic_load<T>(dst: &T, order:Ordering) -> T {
    let dst = cast::transmute(dst);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_load_acq(dst),
        _       => intrinsics::atomic_load(dst)
    })
}

#[inline]
pub unsafe fn atomic_swap<T>(dst: &mut T, val: T, order: Ordering) -> T {
    let dst = cast::transmute(dst);
    let val = cast::transmute(val);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_xchg_acq(dst, val),
        Release => intrinsics::atomic_xchg_rel(dst, val),
        _       => intrinsics::atomic_xchg(dst, val)
    })
}

/// Returns the old value (like __sync_fetch_and_add).
#[inline]
pub unsafe fn atomic_add<T>(dst: &mut T, val: T, order: Ordering) -> T {
    let dst = cast::transmute(dst);
    let val = cast::transmute(val);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_xadd_acq(dst, val),
        Release => intrinsics::atomic_xadd_rel(dst, val),
        _       => intrinsics::atomic_xadd(dst, val)
    })
}

/// Returns the old value (like __sync_fetch_and_sub).
#[inline]
pub unsafe fn atomic_sub<T>(dst: &mut T, val: T, order: Ordering) -> T {
    let dst = cast::transmute(dst);
    let val = cast::transmute(val);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_xsub_acq(dst, val),
        Release => intrinsics::atomic_xsub_rel(dst, val),
        _       => intrinsics::atomic_xsub(dst, val)
    })
}

#[inline]
pub unsafe fn atomic_compare_and_swap<T>(dst:&mut T, old:T, new:T, order: Ordering) -> T {
    let dst = cast::transmute(dst);
    let old = cast::transmute(old);
    let new = cast::transmute(new);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_cxchg_acq(dst, old, new),
        Release => intrinsics::atomic_cxchg_rel(dst, old, new),
        _       => intrinsics::atomic_cxchg(dst, old, new),
    })
}

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

    #[test]
    fn flag() {
        let mut flg = AtomicFlag::new();
        assert!(!flg.test_and_set(SeqCst));
        assert!(flg.test_and_set(SeqCst));

        flg.clear(SeqCst);
        assert!(!flg.test_and_set(SeqCst));
    }

    #[test]
    fn option_empty() {
        assert!(AtomicOption::empty::<()>().is_empty(SeqCst));
    }

    #[test]
    fn option_swap() {
        let mut p = AtomicOption::new(~1);
        let a = ~2;

        let b = p.swap(a, SeqCst);

        assert_eq!(b, Some(~1));
        assert_eq!(p.take(SeqCst), Some(~2));
    }

    #[test]
    fn option_take() {
        let mut p = AtomicOption::new(~1);

        assert_eq!(p.take(SeqCst), Some(~1));
        assert_eq!(p.take(SeqCst), None);

        let p2 = ~2;
        p.swap(p2, SeqCst);

        assert_eq!(p.take(SeqCst), Some(~2));
    }

    #[test]
    fn option_fill() {
        let mut p = AtomicOption::new(~1);
        assert!(p.fill(~2, SeqCst).is_some()); // should fail; shouldn't leak!
        assert_eq!(p.take(SeqCst), Some(~1));

        assert!(p.fill(~2, SeqCst).is_none()); // shouldn't fail
        assert_eq!(p.take(SeqCst), Some(~2));
    }
}
<commit_msg>Added missing memory orderings for atomic types.<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.

/*!
 * Atomic types
 *
 * Basic atomic types supporting atomic operations. Each method takes an `Ordering` which
 * represents the strength of the memory barrier for that operation. These orderings are the same
 * as C++11 atomic orderings [http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync]
 *
 * All atomic types are a single word in size.
 */

use unstable::intrinsics;
use cast;
use option::{Option,Some,None};
use libc::c_void;
use ops::Drop;

/**
 * A simple atomic flag, that can be set and cleared. The most basic atomic type.
 */
pub struct AtomicFlag {
    priv v: int
}

/**
 * An atomic boolean type.
 */
pub struct AtomicBool {
    priv v: uint
}

/**
 * A signed atomic integer type, supporting basic atomic aritmetic operations
 */
pub struct AtomicInt {
    priv v: int
}

/**
 * An unsigned atomic integer type, supporting basic atomic aritmetic operations
 */
pub struct AtomicUint {
    priv v: uint
}

/**
 * An unsafe atomic pointer. Only supports basic atomic operations
 */
pub struct AtomicPtr<T> {
    priv p: *mut T
}

/**
 * An owned atomic pointer. Ensures that only a single reference to the data is held at any time.
 */
#[unsafe_no_drop_flag]
pub struct AtomicOption<T> {
    priv p: *mut c_void
}

pub enum Ordering {
    Relaxed,
    Release,
    Acquire,
    AcqRel,
    SeqCst
}

impl AtomicFlag {

    pub fn new() -> AtomicFlag {
        AtomicFlag { v: 0 }
    }

    /**
     * Clears the atomic flag
     */
    #[inline]
    pub fn clear(&mut self, order: Ordering) {
        unsafe {atomic_store(&mut self.v, 0, order)}
    }

    /**
     * Sets the flag if it was previously unset, returns the previous value of the
     * flag.
     */
    #[inline]
    pub fn test_and_set(&mut self, order: Ordering) -> bool {
        unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0}
    }
}

impl AtomicBool {
    pub fn new(v: bool) -> AtomicBool {
        AtomicBool { v: if v { 1 } else { 0 } }
    }

    #[inline]
    pub fn load(&self, order: Ordering) -> bool {
        unsafe { atomic_load(&self.v, order) > 0 }
    }

    #[inline]
    pub fn store(&mut self, val: bool, order: Ordering) {
        let val = if val { 1 } else { 0 };

        unsafe { atomic_store(&mut self.v, val, order); }
    }

    #[inline]
    pub fn swap(&mut self, val: bool, order: Ordering) -> bool {
        let val = if val { 1 } else { 0 };

        unsafe { atomic_swap(&mut self.v, val, order) > 0}
    }

    #[inline]
    pub fn compare_and_swap(&mut self, old: bool, new: bool, order: Ordering) -> bool {
        let old = if old { 1 } else { 0 };
        let new = if new { 1 } else { 0 };

        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) > 0 }
    }
}

impl AtomicInt {
    pub fn new(v: int) -> AtomicInt {
        AtomicInt { v:v }
    }

    #[inline]
    pub fn load(&self, order: Ordering) -> int {
        unsafe { atomic_load(&self.v, order) }
    }

    #[inline]
    pub fn store(&mut self, val: int, order: Ordering) {
        unsafe { atomic_store(&mut self.v, val, order); }
    }

    #[inline]
    pub fn swap(&mut self, val: int, order: Ordering) -> int {
        unsafe { atomic_swap(&mut self.v, val, order) }
    }

    #[inline]
    pub fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int {
        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
    }

    /// Returns the old value (like __sync_fetch_and_add).
    #[inline]
    pub fn fetch_add(&mut self, val: int, order: Ordering) -> int {
        unsafe { atomic_add(&mut self.v, val, order) }
    }

    /// Returns the old value (like __sync_fetch_and_sub).
    #[inline]
    pub fn fetch_sub(&mut self, val: int, order: Ordering) -> int {
        unsafe { atomic_sub(&mut self.v, val, order) }
    }
}

impl AtomicUint {
    pub fn new(v: uint) -> AtomicUint {
        AtomicUint { v:v }
    }

    #[inline]
    pub fn load(&self, order: Ordering) -> uint {
        unsafe { atomic_load(&self.v, order) }
    }

    #[inline]
    pub fn store(&mut self, val: uint, order: Ordering) {
        unsafe { atomic_store(&mut self.v, val, order); }
    }

    #[inline]
    pub fn swap(&mut self, val: uint, order: Ordering) -> uint {
        unsafe { atomic_swap(&mut self.v, val, order) }
    }

    #[inline]
    pub fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint {
        unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) }
    }

    /// Returns the old value (like __sync_fetch_and_add).
    #[inline]
    pub fn fetch_add(&mut self, val: uint, order: Ordering) -> uint {
        unsafe { atomic_add(&mut self.v, val, order) }
    }

    /// Returns the old value (like __sync_fetch_and_sub)..
    #[inline]
    pub fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint {
        unsafe { atomic_sub(&mut self.v, val, order) }
    }
}

impl<T> AtomicPtr<T> {
    pub fn new(p: *mut T) -> AtomicPtr<T> {
        AtomicPtr { p:p }
    }

    #[inline]
    pub fn load(&self, order: Ordering) -> *mut T {
        unsafe { atomic_load(&self.p, order) }
    }

    #[inline]
    pub fn store(&mut self, ptr: *mut T, order: Ordering) {
        unsafe { atomic_store(&mut self.p, ptr, order); }
    }

    #[inline]
    pub fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T {
        unsafe { atomic_swap(&mut self.p, ptr, order) }
    }

    #[inline]
    pub fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
        unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) }
    }
}

impl<T> AtomicOption<T> {
    pub fn new(p: ~T) -> AtomicOption<T> {
        unsafe {
            AtomicOption {
                p: cast::transmute(p)
            }
        }
    }

    pub fn empty() -> AtomicOption<T> {
        unsafe {
            AtomicOption {
                p: cast::transmute(0)
            }
        }
    }

    #[inline]
    pub fn swap(&mut self, val: ~T, order: Ordering) -> Option<~T> {
        unsafe {
            let val = cast::transmute(val);

            let p = atomic_swap(&mut self.p, val, order);
            let pv : &uint = cast::transmute(&p);

            if *pv == 0 {
                None
            } else {
                Some(cast::transmute(p))
            }
        }
    }

    #[inline]
    pub fn take(&mut self, order: Ordering) -> Option<~T> {
        unsafe {
            self.swap(cast::transmute(0), order)
        }
    }

    /// A compare-and-swap. Succeeds if the option is 'None' and returns 'None'
    /// if so. If the option was already 'Some', returns 'Some' of the rejected
    /// value.
    #[inline]
    pub fn fill(&mut self, val: ~T, order: Ordering) -> Option<~T> {
        unsafe {
            let val = cast::transmute(val);
            let expected = cast::transmute(0);
            let oldval = atomic_compare_and_swap(&mut self.p, expected, val, order);
            if oldval == expected {
                None
            } else {
                Some(cast::transmute(val))
            }
        }
    }

    /// Be careful: The caller must have some external method of ensuring the
    /// result does not get invalidated by another task after this returns.
    #[inline]
    pub fn is_empty(&mut self, order: Ordering) -> bool {
        unsafe { atomic_load(&self.p, order) == cast::transmute(0) }
    }
}

#[unsafe_destructor]
impl<T> Drop for AtomicOption<T> {
    fn drop(&self) {
        // This will ensure that the contained data is
        // destroyed, unless it's null.
        unsafe {
            // FIXME(#4330) Need self by value to get mutability.
            let this : &mut AtomicOption<T> = cast::transmute(self);
            let _ = this.take(SeqCst);
        }
    }
}

#[inline]
pub unsafe fn atomic_store<T>(dst: &mut T, val: T, order:Ordering) {
    let dst = cast::transmute(dst);
    let val = cast::transmute(val);

    match order {
        Release => intrinsics::atomic_store_rel(dst, val),
        Relaxed => intrinsics::atomic_store_relaxed(dst, val),
        _       => intrinsics::atomic_store(dst, val)
    }
}

#[inline]
pub unsafe fn atomic_load<T>(dst: &T, order:Ordering) -> T {
    let dst = cast::transmute(dst);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_load_acq(dst),
        Relaxed => intrinsics::atomic_load_relaxed(dst),
        _       => intrinsics::atomic_load(dst)
    })
}

#[inline]
pub unsafe fn atomic_swap<T>(dst: &mut T, val: T, order: Ordering) -> T {
    let dst = cast::transmute(dst);
    let val = cast::transmute(val);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_xchg_acq(dst, val),
        Release => intrinsics::atomic_xchg_rel(dst, val),
        AcqRel  => intrinsics::atomic_xchg_acqrel(dst, val),
        Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
        _       => intrinsics::atomic_xchg(dst, val)
    })
}

/// Returns the old value (like __sync_fetch_and_add).
#[inline]
pub unsafe fn atomic_add<T>(dst: &mut T, val: T, order: Ordering) -> T {
    let dst = cast::transmute(dst);
    let val = cast::transmute(val);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_xadd_acq(dst, val),
        Release => intrinsics::atomic_xadd_rel(dst, val),
        AcqRel  => intrinsics::atomic_xadd_acqrel(dst, val),
        Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
        _       => intrinsics::atomic_xadd(dst, val)
    })
}

/// Returns the old value (like __sync_fetch_and_sub).
#[inline]
pub unsafe fn atomic_sub<T>(dst: &mut T, val: T, order: Ordering) -> T {
    let dst = cast::transmute(dst);
    let val = cast::transmute(val);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_xsub_acq(dst, val),
        Release => intrinsics::atomic_xsub_rel(dst, val),
        AcqRel  => intrinsics::atomic_xsub_acqrel(dst, val),
        Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
        _       => intrinsics::atomic_xsub(dst, val)
    })
}

#[inline]
pub unsafe fn atomic_compare_and_swap<T>(dst:&mut T, old:T, new:T, order: Ordering) -> T {
    let dst = cast::transmute(dst);
    let old = cast::transmute(old);
    let new = cast::transmute(new);

    cast::transmute(match order {
        Acquire => intrinsics::atomic_cxchg_acq(dst, old, new),
        Release => intrinsics::atomic_cxchg_rel(dst, old, new),
        AcqRel  => intrinsics::atomic_cxchg_acqrel(dst, old, new),
        Relaxed => intrinsics::atomic_cxchg_relaxed(dst, old, new),
        _       => intrinsics::atomic_cxchg(dst, old, new),
    })
}

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

    #[test]
    fn flag() {
        let mut flg = AtomicFlag::new();
        assert!(!flg.test_and_set(SeqCst));
        assert!(flg.test_and_set(SeqCst));

        flg.clear(SeqCst);
        assert!(!flg.test_and_set(SeqCst));
    }

    #[test]
    fn option_empty() {
        assert!(AtomicOption::empty::<()>().is_empty(SeqCst));
    }

    #[test]
    fn option_swap() {
        let mut p = AtomicOption::new(~1);
        let a = ~2;

        let b = p.swap(a, SeqCst);

        assert_eq!(b, Some(~1));
        assert_eq!(p.take(SeqCst), Some(~2));
    }

    #[test]
    fn option_take() {
        let mut p = AtomicOption::new(~1);

        assert_eq!(p.take(SeqCst), Some(~1));
        assert_eq!(p.take(SeqCst), None);

        let p2 = ~2;
        p.swap(p2, SeqCst);

        assert_eq!(p.take(SeqCst), Some(~2));
    }

    #[test]
    fn option_fill() {
        let mut p = AtomicOption::new(~1);
        assert!(p.fill(~2, SeqCst).is_some()); // should fail; shouldn't leak!
        assert_eq!(p.take(SeqCst), Some(~1));

        assert!(p.fill(~2, SeqCst).is_none()); // shouldn't fail
        assert_eq!(p.take(SeqCst), Some(~2));
    }
}
<|endoftext|>


<commit_before>// check-pass

#[cfg(FALSE)]
fn simple_attr() {
    #[attr] if true {}
    #[allow_warnings] if true {}
}

#[cfg(FALSE)]
fn if_else_chain() {
    #[first_attr] if true {
    } else if false {
    } else {
    }
}

#[cfg(FALSE)]
fn if_let() {
    #[attr] if let Some(_) = Some(true) {}
}

macro_rules! custom_macro {
    ($expr:expr) => {}
}

custom_macro! {
    #[attr] if true {}
}

fn main() {}
<commit_msg>Test that cfg-gated if-exprs are not type-checked<commit_after>// check-pass

#[cfg(FALSE)]
fn simple_attr() {
    #[attr] if true {}
    #[allow_warnings] if true {}
}

#[cfg(FALSE)]
fn if_else_chain() {
    #[first_attr] if true {
    } else if false {
    } else {
    }
}

#[cfg(FALSE)]
fn if_let() {
    #[attr] if let Some(_) = Some(true) {}
}

fn bar() {
    #[cfg(FALSE)]
    if true {
        let x: () = true; // Should not error due to the #[cfg(FALSE)]
    }

    #[cfg_attr(not(unset_attr), cfg(FALSE))]
    if true {
        let a: () = true; // Should not error due to the applied #[cfg(FALSE)]
    }
}

macro_rules! custom_macro {
    ($expr:expr) => {}
}

custom_macro! {
    #[attr] if true {}
}

fn main() {}
<|endoftext|>


<commit_before>pub type c_long = i64;
pub type c_ulong = u64;
pub type c_char = u8;

// should be pub(crate), but that requires Rust 1.18.0
cfg_if! {
    if #[cfg(libc_const_size_of)] {
        #[doc(hidden)]
        pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1;
    } else {
        #[doc(hidden)]
        pub const _ALIGNBYTES: usize = 8 - 1;
    }
}

pub const _MAX_PAGE_SHIFT: u32 = 12;
<commit_msg>Auto merge of #2372 - devnexen:obsd_sigcontext_aarch64, r=semarie,JohnTitor<commit_after>pub type c_long = i64;
pub type c_ulong = u64;
pub type c_char = u8;
pub type ucontext_t = sigcontext;

s! {
    pub struct sigcontext {
        __sc_unused: ::c_int,
        pub sc_mask: ::c_int,
        pub sc_sp: ::c_ulong,
        pub sc_lr: ::c_ulong,
        pub sc_elr: ::c_ulong,
        pub sc_spsr: ::c_ulong,
        pub sc_x: [::c_ulong; 30],
        pub sc_cookie: ::c_long,
    }
}

// should be pub(crate), but that requires Rust 1.18.0
cfg_if! {
    if #[cfg(libc_const_size_of)] {
        #[doc(hidden)]
        pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1;
    } else {
        #[doc(hidden)]
        pub const _ALIGNBYTES: usize = 8 - 1;
    }
}

pub const _MAX_PAGE_SHIFT: u32 = 12;
<|endoftext|>


<commit_before>//
// Mnemosyne: a functional systems programming language.
// (c) 2015 Hawk Weisman
//
// Mnemosyne is released under the MIT License. Please refer to
// the LICENSE file at the top-level directory of this distribution
// or at https://github.com/hawkw/mnemosyne/.
//

use std::rc::Rc;
use std::fmt;
use std::fmt::Write;
use std::iter;

use ast;

const ARROW: &'static str       = "\u{8594}";
const FAT_ARROW: &'static str   = "\u{8685}";

#[derive(Debug, Clone, PartialEq)]
pub enum Type {
    /// Reference types
    Ref(Reference),
    /// Primitive types
    Prim(Primitive),
    /// An algebraic data type.
    ///
    /// Represented as a vector of variants.
    Algebraic(Vec<Type>),
    /// A function.
    Function(Signature),
    /// A unique symbol type (`'symbol` syntax)
    Symbol(String)
}

impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self { &Type::Ref(ref r) =>  write!(f, "{}", r)
                   , &Type::Prim(ref p) => write!(f, "{}", p)
                   , &Type::Algebraic(ref variants) =>
                        unimplemented!()
                   , &Type::Function(ref fun) => write!(f, "{}", fun)
                   , &Type::Symbol(ref s) => write!(f, "{}", s)
                   }
    }
}

/// A function signature
///
/// This implements both `Type` and `Node`, since it can be used as
/// a type value (for a higher-order function), or as the AST node
/// for the definition of a function.
#[derive(Clone, Debug, PartialEq)]
pub struct Signature { /// Any typeclass constraints on the function
                       pub constraints: Option<Vec<Constraint>>
                     , /// The actual function type chain globule
                       pub typechain: Vec<Type>
                     }
impl Signature {
    /// The uncurried return type of the function
    ///
    /// This just returns the last element in the type glob
    pub fn return_type(&self) -> &Type { &self.typechain[0] }
    /// Returns the arity of the function
    pub fn arity(&self) -> usize { self.typechain.len() - 1 }
}

 impl fmt::Display for Signature {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unimplemented!()
     }
 }

/// Format a bunch of things to Strings and concatenate them together.
fn concat_all<A,B>(xs: B) -> String
where A: fmt::Display
    , B: Iterator<Item=A>
{
    xs.fold(String::new(), |mut s, x| {
        write!(&mut s, "{}", x).expect("Could not append to string!");
        s
    })
}

 impl ast::Node for Signature {
     fn to_sexpr(&self, level: usize) -> String {
         format!( "{indent}{}({arrow} {})"
                , self.constraints
                      .clone()
                      .map(|ref cs| format!( "({arrow} {})"
                                      , concat_all(cs.iter())
                                      , arrow = FAT_ARROW )
                        )
                    .unwrap_or(String::from(""))
                , concat_all(self.typechain.iter())
                , arrow  = ARROW
                , indent = indent!(level)
                )
     }
 }

#[derive(Clone, Debug, PartialEq)]
pub struct Constraint { pub typeclass: ast::Ident
                      , pub generics: Vec<ast::Ident> }

impl fmt::Display for Constraint {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!()
    }
}

/// Reference types (pointers)
///
/// TODO: how will lifetime analysis actually work?
#[derive(Debug, Clone, PartialEq)]
pub enum Reference {
    /// A reference borrowed from another scope.
    ///
    /// Semantically similar to Rust's `&`-pointers.
    ///
    /// TODO: should this track where it was borrowed from?
    /// (can we even perform this analysis at this stage?)
    Borrowed(Rc<Type>),
    /// A moved reference from another scope
    ///
    /// TODO: should this track where it was moved from?
    /// (can we even perform this analysis at this stage?)
    Moved(Rc<Type>),
    /// A unique (i.e. boxed) reference.
    Unique(Rc<Type>),
    /// A raw (unsafe) reference.
    ///
    /// Unfortunately we have to have this because of
    /// reasons (i.e, FFI).
    Raw(Rc<Type>)
}

impl fmt::Display for Reference {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { Reference::Borrowed(ref t) =>  write!(f, "&{}", t)
                    , Reference::Moved(ref t) =>  write!(f, "move {}", t)
                    , Reference::Unique(ref t) =>  write!(f, "@{}", t)
                    , Reference::Raw(ref t) =>  write!(f, "*{}", t)
                    }
    }
}

/// Language primitive types
///
/// TODO: add some form of provable-refinement (i.e. we know that some value
/// is not just a bool at compile time but that it's true/false, or we know
/// some value is not just a number but the number 1382, or whatever).
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Primitive { Int(Int)
                   , IntSize
                   , Uint(Int)
                   , UintSize
                   , Byte
                   , Char
                   , Str
                   , Bool
                   , Float
                   , Double
                   // TODO: finish
                   }
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Int { Int8  = 8
             , Int16 = 16
             , Int32 = 32
             , Int64 = 64
             }

impl fmt::Display for Primitive {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       match *self { Primitive::Int(bits)  => write!(f, "i{}", bits as isize)
                   , Primitive::Uint(bits) => write!(f, "u{}", bits as isize)
                   , Primitive::IntSize    => write!(f, "int")
                   , Primitive::UintSize   => write!(f, "uint")
                   , Primitive::Double     => write!(f, "double")
                   , Primitive::Float      => write!(f, "float")
                   , Primitive::Bool       => write!(f, "bool")
                   , _ => unimplemented!()
                   }
   }
}
<commit_msg>Use arrows from chars module in types as well<commit_after>//
// Mnemosyne: a functional systems programming language.
// (c) 2015 Hawk Weisman
//
// Mnemosyne is released under the MIT License. Please refer to
// the LICENSE file at the top-level directory of this distribution
// or at https://github.com/hawkw/mnemosyne/.
//

use std::rc::Rc;
use std::fmt;
use std::fmt::Write;
use std::iter;

use ast;
use ::chars;

#[derive(Debug, Clone, PartialEq)]
pub enum Type {
    /// Reference types
    Ref(Reference),
    /// Primitive types
    Prim(Primitive),
    /// An algebraic data type.
    ///
    /// Represented as a vector of variants.
    Algebraic(Vec<Type>),
    /// A function.
    Function(Signature),
    /// A unique symbol type (`'symbol` syntax)
    Symbol(String)
}

impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self { &Type::Ref(ref r) =>  write!(f, "{}", r)
                   , &Type::Prim(ref p) => write!(f, "{}", p)
                   , &Type::Algebraic(ref variants) =>
                        unimplemented!()
                   , &Type::Function(ref fun) => write!(f, "{}", fun)
                   , &Type::Symbol(ref s) => write!(f, "{}", s)
                   }
    }
}

/// A function signature
///
/// This implements both `Type` and `Node`, since it can be used as
/// a type value (for a higher-order function), or as the AST node
/// for the definition of a function.
#[derive(Clone, Debug, PartialEq)]
pub struct Signature { /// Any typeclass constraints on the function
                       pub constraints: Option<Vec<Constraint>>
                     , /// The actual function type chain globule
                       pub typechain: Vec<Type>
                     }
impl Signature {
    /// The uncurried return type of the function
    ///
    /// This just returns the last element in the type glob
    pub fn return_type(&self) -> &Type { &self.typechain[0] }
    /// Returns the arity of the function
    pub fn arity(&self) -> usize { self.typechain.len() - 1 }
}

 impl fmt::Display for Signature {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unimplemented!()
     }
 }

/// Format a bunch of things to Strings and concatenate them together.
fn concat_all<A,B>(xs: B) -> String
where A: fmt::Display
    , B: Iterator<Item=A>
{
    xs.fold(String::new(), |mut s, x| {
        write!(&mut s, "{}", x).expect("Could not append to string!");
        s
    })
}

 impl ast::Node for Signature {
     fn to_sexpr(&self, level: usize) -> String {
         format!( "{indent}{}({arrow} {})"
                , self.constraints
                      .clone()
                      .map(|ref cs| format!( "({arrow} {})"
                                      , concat_all(cs.iter())
                                      , arrow = chars::FAT_ARROW )
                        )
                    .unwrap_or(String::from(""))
                , concat_all(self.typechain.iter())
                , arrow  = chars::ARROW
                , indent = indent!(level)
                )
     }
 }

#[derive(Clone, Debug, PartialEq)]
pub struct Constraint { pub typeclass: ast::Ident
                      , pub generics: Vec<ast::Ident> }

impl fmt::Display for Constraint {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!()
    }
}

/// Reference types (pointers)
///
/// TODO: how will lifetime analysis actually work?
#[derive(Debug, Clone, PartialEq)]
pub enum Reference {
    /// A reference borrowed from another scope.
    ///
    /// Semantically similar to Rust's `&`-pointers.
    ///
    /// TODO: should this track where it was borrowed from?
    /// (can we even perform this analysis at this stage?)
    Borrowed(Rc<Type>),
    /// A moved reference from another scope
    ///
    /// TODO: should this track where it was moved from?
    /// (can we even perform this analysis at this stage?)
    Moved(Rc<Type>),
    /// A unique (i.e. boxed) reference.
    Unique(Rc<Type>),
    /// A raw (unsafe) reference.
    ///
    /// Unfortunately we have to have this because of
    /// reasons (i.e, FFI).
    Raw(Rc<Type>)
}

impl fmt::Display for Reference {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { Reference::Borrowed(ref t) =>  write!(f, "&{}", t)
                    , Reference::Moved(ref t) =>  write!(f, "move {}", t)
                    , Reference::Unique(ref t) =>  write!(f, "@{}", t)
                    , Reference::Raw(ref t) =>  write!(f, "*{}", t)
                    }
    }
}

/// Language primitive types
///
/// TODO: add some form of provable-refinement (i.e. we know that some value
/// is not just a bool at compile time but that it's true/false, or we know
/// some value is not just a number but the number 1382, or whatever).
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Primitive { Int(Int)
                   , IntSize
                   , Uint(Int)
                   , UintSize
                   , Byte
                   , Char
                   , Str
                   , Bool
                   , Float
                   , Double
                   // TODO: finish
                   }
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Int { Int8  = 8
             , Int16 = 16
             , Int32 = 32
             , Int64 = 64
             }

impl fmt::Display for Primitive {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       match *self { Primitive::Int(bits)  => write!(f, "i{}", bits as isize)
                   , Primitive::Uint(bits) => write!(f, "u{}", bits as isize)
                   , Primitive::IntSize    => write!(f, "int")
                   , Primitive::UintSize   => write!(f, "uint")
                   , Primitive::Double     => write!(f, "double")
                   , Primitive::Float      => write!(f, "float")
                   , Primitive::Bool       => write!(f, "bool")
                   , _ => unimplemented!()
                   }
   }
}
<|endoftext|>